182a5dab16
family-chart 0.9.0 stacks all of a person's spouses on one gender-determined side, so someone with two spouses (e.g. a woman with two husbands) renders with both spouses piled above/below her and ambiguous child lines. Patch the library (via patch-package) so the person stays centered and their spouses split to alternating sides — spouse 1 above, spouse 2 below, further spouses farther out — and order each couple's children to match, so children descend from between the correct pair without crossed lines: - setupSpouses: keep the person centered; place spouses at alternating offsets and recenter the cluster on the person's slot. - sortChildrenWithSpouses: order children by spouse order (gender-independent) to match the new spouse positions. Adds patch-package + a postinstall hook, and COPY patches into the Dockerfile deps stage so the patch applies during `npm ci` in CI. Verified the patch re-applies on a clean install and the production build passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Justin Paul <justin@jpaul.me>
119 lines
6.7 KiB
Diff
119 lines
6.7 KiB
Diff
diff --git a/node_modules/family-chart/dist/family-chart.esm.js b/node_modules/family-chart/dist/family-chart.esm.js
|
|
index 3867be0..560c99e 100644
|
|
--- a/node_modules/family-chart/dist/family-chart.esm.js
|
|
+++ b/node_modules/family-chart/dist/family-chart.esm.js
|
|
@@ -10,10 +10,10 @@ function sortChildrenWithSpouses(children, datum, data) {
|
|
const b_p2 = otherParent(b, datum, data);
|
|
const a_i = a_p2 ? spouses.indexOf(a_p2.id) : -1;
|
|
const b_i = b_p2 ? spouses.indexOf(b_p2.id) : -1;
|
|
- if (datum.data.gender === "M")
|
|
- return a_i - b_i;
|
|
- else
|
|
- return b_i - a_i;
|
|
+ // Provenance patch: order children by spouse order (ascending), gender-
|
|
+ // independent, so each couple's children sit next to the matching spouse
|
|
+ // in the centered-spouse layout (see setupSpouses).
|
|
+ return a_i - b_i;
|
|
});
|
|
}
|
|
function sortAddNewChildren(children) {
|
|
@@ -701,20 +701,38 @@ function calculateTree(data, { main_id = null, node_separation = 250, level_sepa
|
|
if (spouses.length > 0) {
|
|
if (one_level_rels && d.depth > 0)
|
|
continue;
|
|
- const side = d.data.data.gender === "M" ? -1 : 1; // female on right
|
|
- d.x += spouses.length / 2 * node_separation * side;
|
|
+ // Provenance patch: keep the person in the MIDDLE and split
|
|
+ // their spouses to alternating sides, then recenter the whole
|
|
+ // cluster on the person's slot, so each couple's children
|
|
+ // descend from between the correct pair instead of all
|
|
+ // spouses stacking on one side. Ordered by relationship order
|
|
+ // (spouse 1 on top, spouse 2 below, further spouses farther
|
|
+ // out) — NOT gender; children are sorted to match in
|
|
+ // sortChildrenWithSpouses.
|
|
+ const offsets = spouses.map((_sp, i) => {
|
|
+ const dir = i % 2 === 0 ? 1 : -1;
|
|
+ const dist = Math.floor(i / 2) + 1; // 1,1,2,2,3,3...
|
|
+ return -(node_separation * dist) * dir;
|
|
+ });
|
|
+ // Mean of the person (offset 0) + every spouse, so the
|
|
+ // cluster stays centered on the person's original slot.
|
|
+ const center = offsets.reduce((a, b) => a + b, 0) / (offsets.length + 1);
|
|
+ const base_x = d.x;
|
|
+ d.x = base_x - center;
|
|
spouses.forEach((sp_id, i) => {
|
|
const spouse = {
|
|
data: data_stash.find(d0 => d0.id === sp_id),
|
|
added: true,
|
|
depth: d.depth,
|
|
spouse: d,
|
|
- x: d.x - (node_separation * (i + 1)) * side,
|
|
+ x: base_x + offsets[i] - center,
|
|
y: d.y,
|
|
tid: `${d.data.id}-spouse-${i}`,
|
|
};
|
|
- spouse.sx = i > 0 ? spouse.x : spouse.x + (node_separation / 2) * side;
|
|
- spouse.sy = i > 0 ? spouse.y : spouse.y + (node_separation / 2) * side;
|
|
+ // Anchor links at the midpoint toward the person.
|
|
+ const toward = spouse.x < d.x ? 1 : -1;
|
|
+ spouse.sx = spouse.x + toward * (node_separation / 2);
|
|
+ spouse.sy = spouse.y;
|
|
if (!d.spouses)
|
|
d.spouses = [];
|
|
d.spouses.push(spouse);
|
|
diff --git a/node_modules/family-chart/dist/family-chart.js b/node_modules/family-chart/dist/family-chart.js
|
|
index 1c750d4..47efcc2 100644
|
|
--- a/node_modules/family-chart/dist/family-chart.js
|
|
+++ b/node_modules/family-chart/dist/family-chart.js
|
|
@@ -33,10 +33,9 @@
|
|
const b_p2 = otherParent(b, datum, data);
|
|
const a_i = a_p2 ? spouses.indexOf(a_p2.id) : -1;
|
|
const b_i = b_p2 ? spouses.indexOf(b_p2.id) : -1;
|
|
- if (datum.data.gender === "M")
|
|
- return a_i - b_i;
|
|
- else
|
|
- return b_i - a_i;
|
|
+ // Provenance patch: order children by spouse order (ascending),
|
|
+ // gender-independent, to match the centered-spouse layout.
|
|
+ return a_i - b_i;
|
|
});
|
|
}
|
|
function sortAddNewChildren(children) {
|
|
@@ -724,20 +723,31 @@
|
|
if (spouses.length > 0) {
|
|
if (one_level_rels && d.depth > 0)
|
|
continue;
|
|
- const side = d.data.data.gender === "M" ? -1 : 1; // female on right
|
|
- d.x += spouses.length / 2 * node_separation * side;
|
|
+ // Provenance patch: keep the person in the MIDDLE and
|
|
+ // split spouses to alternating sides, recentered on the
|
|
+ // person's slot, so each couple's children descend from
|
|
+ // between the correct pair (see esm build for details).
|
|
+ const offsets = spouses.map((_sp, i) => {
|
|
+ const dir = i % 2 === 0 ? 1 : -1;
|
|
+ const dist = Math.floor(i / 2) + 1;
|
|
+ return -(node_separation * dist) * dir;
|
|
+ });
|
|
+ const center = offsets.reduce((a, b) => a + b, 0) / (offsets.length + 1);
|
|
+ const base_x = d.x;
|
|
+ d.x = base_x - center;
|
|
spouses.forEach((sp_id, i) => {
|
|
const spouse = {
|
|
data: data_stash.find(d0 => d0.id === sp_id),
|
|
added: true,
|
|
depth: d.depth,
|
|
spouse: d,
|
|
- x: d.x - (node_separation * (i + 1)) * side,
|
|
+ x: base_x + offsets[i] - center,
|
|
y: d.y,
|
|
tid: `${d.data.id}-spouse-${i}`,
|
|
};
|
|
- spouse.sx = i > 0 ? spouse.x : spouse.x + (node_separation / 2) * side;
|
|
- spouse.sy = i > 0 ? spouse.y : spouse.y + (node_separation / 2) * side;
|
|
+ const toward = spouse.x < d.x ? 1 : -1;
|
|
+ spouse.sx = spouse.x + toward * (node_separation / 2);
|
|
+ spouse.sy = spouse.y;
|
|
if (!d.spouses)
|
|
d.spouses = [];
|
|
d.spouses.push(spouse);
|