@roxyapi/ui-react 0.8.0 → 0.9.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 (42) hide show
  1. package/AGENTS.md +49 -47
  2. package/README.md +74 -47
  3. package/dist/components/ashtakavarga-grid.js.map +1 -1
  4. package/dist/components/biorhythm-chart.js.map +1 -1
  5. package/dist/components/bodygraph.js.map +1 -1
  6. package/dist/components/choghadiya-grid.js.map +1 -1
  7. package/dist/components/compatibility-card.js.map +1 -1
  8. package/dist/components/dasha-timeline.js.map +1 -1
  9. package/dist/components/data.js.map +1 -1
  10. package/dist/components/divisional-chart.js.map +1 -1
  11. package/dist/components/dosha-card.js.map +1 -1
  12. package/dist/components/endpoint-form.js.map +1 -1
  13. package/dist/components/forecast-timeline.js.map +1 -1
  14. package/dist/components/guna-milan.js.map +1 -1
  15. package/dist/components/hexagram.js.map +1 -1
  16. package/dist/components/horoscope-card.js.map +1 -1
  17. package/dist/components/kp-chart.js.map +1 -1
  18. package/dist/components/kp-planets-table.js.map +1 -1
  19. package/dist/components/kp-ruling-planets.js.map +1 -1
  20. package/dist/components/location-search.js.map +1 -1
  21. package/dist/components/moon-phase.js.map +1 -1
  22. package/dist/components/nakshatra-card.js.map +1 -1
  23. package/dist/components/natal-chart.js.map +1 -1
  24. package/dist/components/numerology-card.js.map +1 -1
  25. package/dist/components/panchang-table.js.map +1 -1
  26. package/dist/components/shadbala-table.js.map +1 -1
  27. package/dist/components/synastry-chart.js.map +1 -1
  28. package/dist/components/tarot-card.js.map +1 -1
  29. package/dist/components/tarot-spread.js.map +1 -1
  30. package/dist/components/transits-table.js.map +1 -1
  31. package/dist/components/vedic-kundli.js.map +1 -1
  32. package/dist/components/vedic-planets-table.js.map +1 -1
  33. package/dist/components/western-planets-table.js.map +1 -1
  34. package/dist/components/yoga-list.js.map +1 -1
  35. package/dist/index.cjs +1 -1
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/load-ui.d.ts +1 -1
  40. package/dist/load-ui.js +1 -1
  41. package/dist/load-ui.js.map +1 -1
  42. package/package.json +1 -1
package/AGENTS.md CHANGED
@@ -122,16 +122,15 @@ Every chart endpoint accepts `timezone` as either a decimal-hour offset (`5.5` f
122
122
 
123
123
  ### 4. Secret key in the browser
124
124
 
125
- There are two key classes. **Secret keys are unprefixed** and grant full access; they belong server-side only (Node, Bun, Hono, Next.js route handlers, Workers, Edge functions). **Publishable keys** are prefixed `pk_live_*` or `pk_test_*` and are safe in the browser; they are locked to an origin allowlist at the API gateway. For widgets, embeds, vanilla HTML, and `data-publishable-key` use the publishable key. For the typed SDK on a server, use the secret key.
125
+ Secret keys (`sk_*`) grant full account access and are server side only. Call `createRoxy(process.env.ROXY_API_KEY!)` on your server (Node, Bun, Hono, Next.js route handlers, Workers, Edge functions), then send the response, not the key, to the component. Never ship a secret key in a client bundle.
126
126
 
127
127
  ```ts
128
- // Server (Next.js route handler, Workers, Bun): secret key
128
+ // Secret key: server side only
129
129
  const roxy = createRoxy(process.env.ROXY_API_KEY!);
130
-
131
- // Browser (widgets auto-mount): publishable key
132
- <div data-roxy-widget="natal-chart" data-publishable-key="pk_live_xxx" ...></div>
133
130
  ```
134
131
 
132
+ For direct client-side calls, use a **publishable key** (`pk_live_*` / `pk_test_*`) instead. Publishable keys are browser-safe: mint one at `roxyapi.com/account`, register the origins you embed on, and the API gateway returns 403 for any other origin. See the client-side pattern below.
133
+
135
134
  ### 5. Missing `'use client'` in Next.js App Router
136
135
 
137
136
  The React components in `@roxyapi/ui-react` mount Custom Elements, which need the DOM. In the App Router, files that import them must declare `'use client'` at the top. Server Components can fetch with the SDK; the client component renders.
@@ -194,30 +193,30 @@ import type { NatalChartResponse } from '@roxyapi/sdk';
194
193
 
195
194
  ### Pattern 1: vanilla HTML, no build step
196
195
 
196
+ Fetch on your server with the secret key, then inline the response into the component as a child `<script type="application/json" class="roxy-data">`. The component reads it on load. No key in the browser.
197
+
197
198
  ```html
198
199
  <script
199
200
  src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js"
200
201
  crossorigin="anonymous"
201
202
  ></script>
202
203
 
203
- <roxy-natal-chart id="chart"></roxy-natal-chart>
204
-
205
- <script type="module">
206
- import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@latest/dist/factory.js';
207
- const roxy = createRoxy('pk_live_xxx');
208
- const { data } = await roxy.astrology.generateNatalChart({
209
- body: { date: '1990-01-15', time: '14:30:00', latitude: 19.07, longitude: 72.88, timezone: 5.5 },
210
- });
211
- document.getElementById('chart').data = data;
212
- </script>
204
+ <roxy-natal-chart>
205
+ <script type="application/json" class="roxy-data">
206
+ { "planets": [ ... ], "houses": [ ... ], "aspects": [ ... ] }
207
+ </script>
208
+ </roxy-natal-chart>
213
209
  ```
214
210
 
215
- ### Pattern 2: React, with the typed SDK
211
+ Setting the JavaScript `data` property always wins over the inlined JSON, so the same element also drives dynamic pages.
212
+
213
+ ### Pattern 2: React, interactive
214
+
215
+ `<RoxyLocationSearch>` runs in the browser. On select, call your own route, which holds the secret key, and set the returned data on the chart. The key never reaches the client.
216
216
 
217
217
  ```tsx
218
218
  'use client';
219
219
 
220
- import { createRoxy } from '@roxyapi/sdk';
221
220
  import {
222
221
  RoxyNatalChart,
223
222
  RoxyLocationSearch,
@@ -225,18 +224,18 @@ import {
225
224
  } from '@roxyapi/ui-react';
226
225
  import { useState } from 'react';
227
226
 
228
- const roxy = createRoxy(process.env.NEXT_PUBLIC_ROXY_API_KEY!);
229
-
230
227
  export function BirthChartView() {
231
228
  const [chart, setChart] = useState<RoxyNatalChartProps['data']>(undefined);
232
229
 
233
230
  const onLocationSelect = async (e: CustomEvent<{ latitude?: number; longitude?: number; timezone?: number | string }>) => {
234
231
  const { latitude, longitude, timezone } = e.detail;
235
232
  if (latitude == null || longitude == null) return;
236
- const { data } = await roxy.astrology.generateNatalChart({
237
- body: { date: '1990-01-15', time: '14:30:00', latitude, longitude, timezone },
233
+ // Your route calls roxy.astrology.generateNatalChart with the secret key.
234
+ const res = await fetch('/api/natal-chart', {
235
+ method: 'POST',
236
+ body: JSON.stringify({ date: '1990-01-15', time: '14:30:00', latitude, longitude, timezone }),
238
237
  });
239
- setChart(data);
238
+ setChart(await res.json());
240
239
  };
241
240
 
242
241
  return (
@@ -248,9 +247,11 @@ export function BirthChartView() {
248
247
  }
249
248
  ```
250
249
 
250
+ For a static chart with no picker, fetch in a Server Component and pass `data` to a client component (Pattern 6).
251
+
251
252
  ### Pattern 3: schema-driven form
252
253
 
253
- `<roxy-endpoint-form>` reads the OpenAPI spec and renders the inputs for any endpoint. Listen for the `roxy-submit` event with the validated payload.
254
+ `<roxy-endpoint-form>` reads the OpenAPI spec and renders the inputs for any endpoint. On `roxy-submit`, POST the validated values to your own route, which calls the SDK with the secret key, then set the returned data on the target component.
254
255
 
255
256
  ```html
256
257
  <roxy-endpoint-form
@@ -258,41 +259,42 @@ export function BirthChartView() {
258
259
  method="POST"
259
260
  submit-label="Generate kundli"
260
261
  ></roxy-endpoint-form>
262
+ <roxy-vedic-kundli chart-style="south"></roxy-vedic-kundli>
261
263
 
262
264
  <script type="module">
263
- import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@latest/dist/factory.js';
264
- const roxy = createRoxy('pk_live_xxx');
265
265
  const form = document.querySelector('roxy-endpoint-form');
266
266
  form.addEventListener('roxy-submit', async (e) => {
267
- const { values } = e.detail;
268
- const { data: kundli } = await roxy.vedicAstrology.generateBirthChart({ body: values });
269
- document.querySelector('roxy-vedic-kundli').data = kundli;
267
+ // Your route calls roxy.vedicAstrology.generateBirthChart with the secret key.
268
+ const res = await fetch('/api/kundli', { method: 'POST', body: JSON.stringify(e.detail.values) });
269
+ document.querySelector('roxy-vedic-kundli').data = await res.json();
270
270
  });
271
271
  </script>
272
272
  ```
273
273
 
274
- ### Pattern 4: widgets auto-mount (no JavaScript wiring)
274
+ ### Pattern 4: fully client-side with a publishable key (no server)
275
275
 
276
- Use a publishable key (`pk_live_*` or `pk_test_*`) for client-side embeds. Get one at <https://roxyapi.com/account>. Publishable keys are origin-restricted at the API gateway. Register the customer domain (e.g. `https://customer.com`) when creating the key, and the gateway will reject requests from any other origin. Never use a secret key in client-side code (secret keys are unprefixed and live server-side only).
276
+ When you do not want a backend at all, mint a **publishable key** (`pk_live_*`) at `roxyapi.com/account`, register the origins you embed on, and call RoxyAPI directly from the browser. The publishable key is safe to ship in client code: it is origin-restricted (any other origin gets 403) and cannot read your account. `<roxy-location-search>` accepts the key via its `publishable-key` attribute and fetches geocoding itself; for the data endpoints you make a normal browser `fetch` with the key in the `X-API-Key` header, then assign the response to the rendering component.
277
277
 
278
278
  ```html
279
- <script
280
- src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/widgets.js"
281
- defer
282
- ></script>
279
+ <roxy-location-search publishable-key="pk_live_..."></roxy-location-search>
280
+ <roxy-natal-chart></roxy-natal-chart>
283
281
 
284
- <div
285
- data-roxy-widget="natal-chart"
286
- data-publishable-key="pk_live_xxx"
287
- data-date="1990-01-15"
288
- data-time="14:30:00"
289
- data-latitude="19.07"
290
- data-longitude="72.88"
291
- data-timezone="5.5"
292
- ></div>
282
+ <script type="module">
283
+ const chart = document.querySelector('roxy-natal-chart');
284
+ document.querySelector('roxy-location-search').addEventListener('roxy-location-select', async (e) => {
285
+ const { latitude, longitude, timezone } = e.detail;
286
+ if (latitude == null || longitude == null) return;
287
+ const res = await fetch('https://roxyapi.com/api/v2/astrology/natal-chart', {
288
+ method: 'POST',
289
+ headers: { 'X-API-Key': 'pk_live_...', 'Content-Type': 'application/json' },
290
+ body: JSON.stringify({ date: '1990-01-15', time: '14:30:00', latitude, longitude, timezone }),
291
+ });
292
+ chart.data = await res.json(); // pass the unwrapped response, not an envelope
293
+ });
294
+ </script>
293
295
  ```
294
296
 
295
- The auto-mount script reads `data-*` attributes, calls the matching endpoint, and renders the matching component.
297
+ Rendering components do not fetch on their own; you set `data`. Only `<roxy-location-search>` (and `<roxy-endpoint-form>` for the spec) fetch internally. A zero-wiring `data-*` auto-mount that fetches and renders with no script is still on the roadmap.
296
298
 
297
299
  ### Pattern 5: MCP tool-call response
298
300
 
@@ -360,13 +362,13 @@ This is how the WordPress plugin renders: PHP fetches the response server-side,
360
362
 
361
363
  ## Theming and dark mode
362
364
 
363
- Components react to three signals in priority order. No events to dispatch. No JS bridge to write.
365
+ Components react to three signals in priority order. No events to dispatch. No JS bridge to write. The CDN bundle (`dist/cdn/roxy-ui.js`) auto-loads the design tokens, so a single script tag yields full theming and dark mode with nothing else to add. The npm and React paths inherit the same tokens through the components; only set up `tokens.css` yourself if you import per component without the full bundle.
364
366
 
365
367
  | Signal | Where | Effect |
366
368
  |---|---|---|
367
369
  | `prefers-color-scheme: dark` | OS | Default. Follows user system setting. |
368
370
  | `data-theme="light"` or `data-theme="dark"` | `<html>` / `<body>` / any ancestor / the component itself | Wins over OS. Per-element override scope works. |
369
- | `.dark` class | Any ancestor | Equivalent to `data-theme="dark"`. Use when the host stack already ships a `.dark` toggle (Tailwind, shadcn). |
371
+ | `.dark` class | The component itself or any ancestor (typically `<html>`) | Same effect as `data-theme="dark"`. Use when the host stack already ships a `.dark` toggle (Tailwind, shadcn). |
370
372
 
371
373
  To toggle at runtime:
372
374
 
@@ -396,7 +398,7 @@ Every visible aspect of the chart is driven by `--roxy-*` CSS custom properties
396
398
 
397
399
  ## Domain ordering
398
400
 
399
- When listing domains in user-visible copy, use the canonical order: Western astrology, Vedic astrology, numerology, tarot, biorhythm, I Ching, crystals, dreams, angel numbers. Location is utility, not a selling domain.
401
+ When listing domains in user-visible copy, use the canonical order: Western astrology, Vedic astrology, numerology, tarot, human design, forecast, biorhythm, I Ching, crystals, dreams, angel numbers. Location is utility, not a selling domain.
400
402
 
401
403
  ## What not to ship
402
404
 
package/README.md CHANGED
@@ -55,7 +55,7 @@ Light, dark, your brand. Override one CSS variable and every component updates.
55
55
  ```css
56
56
  :root {
57
57
  /* Surface */
58
- --roxy-bg: #fafafa;
58
+ --roxy-bg: #ffffff;
59
59
  --roxy-fg: #0a0a0a;
60
60
  --roxy-muted: #71717a;
61
61
  --roxy-border: #e4e4e7;
@@ -66,13 +66,13 @@ Light, dark, your brand. Override one CSS variable and every component updates.
66
66
 
67
67
  /* Status (each has a -fg variant for WCAG-AA text contrast) */
68
68
  --roxy-success: #16a34a;
69
- --roxy-warning: #f59e0b;
69
+ --roxy-warning: #ea580c;
70
70
  --roxy-danger: #dc2626;
71
- --roxy-info: #2563eb;
71
+ --roxy-info: #0284c7;
72
72
 
73
73
  /* Shape + motion */
74
- --roxy-radius-md: 12px;
75
- --roxy-shadow-md: 0 4px 12px rgba(0,0,0,0.08);
74
+ --roxy-radius-md: 8px;
75
+ --roxy-shadow-md: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.06);
76
76
  --roxy-motion-duration: 200ms; /* 0ms when prefers-reduced-motion */
77
77
  }
78
78
 
@@ -221,42 +221,24 @@ Tables, cards, forms, and helper components in the [live demo](https://roxyapi.g
221
221
 
222
222
  ## Start with one component
223
223
 
224
- Vanilla HTML. No build step. Replace `YOUR_API_KEY` with a publishable key from <https://roxyapi.com/account>.
224
+ Fetch with the typed SDK, pass `data` to the component. No glue code.
225
225
 
226
- ```html
227
- <script
228
- src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js"
229
- crossorigin="anonymous"
230
- defer
231
- ></script>
232
- <roxy-natal-chart id="chart"></roxy-natal-chart>
233
- <script type="module">
234
- import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@latest/dist/factory.js';
235
- const roxy = createRoxy('YOUR_API_KEY');
236
- const { data } = await roxy.astrology.generateNatalChart({
237
- body: { date: '1990-01-15', time: '14:30:00', latitude: 19.07, longitude: 72.88, timezone: 5.5 },
238
- });
239
- document.getElementById('chart').data = data;
240
- </script>
241
- ```
226
+ ```tsx
227
+ import { createRoxy } from '@roxyapi/sdk';
228
+ import { RoxyHoroscopeCard } from '@roxyapi/ui-react';
242
229
 
243
- > **Unwrap `data` before passing to the component.** The SDK returns `{ data, error, request, response }`. Pass the envelope and the chart renders `[object Object]`. This is the most common integration bug.
230
+ const roxy = createRoxy(process.env.ROXY_API_KEY!);
244
231
 
245
- Want a Vedic kundli instead? Same shape, different SDK method:
232
+ const { data } = await roxy.astrology.getDailyHoroscope({ path: { sign: 'aries' } });
246
233
 
247
- ```html
248
- <roxy-vedic-kundli id="kundli" chart-style="south"></roxy-vedic-kundli>
249
- <script type="module">
250
- import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@latest/dist/factory.js';
251
- const roxy = createRoxy('YOUR_API_KEY');
252
- const { data } = await roxy.vedicAstrology.generateBirthChart({
253
- body: { date: '1990-01-15', time: '14:30:00', latitude: 19.07, longitude: 72.88, timezone: 5.5 },
254
- });
255
- document.getElementById('kundli').data = data;
256
- </script>
234
+ return <RoxyHoroscopeCard data={data} />;
257
235
  ```
258
236
 
259
- In production, geocode the user's city with `<roxy-location-search>` (see [Quick start](#quick-start)) instead of hardcoding coordinates.
237
+ Then expand into natal charts, kundli, dasha, tarot, and every other domain. The SDK returns `data`, the component renders it; the same pairing holds for all 32 components.
238
+
239
+ > **Pass `data`, not the envelope.** The SDK returns `{ data, error, request, response }`. Pass `data`, or the component renders `[object Object]`. This is the most common integration bug.
240
+
241
+ The key stays on your server. Vanilla HTML or a server-rendered page fetches the same way, then [inlines the JSON into the component](#server-rendered-no-javascript-wiring): no build step, no key in the browser. Try every component in the [live demo](https://roxyapi.github.io/ui/), each with Preview, Code, and shadcn tabs and a live color customizer.
260
242
 
261
243
  ## Install
262
244
 
@@ -306,7 +288,12 @@ Always call `/location/search` first. Every chart endpoint expects latitude, lon
306
288
 
307
289
  Server-rendered and cached pages (WordPress, JSX SSR, static HTML) cannot always run JavaScript to set the `data` property per element. Render the response into a child `<script type="application/json" class="roxy-data">` on the server instead. The component reads it on load. No per-element script, no API key in the browser.
308
290
 
291
+ Load the bundle once anywhere on the page. It registers every `roxy-*` element and loads the design tokens, so every component on the page renders themed, in light or dark, from that single tag. Nothing else to add.
292
+
309
293
  ```html
294
+ <!-- Once per page: defines every roxy-* element -->
295
+ <script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js" crossorigin="anonymous" defer></script>
296
+
310
297
  <roxy-natal-chart>
311
298
  <script type="application/json" class="roxy-data">
312
299
  { "planets": [ ... ], "houses": [ ... ], "aspects": [ ... ] }
@@ -458,7 +445,48 @@ const { data: cc } = await roxy.tarot.castCelticCross({
458
445
  <RoxyTarotSpread data={cc} />
459
446
  ```
460
447
 
461
- ### 5. Biorhythm (daily, forecast)
448
+ ### 5. Human Design (bodygraph)
449
+
450
+ The breakout 2026 self-knowledge category, computed from the same ephemeris as Western astrology plus the I Ching gate wheel and chakra-style centers. Self-discovery apps, dating and compatibility products, and AI coaching bots ship the full bodygraph first. No coordinates needed; Human Design uses the birth instant, not the observer location.
451
+
452
+ ```tsx
453
+ import { RoxyBodygraph } from '@roxyapi/ui-react';
454
+
455
+ // Full bodygraph. The head term every Human Design app leads with ("human design chart").
456
+ // Type, strategy, authority, profile, the nine centers, channels, and every gate
457
+ // activation in one call. Pass the birth instant only, no latitude or longitude.
458
+ const { data: bodygraph } = await roxy.humanDesign.generateBodygraph({
459
+ body: { date: '1990-01-15', time: '14:30:00', timezone: 5.5 },
460
+ });
461
+ <RoxyBodygraph data={bodygraph} />
462
+ ```
463
+
464
+ ### 6. Forecast (transits, cross-domain timeline)
465
+
466
+ The first cross-domain, stateless forecast in the catalog: one call merges Western transits, Vedic Vimshottari dasha boundaries, and biorhythm critical days into a single significance-scored, time-ordered timeline. Forecast feeds, transit alerts, and timing tools are the buyers. Acquire on the high-volume `astrology transits` search, convert on the cross-domain timeline no competitor ships. No coordinates needed.
467
+
468
+ ```tsx
469
+ import { RoxyForecastTimeline } from '@roxyapi/ui-react';
470
+
471
+ // Transit forecast. The demand leader. Western transit-to-natal aspects, sign
472
+ // ingresses, and retrograde stations over the window.
473
+ const { data: transits } = await roxy.forecast.forecastTransits({
474
+ body: { birthData: { date: '1990-01-15', time: '14:30:00', timezone: 5.5 } },
475
+ });
476
+ <RoxyForecastTimeline data={transits} />
477
+
478
+ // Cross-domain timeline. The same window merged with Vedic dasha boundaries and
479
+ // biorhythm critical days into one significance-scored timeline.
480
+ const { data: timeline } = await roxy.forecast.generateTimeline({
481
+ body: {
482
+ birthData: { date: '1990-01-15', time: '14:30:00', timezone: 5.5 },
483
+ domains: ['western', 'vedic', 'biorhythm'],
484
+ },
485
+ });
486
+ <RoxyForecastTimeline data={timeline} />
487
+ ```
488
+
489
+ ### 7. Biorhythm (daily, forecast)
462
490
 
463
491
  Zero competition domain. Steady search volume with the top Google result being a static calculator page. Pure land-grab for wellness, productivity, sports, and couples apps.
464
492
 
@@ -479,7 +507,7 @@ const { data: forecast } = await roxy.biorhythm.getForecast({
479
507
  <RoxyBiorhythmChart data={forecast} mode="forecast" />
480
508
  ```
481
509
 
482
- ### 6. I Ching (cast a reading, hexagram lookup)
510
+ ### 8. I Ching (cast a reading, hexagram lookup)
483
511
 
484
512
  Meditation apps, decision-making tools, and wisdom chatbots. `i ching API` and `hexagram API` are the keywords.
485
513
 
@@ -499,12 +527,11 @@ const { data: random } = await roxy.iching.getRandomHexagram();
499
527
 
500
528
  ## API keys
501
529
 
502
- Get keys at <https://roxyapi.com/account>.
530
+ Get a key at <https://roxyapi.com/account>.
503
531
 
504
- - **Secret key** (server-side only). Use in Node, Bun, Hono, Next.js route handlers, Workers. Never commit, never ship in client bundles.
505
- - **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 allowlist.
532
+ Two key types. **Secret keys** (`sk_*`) grant full account access: use them server side only (Node, Bun, Hono, Next.js route handlers, Workers). Never commit one, never ship one in a client bundle. **Publishable keys** (`pk_live_*` / `pk_test_*`) are browser-safe: mint one, register the origins you embed on, and any other origin gets a 403 at the gateway. Use a publishable key when you call RoxyAPI directly from the browser with no backend.
506
533
 
507
- 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 domain registered on it.
534
+ Set `ROXY_API_KEY` to your secret key in your server env for the server-side SDK examples on this page. For direct client-side embedding with no backend, use a publishable key (see the fully client-side pattern in [`AGENTS.md`](AGENTS.md)).
508
535
 
509
536
  ## Distribution
510
537
 
@@ -514,7 +541,7 @@ For the SDK examples on this page, set `ROXY_API_KEY` to a secret key in your se
514
541
  | npm `@roxyapi/ui-react` | `npmjs.com/package/@roxyapi/ui-react` |
515
542
  | jsDelivr CDN (full bundle) | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js` |
516
543
  | jsDelivr CDN (per component) | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/components/{name}.js` |
517
- | Widgets auto-mount | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/widgets.js` |
544
+ | Widgets auto-mount (with browser keys, coming soon) | `cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/widgets.js` |
518
545
  | shadcn registry | `npx shadcn@latest add https://cdn.jsdelivr.net/gh/RoxyAPI/ui@latest/registry/{name}.json` |
519
546
 
520
547
  ## Components
@@ -568,7 +595,7 @@ For the SDK examples on this page, set `ROXY_API_KEY` to a secret key in your se
568
595
 
569
596
  ## Theming
570
597
 
571
- 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.
598
+ 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. The CDN bundle auto-loads these tokens; your `:root { --roxy-* }` overrides always win over the defaults. See [THEMING.md](https://github.com/RoxyAPI/ui/blob/main/packages/ui/THEMING.md) for the full token reference.
572
599
 
573
600
  ```css
574
601
  :root {
@@ -651,7 +678,7 @@ Persist the choice in `localStorage` from your own code; the components do not o
651
678
  <details>
652
679
  <summary><strong>How big is each component? What is the bundle cost?</strong></summary>
653
680
 
654
- Per-component bundles run 6-10 KB gzipped, capped at 30 KB by CI. The full bundle (every component, helpers, base styles) stays well under the 150 KB CI cap, around 45 KB gzipped today. 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.
681
+ Per-component bundles run 6-10 KB gzipped, capped at 30 KB by CI. The full bundle (every component, helpers, base styles, and the inlined design tokens) stays well under the 150 KB CI cap, around 54 KB gzipped today. 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.
655
682
  </details>
656
683
 
657
684
  <details>
@@ -764,7 +791,7 @@ Components ship in Shadow DOM for style isolation; Tailwind utilities are scoped
764
791
  <details>
765
792
  <summary><strong>What is the security model for API keys?</strong></summary>
766
793
 
767
- 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.
794
+ Two key types. Secret keys (`sk_*`) live server side only and grant full access, so never ship one in a client bundle: fetch on your server and pass the rendered response, not the key, to the browser. Publishable keys (`pk_live_*` / `pk_test_*`) are browser-safe for direct client-side embedding: they carry an origin allowlist, so a key leaked to any other origin returns 403 instead of working. Mint either at `roxyapi.com/account`.
768
795
 
769
796
  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.
770
797
  </details>
@@ -775,11 +802,11 @@ For CSP, allow `script-src https://cdn.jsdelivr.net` if loading the bundle from
775
802
  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:
776
803
 
777
804
  ```bash
778
- npm install @roxyapi/ui@0.1.x
805
+ npm install @roxyapi/ui@0.8.x
779
806
  ```
780
807
 
781
808
  ```html
782
- <script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@0.1.5/dist/cdn/roxy-ui.js"></script>
809
+ <script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@0.8.0/dist/cdn/roxy-ui.js"></script>
783
810
  ```
784
811
 
785
812
  The `@latest` URL on this page is for paste-friendly marketing; production code should pin.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/ashtakavarga-grid.tsx", "../../src/load-ui.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { AshtakavargaResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyAshtakavargaGridProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: AshtakavargaResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\n}\n\nexport const RoxyAshtakavargaGrid = React.forwardRef<HTMLElement | null, RoxyAshtakavargaGridProps>(\n\tfunction RoxyAshtakavargaGrid({ data, className, style, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-ashtakavarga-grid', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.8.0\";\n"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { AshtakavargaResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyAshtakavargaGridProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: AshtakavargaResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\n}\n\nexport const RoxyAshtakavargaGrid = React.forwardRef<HTMLElement | null, RoxyAshtakavargaGridProps>(\n\tfunction RoxyAshtakavargaGrid({ data, className, style, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-ashtakavarga-grid', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.9.0\";\n"],
5
5
  "mappings": "AAAA,UAAYA,MAAW,QCSvB,IAAMC,EAAY,oBACZC,EAAkB,2DAClBC,EAAkB,4CAClBC,EAAkB,YAEpBC,EAA+B,KAEnC,SAASC,EAAUC,EAAyB,CAC3C,MAAI,CAACA,GAAWA,IAAY,SAAiBL,EACtC,GAAGC,CAAe,GAAGI,CAAO,GAAGH,CAAe,EACtD,CAEO,SAASI,EAAmBD,EAAkB,SAAyB,CAC7E,OAAI,OAAO,SAAa,IAAoB,QAAQ,QAAQ,EACxDF,IAEJA,EAAS,IAAI,QAAc,CAACI,EAASC,IAAW,CAC/C,IAAMC,EAAM,GAAGL,EAAUC,CAAO,CAAC,cAC7BK,EAAW,SAAS,eAAeX,CAAS,EAChD,GAAIW,EAAU,CACTA,EAAS,QAAQ,SAAW,OAC/BH,EAAQ,GAERG,EAAS,iBAAiB,OAAQ,IAAMH,EAAQ,CAAC,EACjDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,GAElF,MACD,CACAE,EAAW,SAAS,cAAc,QAAQ,EAC1CA,EAAS,GAAKX,EACdW,EAAS,IAAMD,EACfC,EAAS,MAAQ,GACjBA,EAAS,YAAc,YACvBA,EAAS,iBAAiB,OAAQ,IAAM,CACvCA,EAAU,QAAQ,OAAS,OAC3BH,EAAQ,CACT,CAAC,EACDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,EACjF,SAAS,KAAK,YAAYE,CAAQ,CACnC,CAAC,EACMP,EACR,CDjCO,IAAMQ,EAA6B,aACzC,SAA8B,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,EAAO,GAAGC,CAAK,EAAGC,EAAK,CACvE,IAAMC,EAAiB,SAA2B,IAAI,EAChD,sBACLD,EACA,IAAMC,EAAS,QACf,CAAC,CACF,EACA,GAAM,CAACC,EAAQC,CAAS,EAAU,WAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,EAAU,WAAuB,IAAI,EAwB3D,OAtBM,YAAU,IAAM,CACrB,IAAIC,EAAS,GACb,OAAAC,EAAmB,EACjB,KAAK,IAAM,CACPD,GAAQH,EAAU,EAAI,CAC3B,CAAC,EACA,MAAOK,GAAiB,CACnBF,GACLD,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC7D,CAAC,EACK,IAAM,CACZF,EAAS,EACV,CACD,EAAG,CAAC,CAAC,EAEC,YAAU,IAAM,CACrB,IAAMG,EAAKR,EAAS,QAChBQ,GAAMb,IAAS,SACjBa,EAAoC,KAAOb,EAE9C,EAAG,CAACA,EAAMM,CAAM,CAAC,EAEbE,EACU,gBACZ,MACA,CAAE,KAAM,QAAS,UAAAP,EAAW,MAAAC,CAAM,EAClC,+BAA+BM,EAAM,OAAO,EAC7C,EAGY,gBAAc,yBAA0B,CACpD,IAAKH,EACL,UAAAJ,EACA,MAAAC,EACA,GAAGC,CACJ,CAAC,CACF,CACD",
6
6
  "names": ["React", "SCRIPT_ID", "CDN_BASE_LATEST", "CDN_BASE_PREFIX", "CDN_BASE_SUFFIX", "loaded", "buildBase", "version", "ensureScriptLoaded", "resolve", "reject", "url", "existing", "RoxyAshtakavargaGrid", "data", "className", "style", "rest", "ref", "internal", "loaded", "setLoaded", "error", "setError", "active", "ensureScriptLoaded", "err", "el"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/biorhythm-chart.tsx", "../../src/load-ui.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { GetCriticalDaysResponse, GetDailyBiorhythmResponse, GetForecastResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyBiorhythmChartProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: GetDailyBiorhythmResponse | GetForecastResponse | GetCriticalDaysResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\t/** Which biorhythm response shape to render: a single day, a multi-day forecast, or the critical days list. */\n\tmode?: 'daily' | 'forecast' | 'critical-days';\n\n}\n\nexport const RoxyBiorhythmChart = React.forwardRef<HTMLElement | null, RoxyBiorhythmChartProps>(\n\tfunction RoxyBiorhythmChart({ data, className, style, mode, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && mode !== undefined) {\n\t\t\t\t(el as unknown as { mode: 'daily' | 'forecast' | 'critical-days' }).mode = mode;\n\t\t\t}\n\t\t}, [mode, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-biorhythm-chart', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.8.0\";\n"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { GetCriticalDaysResponse, GetDailyBiorhythmResponse, GetForecastResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyBiorhythmChartProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: GetDailyBiorhythmResponse | GetForecastResponse | GetCriticalDaysResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\t/** Which biorhythm response shape to render: a single day, a multi-day forecast, or the critical days list. */\n\tmode?: 'daily' | 'forecast' | 'critical-days';\n\n}\n\nexport const RoxyBiorhythmChart = React.forwardRef<HTMLElement | null, RoxyBiorhythmChartProps>(\n\tfunction RoxyBiorhythmChart({ data, className, style, mode, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && mode !== undefined) {\n\t\t\t\t(el as unknown as { mode: 'daily' | 'forecast' | 'critical-days' }).mode = mode;\n\t\t\t}\n\t\t}, [mode, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-biorhythm-chart', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.9.0\";\n"],
5
5
  "mappings": "AAAA,UAAYA,MAAW,QCSvB,IAAMC,EAAY,oBACZC,EAAkB,2DAClBC,EAAkB,4CAClBC,EAAkB,YAEpBC,EAA+B,KAEnC,SAASC,EAAUC,EAAyB,CAC3C,MAAI,CAACA,GAAWA,IAAY,SAAiBL,EACtC,GAAGC,CAAe,GAAGI,CAAO,GAAGH,CAAe,EACtD,CAEO,SAASI,EAAmBD,EAAkB,SAAyB,CAC7E,OAAI,OAAO,SAAa,IAAoB,QAAQ,QAAQ,EACxDF,IAEJA,EAAS,IAAI,QAAc,CAACI,EAASC,IAAW,CAC/C,IAAMC,EAAM,GAAGL,EAAUC,CAAO,CAAC,cAC7BK,EAAW,SAAS,eAAeX,CAAS,EAChD,GAAIW,EAAU,CACTA,EAAS,QAAQ,SAAW,OAC/BH,EAAQ,GAERG,EAAS,iBAAiB,OAAQ,IAAMH,EAAQ,CAAC,EACjDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,GAElF,MACD,CACAE,EAAW,SAAS,cAAc,QAAQ,EAC1CA,EAAS,GAAKX,EACdW,EAAS,IAAMD,EACfC,EAAS,MAAQ,GACjBA,EAAS,YAAc,YACvBA,EAAS,iBAAiB,OAAQ,IAAM,CACvCA,EAAU,QAAQ,OAAS,OAC3BH,EAAQ,CACT,CAAC,EACDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,EACjF,SAAS,KAAK,YAAYE,CAAQ,CACnC,CAAC,EACMP,EACR,CD/BO,IAAMQ,EAA2B,aACvC,SAA4B,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,EAAO,KAAAC,EAAM,GAAGC,CAAK,EAAGC,EAAK,CAC3E,IAAMC,EAAiB,SAA2B,IAAI,EAChD,sBACLD,EACA,IAAMC,EAAS,QACf,CAAC,CACF,EACA,GAAM,CAACC,EAAQC,CAAS,EAAU,WAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,EAAU,WAAuB,IAAI,EA+B3D,OA7BM,YAAU,IAAM,CACrB,IAAIC,EAAS,GACb,OAAAC,EAAmB,EACjB,KAAK,IAAM,CACPD,GAAQH,EAAU,EAAI,CAC3B,CAAC,EACA,MAAOK,GAAiB,CACnBF,GACLD,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC7D,CAAC,EACK,IAAM,CACZF,EAAS,EACV,CACD,EAAG,CAAC,CAAC,EAEC,YAAU,IAAM,CACrB,IAAMG,EAAKR,EAAS,QAChBQ,GAAMd,IAAS,SACjBc,EAAoC,KAAOd,EAE9C,EAAG,CAACA,EAAMO,CAAM,CAAC,EAEX,YAAU,IAAM,CACrB,IAAMO,EAAKR,EAAS,QAChBQ,GAAMX,IAAS,SACjBW,EAAmE,KAAOX,EAE7E,EAAG,CAACA,EAAMI,CAAM,CAAC,EAEbE,EACU,gBACZ,MACA,CAAE,KAAM,QAAS,UAAAR,EAAW,MAAAC,CAAM,EAClC,+BAA+BO,EAAM,OAAO,EAC7C,EAGY,gBAAc,uBAAwB,CAClD,IAAKH,EACL,UAAAL,EACA,MAAAC,EACA,GAAGE,CACJ,CAAC,CACF,CACD",
6
6
  "names": ["React", "SCRIPT_ID", "CDN_BASE_LATEST", "CDN_BASE_PREFIX", "CDN_BASE_SUFFIX", "loaded", "buildBase", "version", "ensureScriptLoaded", "resolve", "reject", "url", "existing", "RoxyBiorhythmChart", "data", "className", "style", "mode", "rest", "ref", "internal", "loaded", "setLoaded", "error", "setError", "active", "ensureScriptLoaded", "err", "el"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/bodygraph.tsx", "../../src/load-ui.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children'\n>;\n\nexport interface RoxyBodygraphProps extends ElementAttrs {\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\n}\n\nexport const RoxyBodygraph = React.forwardRef<HTMLElement | null, RoxyBodygraphProps>(\n\tfunction RoxyBodygraph({ className, style, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-bodygraph', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.8.0\";\n"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children'\n>;\n\nexport interface RoxyBodygraphProps extends ElementAttrs {\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\n}\n\nexport const RoxyBodygraph = React.forwardRef<HTMLElement | null, RoxyBodygraphProps>(\n\tfunction RoxyBodygraph({ className, style, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-bodygraph', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.9.0\";\n"],
5
5
  "mappings": "AAAA,UAAYA,MAAW,QCSvB,IAAMC,EAAY,oBACZC,EAAkB,2DAClBC,EAAkB,4CAClBC,EAAkB,YAEpBC,EAA+B,KAEnC,SAASC,EAAUC,EAAyB,CAC3C,MAAI,CAACA,GAAWA,IAAY,SAAiBL,EACtC,GAAGC,CAAe,GAAGI,CAAO,GAAGH,CAAe,EACtD,CAEO,SAASI,EAAmBD,EAAkB,SAAyB,CAC7E,OAAI,OAAO,SAAa,IAAoB,QAAQ,QAAQ,EACxDF,IAEJA,EAAS,IAAI,QAAc,CAACI,EAASC,IAAW,CAC/C,IAAMC,EAAM,GAAGL,EAAUC,CAAO,CAAC,cAC7BK,EAAW,SAAS,eAAeX,CAAS,EAChD,GAAIW,EAAU,CACTA,EAAS,QAAQ,SAAW,OAC/BH,EAAQ,GAERG,EAAS,iBAAiB,OAAQ,IAAMH,EAAQ,CAAC,EACjDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,GAElF,MACD,CACAE,EAAW,SAAS,cAAc,QAAQ,EAC1CA,EAAS,GAAKX,EACdW,EAAS,IAAMD,EACfC,EAAS,MAAQ,GACjBA,EAAS,YAAc,YACvBA,EAAS,iBAAiB,OAAQ,IAAM,CACvCA,EAAU,QAAQ,OAAS,OAC3BH,EAAQ,CACT,CAAC,EACDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,EACjF,SAAS,KAAK,YAAYE,CAAQ,CACnC,CAAC,EACMP,EACR,CDpCO,IAAMQ,EAAsB,aAClC,SAAuB,CAAE,UAAAC,EAAW,MAAAC,EAAO,GAAGC,CAAK,EAAGC,EAAK,CAC1D,IAAMC,EAAiB,SAA2B,IAAI,EAChD,sBACLD,EACA,IAAMC,EAAS,QACf,CAAC,CACF,EACA,GAAM,CAACC,EAAQC,CAAS,EAAU,WAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,EAAU,WAAuB,IAAI,EAiB3D,OAfM,YAAU,IAAM,CACrB,IAAIC,EAAS,GACb,OAAAC,EAAmB,EACjB,KAAK,IAAM,CACPD,GAAQH,EAAU,EAAI,CAC3B,CAAC,EACA,MAAOK,GAAiB,CACnBF,GACLD,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC7D,CAAC,EACK,IAAM,CACZF,EAAS,EACV,CACD,EAAG,CAAC,CAAC,EAEDF,EACU,gBACZ,MACA,CAAE,KAAM,QAAS,UAAAP,EAAW,MAAAC,CAAM,EAClC,+BAA+BM,EAAM,OAAO,EAC7C,EAGY,gBAAc,iBAAkB,CAC5C,IAAKH,EACL,UAAAJ,EACA,MAAAC,EACA,GAAGC,CACJ,CAAC,CACF,CACD",
6
6
  "names": ["React", "SCRIPT_ID", "CDN_BASE_LATEST", "CDN_BASE_PREFIX", "CDN_BASE_SUFFIX", "loaded", "buildBase", "version", "ensureScriptLoaded", "resolve", "reject", "url", "existing", "RoxyBodygraph", "className", "style", "rest", "ref", "internal", "loaded", "setLoaded", "error", "setError", "active", "ensureScriptLoaded", "err"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/choghadiya-grid.tsx", "../../src/load-ui.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { GetChoghadiyaResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyChoghadiyaGridProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: GetChoghadiyaResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\n}\n\nexport const RoxyChoghadiyaGrid = React.forwardRef<HTMLElement | null, RoxyChoghadiyaGridProps>(\n\tfunction RoxyChoghadiyaGrid({ data, className, style, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-choghadiya-grid', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.8.0\";\n"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { GetChoghadiyaResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyChoghadiyaGridProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: GetChoghadiyaResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\n}\n\nexport const RoxyChoghadiyaGrid = React.forwardRef<HTMLElement | null, RoxyChoghadiyaGridProps>(\n\tfunction RoxyChoghadiyaGrid({ data, className, style, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-choghadiya-grid', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.9.0\";\n"],
5
5
  "mappings": "AAAA,UAAYA,MAAW,QCSvB,IAAMC,EAAY,oBACZC,EAAkB,2DAClBC,EAAkB,4CAClBC,EAAkB,YAEpBC,EAA+B,KAEnC,SAASC,EAAUC,EAAyB,CAC3C,MAAI,CAACA,GAAWA,IAAY,SAAiBL,EACtC,GAAGC,CAAe,GAAGI,CAAO,GAAGH,CAAe,EACtD,CAEO,SAASI,EAAmBD,EAAkB,SAAyB,CAC7E,OAAI,OAAO,SAAa,IAAoB,QAAQ,QAAQ,EACxDF,IAEJA,EAAS,IAAI,QAAc,CAACI,EAASC,IAAW,CAC/C,IAAMC,EAAM,GAAGL,EAAUC,CAAO,CAAC,cAC7BK,EAAW,SAAS,eAAeX,CAAS,EAChD,GAAIW,EAAU,CACTA,EAAS,QAAQ,SAAW,OAC/BH,EAAQ,GAERG,EAAS,iBAAiB,OAAQ,IAAMH,EAAQ,CAAC,EACjDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,GAElF,MACD,CACAE,EAAW,SAAS,cAAc,QAAQ,EAC1CA,EAAS,GAAKX,EACdW,EAAS,IAAMD,EACfC,EAAS,MAAQ,GACjBA,EAAS,YAAc,YACvBA,EAAS,iBAAiB,OAAQ,IAAM,CACvCA,EAAU,QAAQ,OAAS,OAC3BH,EAAQ,CACT,CAAC,EACDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,EACjF,SAAS,KAAK,YAAYE,CAAQ,CACnC,CAAC,EACMP,EACR,CDjCO,IAAMQ,EAA2B,aACvC,SAA4B,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,EAAO,GAAGC,CAAK,EAAGC,EAAK,CACrE,IAAMC,EAAiB,SAA2B,IAAI,EAChD,sBACLD,EACA,IAAMC,EAAS,QACf,CAAC,CACF,EACA,GAAM,CAACC,EAAQC,CAAS,EAAU,WAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,EAAU,WAAuB,IAAI,EAwB3D,OAtBM,YAAU,IAAM,CACrB,IAAIC,EAAS,GACb,OAAAC,EAAmB,EACjB,KAAK,IAAM,CACPD,GAAQH,EAAU,EAAI,CAC3B,CAAC,EACA,MAAOK,GAAiB,CACnBF,GACLD,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC7D,CAAC,EACK,IAAM,CACZF,EAAS,EACV,CACD,EAAG,CAAC,CAAC,EAEC,YAAU,IAAM,CACrB,IAAMG,EAAKR,EAAS,QAChBQ,GAAMb,IAAS,SACjBa,EAAoC,KAAOb,EAE9C,EAAG,CAACA,EAAMM,CAAM,CAAC,EAEbE,EACU,gBACZ,MACA,CAAE,KAAM,QAAS,UAAAP,EAAW,MAAAC,CAAM,EAClC,+BAA+BM,EAAM,OAAO,EAC7C,EAGY,gBAAc,uBAAwB,CAClD,IAAKH,EACL,UAAAJ,EACA,MAAAC,EACA,GAAGC,CACJ,CAAC,CACF,CACD",
6
6
  "names": ["React", "SCRIPT_ID", "CDN_BASE_LATEST", "CDN_BASE_PREFIX", "CDN_BASE_SUFFIX", "loaded", "buildBase", "version", "ensureScriptLoaded", "resolve", "reject", "url", "existing", "RoxyChoghadiyaGrid", "data", "className", "style", "rest", "ref", "internal", "loaded", "setLoaded", "error", "setError", "active", "ensureScriptLoaded", "err", "el"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/components/compatibility-card.tsx", "../../src/load-ui.ts"],
4
- "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { CalculateBioCompatibilityResponse, CalculateCompatibilityResponse, CalculateNumCompatibilityResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyCompatibilityCardProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: CalculateCompatibilityResponse | CalculateNumCompatibilityResponse | CalculateBioCompatibilityResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\t/** Which compatibility domain the response is from. Themes the card and labels the category breakdown. */\n\tmode?: 'astrology' | 'numerology' | 'biorhythm';\n\n}\n\nexport const RoxyCompatibilityCard = React.forwardRef<HTMLElement | null, RoxyCompatibilityCardProps>(\n\tfunction RoxyCompatibilityCard({ data, className, style, mode, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && mode !== undefined) {\n\t\t\t\t(el as unknown as { mode: 'astrology' | 'numerology' | 'biorhythm' }).mode = mode;\n\t\t\t}\n\t\t}, [mode, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-compatibility-card', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.8.0\";\n"],
4
+ "sourcesContent": ["import * as React from 'react';\nimport { ensureScriptLoaded } from '../load-ui.js';\nimport type { CalculateBioCompatibilityResponse, CalculateCompatibilityResponse, CalculateNumCompatibilityResponse } from '@roxyapi/ui/types';\n\ntype ElementAttrs = Omit<\n\tReact.HTMLAttributes<HTMLElement>,\n\t'children' | 'data'\n>;\n\nexport interface RoxyCompatibilityCardProps extends ElementAttrs {\n\t/** Spec-derived response payload. Pass the raw RoxyAPI response. */\n\tdata?: CalculateCompatibilityResponse | CalculateNumCompatibilityResponse | CalculateBioCompatibilityResponse;\n\tclassName?: string;\n\tstyle?: React.CSSProperties;\n\t/** Which compatibility domain the response is from. Themes the card and labels the category breakdown. */\n\tmode?: 'astrology' | 'numerology' | 'biorhythm';\n\n}\n\nexport const RoxyCompatibilityCard = React.forwardRef<HTMLElement | null, RoxyCompatibilityCardProps>(\n\tfunction RoxyCompatibilityCard({ data, className, style, mode, ...rest }, ref) {\n\t\tconst internal = React.useRef<HTMLElement | null>(null);\n\t\tReact.useImperativeHandle<HTMLElement | null, HTMLElement | null>(\n\t\t\tref,\n\t\t\t() => internal.current,\n\t\t\t[],\n\t\t);\n\t\tconst [loaded, setLoaded] = React.useState(false);\n\t\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t\tReact.useEffect(() => {\n\t\t\tlet active = true;\n\t\t\tensureScriptLoaded()\n\t\t\t\t.then(() => {\n\t\t\t\t\tif (active) setLoaded(true);\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tif (!active) return;\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t});\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t};\n\t\t}, []);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && data !== undefined) {\n\t\t\t\t(el as unknown as { data: unknown }).data = data;\n\t\t\t}\n\t\t}, [data, loaded]);\n\n\t\tReact.useEffect(() => {\n\t\t\tconst el = internal.current;\n\t\t\tif (el && mode !== undefined) {\n\t\t\t\t(el as unknown as { mode: 'astrology' | 'numerology' | 'biorhythm' }).mode = mode;\n\t\t\t}\n\t\t}, [mode, loaded]);\n\n\t\tif (error) {\n\t\t\treturn React.createElement(\n\t\t\t\t'div',\n\t\t\t\t{ role: 'alert', className, style },\n\t\t\t\t`Roxy UI script load failed: ${error.message}`,\n\t\t\t);\n\t\t}\n\n\t\treturn React.createElement('roxy-compatibility-card', {\n\t\t\tref: internal,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\t...rest,\n\t\t});\n\t},\n);\n", "/**\n * Loads the matching component bundle on first mount. Idempotent across\n * many components on the same page. Skips on the server (no document) so\n * React server components and Next.js SSR work without a flash.\n *\n * Pass an explicit `version` (e.g. `'0.1.5'`) to pin the loaded bundle to a\n * specific @roxyapi/ui release; the default ('latest') resolves to whatever\n * the CDN currently serves for @latest.\n */\nconst SCRIPT_ID = 'roxyapi-ui-loader';\nconst CDN_BASE_LATEST = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn\";\nconst CDN_BASE_PREFIX = \"https://cdn.jsdelivr.net/npm/@roxyapi/ui@\";\nconst CDN_BASE_SUFFIX = \"/dist/cdn\";\n\nlet loaded: Promise<void> | null = null;\n\nfunction buildBase(version: string): string {\n\tif (!version || version === 'latest') return CDN_BASE_LATEST;\n\treturn `${CDN_BASE_PREFIX}${version}${CDN_BASE_SUFFIX}`;\n}\n\nexport function ensureScriptLoaded(version: string = 'latest'): Promise<void> {\n\tif (typeof document === 'undefined') return Promise.resolve();\n\tif (loaded) return loaded;\n\n\tloaded = new Promise<void>((resolve, reject) => {\n\t\tconst url = `${buildBase(version)}/roxy-ui.js`;\n\t\tlet existing = document.getElementById(SCRIPT_ID) as HTMLScriptElement | null;\n\t\tif (existing) {\n\t\t\tif (existing.dataset.loaded === 'true') {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\texisting.addEventListener('load', () => resolve());\n\t\t\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\texisting = document.createElement('script');\n\t\texisting.id = SCRIPT_ID;\n\t\texisting.src = url;\n\t\texisting.async = true;\n\t\texisting.crossOrigin = 'anonymous';\n\t\texisting.addEventListener('load', () => {\n\t\t\texisting!.dataset.loaded = 'true';\n\t\t\tresolve();\n\t\t});\n\t\texisting.addEventListener('error', () => reject(new Error('roxy-ui load failed')));\n\t\tdocument.head.appendChild(existing);\n\t});\n\treturn loaded;\n}\n\n// Default export retained for convenience; matches the named export.\nexport default ensureScriptLoaded;\n// Surfaces the embedded @roxyapi/ui version this build of @roxyapi/ui-react\n// was generated against. Useful for diagnostics; not load-bearing.\nexport const ROXY_UI_VERSION = \"0.9.0\";\n"],
5
5
  "mappings": "AAAA,UAAYA,MAAW,QCSvB,IAAMC,EAAY,oBACZC,EAAkB,2DAClBC,EAAkB,4CAClBC,EAAkB,YAEpBC,EAA+B,KAEnC,SAASC,EAAUC,EAAyB,CAC3C,MAAI,CAACA,GAAWA,IAAY,SAAiBL,EACtC,GAAGC,CAAe,GAAGI,CAAO,GAAGH,CAAe,EACtD,CAEO,SAASI,EAAmBD,EAAkB,SAAyB,CAC7E,OAAI,OAAO,SAAa,IAAoB,QAAQ,QAAQ,EACxDF,IAEJA,EAAS,IAAI,QAAc,CAACI,EAASC,IAAW,CAC/C,IAAMC,EAAM,GAAGL,EAAUC,CAAO,CAAC,cAC7BK,EAAW,SAAS,eAAeX,CAAS,EAChD,GAAIW,EAAU,CACTA,EAAS,QAAQ,SAAW,OAC/BH,EAAQ,GAERG,EAAS,iBAAiB,OAAQ,IAAMH,EAAQ,CAAC,EACjDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,GAElF,MACD,CACAE,EAAW,SAAS,cAAc,QAAQ,EAC1CA,EAAS,GAAKX,EACdW,EAAS,IAAMD,EACfC,EAAS,MAAQ,GACjBA,EAAS,YAAc,YACvBA,EAAS,iBAAiB,OAAQ,IAAM,CACvCA,EAAU,QAAQ,OAAS,OAC3BH,EAAQ,CACT,CAAC,EACDG,EAAS,iBAAiB,QAAS,IAAMF,EAAO,IAAI,MAAM,qBAAqB,CAAC,CAAC,EACjF,SAAS,KAAK,YAAYE,CAAQ,CACnC,CAAC,EACMP,EACR,CD/BO,IAAMQ,EAA8B,aAC1C,SAA+B,CAAE,KAAAC,EAAM,UAAAC,EAAW,MAAAC,EAAO,KAAAC,EAAM,GAAGC,CAAK,EAAGC,EAAK,CAC9E,IAAMC,EAAiB,SAA2B,IAAI,EAChD,sBACLD,EACA,IAAMC,EAAS,QACf,CAAC,CACF,EACA,GAAM,CAACC,EAAQC,CAAS,EAAU,WAAS,EAAK,EAC1C,CAACC,EAAOC,CAAQ,EAAU,WAAuB,IAAI,EA+B3D,OA7BM,YAAU,IAAM,CACrB,IAAIC,EAAS,GACb,OAAAC,EAAmB,EACjB,KAAK,IAAM,CACPD,GAAQH,EAAU,EAAI,CAC3B,CAAC,EACA,MAAOK,GAAiB,CACnBF,GACLD,EAASG,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,CAC7D,CAAC,EACK,IAAM,CACZF,EAAS,EACV,CACD,EAAG,CAAC,CAAC,EAEC,YAAU,IAAM,CACrB,IAAMG,EAAKR,EAAS,QAChBQ,GAAMd,IAAS,SACjBc,EAAoC,KAAOd,EAE9C,EAAG,CAACA,EAAMO,CAAM,CAAC,EAEX,YAAU,IAAM,CACrB,IAAMO,EAAKR,EAAS,QAChBQ,GAAMX,IAAS,SACjBW,EAAqE,KAAOX,EAE/E,EAAG,CAACA,EAAMI,CAAM,CAAC,EAEbE,EACU,gBACZ,MACA,CAAE,KAAM,QAAS,UAAAR,EAAW,MAAAC,CAAM,EAClC,+BAA+BO,EAAM,OAAO,EAC7C,EAGY,gBAAc,0BAA2B,CACrD,IAAKH,EACL,UAAAL,EACA,MAAAC,EACA,GAAGE,CACJ,CAAC,CACF,CACD",
6
6
  "names": ["React", "SCRIPT_ID", "CDN_BASE_LATEST", "CDN_BASE_PREFIX", "CDN_BASE_SUFFIX", "loaded", "buildBase", "version", "ensureScriptLoaded", "resolve", "reject", "url", "existing", "RoxyCompatibilityCard", "data", "className", "style", "mode", "rest", "ref", "internal", "loaded", "setLoaded", "error", "setError", "active", "ensureScriptLoaded", "err", "el"]
7
7
  }