natus wheel: aspect line system, element tooltip overhaul, ring/spoke changes — TDD
All checks were successful
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline was successful

- DON/DOFF toggle: aspect lines persist across planet switches & outside clicks; cleared only by DON (new planet) or DOFF; planet-keyed --asp-* colors (--sixU/--terU on light palettes)
- planet tooltip: aspect rows w. 2× thick line legend, planet symbol + .tt-asp-in 'in' + sign icon + orb; applying/separating direction symbols
- element tooltip: 80px square badge (float right); DON/DOFF hidden; symbol-based contributor rows (☉ @ 15.3°  +1); Stellium/Parade +N underlined headers; parade sign-grouped w. parenthetical planet symbols, counterclockwise order
- ring swap: planets outer (0.50–0.68r), houses inner (0.32–0.48r) to reduce stellia crowding
- house spokes: angle cusps only (ASC/IC/DSC/MC); non-angle spokes removed
- outside-click guard: bounding-rect check for DON/DOFF/PRV/NXT so pointer-events:none buttons don't trigger close
- add element-square & energy-vector icon dirs (Ardor/Ossum/Tempo/Nexus/Pneuma/Humor SVGs)
- T11a–f Jasmine specs for DON/DOFF line persistence

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-21 03:17:20 -04:00
parent 9c7d58f0b3
commit ea2bfa6ce1
20 changed files with 1498 additions and 140 deletions

View File

@@ -282,6 +282,155 @@ describe("NatusWheel — tick lines, raise, and cycle navigation", () => {
// x ≥ 200 (right side): left = iRect.right - ttW = x + 10 - 0 = x + 10
// ─────────────────────────────────────────────────────────────────────────────
// ── DON / DOFF aspect line persistence ───────────────────────────────────────
//
// Aspect lines belong to the page session, not the tooltip:
// - DON draws lines into .nw-aspects and disables DON btn (shows ×)
// - closing the tooltip does NOT clear lines
// - re-opening the SAME planet preserves _aspectsVisible → DON still disabled
// - opening a DIFFERENT planet resets state: lines cleared, DON active
// - DOFF clears lines; re-opening same planet finds DON active
// ─────────────────────────────────────────────────────────────────────────────
describe("NatusWheel — DON/DOFF aspect line persistence", () => {
const ASPECT_CHART = {
planets: {
Sun: { sign: "Capricorn", degree: 280.4, retrograde: false },
Moon: { sign: "Scorpio", degree: 220.1, retrograde: false },
Mars: { sign: "Taurus", degree: 40.7, retrograde: false },
},
houses: {
cusps: [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330],
asc: 0, mc: 270,
},
elements: { Fire: 0, Stone: 0, Air: 0, Water: 1, Time: 0, Space: 0 },
aspects: [
{ planet1: "Sun", planet2: "Mars", type: "Trine",
orb: 0.3, angle: 120, applying_planet: "Sun" },
{ planet1: "Sun", planet2: "Moon", type: "Sextile",
orb: 2.9, angle: 60, applying_planet: "Moon" },
],
distinctions: {
"1": 0, "2": 0, "3": 0, "4": 0,
"5": 0, "6": 0, "7": 0, "8": 0,
"9": 0, "10": 0, "11": 0, "12": 0,
},
house_system: "O",
};
let svgEl, tooltipEl;
beforeEach(() => {
svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgEl.setAttribute("id", "id_natus_svg");
svgEl.setAttribute("width", "400");
svgEl.setAttribute("height", "400");
svgEl.style.width = "400px";
svgEl.style.height = "400px";
document.body.appendChild(svgEl);
tooltipEl = document.createElement("div");
tooltipEl.id = "id_natus_tooltip";
tooltipEl.className = "tt";
tooltipEl.style.display = "none";
document.body.appendChild(tooltipEl);
NatusWheel.draw(svgEl, ASPECT_CHART);
});
afterEach(() => {
NatusWheel.clear();
svgEl.remove();
tooltipEl.remove();
});
function clickPlanet(name) {
svgEl.querySelector(`[data-planet="${name}"]`)
.dispatchEvent(new MouseEvent("click", { bubbles: true }));
}
function clickDon() { tooltipEl.querySelector(".nw-asp-don") .dispatchEvent(new MouseEvent("click", { bubbles: true })); }
function clickDoff() { tooltipEl.querySelector(".nw-asp-doff").dispatchEvent(new MouseEvent("click", { bubbles: true })); }
function aspectLines() { return svgEl.querySelectorAll(".nw-aspects line").length; }
function donDisabled() { return tooltipEl.querySelector(".nw-asp-don").classList.contains("btn-disabled"); }
// T11a — DON draws lines
it("T11a: clicking DON draws aspect lines into .nw-aspects", () => {
clickPlanet("Sun");
expect(aspectLines()).toBe(0);
clickDon();
expect(aspectLines()).toBeGreaterThan(0);
});
// T11b — closing tooltip must not clear aspect lines
it("T11b: closing the tooltip (outside click) does not clear aspect lines", () => {
clickPlanet("Sun");
clickDon();
const lineCount = aspectLines();
expect(lineCount).toBeGreaterThan(0);
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
expect(tooltipEl.style.display).toBe("none");
expect(aspectLines()).toBe(lineCount);
});
// T11c — re-opening same planet preserves DON-disabled state
it("T11c: re-opening the same planet after DON keeps DON disabled (lines still active)", () => {
clickPlanet("Sun");
clickDon();
expect(donDisabled()).toBe(true);
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
clickPlanet("Sun");
expect(donDisabled()).toBe(true);
expect(aspectLines()).toBeGreaterThan(0);
});
// T11d — switching planet leaves previous DONned lines intact; DON active for new planet
it("T11d: opening a different planet leaves DONned lines intact — DON active for new planet", () => {
clickPlanet("Sun");
clickDon();
const lineCount = aspectLines();
expect(lineCount).toBeGreaterThan(0);
clickPlanet("Moon");
expect(donDisabled()).toBe(false); // Moon's DON is fresh/active
expect(aspectLines()).toBe(lineCount); // Sun's lines still there
});
// T11f — DONning a second planet replaces the first planet's lines + tick
it("T11f: clicking DON on a second planet clears the first planet's lines", () => {
clickPlanet("Sun");
clickDon();
expect(aspectLines()).toBeGreaterThan(0);
clickPlanet("Moon");
clickDon();
expect(donDisabled()).toBe(true); // Moon's DON now disabled
// Moon aspects — Sun's lines replaced (lines may be 0 if Moon has no aspects)
const sunGrp = svgEl.querySelector('[data-planet="Sun"]');
expect(sunGrp.classList.contains('nw-planet--asp-active')).toBe(false);
});
// T11e — DOFF clears lines; re-opening same planet starts fresh
it("T11e: DOFF clears lines; re-opening same planet finds DON active again", () => {
clickPlanet("Sun");
clickDon();
clickDoff();
expect(aspectLines()).toBe(0);
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true }));
clickPlanet("Sun");
expect(donDisabled()).toBe(false);
expect(aspectLines()).toBe(0);
});
});
xdescribe("NatusWheel — half-wheel tooltip positioning", () => {
const HALF_CHART = {