Skip to content

Commit 208fc25

Browse files
committed
feat(widgets,wrappers): the one-tag embed takes the proxy routes, and a base property can no longer skip the wrappers
The widget bootstrap forwarded neither submit-url nor location-url, so the simplest embed was the publishable-key path only. It now forwards both from one list that also keeps them out of the request parameters, and a tag with no key renders the form and routes both its requests at the host. remember never reached React or Vue. A base property that is missing from the wrapper prop list regenerates byte-identical, so no gate could see it. The base element now states its own public surface: every property carrying an attribute has to be declared, which leaves reactive state out by the same rule.
1 parent f028b38 commit 208fc25

130 files changed

Lines changed: 943 additions & 67 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ For a static chart with no picker, fetch in a Server Component and pass `data` t
377377

378378
`<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. For an endpoint that needs coordinates, add `publishable-key="pk_live_..."` so the built-in city search can geocode.
379379

380-
The city search is the one request the form issues on its own, while a visitor is still typing. When the page routes RoxyAPI traffic through your own server, give it a route for that search and name it with `location-url` (absolute, or relative to the page). Then the form calls your server for cities too, and no key of any kind reaches the browser. The same attribute works on any component in self-fetch mode, alongside `submit-url`.
380+
The city search is the one request the form issues on its own, while a visitor is still typing. When the page routes RoxyAPI traffic through your own server, give it a route for that search and name it with `location-url` (absolute, or relative to the page). Then the form calls your server for cities too, and no key of any kind reaches the browser. The same attribute works on any component in self-fetch mode, alongside `submit-url`, and on a one-tag widget as `data-location-url`.
381381

382382
```html
383383
<roxy-endpoint-form
@@ -421,7 +421,7 @@ In React, the same props are typed: `<RoxyNatalChart endpoint="astrology/natal-c
421421

422422
**Three optional attributes on the self-fetch element.** `lang` sets the response language (`en`, `tr`, `de`, `es`, `hi`, `pt`, `fr`, `ru`): put it on the element (`<roxy-horoscope-card lang="de" ...>`) and the form routes it to the `?lang=` query on submit, so visitors never see a language field. `submit-label` overrides the derived button label. `attribution` renders a small "Spiritual data by RoxyAPI" credit under the result: off by default, and the one-tag script below turns it on unless you set `data-attribution="off"`. None of these apply in controlled mode.
423423

424-
**One tag, no element wiring.** For the simplest embed, load `dist/cdn/widgets.js` and drop a `<div data-roxy-widget="{slug}" data-publishable-key="pk_live_...">`. The script mounts the matching component from a generated slug map: with every path parameter supplied as a `data-*` attribute (`data-sign`, `data-id`) it fetches on mount, otherwise it renders the same input form. A second `data-*` attribute picks a variant (`data-period`, `data-mode`, `data-type`, `data-spread`).
424+
**One tag, no element wiring.** For the simplest embed, load `dist/cdn/widgets.js` and drop a `<div data-roxy-widget="{slug}" data-publishable-key="pk_live_...">`. The script mounts the matching component from a generated slug map: with every path parameter supplied as a `data-*` attribute (`data-sign`, `data-id`) it fetches on mount, otherwise it renders the same input form. A second `data-*` attribute picks a variant (`data-period`, `data-mode`, `data-type`, `data-spread`). To keep every key on your own server instead, drop the publishable key and give the tag `data-submit-url` and `data-location-url`: the widget renders the form and routes both its requests there.
425425

426426
**Theme every widget in one link.** Add `<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/styles/themes/practitioner.css">` for a warm rosewater serif look, or set the `--roxy-font-display` token alone to swap result headings to a display face (it defaults to the body font, so nothing changes until you set it). See [THEMING.md](packages/ui/THEMING.md).
427427

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ Two ways to feed a component, and the key rule for each:
602602

603603
Set `ROXY_API_KEY` to your secret key in your server env for the server-side SDK examples on this page. For self-fetch embedding with no backend, use a publishable key (see the fully client-side pattern in [`AGENTS.md`](AGENTS.md)).
604604

605-
The self-fetch form renders spec-driven inputs (a zodiac tile picker, a boolean toggle, native date and time, a city search), collapses optional fields under one Advanced disclosure, and reads a `lang` attribute for localized responses. When the page routes RoxyAPI traffic through your own server instead, `submit-url` names the route that answers the submitted request and `location-url` names the one that answers the city search, so both halves of a birth-data form go to your server and no key of any kind reaches the browser. For the simplest embed, load `dist/cdn/widgets.js` and drop one `<div data-roxy-widget="{slug}" data-publishable-key="pk_live_...">`: with the required attributes present it fetches on mount, otherwise it renders the form. A single `<link>` to the [practitioner theme preset](https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/styles/themes/practitioner.css) restyles every widget on the page.
605+
The self-fetch form renders spec-driven inputs (a zodiac tile picker, a boolean toggle, native date and time, a city search), collapses optional fields under one Advanced disclosure, and reads a `lang` attribute for localized responses. When the page routes RoxyAPI traffic through your own server instead, `submit-url` names the route that answers the submitted request and `location-url` names the one that answers the city search, so both halves of a birth-data form go to your server and no key of any kind reaches the browser. For the simplest embed, load `dist/cdn/widgets.js` and drop one `<div data-roxy-widget="{slug}" data-publishable-key="pk_live_...">`: with the required attributes present it fetches on mount, otherwise it renders the form. That tag takes `data-submit-url` and `data-location-url` too, so a one-tag embed can route both its requests through your server and carry no key at all. A single `<link>` to the [practitioner theme preset](https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/styles/themes/practitioner.css) restyles every widget on the page.
606606

607607
## Distribution
608608

packages/ui-react/src/components/angel-number-card.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface RoxyAngelNumberCardProps extends ElementAttrs {
3030
lang?: string;
3131
/** Override the self-fetch form submit-button label. Empty derives an outcome-first label from the endpoint (Get reading, Generate, Compare, Cast). */
3232
submitLabel?: string;
33+
/** Persist the last self-fetch form values in sessionStorage, keyed by endpoint, and prefill the form when the visitor returns. Off by default. */
34+
remember?: boolean;
3335
/** Render a small "Spiritual data by RoxyAPI" credit under a self-fetch result, linking back to RoxyAPI. Off by default; set any value to enable, or "off" to force it off. Never shown in controlled mode. */
3436
attribution?: string;
3537
/** Render the chart and the data and omit the written interpretation. Off by default. Use it when the page supplies its own words: the wheels, tables, grids, legends and numbers stay, and the interpretive prose is left out of the markup entirely. */
@@ -40,7 +42,7 @@ export interface RoxyAngelNumberCardProps extends ElementAttrs {
4042
}
4143

4244
export const RoxyAngelNumberCard = React.forwardRef<HTMLElement | null, RoxyAngelNumberCardProps>(
43-
function RoxyAngelNumberCard({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, attribution, hideReadings, hideSections, ...rest }, ref) {
45+
function RoxyAngelNumberCard({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, remember, attribution, hideReadings, hideSections, ...rest }, ref) {
4446
const internal = React.useRef<HTMLElement | null>(null);
4547
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
4648
ref,
@@ -135,6 +137,13 @@ export const RoxyAngelNumberCard = React.forwardRef<HTMLElement | null, RoxyAnge
135137
}
136138
}, [submitLabel, loaded]);
137139

140+
React.useEffect(() => {
141+
const el = internal.current;
142+
if (el && remember !== undefined) {
143+
(el as unknown as { remember: boolean }).remember = remember;
144+
}
145+
}, [remember, loaded]);
146+
138147
React.useEffect(() => {
139148
const el = internal.current;
140149
if (el && attribution !== undefined) {

packages/ui-react/src/components/angel-number-lookup.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface RoxyAngelNumberLookupProps extends ElementAttrs {
3030
lang?: string;
3131
/** Override the self-fetch form submit-button label. Empty derives an outcome-first label from the endpoint (Get reading, Generate, Compare, Cast). */
3232
submitLabel?: string;
33+
/** Persist the last self-fetch form values in sessionStorage, keyed by endpoint, and prefill the form when the visitor returns. Off by default. */
34+
remember?: boolean;
3335
/** Render a small "Spiritual data by RoxyAPI" credit under a self-fetch result, linking back to RoxyAPI. Off by default; set any value to enable, or "off" to force it off. Never shown in controlled mode. */
3436
attribution?: string;
3537
/** Render the chart and the data and omit the written interpretation. Off by default. Use it when the page supplies its own words: the wheels, tables, grids, legends and numbers stay, and the interpretive prose is left out of the markup entirely. */
@@ -40,7 +42,7 @@ export interface RoxyAngelNumberLookupProps extends ElementAttrs {
4042
}
4143

4244
export const RoxyAngelNumberLookup = React.forwardRef<HTMLElement | null, RoxyAngelNumberLookupProps>(
43-
function RoxyAngelNumberLookup({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, attribution, hideReadings, hideSections, ...rest }, ref) {
45+
function RoxyAngelNumberLookup({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, remember, attribution, hideReadings, hideSections, ...rest }, ref) {
4446
const internal = React.useRef<HTMLElement | null>(null);
4547
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
4648
ref,
@@ -135,6 +137,13 @@ export const RoxyAngelNumberLookup = React.forwardRef<HTMLElement | null, RoxyAn
135137
}
136138
}, [submitLabel, loaded]);
137139

140+
React.useEffect(() => {
141+
const el = internal.current;
142+
if (el && remember !== undefined) {
143+
(el as unknown as { remember: boolean }).remember = remember;
144+
}
145+
}, [remember, loaded]);
146+
138147
React.useEffect(() => {
139148
const el = internal.current;
140149
if (el && attribution !== undefined) {

packages/ui-react/src/components/arudha-padas.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface RoxyArudhaPadasProps extends ElementAttrs {
3030
lang?: string;
3131
/** Override the self-fetch form submit-button label. Empty derives an outcome-first label from the endpoint (Get reading, Generate, Compare, Cast). */
3232
submitLabel?: string;
33+
/** Persist the last self-fetch form values in sessionStorage, keyed by endpoint, and prefill the form when the visitor returns. Off by default. */
34+
remember?: boolean;
3335
/** Render a small "Spiritual data by RoxyAPI" credit under a self-fetch result, linking back to RoxyAPI. Off by default; set any value to enable, or "off" to force it off. Never shown in controlled mode. */
3436
attribution?: string;
3537
/** Render the chart and the data and omit the written interpretation. Off by default. Use it when the page supplies its own words: the wheels, tables, grids, legends and numbers stay, and the interpretive prose is left out of the markup entirely. */
@@ -40,7 +42,7 @@ export interface RoxyArudhaPadasProps extends ElementAttrs {
4042
}
4143

4244
export const RoxyArudhaPadas = React.forwardRef<HTMLElement | null, RoxyArudhaPadasProps>(
43-
function RoxyArudhaPadas({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, attribution, hideReadings, hideSections, ...rest }, ref) {
45+
function RoxyArudhaPadas({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, remember, attribution, hideReadings, hideSections, ...rest }, ref) {
4446
const internal = React.useRef<HTMLElement | null>(null);
4547
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
4648
ref,
@@ -135,6 +137,13 @@ export const RoxyArudhaPadas = React.forwardRef<HTMLElement | null, RoxyArudhaPa
135137
}
136138
}, [submitLabel, loaded]);
137139

140+
React.useEffect(() => {
141+
const el = internal.current;
142+
if (el && remember !== undefined) {
143+
(el as unknown as { remember: boolean }).remember = remember;
144+
}
145+
}, [remember, loaded]);
146+
138147
React.useEffect(() => {
139148
const el = internal.current;
140149
if (el && attribution !== undefined) {

packages/ui-react/src/components/ashtakavarga-grid.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface RoxyAshtakavargaGridProps extends ElementAttrs {
3030
lang?: string;
3131
/** Override the self-fetch form submit-button label. Empty derives an outcome-first label from the endpoint (Get reading, Generate, Compare, Cast). */
3232
submitLabel?: string;
33+
/** Persist the last self-fetch form values in sessionStorage, keyed by endpoint, and prefill the form when the visitor returns. Off by default. */
34+
remember?: boolean;
3335
/** Render a small "Spiritual data by RoxyAPI" credit under a self-fetch result, linking back to RoxyAPI. Off by default; set any value to enable, or "off" to force it off. Never shown in controlled mode. */
3436
attribution?: string;
3537
/** Render the chart and the data and omit the written interpretation. Off by default. Use it when the page supplies its own words: the wheels, tables, grids, legends and numbers stay, and the interpretive prose is left out of the markup entirely. */
@@ -40,7 +42,7 @@ export interface RoxyAshtakavargaGridProps extends ElementAttrs {
4042
}
4143

4244
export const RoxyAshtakavargaGrid = React.forwardRef<HTMLElement | null, RoxyAshtakavargaGridProps>(
43-
function RoxyAshtakavargaGrid({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, attribution, hideReadings, hideSections, ...rest }, ref) {
45+
function RoxyAshtakavargaGrid({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, remember, attribution, hideReadings, hideSections, ...rest }, ref) {
4446
const internal = React.useRef<HTMLElement | null>(null);
4547
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
4648
ref,
@@ -135,6 +137,13 @@ export const RoxyAshtakavargaGrid = React.forwardRef<HTMLElement | null, RoxyAsh
135137
}
136138
}, [submitLabel, loaded]);
137139

140+
React.useEffect(() => {
141+
const el = internal.current;
142+
if (el && remember !== undefined) {
143+
(el as unknown as { remember: boolean }).remember = remember;
144+
}
145+
}, [remember, loaded]);
146+
138147
React.useEffect(() => {
139148
const el = internal.current;
140149
if (el && attribution !== undefined) {

packages/ui-react/src/components/aspects-table.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface RoxyAspectsTableProps extends ElementAttrs {
3030
lang?: string;
3131
/** Override the self-fetch form submit-button label. Empty derives an outcome-first label from the endpoint (Get reading, Generate, Compare, Cast). */
3232
submitLabel?: string;
33+
/** Persist the last self-fetch form values in sessionStorage, keyed by endpoint, and prefill the form when the visitor returns. Off by default. */
34+
remember?: boolean;
3335
/** Render a small "Spiritual data by RoxyAPI" credit under a self-fetch result, linking back to RoxyAPI. Off by default; set any value to enable, or "off" to force it off. Never shown in controlled mode. */
3436
attribution?: string;
3537
/** Render the chart and the data and omit the written interpretation. Off by default. Use it when the page supplies its own words: the wheels, tables, grids, legends and numbers stay, and the interpretive prose is left out of the markup entirely. */
@@ -40,7 +42,7 @@ export interface RoxyAspectsTableProps extends ElementAttrs {
4042
}
4143

4244
export const RoxyAspectsTable = React.forwardRef<HTMLElement | null, RoxyAspectsTableProps>(
43-
function RoxyAspectsTable({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, attribution, hideReadings, hideSections, ...rest }, ref) {
45+
function RoxyAspectsTable({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, remember, attribution, hideReadings, hideSections, ...rest }, ref) {
4446
const internal = React.useRef<HTMLElement | null>(null);
4547
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
4648
ref,
@@ -135,6 +137,13 @@ export const RoxyAspectsTable = React.forwardRef<HTMLElement | null, RoxyAspects
135137
}
136138
}, [submitLabel, loaded]);
137139

140+
React.useEffect(() => {
141+
const el = internal.current;
142+
if (el && remember !== undefined) {
143+
(el as unknown as { remember: boolean }).remember = remember;
144+
}
145+
}, [remember, loaded]);
146+
138147
React.useEffect(() => {
139148
const el = internal.current;
140149
if (el && attribution !== undefined) {

packages/ui-react/src/components/astrocartography-map.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export interface RoxyAstrocartographyMapProps extends ElementAttrs {
3030
lang?: string;
3131
/** Override the self-fetch form submit-button label. Empty derives an outcome-first label from the endpoint (Get reading, Generate, Compare, Cast). */
3232
submitLabel?: string;
33+
/** Persist the last self-fetch form values in sessionStorage, keyed by endpoint, and prefill the form when the visitor returns. Off by default. */
34+
remember?: boolean;
3335
/** Render a small "Spiritual data by RoxyAPI" credit under a self-fetch result, linking back to RoxyAPI. Off by default; set any value to enable, or "off" to force it off. Never shown in controlled mode. */
3436
attribution?: string;
3537
/** Render the chart and the data and omit the written interpretation. Off by default. Use it when the page supplies its own words: the wheels, tables, grids, legends and numbers stay, and the interpretive prose is left out of the markup entirely. */
@@ -40,7 +42,7 @@ export interface RoxyAstrocartographyMapProps extends ElementAttrs {
4042
}
4143

4244
export const RoxyAstrocartographyMap = React.forwardRef<HTMLElement | null, RoxyAstrocartographyMapProps>(
43-
function RoxyAstrocartographyMap({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, attribution, hideReadings, hideSections, ...rest }, ref) {
45+
function RoxyAstrocartographyMap({ data, className, style, endpoint, method, publishableKey, baseUrl, submitUrl, locationUrl, specUrl, lang, submitLabel, remember, attribution, hideReadings, hideSections, ...rest }, ref) {
4446
const internal = React.useRef<HTMLElement | null>(null);
4547
React.useImperativeHandle<HTMLElement | null, HTMLElement | null>(
4648
ref,
@@ -135,6 +137,13 @@ export const RoxyAstrocartographyMap = React.forwardRef<HTMLElement | null, Roxy
135137
}
136138
}, [submitLabel, loaded]);
137139

140+
React.useEffect(() => {
141+
const el = internal.current;
142+
if (el && remember !== undefined) {
143+
(el as unknown as { remember: boolean }).remember = remember;
144+
}
145+
}, [remember, loaded]);
146+
138147
React.useEffect(() => {
139148
const el = internal.current;
140149
if (el && attribution !== undefined) {

0 commit comments

Comments
 (0)