@roxyapi/ui 0.12.1 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/components-catalog.json +1 -1
- package/dist/cdn/components/data.js +3 -3
- package/dist/cdn/components/data.js.map +4 -4
- package/dist/cdn/roxy-ui.js +55 -55
- package/dist/cdn/roxy-ui.js.map +3 -3
- package/dist/components/data.d.ts +11 -2
- package/dist/components/data.d.ts.map +1 -1
- package/dist/components/data.js +1 -1
- package/dist/components/data.js.map +4 -4
- package/dist/index.cjs +52 -52
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +53 -53
- package/dist/index.js.map +3 -3
- package/dist/types/types.gen.d.ts +18 -18
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/data.ts +129 -47
- package/src/types/types.gen.ts +18 -18
- package/src/version.ts +1 -1
|
@@ -866,11 +866,11 @@ export type TransitsRequest = {
|
|
|
866
866
|
*/
|
|
867
867
|
natalChart?: {
|
|
868
868
|
/**
|
|
869
|
-
* Date in YYYY-MM-DD format.
|
|
869
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
870
870
|
*/
|
|
871
871
|
date: string;
|
|
872
872
|
/**
|
|
873
|
-
* Time in 24-hour
|
|
873
|
+
* Time in 24-hour format. Seconds are optional and default to 00 (14:30 becomes 14:30:00); a single-digit hour is zero-padded. Out-of-range values are rejected.
|
|
874
874
|
*/
|
|
875
875
|
time: string;
|
|
876
876
|
latitude: number;
|
|
@@ -2749,7 +2749,7 @@ export type BirthChartResponse = {
|
|
|
2749
2749
|
};
|
|
2750
2750
|
};
|
|
2751
2751
|
/**
|
|
2752
|
-
* Twelve classical yogas detected against this chart: Gajakesari (three-rule parashara definition), Sunapha, Anapha, Dhurdhura, Kemadruma, Chandra Mangala, Budha-Aditya, and the five Pancha Mahapurusha (Ruchaka, Bhadra, Hamsa, Malavya, Sasa). Each entry carries an `id` (matches `GET /yoga/{id}` for full glossary lookup), a `present` boolean, and classical-text `evidence` for the rule that triggered or failed.
|
|
2752
|
+
* Twelve classical yogas detected against this chart: Gajakesari (three-rule parashara definition), Sunapha, Anapha, Dhurdhura, Kemadruma, Chandra Mangala, Budha-Aditya, and the five Pancha Mahapurusha (Ruchaka, Bhadra, Hamsa, Malavya, Sasa). Each entry carries an `id` (matches `GET /yoga/{id}` for full glossary lookup), a `present` boolean, a `quality` (Positive, Negative, or Both = auspicious, inauspicious, or context-dependent), and classical-text `evidence` for the rule that triggered or failed.
|
|
2753
2753
|
*/
|
|
2754
2754
|
yogas?: Array<{
|
|
2755
2755
|
/**
|
|
@@ -3586,7 +3586,7 @@ export type SadhesatiRequest = {
|
|
|
3586
3586
|
};
|
|
3587
3587
|
export type YogaDetectResponse = {
|
|
3588
3588
|
/**
|
|
3589
|
-
* Array of 12 detected yogas. Every entry carries a present boolean; filter on present === true for active yogas. Evidence text names the rule that triggered or failed.
|
|
3589
|
+
* Array of 12 detected yogas. Every entry carries a `present` boolean and a `quality` (Positive, Negative, or Both = auspicious, inauspicious, or context-dependent); filter on present === true for active yogas. Evidence text names the rule that triggered or failed.
|
|
3590
3590
|
*/
|
|
3591
3591
|
yogas: Array<{
|
|
3592
3592
|
/**
|
|
@@ -4703,11 +4703,11 @@ export type KpPlanetsIntervalResponse = {
|
|
|
4703
4703
|
};
|
|
4704
4704
|
export type KpPlanetsIntervalRequest = {
|
|
4705
4705
|
/**
|
|
4706
|
-
* Start datetime in ISO 8601
|
|
4706
|
+
* Start datetime in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
4707
4707
|
*/
|
|
4708
4708
|
startDatetime: string;
|
|
4709
4709
|
/**
|
|
4710
|
-
* End datetime in ISO 8601
|
|
4710
|
+
* End datetime in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Maximum 7 days from start. Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
4711
4711
|
*/
|
|
4712
4712
|
endDatetime: string;
|
|
4713
4713
|
/**
|
|
@@ -14042,7 +14042,7 @@ export type GetBasicPanchangResponse = GetBasicPanchangResponses[keyof GetBasicP
|
|
|
14042
14042
|
export type GetDetailedPanchangData = {
|
|
14043
14043
|
body?: {
|
|
14044
14044
|
/**
|
|
14045
|
-
* Date in YYYY-MM-DD format.
|
|
14045
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
14046
14046
|
*/
|
|
14047
14047
|
date: string;
|
|
14048
14048
|
/**
|
|
@@ -14596,7 +14596,7 @@ export type GetDetailedPanchangResponses = {
|
|
|
14596
14596
|
*/
|
|
14597
14597
|
panchaka: {
|
|
14598
14598
|
/**
|
|
14599
|
-
*
|
|
14599
|
+
* True when Panchaka is in effect on this date, whether it is already running at sunrise or begins later in the day, in which case startsAt and endsAt give the window. False only when no Panchaka touches this date.
|
|
14600
14600
|
*/
|
|
14601
14601
|
active: boolean;
|
|
14602
14602
|
/**
|
|
@@ -14613,11 +14613,11 @@ export type GetDetailedPanchangResponses = {
|
|
|
14613
14613
|
endsAt: string;
|
|
14614
14614
|
};
|
|
14615
14615
|
/**
|
|
14616
|
-
* Bhadra (Vishti Karana), the 7th movable karana, avoided for all auspicious activities. Bhadra recurs roughly every 3 to 5 days and lasts about half a tithi
|
|
14616
|
+
* Bhadra (Vishti Karana), the 7th movable karana, avoided for all auspicious activities. Bhadra recurs roughly every 3 to 5 days and lasts about half a tithi. active is true whenever a Bhadra is attributed to this date; startsAt and endsAt give the window, which may end on the next calendar day.
|
|
14617
14617
|
*/
|
|
14618
14618
|
bhadra: {
|
|
14619
14619
|
/**
|
|
14620
|
-
*
|
|
14620
|
+
* True when a Bhadra (Vishti Karana) occurs on this date, in which case startsAt and endsAt give its window. False only when no Bhadra begins on this date.
|
|
14621
14621
|
*/
|
|
14622
14622
|
active: boolean;
|
|
14623
14623
|
/**
|
|
@@ -14713,7 +14713,7 @@ export type GetDetailedPanchangResponse = GetDetailedPanchangResponses[keyof Get
|
|
|
14713
14713
|
export type GetChoghadiyaData = {
|
|
14714
14714
|
body?: {
|
|
14715
14715
|
/**
|
|
14716
|
-
* Date in YYYY-MM-DD format.
|
|
14716
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
14717
14717
|
*/
|
|
14718
14718
|
date: string;
|
|
14719
14719
|
/**
|
|
@@ -14897,7 +14897,7 @@ export type GetChoghadiyaResponse = GetChoghadiyaResponses[keyof GetChoghadiyaRe
|
|
|
14897
14897
|
export type GetHoraData = {
|
|
14898
14898
|
body?: {
|
|
14899
14899
|
/**
|
|
14900
|
-
* Date in YYYY-MM-DD format.
|
|
14900
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
14901
14901
|
*/
|
|
14902
14902
|
date: string;
|
|
14903
14903
|
/**
|
|
@@ -16320,7 +16320,7 @@ export type GetKpRulingPlanetsData = {
|
|
|
16320
16320
|
*/
|
|
16321
16321
|
timezone?: number | string;
|
|
16322
16322
|
/**
|
|
16323
|
-
* ISO 8601 datetime for ruling planets. Defaults to current time.
|
|
16323
|
+
* ISO 8601 datetime (YYYY-MM-DDTHH:MM:SS) for ruling planets. Defaults to current time. Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
16324
16324
|
*/
|
|
16325
16325
|
datetime?: string;
|
|
16326
16326
|
/**
|
|
@@ -16452,11 +16452,11 @@ export type GetKpRulingPlanetsResponse = GetKpRulingPlanetsResponses[keyof GetKp
|
|
|
16452
16452
|
export type GetKpRulingIntervalData = {
|
|
16453
16453
|
body?: {
|
|
16454
16454
|
/**
|
|
16455
|
-
* Start of the interval range in ISO 8601
|
|
16455
|
+
* Start of the interval range in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
16456
16456
|
*/
|
|
16457
16457
|
startDatetime: string;
|
|
16458
16458
|
/**
|
|
16459
|
-
* End of the interval range in ISO 8601
|
|
16459
|
+
* End of the interval range in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
16460
16460
|
*/
|
|
16461
16461
|
endDatetime: string;
|
|
16462
16462
|
/**
|
|
@@ -21156,7 +21156,7 @@ export type CalculatePersonalDayData = {
|
|
|
21156
21156
|
*/
|
|
21157
21157
|
day: number;
|
|
21158
21158
|
/**
|
|
21159
|
-
* Target date in YYYY-MM-DD format
|
|
21159
|
+
* Target date in YYYY-MM-DD format. Defaults to today (UTC).
|
|
21160
21160
|
*/
|
|
21161
21161
|
targetDate?: string;
|
|
21162
21162
|
};
|
|
@@ -33097,7 +33097,7 @@ export type GetCrystalPairingsData = {
|
|
|
33097
33097
|
body?: never;
|
|
33098
33098
|
path: {
|
|
33099
33099
|
/**
|
|
33100
|
-
* URL-safe crystal identifier to find pairings for (e.g., "amethyst", "rose-quartz").
|
|
33100
|
+
* URL-safe crystal identifier to find pairings for, case-insensitive (e.g., "amethyst", "Amethyst", "rose-quartz" all resolve).
|
|
33101
33101
|
*/
|
|
33102
33102
|
id: string;
|
|
33103
33103
|
};
|
|
@@ -34026,7 +34026,7 @@ export type GetCrystalData = {
|
|
|
34026
34026
|
body?: never;
|
|
34027
34027
|
path: {
|
|
34028
34028
|
/**
|
|
34029
|
-
* URL-safe crystal identifier (e.g., "amethyst", "
|
|
34029
|
+
* URL-safe crystal identifier, case-insensitive (e.g., "amethyst", "Amethyst", "rose-quartz" all resolve). Must match an entry in the database.
|
|
34030
34030
|
*/
|
|
34031
34031
|
id: string;
|
|
34032
34032
|
};
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const ROXY_UI_VERSION = "0.12.
|
|
1
|
+
export declare const ROXY_UI_VERSION = "0.12.3";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roxyapi/ui",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "Web components for the RoxyAPI catalog. Drop-in charts, tables, cards, forms for astrology, tarot, numerology, biorhythm, I Ching, crystals, dreams, angel numbers, and more. One key, beautiful in 30 minutes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
package/src/components/data.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { css, html, nothing, type TemplateResult } from 'lit';
|
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
import { RoxyDataElement } from '../utils/base-element.js';
|
|
4
4
|
import { baseStyles } from '../utils/base-styles.js';
|
|
5
|
+
import { formatDate, formatNumber, formatTime } from '../utils/format.js';
|
|
5
6
|
import { humanize } from '../utils/string.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -13,19 +14,31 @@ import { humanize } from '../utils/string.js';
|
|
|
13
14
|
* 1. Primitive (string, number, boolean) -> single line.
|
|
14
15
|
* 2. Array of primitives -> chip list.
|
|
15
16
|
* 3. Array of objects with shared keys -> table.
|
|
16
|
-
* 4. Object with title-like field -> card with key/value rows
|
|
17
|
+
* 4. Object with title-like field -> card with key/value rows; object and
|
|
18
|
+
* object-array values promote to full-width sections below the rows so
|
|
19
|
+
* nested tables keep the whole container width.
|
|
17
20
|
* 5. Otherwise -> definition list of all keys.
|
|
18
21
|
*
|
|
22
|
+
* Scalar display rules (shared by rows, chips, and table cells): numbers
|
|
23
|
+
* round to 2 decimals, booleans read Yes/No, ISO dates and datetimes format
|
|
24
|
+
* for the locale, SCREAMING_SNAKE enums humanize, http(s) strings link out.
|
|
25
|
+
*
|
|
19
26
|
* When a schema declares an `x-roxy-ui` hint, a future dispatcher can opt
|
|
20
27
|
* into a hand-tuned component instead of this fallback.
|
|
21
28
|
*/
|
|
22
29
|
|
|
23
30
|
type Json = string | number | boolean | null | Json[] | { [key: string]: Json };
|
|
31
|
+
type Scalar = string | number | boolean;
|
|
24
32
|
|
|
25
33
|
const TITLE_KEYS = ['title', 'name', 'label', 'heading', 'overview', 'summary'];
|
|
26
34
|
const IMAGE_KEYS = ['imageUrl', 'image', 'icon', 'symbol'];
|
|
27
35
|
const SKIP_KEYS = ['imageUrl', 'image']; // rendered separately, not in body rows
|
|
28
36
|
|
|
37
|
+
const ISO_DATE =
|
|
38
|
+
/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
39
|
+
const ENUM_STRING = /^[A-Z0-9]+(_[A-Z0-9]+)+$/;
|
|
40
|
+
const LINK_STRING = /^https?:\/\//;
|
|
41
|
+
|
|
29
42
|
// Hard cap on recursion. Real RoxyAPI responses nest at most 5-6 deep; anything
|
|
30
43
|
// deeper is either a circular reference (which would otherwise infinite-loop)
|
|
31
44
|
// or a payload too rich for the generic fallback to render usefully. The
|
|
@@ -34,6 +47,21 @@ const SKIP_KEYS = ['imageUrl', 'image']; // rendered separately, not in body row
|
|
|
34
47
|
// this same class without a separate import.
|
|
35
48
|
const MAX_DEPTH = 6;
|
|
36
49
|
|
|
50
|
+
function isPrimitive(value: Json | undefined): value is Scalar | null {
|
|
51
|
+
return (
|
|
52
|
+
value === null || ['string', 'number', 'boolean'].includes(typeof value)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Object or object-bearing array: needs full width, never fits a dl value cell. */
|
|
57
|
+
function isComplex(value: Json): boolean {
|
|
58
|
+
return (
|
|
59
|
+
value !== null &&
|
|
60
|
+
typeof value === 'object' &&
|
|
61
|
+
!(Array.isArray(value) && value.every(isPrimitive))
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
37
65
|
@customElement('roxy-data')
|
|
38
66
|
export class RoxyData extends RoxyDataElement<Json> {
|
|
39
67
|
static styles = [
|
|
@@ -47,6 +75,10 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
47
75
|
box-shadow: var(--roxy-shadow-sm);
|
|
48
76
|
}
|
|
49
77
|
|
|
78
|
+
.roxy-card a {
|
|
79
|
+
color: var(--roxy-accent-ink, #b45309);
|
|
80
|
+
}
|
|
81
|
+
|
|
50
82
|
.roxy-title {
|
|
51
83
|
font-size: var(--roxy-text-lg, 1.125rem);
|
|
52
84
|
font-weight: var(--roxy-weight-bold, 600);
|
|
@@ -95,6 +127,9 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
95
127
|
font-size: var(--roxy-text-xs, 0.75rem);
|
|
96
128
|
}
|
|
97
129
|
|
|
130
|
+
.roxy-table-wrap {
|
|
131
|
+
overflow-x: auto;
|
|
132
|
+
}
|
|
98
133
|
table.roxy-table {
|
|
99
134
|
width: 100%;
|
|
100
135
|
border-collapse: collapse;
|
|
@@ -106,6 +141,8 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
106
141
|
padding: var(--roxy-space-sm, 0.5rem);
|
|
107
142
|
text-align: left;
|
|
108
143
|
text-transform: none;
|
|
144
|
+
word-break: normal;
|
|
145
|
+
overflow-wrap: normal;
|
|
109
146
|
}
|
|
110
147
|
table.roxy-table th {
|
|
111
148
|
color: var(--roxy-muted, #71717a);
|
|
@@ -113,6 +150,7 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
113
150
|
text-transform: capitalize;
|
|
114
151
|
font-size: var(--roxy-text-xs, 0.75rem);
|
|
115
152
|
letter-spacing: 0.04em;
|
|
153
|
+
white-space: nowrap;
|
|
116
154
|
}
|
|
117
155
|
|
|
118
156
|
.roxy-image {
|
|
@@ -123,7 +161,7 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
123
161
|
}
|
|
124
162
|
|
|
125
163
|
.roxy-section {
|
|
126
|
-
margin-
|
|
164
|
+
margin-top: var(--roxy-space-md, 1rem);
|
|
127
165
|
}
|
|
128
166
|
.roxy-section h4 {
|
|
129
167
|
font-size: var(--roxy-text-sm, 0.875rem);
|
|
@@ -143,7 +181,9 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
143
181
|
|
|
144
182
|
protected renderData(data: Json) {
|
|
145
183
|
if (this.depth >= MAX_DEPTH) {
|
|
146
|
-
return html`<div class="roxy-empty" role="status"
|
|
184
|
+
return html`<div class="roxy-empty" role="status">
|
|
185
|
+
Nested data omitted
|
|
186
|
+
</div>`;
|
|
147
187
|
}
|
|
148
188
|
return html`<div class="roxy-card" aria-label="Generic data display">
|
|
149
189
|
${this.renderValue(data)}
|
|
@@ -152,10 +192,7 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
152
192
|
|
|
153
193
|
private renderValue(value: Json): TemplateResult | typeof nothing {
|
|
154
194
|
if (value === null || value === undefined) return nothing;
|
|
155
|
-
if (
|
|
156
|
-
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
157
|
-
return html`<p>${String(value)}</p>`;
|
|
158
|
-
}
|
|
195
|
+
if (isPrimitive(value)) return html`<p>${this.scalarTemplate(value)}</p>`;
|
|
159
196
|
if (Array.isArray(value)) return this.renderArray(value);
|
|
160
197
|
return this.renderObject(value as Record<string, Json>);
|
|
161
198
|
}
|
|
@@ -164,13 +201,8 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
164
201
|
if (arr.length === 0) {
|
|
165
202
|
return html`<div class="roxy-empty" role="status">Empty list</div>`;
|
|
166
203
|
}
|
|
167
|
-
|
|
168
|
-
(
|
|
169
|
-
);
|
|
170
|
-
if (allPrimitive) {
|
|
171
|
-
return html`<ul class="roxy-chips">
|
|
172
|
-
${arr.map((v) => html`<li>${String(v)}</li>`)}
|
|
173
|
-
</ul>`;
|
|
204
|
+
if (arr.every(isPrimitive)) {
|
|
205
|
+
return this.renderChips(arr as (Scalar | null)[]);
|
|
174
206
|
}
|
|
175
207
|
const allObjects = arr.every(
|
|
176
208
|
(v) => v !== null && typeof v === 'object' && !Array.isArray(v),
|
|
@@ -181,22 +213,37 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
181
213
|
</ol>`;
|
|
182
214
|
}
|
|
183
215
|
|
|
216
|
+
private renderChips(arr: (Scalar | null)[]): TemplateResult {
|
|
217
|
+
return html`<ul class="roxy-chips">
|
|
218
|
+
${arr
|
|
219
|
+
.filter((v): v is Scalar => v !== null)
|
|
220
|
+
.map((v) => html`<li>${this.formatScalar(v)}</li>`)}
|
|
221
|
+
</ul>`;
|
|
222
|
+
}
|
|
223
|
+
|
|
184
224
|
private renderTable(rows: Record<string, Json>[]): TemplateResult {
|
|
185
225
|
const keys = this.collectKeys(rows);
|
|
186
|
-
return html`<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
${keys.map((k) => html`<
|
|
196
|
-
</tr
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
226
|
+
return html`<div
|
|
227
|
+
class="roxy-table-wrap"
|
|
228
|
+
role="group"
|
|
229
|
+
aria-label="Data table"
|
|
230
|
+
tabindex="0"
|
|
231
|
+
>
|
|
232
|
+
<table class="roxy-table" role="table">
|
|
233
|
+
<thead>
|
|
234
|
+
<tr>
|
|
235
|
+
${keys.map((k) => html`<th>${humanize(k)}</th>`)}
|
|
236
|
+
</tr>
|
|
237
|
+
</thead>
|
|
238
|
+
<tbody>
|
|
239
|
+
${rows.map(
|
|
240
|
+
(row) => html`<tr>
|
|
241
|
+
${keys.map((k) => html`<td>${this.renderCell(row[k])}</td>`)}
|
|
242
|
+
</tr>`,
|
|
243
|
+
)}
|
|
244
|
+
</tbody>
|
|
245
|
+
</table>
|
|
246
|
+
</div>`;
|
|
200
247
|
}
|
|
201
248
|
|
|
202
249
|
private renderObject(obj: Record<string, Json>): TemplateResult {
|
|
@@ -209,7 +256,7 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
209
256
|
titleKey !== 'summary' && typeof obj.summary === 'string'
|
|
210
257
|
? 'summary'
|
|
211
258
|
: null;
|
|
212
|
-
const
|
|
259
|
+
const entries = Object.entries(obj).filter(
|
|
213
260
|
([k, v]) =>
|
|
214
261
|
k !== titleKey &&
|
|
215
262
|
k !== summaryKey &&
|
|
@@ -217,6 +264,11 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
217
264
|
v !== null &&
|
|
218
265
|
v !== undefined,
|
|
219
266
|
);
|
|
267
|
+
// Scalars and primitive arrays fit the two-column rows; objects and
|
|
268
|
+
// object arrays promote to full-width sections so nested tables are
|
|
269
|
+
// not squeezed into the value column.
|
|
270
|
+
const rows = entries.filter(([, v]) => !isComplex(v));
|
|
271
|
+
const sections = entries.filter(([, v]) => isComplex(v));
|
|
220
272
|
|
|
221
273
|
return html`
|
|
222
274
|
${
|
|
@@ -243,34 +295,64 @@ export class RoxyData extends RoxyDataElement<Json> {
|
|
|
243
295
|
</dl>`
|
|
244
296
|
: nothing
|
|
245
297
|
}
|
|
298
|
+
${sections.map(
|
|
299
|
+
([k, v]) => html`<div class="roxy-section">
|
|
300
|
+
<h4>${humanize(k)}</h4>
|
|
301
|
+
${this.renderField(v)}
|
|
302
|
+
</div>`,
|
|
303
|
+
)}
|
|
246
304
|
`;
|
|
247
305
|
}
|
|
248
306
|
|
|
249
307
|
private renderField(value: Json): TemplateResult | string {
|
|
250
308
|
if (value === null || value === undefined) return '';
|
|
251
|
-
if (
|
|
252
|
-
if (
|
|
253
|
-
return
|
|
254
|
-
if (Array.isArray(value)) {
|
|
255
|
-
const allPrimitive = value.every((v) =>
|
|
256
|
-
['string', 'number', 'boolean'].includes(typeof v),
|
|
257
|
-
);
|
|
258
|
-
if (allPrimitive) {
|
|
259
|
-
return html`<ul class="roxy-chips">
|
|
260
|
-
${value.map((v) => html`<li>${String(v)}</li>`)}
|
|
261
|
-
</ul>`;
|
|
262
|
-
}
|
|
309
|
+
if (isPrimitive(value)) return html`${this.scalarTemplate(value)}`;
|
|
310
|
+
if (Array.isArray(value) && value.every(isPrimitive)) {
|
|
311
|
+
return this.renderChips(value as (Scalar | null)[]);
|
|
263
312
|
}
|
|
264
313
|
return html`<roxy-data .data=${value} .depth=${this.depth + 1}></roxy-data>`;
|
|
265
314
|
}
|
|
266
315
|
|
|
267
|
-
private
|
|
316
|
+
private renderCell(value: Json | undefined): TemplateResult | string {
|
|
268
317
|
if (value === null || value === undefined) return '';
|
|
269
|
-
if (
|
|
270
|
-
if (
|
|
271
|
-
return
|
|
272
|
-
|
|
273
|
-
|
|
318
|
+
if (isPrimitive(value)) return this.scalarTemplate(value);
|
|
319
|
+
if (Array.isArray(value) && value.every(isPrimitive)) {
|
|
320
|
+
return (value as (Scalar | null)[])
|
|
321
|
+
.filter((v): v is Scalar => v !== null)
|
|
322
|
+
.map((v) => this.formatScalar(v))
|
|
323
|
+
.join(', ');
|
|
324
|
+
}
|
|
325
|
+
// Nested object or object array inside a row: recurse instead of
|
|
326
|
+
// stringifying to [object Object]. `bare` drops the card surface so
|
|
327
|
+
// the cell does not paint a card inside a cell.
|
|
328
|
+
return html`<roxy-data
|
|
329
|
+
bare
|
|
330
|
+
.data=${value}
|
|
331
|
+
.depth=${this.depth + 1}
|
|
332
|
+
></roxy-data>`;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private scalarTemplate(value: Scalar): TemplateResult | string {
|
|
336
|
+
if (typeof value === 'string' && LINK_STRING.test(value)) {
|
|
337
|
+
return html`<a href=${value} target="_blank" rel="noopener noreferrer"
|
|
338
|
+
>${value}</a
|
|
339
|
+
>`;
|
|
340
|
+
}
|
|
341
|
+
return this.formatScalar(value);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private formatScalar(value: Scalar): string {
|
|
345
|
+
if (typeof value === 'number') {
|
|
346
|
+
return formatNumber(value, 2) || String(value);
|
|
347
|
+
}
|
|
348
|
+
if (typeof value === 'boolean') return value ? 'Yes' : 'No';
|
|
349
|
+
if (ISO_DATE.test(value)) {
|
|
350
|
+
const time = formatTime(value);
|
|
351
|
+
const date = formatDate(value);
|
|
352
|
+
return time ? `${date}, ${time}` : date;
|
|
353
|
+
}
|
|
354
|
+
if (ENUM_STRING.test(value)) return humanize(value.toLowerCase());
|
|
355
|
+
return value;
|
|
274
356
|
}
|
|
275
357
|
|
|
276
358
|
private collectKeys(rows: Record<string, Json>[]): string[] {
|
package/src/types/types.gen.ts
CHANGED
|
@@ -877,11 +877,11 @@ export type TransitsRequest = {
|
|
|
877
877
|
*/
|
|
878
878
|
natalChart?: {
|
|
879
879
|
/**
|
|
880
|
-
* Date in YYYY-MM-DD format.
|
|
880
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
881
881
|
*/
|
|
882
882
|
date: string;
|
|
883
883
|
/**
|
|
884
|
-
* Time in 24-hour
|
|
884
|
+
* Time in 24-hour format. Seconds are optional and default to 00 (14:30 becomes 14:30:00); a single-digit hour is zero-padded. Out-of-range values are rejected.
|
|
885
885
|
*/
|
|
886
886
|
time: string;
|
|
887
887
|
latitude: number;
|
|
@@ -2779,7 +2779,7 @@ export type BirthChartResponse = {
|
|
|
2779
2779
|
};
|
|
2780
2780
|
};
|
|
2781
2781
|
/**
|
|
2782
|
-
* Twelve classical yogas detected against this chart: Gajakesari (three-rule parashara definition), Sunapha, Anapha, Dhurdhura, Kemadruma, Chandra Mangala, Budha-Aditya, and the five Pancha Mahapurusha (Ruchaka, Bhadra, Hamsa, Malavya, Sasa). Each entry carries an `id` (matches `GET /yoga/{id}` for full glossary lookup), a `present` boolean, and classical-text `evidence` for the rule that triggered or failed.
|
|
2782
|
+
* Twelve classical yogas detected against this chart: Gajakesari (three-rule parashara definition), Sunapha, Anapha, Dhurdhura, Kemadruma, Chandra Mangala, Budha-Aditya, and the five Pancha Mahapurusha (Ruchaka, Bhadra, Hamsa, Malavya, Sasa). Each entry carries an `id` (matches `GET /yoga/{id}` for full glossary lookup), a `present` boolean, a `quality` (Positive, Negative, or Both = auspicious, inauspicious, or context-dependent), and classical-text `evidence` for the rule that triggered or failed.
|
|
2783
2783
|
*/
|
|
2784
2784
|
yogas?: Array<{
|
|
2785
2785
|
/**
|
|
@@ -3632,7 +3632,7 @@ export type SadhesatiRequest = {
|
|
|
3632
3632
|
|
|
3633
3633
|
export type YogaDetectResponse = {
|
|
3634
3634
|
/**
|
|
3635
|
-
* Array of 12 detected yogas. Every entry carries a present boolean; filter on present === true for active yogas. Evidence text names the rule that triggered or failed.
|
|
3635
|
+
* Array of 12 detected yogas. Every entry carries a `present` boolean and a `quality` (Positive, Negative, or Both = auspicious, inauspicious, or context-dependent); filter on present === true for active yogas. Evidence text names the rule that triggered or failed.
|
|
3636
3636
|
*/
|
|
3637
3637
|
yogas: Array<{
|
|
3638
3638
|
/**
|
|
@@ -4765,11 +4765,11 @@ export type KpPlanetsIntervalResponse = {
|
|
|
4765
4765
|
|
|
4766
4766
|
export type KpPlanetsIntervalRequest = {
|
|
4767
4767
|
/**
|
|
4768
|
-
* Start datetime in ISO 8601
|
|
4768
|
+
* Start datetime in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
4769
4769
|
*/
|
|
4770
4770
|
startDatetime: string;
|
|
4771
4771
|
/**
|
|
4772
|
-
* End datetime in ISO 8601
|
|
4772
|
+
* End datetime in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Maximum 7 days from start. Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
4773
4773
|
*/
|
|
4774
4774
|
endDatetime: string;
|
|
4775
4775
|
/**
|
|
@@ -14341,7 +14341,7 @@ export type GetBasicPanchangResponse = GetBasicPanchangResponses[keyof GetBasicP
|
|
|
14341
14341
|
export type GetDetailedPanchangData = {
|
|
14342
14342
|
body?: {
|
|
14343
14343
|
/**
|
|
14344
|
-
* Date in YYYY-MM-DD format.
|
|
14344
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
14345
14345
|
*/
|
|
14346
14346
|
date: string;
|
|
14347
14347
|
/**
|
|
@@ -14898,7 +14898,7 @@ export type GetDetailedPanchangResponses = {
|
|
|
14898
14898
|
*/
|
|
14899
14899
|
panchaka: {
|
|
14900
14900
|
/**
|
|
14901
|
-
*
|
|
14901
|
+
* True when Panchaka is in effect on this date, whether it is already running at sunrise or begins later in the day, in which case startsAt and endsAt give the window. False only when no Panchaka touches this date.
|
|
14902
14902
|
*/
|
|
14903
14903
|
active: boolean;
|
|
14904
14904
|
/**
|
|
@@ -14915,11 +14915,11 @@ export type GetDetailedPanchangResponses = {
|
|
|
14915
14915
|
endsAt: string;
|
|
14916
14916
|
};
|
|
14917
14917
|
/**
|
|
14918
|
-
* Bhadra (Vishti Karana), the 7th movable karana, avoided for all auspicious activities. Bhadra recurs roughly every 3 to 5 days and lasts about half a tithi
|
|
14918
|
+
* Bhadra (Vishti Karana), the 7th movable karana, avoided for all auspicious activities. Bhadra recurs roughly every 3 to 5 days and lasts about half a tithi. active is true whenever a Bhadra is attributed to this date; startsAt and endsAt give the window, which may end on the next calendar day.
|
|
14919
14919
|
*/
|
|
14920
14920
|
bhadra: {
|
|
14921
14921
|
/**
|
|
14922
|
-
*
|
|
14922
|
+
* True when a Bhadra (Vishti Karana) occurs on this date, in which case startsAt and endsAt give its window. False only when no Bhadra begins on this date.
|
|
14923
14923
|
*/
|
|
14924
14924
|
active: boolean;
|
|
14925
14925
|
/**
|
|
@@ -15017,7 +15017,7 @@ export type GetDetailedPanchangResponse = GetDetailedPanchangResponses[keyof Get
|
|
|
15017
15017
|
export type GetChoghadiyaData = {
|
|
15018
15018
|
body?: {
|
|
15019
15019
|
/**
|
|
15020
|
-
* Date in YYYY-MM-DD format.
|
|
15020
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
15021
15021
|
*/
|
|
15022
15022
|
date: string;
|
|
15023
15023
|
/**
|
|
@@ -15206,7 +15206,7 @@ export type GetChoghadiyaResponse = GetChoghadiyaResponses[keyof GetChoghadiyaRe
|
|
|
15206
15206
|
export type GetHoraData = {
|
|
15207
15207
|
body?: {
|
|
15208
15208
|
/**
|
|
15209
|
-
* Date in YYYY-MM-DD format.
|
|
15209
|
+
* Date in YYYY-MM-DD format. A single-digit month or day is accepted and zero-padded (2026-3-5 becomes 2026-03-05). Impossible calendar dates are rejected.
|
|
15210
15210
|
*/
|
|
15211
15211
|
date: string;
|
|
15212
15212
|
/**
|
|
@@ -16684,7 +16684,7 @@ export type GetKpRulingPlanetsData = {
|
|
|
16684
16684
|
*/
|
|
16685
16685
|
timezone?: number | string;
|
|
16686
16686
|
/**
|
|
16687
|
-
* ISO 8601 datetime for ruling planets. Defaults to current time.
|
|
16687
|
+
* ISO 8601 datetime (YYYY-MM-DDTHH:MM:SS) for ruling planets. Defaults to current time. Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
16688
16688
|
*/
|
|
16689
16689
|
datetime?: string;
|
|
16690
16690
|
/**
|
|
@@ -16821,11 +16821,11 @@ export type GetKpRulingPlanetsResponse = GetKpRulingPlanetsResponses[keyof GetKp
|
|
|
16821
16821
|
export type GetKpRulingIntervalData = {
|
|
16822
16822
|
body?: {
|
|
16823
16823
|
/**
|
|
16824
|
-
* Start of the interval range in ISO 8601
|
|
16824
|
+
* Start of the interval range in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
16825
16825
|
*/
|
|
16826
16826
|
startDatetime: string;
|
|
16827
16827
|
/**
|
|
16828
|
-
* End of the interval range in ISO 8601
|
|
16828
|
+
* End of the interval range in ISO 8601 (YYYY-MM-DDTHH:MM:SS). Interpreted as local time when a non-zero timezone is provided (a trailing Z is accepted but ignored); with timezone 0 it is UTC.
|
|
16829
16829
|
*/
|
|
16830
16830
|
endDatetime: string;
|
|
16831
16831
|
/**
|
|
@@ -21665,7 +21665,7 @@ export type CalculatePersonalDayData = {
|
|
|
21665
21665
|
*/
|
|
21666
21666
|
day: number;
|
|
21667
21667
|
/**
|
|
21668
|
-
* Target date in YYYY-MM-DD format
|
|
21668
|
+
* Target date in YYYY-MM-DD format. Defaults to today (UTC).
|
|
21669
21669
|
*/
|
|
21670
21670
|
targetDate?: string;
|
|
21671
21671
|
};
|
|
@@ -33896,7 +33896,7 @@ export type GetCrystalPairingsData = {
|
|
|
33896
33896
|
body?: never;
|
|
33897
33897
|
path: {
|
|
33898
33898
|
/**
|
|
33899
|
-
* URL-safe crystal identifier to find pairings for (e.g., "amethyst", "rose-quartz").
|
|
33899
|
+
* URL-safe crystal identifier to find pairings for, case-insensitive (e.g., "amethyst", "Amethyst", "rose-quartz" all resolve).
|
|
33900
33900
|
*/
|
|
33901
33901
|
id: string;
|
|
33902
33902
|
};
|
|
@@ -34855,7 +34855,7 @@ export type GetCrystalData = {
|
|
|
34855
34855
|
body?: never;
|
|
34856
34856
|
path: {
|
|
34857
34857
|
/**
|
|
34858
|
-
* URL-safe crystal identifier (e.g., "amethyst", "
|
|
34858
|
+
* URL-safe crystal identifier, case-insensitive (e.g., "amethyst", "Amethyst", "rose-quartz" all resolve). Must match an entry in the database.
|
|
34859
34859
|
*/
|
|
34860
34860
|
id: string;
|
|
34861
34861
|
};
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by scripts/sync-version.ts. Do not edit.
|
|
2
|
-
export const ROXY_UI_VERSION = '0.12.
|
|
2
|
+
export const ROXY_UI_VERSION = '0.12.3';
|