schematex 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dist/ai/ai-sdk.cjs +25 -25
  2. package/dist/ai/ai-sdk.d.cts +1 -1
  3. package/dist/ai/ai-sdk.d.ts +1 -1
  4. package/dist/ai/ai-sdk.js +20 -20
  5. package/dist/ai/index.cjs +28 -28
  6. package/dist/ai/index.d.cts +1 -1
  7. package/dist/ai/index.d.ts +1 -1
  8. package/dist/ai/index.js +20 -20
  9. package/dist/browser.cjs +22 -22
  10. package/dist/browser.js +20 -20
  11. package/dist/{chunk-TYCHEOQX.js → chunk-2J2QWNGI.js} +26 -20
  12. package/dist/chunk-2J2QWNGI.js.map +1 -0
  13. package/dist/{chunk-MCFQAUQV.cjs → chunk-2UJAVPA4.cjs} +58 -39
  14. package/dist/chunk-2UJAVPA4.cjs.map +1 -0
  15. package/dist/{chunk-5AEN2PLB.cjs → chunk-3YXXZ4LT.cjs} +33 -33
  16. package/dist/{chunk-5AEN2PLB.cjs.map → chunk-3YXXZ4LT.cjs.map} +1 -1
  17. package/dist/{chunk-RP5UATRA.js → chunk-56LXBM45.js} +4 -4
  18. package/dist/{chunk-RP5UATRA.js.map → chunk-56LXBM45.js.map} +1 -1
  19. package/dist/{chunk-OC22GGQN.js → chunk-6BKUD5EJ.js} +54 -4
  20. package/dist/chunk-6BKUD5EJ.js.map +1 -0
  21. package/dist/{chunk-ULYRO2KY.cjs → chunk-75BMFCP5.cjs} +44 -44
  22. package/dist/{chunk-ULYRO2KY.cjs.map → chunk-75BMFCP5.cjs.map} +1 -1
  23. package/dist/{chunk-ZNDIGQJD.js → chunk-7BEJHG43.js} +3 -3
  24. package/dist/{chunk-ZNDIGQJD.js.map → chunk-7BEJHG43.js.map} +1 -1
  25. package/dist/{chunk-WYFXOXVK.cjs → chunk-7MVDN5UC.cjs} +35 -35
  26. package/dist/{chunk-WYFXOXVK.cjs.map → chunk-7MVDN5UC.cjs.map} +1 -1
  27. package/dist/{chunk-JDTB7IKL.js → chunk-BJ65PKDU.js} +3 -3
  28. package/dist/{chunk-JDTB7IKL.js.map → chunk-BJ65PKDU.js.map} +1 -1
  29. package/dist/{chunk-FE6GAUNW.js → chunk-BJWMPPEA.js} +5 -5
  30. package/dist/{chunk-FE6GAUNW.js.map → chunk-BJWMPPEA.js.map} +1 -1
  31. package/dist/{chunk-MJGDP3CS.cjs → chunk-BUN3CRMP.cjs} +488 -109
  32. package/dist/chunk-BUN3CRMP.cjs.map +1 -0
  33. package/dist/{chunk-COLTVQWR.cjs → chunk-C3IVD7DI.cjs} +25 -25
  34. package/dist/{chunk-COLTVQWR.cjs.map → chunk-C3IVD7DI.cjs.map} +1 -1
  35. package/dist/{chunk-3YZ6FPQW.cjs → chunk-EYHD7LV3.cjs} +131 -131
  36. package/dist/{chunk-3YZ6FPQW.cjs.map → chunk-EYHD7LV3.cjs.map} +1 -1
  37. package/dist/{chunk-UGCUNADI.js → chunk-F6OROIHS.js} +35 -16
  38. package/dist/chunk-F6OROIHS.js.map +1 -0
  39. package/dist/{chunk-3FKS4KQK.cjs → chunk-GYTWJ6VB.cjs} +65 -59
  40. package/dist/chunk-GYTWJ6VB.cjs.map +1 -0
  41. package/dist/{chunk-VLMK7MQK.js → chunk-H4CJTKEH.js} +23 -4
  42. package/dist/chunk-H4CJTKEH.js.map +1 -0
  43. package/dist/{chunk-45KP67RR.js → chunk-HIQPEAL7.js} +5 -5
  44. package/dist/chunk-HIQPEAL7.js.map +1 -0
  45. package/dist/{chunk-NB56L5QK.js → chunk-IT2TVXC7.js} +4 -4
  46. package/dist/{chunk-NB56L5QK.js.map → chunk-IT2TVXC7.js.map} +1 -1
  47. package/dist/{chunk-2JDVJRR3.cjs → chunk-K5QG53GT.cjs} +28 -28
  48. package/dist/chunk-K5QG53GT.cjs.map +1 -0
  49. package/dist/{chunk-B37IKTI7.cjs → chunk-KUXOHLGC.cjs} +97 -47
  50. package/dist/chunk-KUXOHLGC.cjs.map +1 -0
  51. package/dist/{chunk-A5D2IMOX.cjs → chunk-L2KUGWFR.cjs} +47 -47
  52. package/dist/{chunk-A5D2IMOX.cjs.map → chunk-L2KUGWFR.cjs.map} +1 -1
  53. package/dist/{chunk-HDKDQAEQ.cjs → chunk-LFZZ4NCP.cjs} +14 -2
  54. package/dist/chunk-LFZZ4NCP.cjs.map +1 -0
  55. package/dist/{chunk-U6L3FAML.js → chunk-M3R6RCXY.js} +3 -3
  56. package/dist/{chunk-U6L3FAML.js.map → chunk-M3R6RCXY.js.map} +1 -1
  57. package/dist/{chunk-5YYAYW67.js → chunk-M5ZC3LFJ.js} +3 -3
  58. package/dist/{chunk-5YYAYW67.js.map → chunk-M5ZC3LFJ.js.map} +1 -1
  59. package/dist/{chunk-B6INLQBU.cjs → chunk-MKKFIPKU.cjs} +46 -46
  60. package/dist/{chunk-B6INLQBU.cjs.map → chunk-MKKFIPKU.cjs.map} +1 -1
  61. package/dist/{chunk-M5B2UUNW.js → chunk-NFT6VW73.js} +4 -4
  62. package/dist/{chunk-M5B2UUNW.js.map → chunk-NFT6VW73.js.map} +1 -1
  63. package/dist/{chunk-X7RPFTTR.cjs → chunk-OK5RYX55.cjs} +26 -26
  64. package/dist/{chunk-X7RPFTTR.cjs.map → chunk-OK5RYX55.cjs.map} +1 -1
  65. package/dist/{chunk-NNU4RGT3.js → chunk-RNGYXGHS.js} +39 -27
  66. package/dist/chunk-RNGYXGHS.js.map +1 -0
  67. package/dist/{chunk-SQKLKBBK.cjs → chunk-RODV6PC4.cjs} +25 -6
  68. package/dist/chunk-RODV6PC4.cjs.map +1 -0
  69. package/dist/{chunk-H2OEUBPO.js → chunk-SE23X5OE.js} +441 -62
  70. package/dist/chunk-SE23X5OE.js.map +1 -0
  71. package/dist/{chunk-FCGHV6ZK.js → chunk-SFSZUOFT.js} +4 -4
  72. package/dist/{chunk-FCGHV6ZK.js.map → chunk-SFSZUOFT.js.map} +1 -1
  73. package/dist/{chunk-NZH4GWE6.cjs → chunk-UK7JF5QB.cjs} +37 -37
  74. package/dist/{chunk-NZH4GWE6.cjs.map → chunk-UK7JF5QB.cjs.map} +1 -1
  75. package/dist/{chunk-QSQX77S2.cjs → chunk-W7GIQTJV.cjs} +21 -21
  76. package/dist/{chunk-QSQX77S2.cjs.map → chunk-W7GIQTJV.cjs.map} +1 -1
  77. package/dist/{chunk-KLJEK547.js → chunk-WHJXRLFD.js} +14 -3
  78. package/dist/chunk-WHJXRLFD.js.map +1 -0
  79. package/dist/{chunk-YQANC7HQ.js → chunk-X4F6VVEJ.js} +3 -3
  80. package/dist/{chunk-YQANC7HQ.js.map → chunk-X4F6VVEJ.js.map} +1 -1
  81. package/dist/{chunk-ZNOD4VZT.cjs → chunk-XI6JOG76.cjs} +46 -46
  82. package/dist/{chunk-ZNOD4VZT.cjs.map → chunk-XI6JOG76.cjs.map} +1 -1
  83. package/dist/{chunk-K2SOC3XF.cjs → chunk-XUEROLSB.cjs} +70 -19
  84. package/dist/chunk-XUEROLSB.cjs.map +1 -0
  85. package/dist/{chunk-XTATRNUN.cjs → chunk-YTEEZV6J.cjs} +442 -430
  86. package/dist/chunk-YTEEZV6J.cjs.map +1 -0
  87. package/dist/{chunk-XZNPAD6E.js → chunk-ZNLEUL7T.js} +58 -7
  88. package/dist/chunk-ZNLEUL7T.js.map +1 -0
  89. package/dist/{chunk-DNZFOCV7.js → chunk-ZTSO3S4P.js} +3 -3
  90. package/dist/{chunk-DNZFOCV7.js.map → chunk-ZTSO3S4P.js.map} +1 -1
  91. package/dist/diagrams/blockdiagram/index.cjs +6 -6
  92. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  93. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  94. package/dist/diagrams/blockdiagram/index.js +2 -2
  95. package/dist/diagrams/circuit/index.cjs +8 -8
  96. package/dist/diagrams/circuit/index.d.cts +1 -1
  97. package/dist/diagrams/circuit/index.d.ts +1 -1
  98. package/dist/diagrams/circuit/index.js +2 -2
  99. package/dist/diagrams/ecomap/index.cjs +8 -8
  100. package/dist/diagrams/ecomap/index.d.cts +1 -1
  101. package/dist/diagrams/ecomap/index.d.ts +1 -1
  102. package/dist/diagrams/ecomap/index.js +3 -3
  103. package/dist/diagrams/entity/index.cjs +6 -6
  104. package/dist/diagrams/entity/index.d.cts +1 -1
  105. package/dist/diagrams/entity/index.d.ts +1 -1
  106. package/dist/diagrams/entity/index.js +2 -2
  107. package/dist/diagrams/fishbone/index.cjs +8 -8
  108. package/dist/diagrams/fishbone/index.d.cts +1 -1
  109. package/dist/diagrams/fishbone/index.d.ts +1 -1
  110. package/dist/diagrams/fishbone/index.js +2 -2
  111. package/dist/diagrams/flowchart/index.cjs +8 -8
  112. package/dist/diagrams/flowchart/index.d.cts +2 -2
  113. package/dist/diagrams/flowchart/index.d.ts +2 -2
  114. package/dist/diagrams/flowchart/index.js +2 -2
  115. package/dist/diagrams/genogram/index.cjs +10 -10
  116. package/dist/diagrams/genogram/index.d.cts +1 -1
  117. package/dist/diagrams/genogram/index.d.ts +1 -1
  118. package/dist/diagrams/genogram/index.js +3 -3
  119. package/dist/diagrams/ladder/index.cjs +6 -6
  120. package/dist/diagrams/ladder/index.d.cts +1 -1
  121. package/dist/diagrams/ladder/index.d.ts +1 -1
  122. package/dist/diagrams/ladder/index.js +2 -2
  123. package/dist/diagrams/logic/index.cjs +6 -6
  124. package/dist/diagrams/logic/index.d.cts +1 -1
  125. package/dist/diagrams/logic/index.d.ts +1 -1
  126. package/dist/diagrams/logic/index.js +2 -2
  127. package/dist/diagrams/orgchart/index.cjs +7 -7
  128. package/dist/diagrams/orgchart/index.d.cts +1 -1
  129. package/dist/diagrams/orgchart/index.d.ts +1 -1
  130. package/dist/diagrams/orgchart/index.js +2 -2
  131. package/dist/diagrams/pedigree/index.cjs +8 -8
  132. package/dist/diagrams/pedigree/index.d.cts +1 -1
  133. package/dist/diagrams/pedigree/index.d.ts +1 -1
  134. package/dist/diagrams/pedigree/index.js +3 -3
  135. package/dist/diagrams/phylo/index.cjs +7 -7
  136. package/dist/diagrams/phylo/index.d.cts +1 -1
  137. package/dist/diagrams/phylo/index.d.ts +1 -1
  138. package/dist/diagrams/phylo/index.js +2 -2
  139. package/dist/diagrams/sld/index.cjs +6 -6
  140. package/dist/diagrams/sld/index.d.cts +1 -1
  141. package/dist/diagrams/sld/index.d.ts +1 -1
  142. package/dist/diagrams/sld/index.js +2 -2
  143. package/dist/diagrams/sociogram/index.cjs +7 -7
  144. package/dist/diagrams/sociogram/index.d.cts +1 -1
  145. package/dist/diagrams/sociogram/index.d.ts +1 -1
  146. package/dist/diagrams/sociogram/index.js +3 -3
  147. package/dist/diagrams/timing/index.cjs +5 -5
  148. package/dist/diagrams/timing/index.d.cts +1 -1
  149. package/dist/diagrams/timing/index.d.ts +1 -1
  150. package/dist/diagrams/timing/index.js +2 -2
  151. package/dist/diagrams/venn/index.cjs +9 -9
  152. package/dist/diagrams/venn/index.d.cts +1 -1
  153. package/dist/diagrams/venn/index.d.ts +1 -1
  154. package/dist/diagrams/venn/index.js +2 -2
  155. package/dist/{index-ivhNGsyU.d.cts → index-BrLxEzSQ.d.cts} +1 -1
  156. package/dist/{index-CUwp4GXI.d.ts → index-dWDwG6BW.d.ts} +1 -1
  157. package/dist/index.cjs +41 -41
  158. package/dist/index.d.cts +2 -2
  159. package/dist/index.d.ts +2 -2
  160. package/dist/index.js +19 -19
  161. package/dist/react.cjs +20 -20
  162. package/dist/react.cjs.map +1 -1
  163. package/dist/react.js +19 -19
  164. package/dist/react.js.map +1 -1
  165. package/dist/{types-Bl-Pn7Wj.d.cts → types-BtiUg7Gx.d.cts} +24 -3
  166. package/dist/{types-Bl-Pn7Wj.d.ts → types-BtiUg7Gx.d.ts} +24 -3
  167. package/package.json +1 -1
  168. package/dist/chunk-2JDVJRR3.cjs.map +0 -1
  169. package/dist/chunk-3FKS4KQK.cjs.map +0 -1
  170. package/dist/chunk-45KP67RR.js.map +0 -1
  171. package/dist/chunk-B37IKTI7.cjs.map +0 -1
  172. package/dist/chunk-H2OEUBPO.js.map +0 -1
  173. package/dist/chunk-HDKDQAEQ.cjs.map +0 -1
  174. package/dist/chunk-K2SOC3XF.cjs.map +0 -1
  175. package/dist/chunk-KLJEK547.js.map +0 -1
  176. package/dist/chunk-MCFQAUQV.cjs.map +0 -1
  177. package/dist/chunk-MJGDP3CS.cjs.map +0 -1
  178. package/dist/chunk-NNU4RGT3.js.map +0 -1
  179. package/dist/chunk-OC22GGQN.js.map +0 -1
  180. package/dist/chunk-SQKLKBBK.cjs.map +0 -1
  181. package/dist/chunk-TYCHEOQX.js.map +0 -1
  182. package/dist/chunk-UGCUNADI.js.map +0 -1
  183. package/dist/chunk-VLMK7MQK.js.map +0 -1
  184. package/dist/chunk-XTATRNUN.cjs.map +0 -1
  185. package/dist/chunk-XZNPAD6E.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkULYRO2KY_cjs = require('./chunk-ULYRO2KY.cjs');
3
+ var chunk75BMFCP5_cjs = require('./chunk-75BMFCP5.cjs');
4
4
  var chunkD7EHZFK4_cjs = require('./chunk-D7EHZFK4.cjs');
5
- var chunkHDKDQAEQ_cjs = require('./chunk-HDKDQAEQ.cjs');
5
+ var chunkLFZZ4NCP_cjs = require('./chunk-LFZZ4NCP.cjs');
6
6
 
7
7
  // src/diagrams/genogram/parser.ts
8
8
  var ParseError = class extends Error {
@@ -19,6 +19,9 @@ var ParseError = class extends Error {
19
19
  source;
20
20
  };
21
21
  var COUPLE_OPS = [
22
+ { token: "~/~", type: "cohabiting-ended" },
23
+ { token: "-//", type: "separated" },
24
+ // alias for -/-
22
25
  { token: "-x-", type: "divorced" },
23
26
  { token: "-/-", type: "separated" },
24
27
  { token: "-o-", type: "engaged" },
@@ -39,6 +42,7 @@ var SPECIAL_CHILD_PROPS = /* @__PURE__ */ new Set([
39
42
  "twin-identical",
40
43
  "twin-fraternal"
41
44
  ]);
45
+ var SECONDARY_LINK_PROPS = /* @__PURE__ */ new Set(["foster", "adopted", "guardian"]);
42
46
  var VALID_FILLS = /* @__PURE__ */ new Set([
43
47
  "full",
44
48
  "half-left",
@@ -112,6 +116,8 @@ function parseGenogram(text2) {
112
116
  const relationships = [];
113
117
  const childSpecialProps = /* @__PURE__ */ new Map();
114
118
  const legendOverrides = {};
119
+ const childrenWithPrimary = /* @__PURE__ */ new Set();
120
+ let unknownSibCounter = 0;
115
121
  skipBlankAndComments(state);
116
122
  while (state.currentLine < state.lines.length) {
117
123
  skipBlankAndComments(state);
@@ -122,7 +128,7 @@ function parseGenogram(text2) {
122
128
  state.currentLine++;
123
129
  continue;
124
130
  }
125
- if (chunkULYRO2KY_cjs.parseLegendDirective(trimmed, legendOverrides)) {
131
+ if (chunk75BMFCP5_cjs.parseLegendDirective(trimmed, legendOverrides)) {
126
132
  state.currentLine++;
127
133
  continue;
128
134
  }
@@ -166,8 +172,12 @@ function parseGenogram(text2) {
166
172
  }
167
173
  const rightKey = rightId.toLowerCase();
168
174
  if (rightProps) {
169
- const rightIndividual = buildIndividual(rightId, rightProps, lineNum, lineText);
170
- individualsMap.set(rightKey, rightIndividual);
175
+ const incoming = buildIndividual(rightId, rightProps, lineNum, lineText);
176
+ const existing = individualsMap.get(rightKey);
177
+ individualsMap.set(
178
+ rightKey,
179
+ existing ? mergeIndividual(existing, incoming, lineNum, lineText) : incoming
180
+ );
171
181
  } else if (!individualsMap.has(rightKey)) {
172
182
  throw new ParseError(
173
183
  `Unknown individual '${rightId}'`,
@@ -191,26 +201,47 @@ function parseGenogram(text2) {
191
201
  const childIndent = getIndent(childLine);
192
202
  if (childIndent <= coupleIndent) break;
193
203
  const childLineNum = state.currentLine + 1;
194
- const { id: childId, propsStr } = splitIdAndProps(childTrimmed);
195
- const childKey = childId.toLowerCase();
196
- const individual = buildIndividual(
197
- childId,
198
- propsStr,
204
+ let parsedId;
205
+ let parsedProps;
206
+ if (childTrimmed === "?" || childTrimmed.startsWith("? ")) {
207
+ parsedId = `__unknown_siblings_${++unknownSibCounter}`;
208
+ parsedProps = "unknown, unknown-siblings";
209
+ } else {
210
+ const split = splitIdAndProps(childTrimmed);
211
+ parsedId = split.id;
212
+ parsedProps = split.propsStr;
213
+ }
214
+ const childKey = parsedId.toLowerCase();
215
+ const incoming = buildIndividual(
216
+ parsedId,
217
+ parsedProps,
199
218
  childLineNum,
200
219
  childLine
201
220
  );
202
- if (propsStr) {
203
- for (const sp of SPECIAL_CHILD_PROPS) {
204
- if (propsTokens(propsStr).includes(sp)) {
205
- childSpecialProps.set(childKey, sp);
206
- }
207
- }
221
+ const tokens = parsedProps ? propsTokens(parsedProps) : [];
222
+ for (const sp of SPECIAL_CHILD_PROPS) {
223
+ if (tokens.includes(sp)) childSpecialProps.set(childKey, sp);
208
224
  }
209
- individualsMap.set(childKey, individual);
225
+ const isSecondaryDecl = tokens.some((t) => SECONDARY_LINK_PROPS.has(t));
226
+ const existing = individualsMap.get(childKey);
227
+ individualsMap.set(
228
+ childKey,
229
+ existing ? mergeIndividual(existing, incoming, childLineNum, childLine) : incoming
230
+ );
210
231
  const coupleKey = `${leftKey}+${rightKey}`;
211
- const pcType = childSpecialProps.get(childKey);
212
- const relType = pcType && (pcType === "adopted" || pcType === "foster") ? pcType : "parent-child";
213
- relationships.push({ type: relType, from: coupleKey, to: childKey });
232
+ const lineChildType = tokens.find(
233
+ (t) => SPECIAL_CHILD_PROPS.has(t)
234
+ );
235
+ const relType = lineChildType === "adopted" || lineChildType === "foster" ? lineChildType : "parent-child";
236
+ const isSecondary = isSecondaryDecl && childrenWithPrimary.has(childKey);
237
+ const rel2 = {
238
+ type: relType,
239
+ from: coupleKey,
240
+ to: childKey
241
+ };
242
+ if (isSecondary) rel2.secondary = true;
243
+ relationships.push(rel2);
244
+ if (!isSecondary) childrenWithPrimary.add(childKey);
214
245
  state.currentLine++;
215
246
  }
216
247
  } else {
@@ -220,7 +251,10 @@ function parseGenogram(text2) {
220
251
  const individual = buildIndividual(id, propsStr, lineNum, lineText);
221
252
  const existing = individualsMap.get(key);
222
253
  if (existing) {
223
- individualsMap.set(key, mergeIndividual(existing, individual));
254
+ individualsMap.set(
255
+ key,
256
+ mergeIndividual(existing, individual, lineNum, lineText)
257
+ );
224
258
  } else {
225
259
  individualsMap.set(key, individual);
226
260
  }
@@ -251,6 +285,7 @@ function parseGenogram(text2) {
251
285
  });
252
286
  }
253
287
  }
288
+ normalizePrimaryParentRels(relationships);
254
289
  const hasLegendOverrides = Object.keys(legendOverrides).length > 0 && Object.values(legendOverrides).some((v) => v !== void 0);
255
290
  return {
256
291
  type: "genogram",
@@ -260,6 +295,33 @@ function parseGenogram(text2) {
260
295
  legendOverrides: hasLegendOverrides ? legendOverrides : void 0
261
296
  };
262
297
  }
298
+ function normalizePrimaryParentRels(relationships) {
299
+ const PARENT_CHILD_TYPES = /* @__PURE__ */ new Set([
300
+ "parent-child",
301
+ "adopted",
302
+ "foster"
303
+ ]);
304
+ const byChild = /* @__PURE__ */ new Map();
305
+ for (let i = 0; i < relationships.length; i++) {
306
+ const r = relationships[i];
307
+ if (!PARENT_CHILD_TYPES.has(r.type)) continue;
308
+ const arr = byChild.get(r.to) ?? [];
309
+ arr.push(i);
310
+ byChild.set(r.to, arr);
311
+ }
312
+ for (const indices of byChild.values()) {
313
+ if (indices.length < 2) continue;
314
+ let primaryIdx = indices.find((i) => relationships[i].type === "parent-child");
315
+ if (primaryIdx === void 0) primaryIdx = indices[0];
316
+ for (const i of indices) {
317
+ if (i === primaryIdx) {
318
+ delete relationships[i].secondary;
319
+ } else {
320
+ relationships[i].secondary = true;
321
+ }
322
+ }
323
+ }
324
+ }
263
325
  function currentLineText(state) {
264
326
  return state.lines[state.currentLine];
265
327
  }
@@ -391,7 +453,11 @@ function buildIndividual(id, propsStr, lineNum, lineText) {
391
453
  } else if (tokenLower === "index") {
392
454
  if (!individual.markers) individual.markers = [];
393
455
  individual.markers.push("index-person");
394
- } else if (SPECIAL_CHILD_PROPS.has(tokenLower)) {
456
+ } else if (tokenLower === "unknown-siblings") {
457
+ if (!individual.markers) individual.markers = [];
458
+ individual.markers.push("unknown-siblings");
459
+ if (!individual.label || individual.label === id) individual.label = "?";
460
+ } else if (SPECIAL_CHILD_PROPS.has(tokenLower) || tokenLower === "guardian") {
395
461
  continue;
396
462
  } else if (/^\d{4}$/.test(tokenLower)) {
397
463
  if (individual.birthYear !== void 0) {
@@ -417,13 +483,27 @@ function buildIndividual(id, propsStr, lineNum, lineText) {
417
483
  if (!isNaN(deathNum)) individual.deathYear = deathNum;
418
484
  } else if (key === "label") {
419
485
  individual.label = value.replace(/^"|"$/g, "");
486
+ } else if (key === "sibling-of") {
487
+ individual.siblingOf = value.toLowerCase();
488
+ } else if (key === "shape") {
489
+ const v = value.toLowerCase();
490
+ if (v === "square" || v === "circle" || v === "diamond" || v === "triangle" || v === "triangle-down") {
491
+ individual.shape = v;
492
+ } else {
493
+ throw new ParseError(
494
+ `Invalid shape '${value}'. Valid: square, circle, diamond, triangle, triangle-down`,
495
+ lineNum,
496
+ 1,
497
+ lineText
498
+ );
499
+ }
420
500
  } else {
421
501
  if (!individual.properties) individual.properties = {};
422
502
  individual.properties[key] = value;
423
503
  }
424
504
  } else {
425
505
  throw new ParseError(
426
- `Unknown property '${token}'. Valid: male, female, unknown, deceased, stillborn, miscarriage, abortion, adopted, foster, twin-identical, twin-fraternal, index, a 4-digit year, conditions:..., age:N, death:YYYY, or key:value`,
506
+ `Unknown property '${token}'. Valid: male, female, unknown, deceased, stillborn, miscarriage, abortion, adopted, foster, guardian, twin-identical, twin-fraternal, index, unknown-siblings, a 4-digit year, conditions:..., age:N, death:YYYY, label:"...", sibling-of:ID, or key:value`,
427
507
  lineNum,
428
508
  1,
429
509
  lineText
@@ -463,20 +543,81 @@ function parseConditions(raw, lineNum, lineText) {
463
543
  }
464
544
  return conditions;
465
545
  }
466
- function mergeIndividual(existing, incoming) {
546
+ function mergeIndividual(existing, incoming, lineNum, lineText) {
547
+ let mergedSex = existing.sex;
548
+ if (incoming.sex !== "unknown") {
549
+ if (existing.sex !== "unknown" && existing.sex !== incoming.sex) {
550
+ throw new ParseError(
551
+ `Conflicting sex for '${existing.id}': previously '${existing.sex}', now '${incoming.sex}'`,
552
+ lineNum,
553
+ 1,
554
+ lineText
555
+ );
556
+ }
557
+ mergedSex = incoming.sex;
558
+ }
559
+ let mergedStatus = existing.status;
560
+ if (incoming.status !== "alive") {
561
+ if (existing.status !== "alive" && existing.status !== incoming.status) {
562
+ throw new ParseError(
563
+ `Conflicting status for '${existing.id}': previously '${existing.status}', now '${incoming.status}'`,
564
+ lineNum,
565
+ 1,
566
+ lineText
567
+ );
568
+ }
569
+ mergedStatus = incoming.status;
570
+ }
571
+ if (incoming.birthYear !== void 0 && existing.birthYear !== void 0 && incoming.birthYear !== existing.birthYear) {
572
+ throw new ParseError(
573
+ `Conflicting birth year for '${existing.id}': previously ${existing.birthYear}, now ${incoming.birthYear}`,
574
+ lineNum,
575
+ 1,
576
+ lineText
577
+ );
578
+ }
579
+ if (incoming.deathYear !== void 0 && existing.deathYear !== void 0 && incoming.deathYear !== existing.deathYear) {
580
+ throw new ParseError(
581
+ `Conflicting death year for '${existing.id}': previously ${existing.deathYear}, now ${incoming.deathYear}`,
582
+ lineNum,
583
+ 1,
584
+ lineText
585
+ );
586
+ }
587
+ const incomingHasExplicitLabel = incoming.label !== incoming.id && incoming.label !== "";
588
+ const existingHasExplicitLabel = existing.label !== existing.id && existing.label !== "";
589
+ const mergedLabel = incomingHasExplicitLabel ? incoming.label : existingHasExplicitLabel ? existing.label : existing.label;
590
+ const mergedMarkers = mergeArrayUnique(existing.markers, incoming.markers);
467
591
  return {
468
592
  ...existing,
469
- sex: incoming.sex !== "unknown" ? incoming.sex : existing.sex,
470
- status: incoming.status !== "alive" ? incoming.status : existing.status,
593
+ sex: mergedSex,
594
+ status: mergedStatus,
595
+ label: mergedLabel,
471
596
  birthYear: incoming.birthYear ?? existing.birthYear,
472
597
  deathYear: incoming.deathYear ?? existing.deathYear,
598
+ age: incoming.age ?? existing.age,
473
599
  conditions: incoming.conditions ?? existing.conditions,
600
+ heritage: incoming.heritage ?? existing.heritage,
601
+ siblingOf: incoming.siblingOf ?? existing.siblingOf,
602
+ markers: mergedMarkers,
474
603
  properties: {
475
604
  ...existing.properties,
476
605
  ...incoming.properties
477
606
  }
478
607
  };
479
608
  }
609
+ function mergeArrayUnique(a, b) {
610
+ if (!a && !b) return void 0;
611
+ const seen = /* @__PURE__ */ new Set();
612
+ const out = [];
613
+ for (const v of [...a ?? [], ...b ?? []]) {
614
+ if (!seen.has(v)) {
615
+ seen.add(v);
616
+ out.push(v);
617
+ }
618
+ }
619
+ return out.length ? out : void 0;
620
+ }
480
621
 
481
622
  // src/diagrams/genogram/layout.ts
482
623
  function layoutGenogram(ast, config) {
@@ -485,8 +626,19 @@ function layoutGenogram(ast, config) {
485
626
  const ordered = orderNodesInGenerations(graph);
486
627
  const positions = assignPositions(ordered, graph, config);
487
628
  const edges = computeEdges(graph, positions, config);
629
+ const secondaryEdges = computeSecondaryParentEdges(
630
+ ast.relationships,
631
+ graph,
632
+ positions,
633
+ config
634
+ );
488
635
  const emotionalEdges = computeEmotionalEdges(ast.relationships, positions, config);
489
- return packageResult(positions, [...edges, ...emotionalEdges], graph, config);
636
+ return packageResult(
637
+ positions,
638
+ [...edges, ...secondaryEdges, ...emotionalEdges],
639
+ graph,
640
+ config
641
+ );
490
642
  }
491
643
  function buildGraph(ast) {
492
644
  const individuals = /* @__PURE__ */ new Map();
@@ -496,7 +648,7 @@ function buildGraph(ast) {
496
648
  const familyUnits = [];
497
649
  const childOf = /* @__PURE__ */ new Map();
498
650
  const coupleRels = ast.relationships.filter(
499
- (r) => r.type === "married" || r.type === "divorced" || r.type === "separated" || r.type === "engaged" || r.type === "cohabiting" || r.type === "consanguineous"
651
+ (r) => r.type === "married" || r.type === "divorced" || r.type === "separated" || r.type === "engaged" || r.type === "cohabiting" || r.type === "cohabiting-ended" || r.type === "consanguineous"
500
652
  );
501
653
  for (const rel of coupleRels) {
502
654
  const fuId = `${rel.from}+${rel.to}`;
@@ -518,7 +670,7 @@ function buildGraph(ast) {
518
670
  }
519
671
  const children = [];
520
672
  for (const r of ast.relationships) {
521
- if ((r.type === "parent-child" || r.type === "adopted" || r.type === "foster") && r.from === fuId) {
673
+ if ((r.type === "parent-child" || r.type === "adopted" || r.type === "foster") && r.from === fuId && !r.secondary) {
522
674
  children.push(r.to);
523
675
  childOf.set(r.to, fuId);
524
676
  }
@@ -541,7 +693,12 @@ function buildGraph(ast) {
541
693
  function assignGenerations(graph) {
542
694
  const { individuals, familyUnits, childOf, generations } = graph;
543
695
  const allIds = Array.from(individuals.keys());
544
- const roots = allIds.filter((id) => !childOf.has(id));
696
+ const roots = allIds.filter((id) => {
697
+ if (childOf.has(id)) return false;
698
+ const ind = individuals.get(id);
699
+ if (ind?.siblingOf) return false;
700
+ return true;
701
+ });
545
702
  if (roots.length === 0 && allIds.length > 0) {
546
703
  for (const id of allIds) generations.set(id, 0);
547
704
  return;
@@ -589,6 +746,21 @@ function assignGenerations(graph) {
589
746
  }
590
747
  }
591
748
  }
749
+ let siblingChanged = true;
750
+ let safety = 0;
751
+ while (siblingChanged && safety++ < allIds.length + 1) {
752
+ siblingChanged = false;
753
+ for (const id of allIds) {
754
+ if (generations.has(id)) continue;
755
+ const ind = individuals.get(id);
756
+ if (!ind?.siblingOf) continue;
757
+ const refGen = generations.get(ind.siblingOf);
758
+ if (refGen !== void 0) {
759
+ generations.set(id, refGen);
760
+ siblingChanged = true;
761
+ }
762
+ }
763
+ }
592
764
  for (const id of allIds) {
593
765
  if (!generations.has(id)) {
594
766
  generations.set(id, 0);
@@ -664,15 +836,33 @@ function orderGeneration(nodeIds, _genIdx, graph, familyUnits) {
664
836
  }
665
837
  }
666
838
  const remaining = nodeIds.filter((id) => !placed.has(id));
667
- remaining.sort((a, b) => {
839
+ const siblingOfRemaining = remaining.filter((id) => {
840
+ const ind = graph.individuals.get(id);
841
+ return ind?.siblingOf && placed.has(ind.siblingOf);
842
+ });
843
+ const otherRemaining = remaining.filter(
844
+ (id) => !siblingOfRemaining.includes(id)
845
+ );
846
+ otherRemaining.sort((a, b) => {
668
847
  const indA = graph.individuals.get(a);
669
848
  const indB = graph.individuals.get(b);
670
849
  return (indA?.birthYear ?? 9999) - (indB?.birthYear ?? 9999);
671
850
  });
672
- for (const id of remaining) {
851
+ for (const id of otherRemaining) {
673
852
  ordered.push(id);
674
853
  placed.add(id);
675
854
  }
855
+ for (const id of siblingOfRemaining) {
856
+ const ind = graph.individuals.get(id);
857
+ if (!ind?.siblingOf) continue;
858
+ const refIdx = ordered.indexOf(ind.siblingOf);
859
+ if (refIdx === -1) {
860
+ ordered.push(id);
861
+ } else {
862
+ ordered.splice(refIdx + 1, 0, id);
863
+ }
864
+ placed.add(id);
865
+ }
676
866
  return ordered;
677
867
  }
678
868
  var LABEL_HEIGHT = 20;
@@ -700,9 +890,10 @@ function assignPositions(orderedGens, graph, config) {
700
890
  }
701
891
  }
702
892
  }
703
- resolveOverlaps(positions, orderedGens, config);
893
+ resolveOverlaps(positions, orderedGens, config, graph);
704
894
  centerChildrenUnderParents(positions, graph, config);
705
- resolveOverlaps(positions, orderedGens, config);
895
+ unscrambleSibships(positions, graph, config);
896
+ resolveOverlaps(positions, orderedGens, config, graph);
706
897
  return positions;
707
898
  }
708
899
  function buildSegments(nodeIds, _genIdx, graph) {
@@ -850,15 +1041,81 @@ function centerChildrenUnderParents(positions, graph, config) {
850
1041
  }
851
1042
  }
852
1043
  }
853
- function resolveOverlaps(positions, orderedGens, config) {
1044
+ function unscrambleSibships(positions, graph, config) {
1045
+ const familyGap = config.nodeWidth + config.nodeSpacingX * 1.5;
1046
+ const childSpacing = config.nodeWidth + config.nodeSpacingX;
1047
+ const byGen = /* @__PURE__ */ new Map();
1048
+ for (const [id, pos] of positions) {
1049
+ const arr = byGen.get(pos.generation) ?? [];
1050
+ arr.push(id);
1051
+ byGen.set(pos.generation, arr);
1052
+ }
1053
+ for (const [, ids] of byGen) {
1054
+ const sibshipMap = /* @__PURE__ */ new Map();
1055
+ for (const id of ids) {
1056
+ const fu = graph.childOf.get(id);
1057
+ if (!fu) continue;
1058
+ const arr = sibshipMap.get(fu) ?? [];
1059
+ arr.push(id);
1060
+ sibshipMap.set(fu, arr);
1061
+ }
1062
+ if (sibshipMap.size <= 1) continue;
1063
+ const sibships = [...sibshipMap.entries()].map(([fuId, children]) => {
1064
+ const fu = graph.familyUnits.find((f) => f.id === fuId);
1065
+ if (!fu) return null;
1066
+ const pa = positions.get(fu.partners[0]);
1067
+ const pb = positions.get(fu.partners[1]);
1068
+ if (!pa || !pb) return null;
1069
+ return { fuId, children, midX: (pa.x + pb.x) / 2 };
1070
+ }).filter((x) => x !== null).sort((a, b) => a.midX - b.midX);
1071
+ let cursor = null;
1072
+ for (const ss of sibships) {
1073
+ const sortedKids = [...ss.children].sort((a, b) => {
1074
+ const ya = graph.individuals.get(a)?.birthYear ?? 9999;
1075
+ const yb = graph.individuals.get(b)?.birthYear ?? 9999;
1076
+ return ya - yb;
1077
+ });
1078
+ const totalWidth = Math.max(0, (sortedKids.length - 1) * childSpacing);
1079
+ let startX = ss.midX - totalWidth / 2;
1080
+ if (cursor !== null && startX < cursor) startX = cursor;
1081
+ for (let i = 0; i < sortedKids.length; i++) {
1082
+ const pos = positions.get(sortedKids[i]);
1083
+ if (pos) pos.x = startX + i * childSpacing;
1084
+ }
1085
+ cursor = startX + totalWidth + familyGap;
1086
+ }
1087
+ }
1088
+ }
1089
+ function resolveOverlaps(positions, orderedGens, config, graph) {
854
1090
  const minGap = config.nodeWidth + config.nodeSpacingX;
1091
+ const familyGap = config.nodeWidth + config.nodeSpacingX * 1.5;
1092
+ const cluster = /* @__PURE__ */ new Map();
1093
+ if (graph) {
1094
+ for (const [id] of positions) {
1095
+ const fu = graph.childOf.get(id);
1096
+ if (fu) cluster.set(id, fu);
1097
+ }
1098
+ for (const fu of graph.familyUnits) {
1099
+ for (const p of fu.partners) {
1100
+ if (cluster.has(p)) continue;
1101
+ const other = fu.partners[0] === p ? fu.partners[1] : fu.partners[0];
1102
+ const otherCluster = cluster.get(other);
1103
+ if (otherCluster) cluster.set(p, otherCluster);
1104
+ }
1105
+ }
1106
+ }
855
1107
  for (const gen of orderedGens) {
856
1108
  const genNodes = gen.nodeIds.map((id) => positions.get(id)).filter((p) => p !== void 0);
857
1109
  genNodes.sort((a, b) => a.x - b.x);
858
1110
  for (let i = 1; i < genNodes.length; i++) {
859
- const gap = genNodes[i].x - genNodes[i - 1].x;
860
- if (gap < minGap) {
861
- const shift = minGap - gap;
1111
+ const prev = genNodes[i - 1];
1112
+ const cur = genNodes[i];
1113
+ const cPrev = cluster.get(prev.id);
1114
+ const cCur = cluster.get(cur.id);
1115
+ const required = cPrev && cCur && cPrev !== cCur ? familyGap : minGap;
1116
+ const gap = cur.x - prev.x;
1117
+ if (gap < required) {
1118
+ const shift = required - gap;
862
1119
  for (let j = i; j < genNodes.length; j++) {
863
1120
  genNodes[j].x += shift;
864
1121
  }
@@ -1091,6 +1348,34 @@ function computeEmotionalEdges(relationships, positions, config) {
1091
1348
  }
1092
1349
  return edges;
1093
1350
  }
1351
+ function computeSecondaryParentEdges(relationships, graph, positions, config) {
1352
+ const edges = [];
1353
+ const half = config.nodeHeight / 2;
1354
+ for (const rel of relationships) {
1355
+ if (!rel.secondary) continue;
1356
+ if (rel.type !== "parent-child" && rel.type !== "foster" && rel.type !== "adopted")
1357
+ continue;
1358
+ const fu = graph.familyUnits.find((f) => f.id === rel.from);
1359
+ if (!fu) continue;
1360
+ const posA = positions.get(fu.partners[0]);
1361
+ const posB = positions.get(fu.partners[1]);
1362
+ const childPos = positions.get(rel.to);
1363
+ if (!posA || !posB || !childPos) continue;
1364
+ const coupleMidX = (posA.x + posB.x) / 2;
1365
+ const coupleY = posA.y;
1366
+ const startX = coupleMidX;
1367
+ const startY = coupleY + half + 4;
1368
+ const childTopY = childPos.y - half - 4;
1369
+ const path2 = childPos.y === coupleY ? `M ${startX} ${startY} L ${startX} ${startY + 16} L ${childPos.x} ${startY + 16} L ${childPos.x} ${childPos.y - half - 4}` : `M ${startX} ${startY} L ${startX} ${(startY + childTopY) / 2} L ${childPos.x} ${(startY + childTopY) / 2} L ${childPos.x} ${childTopY}`;
1370
+ edges.push({
1371
+ from: rel.from,
1372
+ to: rel.to,
1373
+ relationship: rel,
1374
+ path: path2
1375
+ });
1376
+ }
1377
+ return edges;
1378
+ }
1094
1379
  function shiftPath(pathData, dx, dy) {
1095
1380
  return pathData.replace(
1096
1381
  /([\d.-]+)\s+([\d.-]+)/g,
@@ -1111,13 +1396,13 @@ function renderIndividualSymbol(individual, x, y, size) {
1111
1396
  ];
1112
1397
  if (individual.status === "deceased") classes.push("schematex-genogram-deceased");
1113
1398
  const titleText = formatTitle(individual);
1114
- const children = [chunkHDKDQAEQ_cjs.title(titleText)];
1399
+ const children = [chunkLFZZ4NCP_cjs.title(titleText)];
1115
1400
  const isIndex = individual.markers?.includes("index-person");
1116
1401
  if (isIndex) {
1117
1402
  children.push(indexBorder(individual.sex, half));
1118
1403
  classes.push("schematex-genogram-index-person");
1119
1404
  }
1120
- children.push(baseShape(individual.sex, half));
1405
+ children.push(baseShape(individual.sex, half, individual.shape));
1121
1406
  if (individual.conditions?.length) {
1122
1407
  for (const cond of individual.conditions) {
1123
1408
  children.push(conditionFillElement(individual.sex, half, cond));
@@ -1129,7 +1414,7 @@ function renderIndividualSymbol(individual, x, y, size) {
1129
1414
  const ageToShow = individual.age ?? calcAge(individual);
1130
1415
  if (ageToShow !== void 0) {
1131
1416
  children.push(
1132
- chunkHDKDQAEQ_cjs.text(
1417
+ chunkLFZZ4NCP_cjs.text(
1133
1418
  {
1134
1419
  x: 0,
1135
1420
  y: 5,
@@ -1141,7 +1426,24 @@ function renderIndividualSymbol(individual, x, y, size) {
1141
1426
  )
1142
1427
  );
1143
1428
  }
1144
- return chunkHDKDQAEQ_cjs.group(
1429
+ const isUnknownSiblings = individual.markers?.includes("unknown-siblings");
1430
+ if (isUnknownSiblings) {
1431
+ classes.push("schematex-genogram-unknown-siblings");
1432
+ children.push(
1433
+ chunkLFZZ4NCP_cjs.text(
1434
+ {
1435
+ x: 0,
1436
+ y: 5,
1437
+ class: "schematex-genogram-unknown-siblings-mark",
1438
+ "text-anchor": "middle",
1439
+ "font-size": "16",
1440
+ "font-weight": "bold"
1441
+ },
1442
+ "?"
1443
+ )
1444
+ );
1445
+ }
1446
+ return chunkLFZZ4NCP_cjs.group(
1145
1447
  {
1146
1448
  class: classes.join(" "),
1147
1449
  "data-individual-id": individual.id,
@@ -1161,14 +1463,14 @@ function getRequiredDefs(individuals, includeArrowMarker = false) {
1161
1463
  }
1162
1464
  const children = [];
1163
1465
  function quadClips(suffix, x, y, w, h) {
1164
- const r = chunkHDKDQAEQ_cjs.rect({ x, y, width: w, height: h });
1466
+ const r = chunkLFZZ4NCP_cjs.rect({ x, y, width: w, height: h });
1165
1467
  children.push(
1166
- chunkHDKDQAEQ_cjs.el(
1468
+ chunkLFZZ4NCP_cjs.el(
1167
1469
  "clipPath",
1168
1470
  { id: `schematex-genogram-clip-${suffix}-rect`, clipPathUnits: "objectBoundingBox" },
1169
1471
  [r]
1170
1472
  ),
1171
- chunkHDKDQAEQ_cjs.el(
1473
+ chunkLFZZ4NCP_cjs.el(
1172
1474
  "clipPath",
1173
1475
  { id: `schematex-genogram-clip-${suffix}-circle`, clipPathUnits: "objectBoundingBox" },
1174
1476
  [r]
@@ -1186,7 +1488,7 @@ function getRequiredDefs(individuals, includeArrowMarker = false) {
1186
1488
  if (neededFills.has("quad-br")) quadClips("quad-br", 0.5, 0.5, 0.5, 0.5);
1187
1489
  if (neededFills.has("striped")) {
1188
1490
  children.push(
1189
- chunkHDKDQAEQ_cjs.pattern(
1491
+ chunkLFZZ4NCP_cjs.pattern(
1190
1492
  {
1191
1493
  id: "schematex-genogram-pattern-striped",
1192
1494
  patternUnits: "userSpaceOnUse",
@@ -1194,7 +1496,7 @@ function getRequiredDefs(individuals, includeArrowMarker = false) {
1194
1496
  height: "4"
1195
1497
  },
1196
1498
  [
1197
- chunkHDKDQAEQ_cjs.path({
1499
+ chunkLFZZ4NCP_cjs.path({
1198
1500
  d: "M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2",
1199
1501
  stroke: "#333",
1200
1502
  "stroke-width": "1"
@@ -1205,7 +1507,7 @@ function getRequiredDefs(individuals, includeArrowMarker = false) {
1205
1507
  }
1206
1508
  if (neededFills.has("dotted")) {
1207
1509
  children.push(
1208
- chunkHDKDQAEQ_cjs.pattern(
1510
+ chunkLFZZ4NCP_cjs.pattern(
1209
1511
  {
1210
1512
  id: "schematex-genogram-pattern-dotted",
1211
1513
  patternUnits: "userSpaceOnUse",
@@ -1213,14 +1515,14 @@ function getRequiredDefs(individuals, includeArrowMarker = false) {
1213
1515
  height: "6"
1214
1516
  },
1215
1517
  [
1216
- chunkHDKDQAEQ_cjs.circle({ cx: "3", cy: "3", r: "1", fill: "#333" })
1518
+ chunkLFZZ4NCP_cjs.circle({ cx: "3", cy: "3", r: "1", fill: "#333" })
1217
1519
  ]
1218
1520
  )
1219
1521
  );
1220
1522
  }
1221
1523
  if (includeArrowMarker) {
1222
1524
  children.push(
1223
- chunkHDKDQAEQ_cjs.el("marker", {
1525
+ chunkLFZZ4NCP_cjs.el("marker", {
1224
1526
  id: "schematex-genogram-arrow",
1225
1527
  viewBox: "0 0 10 10",
1226
1528
  refX: "10",
@@ -1229,11 +1531,11 @@ function getRequiredDefs(individuals, includeArrowMarker = false) {
1229
1531
  markerHeight: "6",
1230
1532
  orient: "auto"
1231
1533
  }, [
1232
- chunkHDKDQAEQ_cjs.path({ d: "M 0 0 L 10 5 L 0 10 z", fill: "#333" })
1534
+ chunkLFZZ4NCP_cjs.path({ d: "M 0 0 L 10 5 L 0 10 z", fill: "#333" })
1233
1535
  ])
1234
1536
  );
1235
1537
  }
1236
- return chunkHDKDQAEQ_cjs.defs(children);
1538
+ return chunkLFZZ4NCP_cjs.defs(children);
1237
1539
  }
1238
1540
  function capitalize(s) {
1239
1541
  return s.charAt(0).toUpperCase() + s.slice(1);
@@ -1258,7 +1560,7 @@ function indexBorder(sex, half) {
1258
1560
  const outer = half + 4;
1259
1561
  switch (sex) {
1260
1562
  case "male":
1261
- return chunkHDKDQAEQ_cjs.rect({
1563
+ return chunkLFZZ4NCP_cjs.rect({
1262
1564
  x: -outer,
1263
1565
  y: -outer,
1264
1566
  width: outer * 2,
@@ -1266,7 +1568,7 @@ function indexBorder(sex, half) {
1266
1568
  class: "schematex-genogram-index-border"
1267
1569
  });
1268
1570
  case "female":
1269
- return chunkHDKDQAEQ_cjs.circle({
1571
+ return chunkLFZZ4NCP_cjs.circle({
1270
1572
  cx: 0,
1271
1573
  cy: 0,
1272
1574
  r: outer,
@@ -1276,43 +1578,42 @@ function indexBorder(sex, half) {
1276
1578
  case "other":
1277
1579
  case "nonbinary":
1278
1580
  case "intersex":
1279
- return chunkHDKDQAEQ_cjs.polygon({
1581
+ return chunkLFZZ4NCP_cjs.polygon({
1280
1582
  points: `0,${-outer} ${outer},0 0,${outer} ${-outer},0`,
1281
1583
  class: "schematex-genogram-index-border"
1282
1584
  });
1283
1585
  }
1284
1586
  }
1285
- function baseShape(sex, half) {
1587
+ function baseShape(sex, half, shape) {
1588
+ const cls = "schematex-genogram-shape";
1589
+ switch (shape) {
1590
+ case "square":
1591
+ return chunkLFZZ4NCP_cjs.rect({ x: -half, y: -half, width: half * 2, height: half * 2, class: cls });
1592
+ case "circle":
1593
+ return chunkLFZZ4NCP_cjs.circle({ cx: 0, cy: 0, r: half, class: cls });
1594
+ case "diamond":
1595
+ return chunkLFZZ4NCP_cjs.polygon({ points: `0,${-half} ${half},0 0,${half} ${-half},0`, class: cls });
1596
+ case "triangle":
1597
+ return chunkLFZZ4NCP_cjs.polygon({ points: `0,${-half} ${half},${half} ${-half},${half}`, class: cls });
1598
+ case "triangle-down":
1599
+ return chunkLFZZ4NCP_cjs.polygon({ points: `${-half},${-half} ${half},${-half} 0,${half}`, class: cls });
1600
+ }
1286
1601
  switch (sex) {
1287
1602
  case "male":
1288
- return chunkHDKDQAEQ_cjs.rect({
1289
- x: -half,
1290
- y: -half,
1291
- width: half * 2,
1292
- height: half * 2,
1293
- class: "schematex-genogram-shape"
1294
- });
1603
+ return chunkLFZZ4NCP_cjs.rect({ x: -half, y: -half, width: half * 2, height: half * 2, class: cls });
1295
1604
  case "female":
1296
- return chunkHDKDQAEQ_cjs.circle({
1297
- cx: 0,
1298
- cy: 0,
1299
- r: half,
1300
- class: "schematex-genogram-shape"
1301
- });
1605
+ return chunkLFZZ4NCP_cjs.circle({ cx: 0, cy: 0, r: half, class: cls });
1302
1606
  case "unknown":
1303
1607
  case "other":
1304
1608
  case "nonbinary":
1305
1609
  case "intersex":
1306
- return chunkHDKDQAEQ_cjs.polygon({
1307
- points: `0,${-half} ${half},0 0,${half} ${-half},0`,
1308
- class: "schematex-genogram-shape"
1309
- });
1610
+ return chunkLFZZ4NCP_cjs.polygon({ points: `0,${-half} ${half},0 0,${half} ${-half},0`, class: cls });
1310
1611
  }
1311
1612
  }
1312
1613
  function deceasedOverlay(sex, half) {
1313
1614
  const extend = sex === "female" ? half * 0.707 : half;
1314
1615
  return [
1315
- chunkHDKDQAEQ_cjs.line({
1616
+ chunkLFZZ4NCP_cjs.line({
1316
1617
  x1: -extend,
1317
1618
  y1: -extend,
1318
1619
  x2: extend,
@@ -1321,7 +1622,7 @@ function deceasedOverlay(sex, half) {
1321
1622
  stroke: "#333",
1322
1623
  "stroke-width": "2"
1323
1624
  }),
1324
- chunkHDKDQAEQ_cjs.line({
1625
+ chunkLFZZ4NCP_cjs.line({
1325
1626
  x1: extend,
1326
1627
  y1: -extend,
1327
1628
  x2: -extend,
@@ -1349,15 +1650,15 @@ function conditionFillElement(sex, half, cond) {
1349
1650
  attrs.class = `schematex-genogram-condition-fill schematex-genogram-condition-${cond.label}`;
1350
1651
  switch (sex) {
1351
1652
  case "male":
1352
- return chunkHDKDQAEQ_cjs.rect({ x: -half, y: -half, width: half * 2, height: half * 2, ...attrs });
1653
+ return chunkLFZZ4NCP_cjs.rect({ x: -half, y: -half, width: half * 2, height: half * 2, ...attrs });
1353
1654
  case "female":
1354
- return chunkHDKDQAEQ_cjs.circle({ cx: 0, cy: 0, r: half, ...attrs });
1655
+ return chunkLFZZ4NCP_cjs.circle({ cx: 0, cy: 0, r: half, ...attrs });
1355
1656
  case "unknown":
1356
1657
  case "other":
1357
1658
  case "nonbinary":
1358
1659
  case "intersex":
1359
1660
  default:
1360
- return chunkHDKDQAEQ_cjs.polygon({
1661
+ return chunkLFZZ4NCP_cjs.polygon({
1361
1662
  points: `0,${-half} ${half},0 0,${half} ${-half},0`,
1362
1663
  ...attrs
1363
1664
  });
@@ -1403,6 +1704,7 @@ var STRUCTURAL_TYPES = /* @__PURE__ */ new Set([
1403
1704
  "separated",
1404
1705
  "engaged",
1405
1706
  "cohabiting",
1707
+ "cohabiting-ended",
1406
1708
  "domestic-partnership",
1407
1709
  "consanguineous",
1408
1710
  "parent-child",
@@ -1595,6 +1897,7 @@ function buildStructuralItems(rels, theme) {
1595
1897
  "separated",
1596
1898
  "engaged",
1597
1899
  "cohabiting",
1900
+ "cohabiting-ended",
1598
1901
  "domestic-partnership",
1599
1902
  "consanguineous",
1600
1903
  "adopted",
@@ -1624,6 +1927,14 @@ function structuralItem(t, theme) {
1624
1927
  return { ...base, kind: "edge", marker: "X", pattern: "solid" };
1625
1928
  case "separated":
1626
1929
  return { ...base, kind: "edge", marker: "slash", pattern: "solid" };
1930
+ case "cohabiting-ended":
1931
+ return {
1932
+ ...base,
1933
+ label: "Cohabiting (ended)",
1934
+ kind: "edge",
1935
+ marker: "slash",
1936
+ pattern: "dashed"
1937
+ };
1627
1938
  case "engaged":
1628
1939
  case "cohabiting":
1629
1940
  case "adopted":
@@ -1786,7 +2097,8 @@ function buildMarkerItems(individuals, theme) {
1786
2097
  "index-person",
1787
2098
  "transgender",
1788
2099
  "no-children",
1789
- "infertile"
2100
+ "infertile",
2101
+ "unknown-siblings"
1790
2102
  ];
1791
2103
  const items = [];
1792
2104
  for (const m of order) {
@@ -1819,6 +2131,16 @@ function markerItem(m, theme) {
1819
2131
  return { key: `marker.${m}`, label: "No children (by choice)", kind: "marker", marker: "slash", section: "markers" };
1820
2132
  case "infertile":
1821
2133
  return { key: `marker.${m}`, label: "Infertile", kind: "marker", marker: "X", section: "markers" };
2134
+ case "unknown-siblings":
2135
+ return {
2136
+ key: `marker.${m}`,
2137
+ label: "Sibling(s) \u2014 unknown count",
2138
+ kind: "shape",
2139
+ shape: "diamond",
2140
+ fill: "#ffffff",
2141
+ color: theme?.stroke,
2142
+ section: "markers"
2143
+ };
1822
2144
  default:
1823
2145
  return { key: `marker.${m}`, label: humanize(m), kind: "marker", marker: "dot", section: "markers" };
1824
2146
  }
@@ -1839,15 +2161,19 @@ function renderGenogram(layout, config, ast) {
1839
2161
  const emotionalLayer = renderEmotionalEdges(emotionalEdges);
1840
2162
  const nodeLayers = renderNodes(genGroups);
1841
2163
  const labelLayer = renderLabels(layout.nodes, config);
1842
- const edgeLabelLayer = renderEdgeLabels(structuralEdges, config);
2164
+ const labelEdges = structuralEdges.filter(
2165
+ (e) => !e.relationship.secondary
2166
+ );
2167
+ const edgeLabelLayer = renderEdgeLabels(labelEdges, config);
2168
+ const siblingOfLayer = renderSiblingOfBrackets(layout, ast);
1843
2169
  const nodeCount = layout.nodes.length;
1844
2170
  const genCount = genGroups.size;
1845
2171
  const chartTitle = ast?.metadata?.title;
1846
2172
  const titleHeight = chartTitle ? 40 : 0;
1847
2173
  const totalHeight = layout.height + titleHeight;
1848
2174
  const layers = [
1849
- chunkHDKDQAEQ_cjs.title(chartTitle ? `Genogram: ${chartTitle}` : "Genogram"),
1850
- chunkHDKDQAEQ_cjs.desc(
2175
+ chunkLFZZ4NCP_cjs.title(chartTitle ? `Genogram: ${chartTitle}` : "Genogram"),
2176
+ chunkLFZZ4NCP_cjs.desc(
1851
2177
  `Genogram diagram with ${nodeCount} individuals across ${genCount} generations`
1852
2178
  ),
1853
2179
  defsStr,
@@ -1856,7 +2182,7 @@ function renderGenogram(layout, config, ast) {
1856
2182
  const chartContent = [];
1857
2183
  if (chartTitle) {
1858
2184
  chartContent.push(
1859
- chunkHDKDQAEQ_cjs.text(
2185
+ chunkLFZZ4NCP_cjs.text(
1860
2186
  {
1861
2187
  x: layout.width / 2,
1862
2188
  y: 28,
@@ -1871,9 +2197,9 @@ function renderGenogram(layout, config, ast) {
1871
2197
  );
1872
2198
  }
1873
2199
  chartContent.push(
1874
- chunkHDKDQAEQ_cjs.group(
2200
+ chunkLFZZ4NCP_cjs.group(
1875
2201
  { transform: titleHeight > 0 ? `translate(0, ${titleHeight})` : void 0 },
1876
- [edgeLayers, emotionalLayer, ...nodeLayers, labelLayer, edgeLabelLayer]
2202
+ [edgeLayers, siblingOfLayer, emotionalLayer, ...nodeLayers, labelLayer, edgeLabelLayer]
1877
2203
  )
1878
2204
  );
1879
2205
  let finalWidth = layout.width;
@@ -1882,9 +2208,9 @@ function renderGenogram(layout, config, ast) {
1882
2208
  if (ast) {
1883
2209
  const themeBase = chunkD7EHZFK4_cjs.resolveGenogramTheme(config.theme);
1884
2210
  const autoSpec = buildGenogramLegend(ast, themeBase);
1885
- const finalSpec = chunkULYRO2KY_cjs.applyLegendOverrides(autoSpec, ast.legendOverrides);
2211
+ const finalSpec = chunk75BMFCP5_cjs.applyLegendOverrides(autoSpec, ast.legendOverrides);
1886
2212
  if (finalSpec.mode === "on" && finalSpec.items.length > 0) {
1887
- const { svg, bbox: lb } = chunkULYRO2KY_cjs.renderLegend(
2213
+ const { svg, bbox: lb } = chunk75BMFCP5_cjs.renderLegend(
1888
2214
  finalSpec,
1889
2215
  {
1890
2216
  canvasWidth: layout.width,
@@ -1906,13 +2232,13 @@ function renderGenogram(layout, config, ast) {
1906
2232
  }
1907
2233
  const chartXOffset = Math.max(0, (finalWidth - layout.width) / 2);
1908
2234
  layers.push(
1909
- chunkHDKDQAEQ_cjs.group(
2235
+ chunkLFZZ4NCP_cjs.group(
1910
2236
  { transform: chartXOffset > 0 ? `translate(${chartXOffset}, 0)` : void 0 },
1911
2237
  chartContent
1912
2238
  )
1913
2239
  );
1914
2240
  if (legendSvg) layers.push(legendSvg);
1915
- return chunkHDKDQAEQ_cjs.svgRoot(
2241
+ return chunkLFZZ4NCP_cjs.svgRoot(
1916
2242
  {
1917
2243
  viewBox: `0 0 ${finalWidth} ${finalHeight}`,
1918
2244
  class: "schematex-diagram schematex-genogram",
@@ -1935,8 +2261,15 @@ function buildStyles(config) {
1935
2261
  .schematex-genogram-label { font-family: ${config.fontFamily}; font-size: ${config.fontSize}px; text-anchor: middle; fill: ${t.text}; }
1936
2262
  .schematex-genogram-edge { stroke: ${t.neutral}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; fill: none; stroke-linecap: round; stroke-linejoin: round; }
1937
2263
  .schematex-genogram-edge-cohabiting path { stroke-dasharray: 6,4; }
2264
+ .schematex-genogram-edge-cohabiting-ended path { stroke-dasharray: 6,4; }
1938
2265
  .schematex-genogram-edge-divorced .schematex-genogram-divorce-mark { stroke: ${t.neutral}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; }
1939
2266
  .schematex-genogram-edge-separated .schematex-genogram-separation-mark { stroke: ${t.neutral}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; }
2267
+ .schematex-genogram-edge-cohabiting-ended .schematex-genogram-separation-mark { stroke: ${t.neutral}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; }
2268
+ /* Secondary parent-child link (foster/adopted "current caregiver") \u2014 dotted, muted */
2269
+ .schematex-genogram-edge-secondary path { stroke: ${t.neutral}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; stroke-dasharray: 2,4; fill: none; opacity: 0.85; }
2270
+ /* Sibling-of bracket (known relative, unknown ancestry) \u2014 dashed */
2271
+ .schematex-genogram-sibling-of path { stroke: ${t.neutral}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; stroke-dasharray: 4,3; fill: none; opacity: 0.7; }
2272
+ .schematex-genogram-unknown-siblings-mark { fill: ${t.text}; pointer-events: none; }
1940
2273
  .schematex-genogram-deceased-mark { stroke: ${t.deceasedMark}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.normal}; stroke-linecap: round; }
1941
2274
  /* Inline fill on each .schematex-genogram-condition-fill element comes from cond.color. The CSS only sets a default for elements that did not receive an inline fill attribute. */
1942
2275
  .schematex-genogram-condition-fill:not([fill]) { fill: ${t.conditionFill}; }
@@ -1945,7 +2278,7 @@ function buildStyles(config) {
1945
2278
  .schematex-genogram-edge-label { font-family: ${config.fontFamily}; fill: ${t.text}; }
1946
2279
  .schematex-genogram-index-border { stroke: ${t.warn}; stroke-width: ${chunkD7EHZFK4_cjs.STROKE_WIDTH.thick}; fill: none; }
1947
2280
  `;
1948
- return chunkHDKDQAEQ_cjs.el("style", {}, css);
2281
+ return chunkLFZZ4NCP_cjs.el("style", {}, css);
1949
2282
  }
1950
2283
  var EMOTIONAL_REL_TYPES2 = /* @__PURE__ */ new Set([
1951
2284
  "harmony",
@@ -2006,7 +2339,7 @@ function getEmotionalStrokeWidth(type) {
2006
2339
  return 2;
2007
2340
  }
2008
2341
  function renderEmotionalEdges(edges) {
2009
- if (edges.length === 0) return chunkHDKDQAEQ_cjs.group({ class: "schematex-genogram-emotional-edges" }, []);
2342
+ if (edges.length === 0) return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-emotional-edges" }, []);
2010
2343
  const children = [];
2011
2344
  for (const edge of edges) {
2012
2345
  const type = edge.relationship.type;
@@ -2015,7 +2348,7 @@ function renderEmotionalEdges(edges) {
2015
2348
  const strokeWidth = getEmotionalStrokeWidth(type);
2016
2349
  const directional = edge.relationship.directional;
2017
2350
  const elements = [
2018
- chunkHDKDQAEQ_cjs.el("path", {
2351
+ chunkLFZZ4NCP_cjs.el("path", {
2019
2352
  d: edge.path,
2020
2353
  fill: "none",
2021
2354
  stroke: color,
@@ -2028,7 +2361,7 @@ function renderEmotionalEdges(edges) {
2028
2361
  const mid = pathMidpoint(edge.path);
2029
2362
  if (mid) {
2030
2363
  elements.push(
2031
- chunkHDKDQAEQ_cjs.text(
2364
+ chunkLFZZ4NCP_cjs.text(
2032
2365
  {
2033
2366
  x: mid.x,
2034
2367
  y: mid.y - 6,
@@ -2043,7 +2376,7 @@ function renderEmotionalEdges(edges) {
2043
2376
  }
2044
2377
  }
2045
2378
  children.push(
2046
- chunkHDKDQAEQ_cjs.group(
2379
+ chunkLFZZ4NCP_cjs.group(
2047
2380
  {
2048
2381
  class: `schematex-genogram-emotional schematex-genogram-emotional-${type}`,
2049
2382
  "data-from": edge.from,
@@ -2054,7 +2387,7 @@ function renderEmotionalEdges(edges) {
2054
2387
  )
2055
2388
  );
2056
2389
  }
2057
- return chunkHDKDQAEQ_cjs.group({ class: "schematex-genogram-emotional-edges" }, children);
2390
+ return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-emotional-edges" }, children);
2058
2391
  }
2059
2392
  function renderEdgeLabels(edges, config) {
2060
2393
  const labels = [];
@@ -2063,7 +2396,7 @@ function renderEdgeLabels(edges, config) {
2063
2396
  const mid = pathMidpoint(edge.path);
2064
2397
  if (!mid) continue;
2065
2398
  labels.push(
2066
- chunkHDKDQAEQ_cjs.text(
2399
+ chunkLFZZ4NCP_cjs.text(
2067
2400
  {
2068
2401
  x: mid.x,
2069
2402
  y: mid.y - 6,
@@ -2076,21 +2409,38 @@ function renderEdgeLabels(edges, config) {
2076
2409
  )
2077
2410
  );
2078
2411
  }
2079
- return chunkHDKDQAEQ_cjs.group({ class: "schematex-genogram-edge-labels" }, labels);
2412
+ return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-edge-labels" }, labels);
2080
2413
  }
2081
2414
  function renderEdges(edges) {
2082
2415
  const children = [];
2083
2416
  for (const edge of edges) {
2084
2417
  const relType = edge.relationship.type;
2085
- const cssClass = `schematex-genogram-edge schematex-genogram-edge-${relType}`;
2418
+ const isSecondary = edge.relationship.secondary === true;
2419
+ const cssClass = isSecondary ? `schematex-genogram-edge schematex-genogram-edge-secondary schematex-genogram-edge-secondary-${relType}` : `schematex-genogram-edge schematex-genogram-edge-${relType}`;
2086
2420
  const elements = [
2087
- chunkHDKDQAEQ_cjs.el("path", { d: edge.path, class: "schematex-genogram-edge-path" })
2421
+ chunkLFZZ4NCP_cjs.el("path", { d: edge.path, class: "schematex-genogram-edge-path" })
2088
2422
  ];
2423
+ if (relType === "cohabiting-ended" && !isSecondary) {
2424
+ const mid = pathMidpoint(edge.path);
2425
+ if (mid) {
2426
+ elements.push(
2427
+ chunkLFZZ4NCP_cjs.el("line", {
2428
+ x1: mid.x - 4,
2429
+ y1: mid.y - 6,
2430
+ x2: mid.x + 4,
2431
+ y2: mid.y + 6,
2432
+ class: "schematex-genogram-separation-mark",
2433
+ stroke: "#333",
2434
+ "stroke-width": "2"
2435
+ })
2436
+ );
2437
+ }
2438
+ }
2089
2439
  if (relType === "divorced") {
2090
2440
  const mid = pathMidpoint(edge.path);
2091
2441
  if (mid) {
2092
2442
  elements.push(
2093
- chunkHDKDQAEQ_cjs.el("line", {
2443
+ chunkLFZZ4NCP_cjs.el("line", {
2094
2444
  x1: mid.x - 4,
2095
2445
  y1: mid.y - 6,
2096
2446
  x2: mid.x + 4,
@@ -2099,7 +2449,7 @@ function renderEdges(edges) {
2099
2449
  stroke: "#333",
2100
2450
  "stroke-width": "2"
2101
2451
  }),
2102
- chunkHDKDQAEQ_cjs.el("line", {
2452
+ chunkLFZZ4NCP_cjs.el("line", {
2103
2453
  x1: mid.x - 4 + 6,
2104
2454
  y1: mid.y - 6,
2105
2455
  x2: mid.x + 4 + 6,
@@ -2115,7 +2465,7 @@ function renderEdges(edges) {
2115
2465
  const mid = pathMidpoint(edge.path);
2116
2466
  if (mid) {
2117
2467
  elements.push(
2118
- chunkHDKDQAEQ_cjs.el("line", {
2468
+ chunkLFZZ4NCP_cjs.el("line", {
2119
2469
  x1: mid.x - 4,
2120
2470
  y1: mid.y - 6,
2121
2471
  x2: mid.x + 4,
@@ -2128,7 +2478,7 @@ function renderEdges(edges) {
2128
2478
  }
2129
2479
  }
2130
2480
  children.push(
2131
- chunkHDKDQAEQ_cjs.group(
2481
+ chunkLFZZ4NCP_cjs.group(
2132
2482
  {
2133
2483
  class: cssClass,
2134
2484
  "data-from": edge.from,
@@ -2138,7 +2488,7 @@ function renderEdges(edges) {
2138
2488
  )
2139
2489
  );
2140
2490
  }
2141
- return chunkHDKDQAEQ_cjs.group({ class: "schematex-genogram-edges" }, children);
2491
+ return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-edges" }, children);
2142
2492
  }
2143
2493
  function pathMidpoint(pathData) {
2144
2494
  const coords = pathData.match(/[\d.-]+/g);
@@ -2173,7 +2523,7 @@ function renderNodes(genGroups) {
2173
2523
  );
2174
2524
  }
2175
2525
  layers.push(
2176
- chunkHDKDQAEQ_cjs.group(
2526
+ chunkLFZZ4NCP_cjs.group(
2177
2527
  {
2178
2528
  class: `schematex-genogram-generation schematex-genogram-generation-${genIdx}`,
2179
2529
  "data-generation": genIdx
@@ -2184,6 +2534,35 @@ function renderNodes(genGroups) {
2184
2534
  }
2185
2535
  return layers;
2186
2536
  }
2537
+ function renderSiblingOfBrackets(layout, ast) {
2538
+ if (!ast) return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-sibling-of-edges" }, []);
2539
+ const elements = [];
2540
+ const nodeById = new Map(layout.nodes.map((n) => [n.id, n]));
2541
+ for (const ind of ast.individuals) {
2542
+ if (!ind.siblingOf) continue;
2543
+ const fromNode = nodeById.get(ind.id);
2544
+ const toNode = nodeById.get(ind.siblingOf);
2545
+ if (!fromNode || !toNode) continue;
2546
+ if (fromNode.generation !== toNode.generation) continue;
2547
+ const fromCx = fromNode.x + fromNode.width / 2;
2548
+ const fromTopY = fromNode.y;
2549
+ const toCx = toNode.x + toNode.width / 2;
2550
+ const toTopY = toNode.y;
2551
+ const bracketY = Math.min(fromTopY, toTopY) - 12;
2552
+ const path2 = `M ${fromCx} ${fromTopY} L ${fromCx} ${bracketY} L ${toCx} ${bracketY} L ${toCx} ${toTopY}`;
2553
+ elements.push(
2554
+ chunkLFZZ4NCP_cjs.group(
2555
+ {
2556
+ class: "schematex-genogram-sibling-of",
2557
+ "data-from": ind.id,
2558
+ "data-to": ind.siblingOf
2559
+ },
2560
+ [chunkLFZZ4NCP_cjs.el("path", { d: path2 })]
2561
+ )
2562
+ );
2563
+ }
2564
+ return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-sibling-of-edges" }, elements);
2565
+ }
2187
2566
  function renderLabels(nodes, config) {
2188
2567
  const labels = [];
2189
2568
  for (const node of nodes) {
@@ -2198,7 +2577,7 @@ function renderLabels(nodes, config) {
2198
2577
  labelText += ` (b. ${ind.birthYear})`;
2199
2578
  }
2200
2579
  labels.push(
2201
- chunkHDKDQAEQ_cjs.text(
2580
+ chunkLFZZ4NCP_cjs.text(
2202
2581
  {
2203
2582
  x: cx,
2204
2583
  y: labelY,
@@ -2209,7 +2588,7 @@ function renderLabels(nodes, config) {
2209
2588
  )
2210
2589
  );
2211
2590
  }
2212
- return chunkHDKDQAEQ_cjs.group({ class: "schematex-genogram-labels" }, labels);
2591
+ return chunkLFZZ4NCP_cjs.group({ class: "schematex-genogram-labels" }, labels);
2213
2592
  }
2214
2593
 
2215
2594
  // src/diagrams/genogram/index.ts
@@ -2246,5 +2625,5 @@ exports.layoutGenogram = layoutGenogram;
2246
2625
  exports.parseGenogram = parseGenogram;
2247
2626
  exports.renderGenogram = renderGenogram;
2248
2627
  exports.renderIndividualSymbol = renderIndividualSymbol;
2249
- //# sourceMappingURL=chunk-MJGDP3CS.cjs.map
2250
- //# sourceMappingURL=chunk-MJGDP3CS.cjs.map
2628
+ //# sourceMappingURL=chunk-BUN3CRMP.cjs.map
2629
+ //# sourceMappingURL=chunk-BUN3CRMP.cjs.map