You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(components,utils,tests): correct aspect glyphs, centralize formatting, close the phone width layout gap
Aspect glyphs are now the nine Unicode astrological aspects (260C, 26BA, 2220,
26B9, 25A1, 25B3, 26BC, 26BB, 260D). Semisextile and quincunx were drawn with
the XOR and NAND maths operators and were swapped, so every chart rendered a
150 degree quincunx with the 30 degree symbol and back. Semisquare and
sesquiquadrate had no entry at all and the aspect grid printed the literal
text ses.
Aspect names had four divergent inline normalizers. The aspects endpoint
returns SEMI SEXTILE where synastry returns SEMI_SEXTILE, and only the
underscore was folded, so the space form missed every ASPECT_CLASS and
ASPECT_SYMBOL lookup and the same aspect rendered coloured in one card and in
the neutral fallback in another. normalizeAspect is now the single lookup key
and formatAspectName the single label.
Dates, ranges and ayanamsa move to utils/format.ts the same way: eleven
components were concatenating raw ISO strings beside siblings that formatted
the same field. formatDateTime accepts the split date plus time that birth
details actually arrive as.
Layout: guna-milan clipped its Score column off the card and
local-space-compass pushed its header, dial, summary and table 170px past the
edge at 375px. Both are the grid item min-width auto class. The e2e layout
guard existed but ran only at the Playwright desktop default, and all three
projects are Desktop, so nothing ever measured a card below 1280px. It now
loops 375 / 768 / 1280, and both defects were reproduced by deleting the fix
and re-running.
Every tab now carries an aria-controls that resolves. The APG puts it on each
element with role tab, not just the selected one; the helper emits an empty
hidden panel for the inactive tabs so panel content stays lazy.
Also: dasha bar dates take their grain from the shortest period and keep the
year at day grain, forecast digest orders its window by significance,
relocation names the ascendant sign in both branches instead of contradicting
its own summary, roxy-data drops sections that would render empty, transits
speed carries a unit, and headings are sentence case throughout.
Pages deploys from the release run. The release: [published] trigger in
pages.yml never fired once, because GitHub does not start a workflow from an
event created with the default GITHUB_TOKEN, so the demo sat a release behind.
@@ -625,18 +639,27 @@ function grainFor(maxYears: number): DateGrain {
625
639
return'day';
626
640
}
627
641
628
-
/** One end of a bar, at the chosen granularity. Day grain drops the year: these rows sit under a parent line that already states it, and the column is only 8rem wide. */
642
+
/**
643
+
* One end of a bar, at the chosen granularity.
644
+
*
645
+
* @remarks
646
+
* Every grain carries the year. Day grain used to drop it on the grounds that the parent line states it, but a sookshma period routinely straddles new year, so a bar read `28 Dec - 3 Jan` with nothing saying which side moved. A dasha table is a date reference: a practitioner reads a boundary off it and writes it down.
647
+
*
648
+
* The API returns naive datetimes (`1990-01-15T14:30:00`), which are wall clocks in the timezone of the CHART, not instants. {@link resolveDisplayDate} pins them to UTC so a boundary landing in the DST gap of the viewer cannot silently shift a day.
Copy file name to clipboardExpand all lines: packages/ui/src/components/data.ts
+17-2Lines changed: 17 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -109,6 +109,22 @@ function isComplex(value: Json): boolean {
109
109
);
110
110
}
111
111
112
+
/**
113
+
* True when a value would render as nothing: `[]`, `{}`, or an object whose every value is itself empty.
114
+
*
115
+
* @remarks
116
+
* An empty object still counts as {@link isComplex}, so it is promoted to a full-width section and draws a heading over a blank body. This is the generic fallback renderer for endpoints with no bespoke component, so it receives whatever shape the API returns and a heading with nothing under it is the most visible way it can look broken.
117
+
*
118
+
* Recursive because emptiness nests: `{ breakdown: { western: [], vedic: [] } }` has keys at the top level and still renders as nothing.
0 commit comments