Scope font-size rules to fng-container to avoid overriding full-diagram styles

This commit is contained in:
2026-03-16 21:04:11 +01:00
parent c9d1054d37
commit 9321011bfe
4 changed files with 61 additions and 12 deletions

View File

@@ -64,15 +64,15 @@
fill: rgba(255, 255, 255, 0.6);
}
/* Card text */
.person-card .person-name {
font-size: 9px;
/* Card text — scoped to fng-container to avoid overriding full-diagram */
.fng-container .person-card .person-name {
font-size: 8px;
font-weight: 600;
fill: #212529;
dominant-baseline: auto;
}
.person-card .person-dates {
.fng-container .person-card .person-dates {
font-size: 8px;
fill: #6c757d;
dominant-baseline: auto;

File diff suppressed because one or more lines are too long

View File

@@ -153,13 +153,13 @@ export function renderPersonCard(parent, person, config, onClick) {
const firstName = data["first name"] || "";
const lastName = data["last name"] || "";
const displayName = formatDisplayName(firstName, lastName, data.fullName);
const maxTextWidth = w - textXOffset - 5;
const maxTextWidth = w - textXOffset;
g.append("text")
.attr("class", "person-name")
.attr("x", textXOffset)
.attr("y", h / 2 - 4)
.text(truncateText(displayName, maxTextWidth, 5.5));
.text(truncateText(displayName, maxTextWidth, 4.5));
// Dates line (compact)
const dates = formatDates(data.birthYear, data.deathYear, data.isDead);

View File

@@ -58,7 +58,7 @@ export function computeLayout(persons, mainId, config) {
if (pid !== mainId) activeSpouseIds.add(pid);
}
}
if (activeRootFamilies.length >= 2) {
if (activeRootFamilies.length >= 1 && rootSpouses.size >= 2) {
for (const sid of activeSpouseIds) {
if (gen.has(sid)) gen.set(sid, 0.5);
}
@@ -80,6 +80,17 @@ export function computeLayout(persons, mainId, config) {
const ids = genGroups.get(g);
const ordered = orderGeneration(ids, g, mainId, families, personById, activeRootFamilies);
// Single active spouse staggered: position at right column (same x as S1)
if (g === 0.5 && activeRootFamilies.length === 1) {
const rowWidth = 2 * cw + hGap;
const rightX = -rowWidth / 2 + cw / 2 + cw + hGap;
for (const id of ordered) {
positions.set(id, { x: rightX, y: currentY });
}
currentY += ch + vGap * 0.6;
continue;
}
// Multi-spouse children: position each family's children as
// two side-by-side columns (1 card wide each) to stay within 2-card width
if (g >= 1 && activeRootFamilies.length >= 2) {
@@ -433,7 +444,10 @@ function buildConnectors(families, positions, config, mainId, activeRootFamilies
const halfH = config.cardHeight / 2;
const cw = config.cardWidth;
const vGap = config.verticalSpacing;
const rootPerson = personById.get(mainId);
const rootSpouseIds = rootPerson?.rels?.spouses || [];
const multiSpouse = activeRootFamilies.length >= 2;
const staggeredLayout = activeRootFamilies.length >= 1 && rootSpouseIds.length >= 2;
const rootPos = positions.get(mainId);
const margin = 12;
@@ -441,8 +455,8 @@ function buildConnectors(families, positions, config, mainId, activeRootFamilies
const rootFamIdx = activeRootFamilies.indexOf(family);
const isActiveRootFamily = rootFamIdx >= 0;
// Multi-spouse active families get custom routing below
if (isActiveRootFamily && multiSpouse) continue;
// Staggered/multi-spouse active families get custom routing below
if (isActiveRootFamily && staggeredLayout) continue;
const parentPos = family.parents
.map((pid) => positions.get(pid))
@@ -559,15 +573,50 @@ function buildConnectors(families, positions, config, mainId, activeRootFamilies
}
}
// ── Single active spouse staggered: root → S2 → children ──
if (!multiSpouse && staggeredLayout && rootPos) {
const family = activeRootFamilies[0];
const spouseId = family.parents.find((p) => p !== mainId);
const spousePos = spouseId ? positions.get(spouseId) : null;
const childPos = family.children
.map((cid) => ({ id: cid, ...positions.get(cid) }))
.filter((c) => c.x !== undefined);
if (spousePos && childPos.length > 0) {
const spouseBottomY = spousePos.y + halfH;
const childTopY = Math.min(...childPos.map((c) => c.y)) - halfH;
const gap = childTopY - spouseBottomY;
const coupleBarY = spouseBottomY + gap * 0.3;
// Root vertical down to couple bar
connections.push({
path: `M ${rootPos.x} ${rootPos.y + halfH} L ${rootPos.x} ${coupleBarY}`,
cssClass: "link couple-link",
});
// Horizontal couple bar from root to spouse
connections.push({
path: `M ${rootPos.x} ${coupleBarY} L ${spousePos.x} ${coupleBarY}`,
cssClass: "link couple-link",
});
// Spouse vertical down to couple bar
connections.push({
path: `M ${spousePos.x} ${spouseBottomY} L ${spousePos.x} ${coupleBarY}`,
cssClass: "link couple-link",
});
// Children from couple bar, spine centered between root and spouse
const spineX = (rootPos.x + spousePos.x) / 2;
drawChildConnectors(connections, childPos, spineX, coupleBarY, halfH, vGap);
}
}
// ── Couple links for childless spouses (same row as root) ──
const rootPerson = personById.get(mainId);
const childlessActiveIds = new Set();
for (const f of activeRootFamilies) {
for (const pid of f.parents) {
if (pid !== mainId) childlessActiveIds.add(pid);
}
}
if (rootPerson && rootPos && multiSpouse) {
if (rootPerson && rootPos && staggeredLayout) {
for (const sid of rootPerson.rels.spouses || []) {
if (childlessActiveIds.has(sid)) continue;
const spPos = positions.get(sid);