natus wheel: aspect line system, element tooltip overhaul, ring/spoke changes — TDD
- 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:
@@ -450,7 +450,8 @@ html.natus-open .natus-modal-wrap {
|
||||
stroke-linecap: round;
|
||||
transition: stroke-opacity 0.15s ease;
|
||||
}
|
||||
.nw-planet-group.nw-planet--active .nw-planet-tick {
|
||||
.nw-planet-group.nw-planet--active .nw-planet-tick,
|
||||
.nw-planet-group.nw-planet--asp-active .nw-planet-tick {
|
||||
stroke: rgba(var(--terUser), 1);
|
||||
stroke-opacity: 0.7;
|
||||
filter: drop-shadow(0 0 3px rgba(var(--terUser), 0.8))
|
||||
@@ -467,7 +468,21 @@ html.natus-open .natus-modal-wrap {
|
||||
.nw-planet-tick--np { stroke: rgba(var(--priNp), 1); }
|
||||
.nw-planet-tick--pu { stroke: rgba(var(--priPu), 1); }
|
||||
|
||||
// Aspects
|
||||
// Aspects — per-planet color tokens (light shades on dark palettes; mid on light)
|
||||
:root {
|
||||
--asp-Au: var(--sixAu); --asp-Ag: var(--sixAg);
|
||||
--asp-Hg: var(--sixHg); --asp-Cu: var(--sixCu);
|
||||
--asp-Fe: var(--sixFe); --asp-Sn: var(--sixSn);
|
||||
--asp-Pb: var(--sixPb); --asp-U: var(--sixU);
|
||||
--asp-Np: var(--sixNp); --asp-Pu: var(--sixPu);
|
||||
}
|
||||
body[class*="-light"] {
|
||||
--asp-Au: var(--terAu); --asp-Ag: var(--terAg);
|
||||
--asp-Hg: var(--terHg); --asp-Cu: var(--terCu);
|
||||
--asp-Fe: var(--terFe); --asp-Sn: var(--terSn);
|
||||
--asp-Pb: var(--terPb); --asp-U: var(--terU);
|
||||
--asp-Np: var(--terNp); --asp-Pu: var(--terPu);
|
||||
}
|
||||
.nw-aspects { opacity: 0.8; }
|
||||
|
||||
// Element pie — deasil order: Fire → Stone → Time → Space → Air → Water
|
||||
@@ -487,12 +502,24 @@ html.natus-open .natus-modal-wrap {
|
||||
position: fixed;
|
||||
z-index: 200;
|
||||
pointer-events: auto;
|
||||
padding: 0.75rem 1.5rem;
|
||||
padding: 0.75rem 0.75rem 0.75rem 1.5rem;
|
||||
min-width: 14rem;
|
||||
|
||||
.tt-title { font-size: 1rem; font-weight: 700; }
|
||||
.tt-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 0.3rem; }
|
||||
.tt-description { font-size: 0.75rem; }
|
||||
.tt-sign-icon { fill: currentColor; vertical-align: middle; margin-bottom: 0.1em; }
|
||||
|
||||
// DON|DOFF aspect line toggle — stacked at top-left outside the tooltip box,
|
||||
// matching the PRV/NXT pattern at the bottom corners.
|
||||
.nw-asp-don,
|
||||
.nw-asp-doff {
|
||||
position: absolute;
|
||||
left: -1rem;
|
||||
margin: 0;
|
||||
}
|
||||
.nw-asp-don { top: -1rem; }
|
||||
.nw-asp-doff { top: 1.2rem; }
|
||||
|
||||
.nw-tt-prv,
|
||||
.nw-tt-nxt {
|
||||
position: absolute;
|
||||
@@ -502,6 +529,82 @@ html.natus-open .natus-modal-wrap {
|
||||
.nw-tt-prv { left: -1rem; }
|
||||
.nw-tt-nxt { right: -1rem; }
|
||||
|
||||
// Aspect list — always visible below planet description
|
||||
.tt-aspects {
|
||||
display: block;
|
||||
margin-top: 0.6rem;
|
||||
font-size: 0.94rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.85;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.tt-asp-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tt-asp-line { flex-shrink: 0; vertical-align: middle; }
|
||||
|
||||
.tt-asp-orb,
|
||||
.tt-asp-in {
|
||||
opacity: 0.6;
|
||||
font-size: 0.65rem;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
// Element tooltip — title + square badge
|
||||
.tt-el-header {
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.tt-el-square {
|
||||
float: right;
|
||||
display: block;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.tt-el-vec {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
margin: 0 0.1em;
|
||||
}
|
||||
|
||||
.tt-el-body-line {
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.tt-el-contribs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
.tt-el-planet-row {
|
||||
opacity: 0.75;
|
||||
margin-left: 0.5rem;
|
||||
margin-top: -0.1rem;
|
||||
}
|
||||
|
||||
.tt-el-formation-header {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.tt-el-formation {
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.7;
|
||||
margin-top: 0.2rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
// Planet title colors — senary (brightest) tier on dark palettes
|
||||
.tt-title--au { color: rgba(var(--sixAu), 1); } // Sun
|
||||
.tt-title--ag { color: rgba(var(--sixAg), 1); } // Moon
|
||||
|
||||
@@ -126,49 +126,49 @@
|
||||
--priOr: 225, 133, 40;
|
||||
--secOr: 187, 111, 30;
|
||||
--terOr: 150, 88, 17;
|
||||
// yellow (
|
||||
// yellow (A-Time)
|
||||
--priYl: 255, 207, 52;
|
||||
--secYl: 211, 172, 44;
|
||||
--terYl: 168, 138, 33;
|
||||
// lime
|
||||
// lime (B-Time)
|
||||
--priLm: 151, 174, 60;
|
||||
--secLm: 124, 145, 48;
|
||||
--terLm: 97, 117, 36;
|
||||
// green
|
||||
// green (A-Space)
|
||||
--priGn: 0, 160, 75;
|
||||
--secGn: 0, 135, 62;
|
||||
--terGn: 0, 109, 48;
|
||||
// teal
|
||||
// teal (B-Space)
|
||||
--priTk: 0, 184, 162;
|
||||
--secTk: 0, 154, 136;
|
||||
--terTk: 0, 125, 110;
|
||||
// cyan
|
||||
// cyan (A-Air)
|
||||
--priCy: 13, 179, 200;
|
||||
--secCy: 12, 150, 168;
|
||||
--terCy: 0, 121, 136;
|
||||
// blue
|
||||
// blue (B-Air)
|
||||
--priBl: 20, 141, 205;
|
||||
--secBl: 18, 119, 173;
|
||||
--terBl: 8, 95, 140;
|
||||
// indigo
|
||||
// indigo (A-Water)
|
||||
--priId: 79, 102, 212;
|
||||
--secId: 66, 88, 184;
|
||||
--terId: 53, 74, 156;
|
||||
--quaId: 44, 60, 131;
|
||||
--quiId: 32, 44, 106;
|
||||
--sixId: 21, 29, 71;
|
||||
// violet
|
||||
// violet (B-Water)
|
||||
--priVt: 120, 72, 183;
|
||||
--secVt: 108, 65, 165;
|
||||
--terVt: 96, 58, 147;
|
||||
--quaVt: 80, 45, 124;
|
||||
--quiVt: 64, 30, 100;
|
||||
--sixVt: 43, 20, 66;
|
||||
// fuschia
|
||||
// fuschia (A-Stone)
|
||||
--priFs: 158, 61, 150;
|
||||
--secFs: 133, 47, 126;
|
||||
--terFs: 107, 31, 101;
|
||||
// magenta
|
||||
// magenta (B-Stone)
|
||||
--priMe: 237, 30, 129;
|
||||
--secMe: 196, 18, 108;
|
||||
--terMe: 158, 1, 86;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user