compasso 0.4.1 → 0.5.0
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.
- package/README.md +86 -5
- package/dist/{chunk-WJYYBGZW.js → chunk-2NDET6O5.js} +3 -3
- package/dist/{chunk-WJYYBGZW.js.map → chunk-2NDET6O5.js.map} +1 -1
- package/dist/{chunk-LR7BXUWM.js → chunk-3RGYLVTN.js} +3 -3
- package/dist/{chunk-LR7BXUWM.js.map → chunk-3RGYLVTN.js.map} +1 -1
- package/dist/chunk-BM7UJBK5.js +680 -0
- package/dist/chunk-BM7UJBK5.js.map +1 -0
- package/dist/chunk-DVLWT565.js +372 -0
- package/dist/chunk-DVLWT565.js.map +1 -0
- package/dist/{chunk-IPE7JZO5.js → chunk-JBDA7E2O.js} +3 -3
- package/dist/{chunk-IPE7JZO5.js.map → chunk-JBDA7E2O.js.map} +1 -1
- package/dist/chunk-MIJTBYX2.js +982 -0
- package/dist/chunk-MIJTBYX2.js.map +1 -0
- package/dist/{chunk-PGUMLTIM.js → chunk-PJHLWSGD.js} +3 -3
- package/dist/{chunk-PGUMLTIM.js.map → chunk-PJHLWSGD.js.map} +1 -1
- package/dist/{chunk-M4WA6ME7.js → chunk-RDH4XHA2.js} +3 -3
- package/dist/{chunk-M4WA6ME7.js.map → chunk-RDH4XHA2.js.map} +1 -1
- package/dist/{chunk-TAE2UB7D.js → chunk-WEHUSHVI.js} +4 -40
- package/dist/chunk-WEHUSHVI.js.map +1 -0
- package/dist/{chunk-FYBABYC7.js → chunk-Z66YUOUM.js} +3 -3
- package/dist/{chunk-FYBABYC7.js.map → chunk-Z66YUOUM.js.map} +1 -1
- package/dist/core/index.cjs +217 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +79 -3
- package/dist/core/index.d.ts +79 -3
- package/dist/core/index.js +1 -1
- package/dist/ecomap/index.js +2 -2
- package/dist/fault-tree/index.d.cts +2 -2
- package/dist/fault-tree/index.d.ts +2 -2
- package/dist/fault-tree/index.js +2 -2
- package/dist/fishbone/index.js +2 -2
- package/dist/genogram/index.d.cts +2 -2
- package/dist/genogram/index.d.ts +2 -2
- package/dist/genogram/index.js +2 -2
- package/dist/geometry-P-XGqGe7.d.cts +8 -0
- package/dist/geometry-P-XGqGe7.d.ts +8 -0
- package/dist/grid-BMgUSly1.d.cts +79 -0
- package/dist/grid-BMgUSly1.d.ts +79 -0
- package/dist/index.cjs +2263 -380
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +10 -8
- package/dist/labels-Br8yjc3C.d.cts +29 -0
- package/dist/labels-Br8yjc3C.d.ts +29 -0
- package/dist/labels-D1v1RWZd.d.cts +97 -0
- package/dist/labels-D1v1RWZd.d.ts +97 -0
- package/dist/layered-DmZluAqe.d.cts +72 -0
- package/dist/layered-DmZluAqe.d.ts +72 -0
- package/dist/locales/pt-br.cjs +53 -0
- package/dist/locales/pt-br.cjs.map +1 -1
- package/dist/locales/pt-br.d.cts +7 -1
- package/dist/locales/pt-br.d.ts +7 -1
- package/dist/locales/pt-br.js +50 -1
- package/dist/locales/pt-br.js.map +1 -1
- package/dist/org-chart/index.cjs +38 -36
- package/dist/org-chart/index.cjs.map +1 -1
- package/dist/org-chart/index.d.cts +5 -31
- package/dist/org-chart/index.d.ts +5 -31
- package/dist/org-chart/index.js +2 -2
- package/dist/pedigree/index.d.cts +2 -2
- package/dist/pedigree/index.d.ts +2 -2
- package/dist/pedigree/index.js +2 -2
- package/dist/phylo/index.d.cts +2 -2
- package/dist/phylo/index.d.ts +2 -2
- package/dist/phylo/index.js +2 -2
- package/dist/prisma/index.cjs +882 -0
- package/dist/prisma/index.cjs.map +1 -0
- package/dist/prisma/index.d.cts +174 -0
- package/dist/prisma/index.d.ts +174 -0
- package/dist/prisma/index.js +4 -0
- package/dist/prisma/index.js.map +1 -0
- package/dist/{text-DuO_PwYw.d.cts → text-DDVzpwPZ.d.cts} +1 -8
- package/dist/{text-DuO_PwYw.d.ts → text-DDVzpwPZ.d.ts} +1 -8
- package/dist/uml/index.cjs +1214 -0
- package/dist/uml/index.cjs.map +1 -0
- package/dist/uml/index.d.cts +189 -0
- package/dist/uml/index.d.ts +189 -0
- package/dist/uml/index.js +4 -0
- package/dist/uml/index.js.map +1 -0
- package/package.json +28 -2
- package/dist/chunk-SD4NTRBM.js +0 -171
- package/dist/chunk-SD4NTRBM.js.map +0 -1
- package/dist/chunk-TAE2UB7D.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/xml.ts","../src/core/roman.ts","../src/core/geometry.ts","../src/core/text.ts","../src/core/legend.ts","../src/core/stroke.ts","../src/core/annotation.ts","../src/core/layered.ts","../src/core/glyph.ts","../src/core/compartment.ts","../src/core/grid.ts"],"names":["round","r"],"mappings":"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","file":"chunk-DVLWT565.js","sourcesContent":["// XML/SVG escaping — every interpolated text in an emitted SVG MUST pass through\n// this. Diagram labels are typically user/author-controlled, and the SVG string may\n// be injected via innerHTML in a browser or embedded as vectors in a PDF — an\n// unescaped label is an XSS / `</svg>`-breakout vector on every surface at once.\n\n/** Escapes a string for use in SVG/XML text content AND attribute values. */\nexport function xmlEscape(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","// Roman numeral formatting for level/generation labels (pedigree generation rows\n// I, II, III…; any leveled diagram). Standard subtractive notation, valid for\n// integers 1..3999. A renderer must NEVER crash on a weird generation index, so\n// out-of-range / non-integer inputs fall back to the Arabic number as a string\n// rather than throwing or emitting nonsense like \"MMMM…\". Pure + deterministic.\n\nconst ROMAN_TABLE: ReadonlyArray<readonly [number, string]> = [\n [1000, \"M\"],\n [900, \"CM\"],\n [500, \"D\"],\n [400, \"CD\"],\n [100, \"C\"],\n [90, \"XC\"],\n [50, \"L\"],\n [40, \"XL\"],\n [10, \"X\"],\n [9, \"IX\"],\n [5, \"V\"],\n [4, \"IV\"],\n [1, \"I\"],\n];\n\n/** Uppercase Roman numeral for an integer in 1..3999 (1→\"I\", 4→\"IV\", 1990→\"MCMXC\").\n * Out of range or non-integer → the Arabic number as a string (graceful fallback). */\nexport function romanNumeral(n: number): string {\n if (!Number.isInteger(n) || n < 1 || n > 3999) return String(n);\n let remaining = n;\n let out = \"\";\n for (const [value, symbol] of ROMAN_TABLE) {\n while (remaining >= value) {\n out += symbol;\n remaining -= value;\n }\n }\n return out;\n}\n","// Shared geometry primitives.\n\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** \"M x y L x y …\" path data from a polyline. */\nexport function pathData(points: Point[]): string {\n return points.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x} ${p.y}`).join(\" \");\n}\n","// Pure, deterministic text metrics — no DOM, no canvas, no font files. Every layout\n// in this library reserves space from these estimates and every emitter draws with\n// the same constants, so what is proven collision-free is what is drawn.\n\n/**\n * Conservative per-character advance, as a fraction of the font size. The pure module\n * can't measure real glyphs (no DOM/canvas), so it estimates width = chars * font *\n * CHAR_W. It is deliberately a touch WIDER than Helvetica's ~0.5 average advance: a\n * layout reserves slightly more room than the text needs, so the real render always\n * fits inside its reserved box.\n */\nexport const CHAR_W = 0.6;\n\n/** Pure, deterministic width estimate for a single line of text at `fontPx`. */\nexport function estimateTextWidth(text: string, fontPx: number): number {\n return text.length * fontPx * CHAR_W;\n}\n\n/**\n * Wraps a label onto up to `maxLines` lines (default 2) so long labels don't sprawl.\n * Greedy word fill; each line capped at `perLine` chars (…-truncated only if a line\n * still overflows). The LAST allowed line absorbs every remaining word before the cap\n * applies — words are never dropped mid-label, only visibly elided. Pure + shared so\n * every renderer wraps identically. The full text is always kept elsewhere (the\n * node's `label`, an SVG <title>, or a side list), so nothing is silently lost.\n *\n * INVARIANT: with the default `maxLines` the output is byte-identical to the\n * historical two-line implementation (pinned by test/core/text.test.ts) — both\n * shipped renderers wrap through here.\n */\nexport function wrapLabel(label: string, perLine: number, maxLines = 2): string[] {\n if (label.length <= perLine) return [label];\n const cap = (s: string): string =>\n s.length > perLine ? s.slice(0, Math.max(1, perLine - 1)) + \"…\" : s;\n const lines: string[] = [\"\"];\n for (const word of label.split(/\\s+/)) {\n const last = lines.length - 1;\n const current = lines[last]!;\n if (current === \"\" || (current + \" \" + word).length <= perLine) {\n lines[last] = current === \"\" ? word : `${current} ${word}`;\n } else if (lines.length < maxLines) {\n lines.push(word);\n } else {\n lines[last] = `${current} ${word}`;\n }\n }\n // A trailing-whitespace \"word\" (\"a b \".split(/\\s+/) → [\"a\",\"b\",\"\"]) may open a line\n // it never fills; the historical code dropped that empty line, so this does too.\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n return lines.map(cap);\n}\n\n/**\n * House \"balanced\" wrap policy (extracted verbatim from the ecomap's tie-label wrap,\n * itself mirroring the genogram's): per-line budget `min(26, max(14, ceil(len/2)+2))`\n * splits a medium label into two roughly even lines instead of one long + one short,\n * then the greedy `wrapLabel` fill (and its `maxLines` semantics) applies. The shipped\n * renderers keep their local copies for now — new modules consume this one; migrating\n * them is a separate provably-zero-change refactor.\n */\nexport function wrapLabelBalanced(label: string, maxLines?: number): string[] {\n const perLine = Math.min(26, Math.max(14, Math.ceil(label.length / 2) + 2));\n return wrapLabel(label, perLine, maxLines);\n}\n\n/** Caps a verbatim label for a COMPACT render (preview); full text kept by the caller. */\nexport function clampLabel(label: string, maxChars: number | undefined): string {\n if (maxChars === undefined || label.length <= maxChars) return label;\n return label.slice(0, Math.max(1, maxChars - 1)) + \"…\";\n}\n\n/** Font stack shared by every emitter; PDF embedders typically map it onto Helvetica. */\nexport const FONT_FAMILY = \"Helvetica, Arial, sans-serif\";\n","// Shared legend machinery — the exact row format the genogram and ecomap emitters\n// currently duplicate character-for-character (`<g data-compasso-legend=\"true\">` with\n// swatch-closure rows). Extracted so new diagram modules don't add a third copy;\n// the two shipped emitters keep their local blocks for now (migrating them is a\n// separate, provably-zero-change refactor — pinned byte-for-byte against the ecomap's\n// emitted legend in test/core/legend.test.ts).\n//\n// The caller stays in charge of the HONESTY RULE half: it decides WHICH entries exist\n// (used-keys-only) and what each swatch draws; this module only owns the row geometry,\n// the text emission (xmlEscape — labels may come from caller-supplied packs), and the\n// width/height bookkeeping both renderers compute identically.\n\nimport { FONT_FAMILY, estimateTextWidth } from \"./text\";\nimport { xmlEscape } from \"./xml\";\n\n// Row metrics shared by every legend in the library. Exported because swatch builders\n// need them (a line swatch spans LEGEND_SWATCH_W; a glyph swatch centers on it).\nexport const LEGEND_ROW_H = 18;\nexport const LEGEND_PAD = 16;\nexport const LEGEND_SWATCH_W = 22;\nexport const LEGEND_GAP = 14;\nexport const LEGEND_FONT = 11;\n\n// Legend text ink — the zinc glyph stroke both shipped emitters use for legend labels.\nconst LEGEND_TEXT_FILL = \"#52525b\";\n\nexport interface LegendEntry {\n /**\n * Swatch markup builder, called with the swatch's left x and the row's center y.\n * The builder owns its own escaping/rounding (it typically reuses the module's\n * glyph/line emitters); it should draw within LEGEND_SWATCH_W of x.\n */\n swatch: (x: number, yCenter: number) => string;\n /** Display label (escaped here; verbatim pack text in, escaped SVG out). */\n label: string;\n}\n\nexport interface LegendBlock {\n /** `<g data-compasso-legend=\"true\">…</g>` — empty string when there are no entries. */\n svg: string;\n /** Minimum canvas width the legend needs; callers take `max(width, block.width)`. */\n width: number;\n /** New total canvas height including the legend; callers assign it directly. */\n height: number;\n}\n\n/**\n * Emits the legend group for the given entries below `startY` (the diagram's current\n * height). Pure + deterministic; coordinates are interpolated exactly as the shipped\n * emitters do. Zero entries (used-keys-only found nothing) → no markup, zero width\n * contribution, height unchanged — safe to call unconditionally.\n */\nexport function legendBlock(entries: readonly LegendEntry[], startY: number): LegendBlock {\n if (entries.length === 0) return { svg: \"\", width: 0, height: startY };\n const rows = entries.map((entry, i) => {\n const rowCenterY = startY + i * LEGEND_ROW_H + LEGEND_ROW_H / 2;\n const textX = LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP;\n return (\n entry.swatch(LEGEND_PAD, rowCenterY) +\n `<text x=\"${textX}\" y=\"${rowCenterY + LEGEND_FONT * 0.32}\" font-family=\"${FONT_FAMILY}\" font-size=\"${LEGEND_FONT}\" fill=\"${LEGEND_TEXT_FILL}\">${xmlEscape(entry.label)}</text>`\n );\n });\n const widestLabel = entries.reduce((m, e) => Math.max(m, estimateTextWidth(e.label, LEGEND_FONT)), 0);\n return {\n svg: `<g data-compasso-legend=\"true\">${rows.join(\"\")}</g>`,\n width: LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP + widestLabel + LEGEND_PAD,\n height: startY + entries.length * LEGEND_ROW_H + LEGEND_PAD / 2,\n };\n}\n","// Edge line styles — a neutral, presentation-only style for a relationship line.\n// NOT a judgment: a deterministic, lexical hint derived from the author's own quality\n// word. The literal word always rides the element's <title>, so a style never replaces\n// what was said. Unknown/ambiguous quality → \"plain\".\n\nexport type EdgeLineStyle = \"plain\" | \"close\" | \"distant\" | \"conflict\" | \"cutoff\";\n\n/** Stroke attributes per style — shared by every renderer so SVG and PDF match. */\nexport interface EdgeStroke {\n width: number;\n /** SVG dash array / PDF dash pattern as [dash, gap]; null = solid. */\n dash: [number, number] | null;\n opacity: number;\n}\n\nexport const EDGE_STROKE: Record<EdgeLineStyle, EdgeStroke> = {\n plain: { width: 1.5, dash: null, opacity: 0.6 },\n close: { width: 3, dash: null, opacity: 0.85 },\n distant: { width: 1.5, dash: [4, 4], opacity: 0.55 },\n conflict: { width: 2, dash: [2, 2], opacity: 0.75 },\n cutoff: { width: 1.5, dash: [6, 5], opacity: 0.4 },\n};\n\n/**\n * A pluggable lexicon mapping free-text quality words onto line styles. Needles are\n * diacritic-free, lowercase substrings of the author's own words; `negations` are\n * whole words that flip the meaning of the very word a needle would match (\"not\n * close\"), so their presence makes the matcher abstain to \"plain\" rather than risk\n * an inverted visual. Locale packs (e.g. `compasso/locales/pt-br`) ship alternates.\n */\nexport interface QualityLexicon {\n buckets: readonly { style: Exclude<EdgeLineStyle, \"plain\">; needles: readonly string[] }[];\n negations: readonly string[];\n}\n\n// English default. Conservative stems: each needle is a substring match on the\n// normalized text, and the SINGLE-BUCKET rule below keeps competing signals honest.\n// \"no\" alone is deliberately NOT a negation: \"no contact\" is a genuine cutoff signal.\nexport const QUALITY_LEXICON_EN: QualityLexicon = {\n buckets: [\n {\n style: \"close\",\n needles: [\"close\", \"warm\", \"support\", \"lov\", \"affection\", \"caring\", \"tight\", \"harmon\", \"healthy\"],\n },\n {\n style: \"distant\",\n needles: [\"distant\", \"detach\", \"absent\", \"cold\", \"drift\"],\n },\n {\n style: \"conflict\",\n needles: [\"conflict\", \"fight\", \"tens\", \"difficult\", \"hostil\", \"violen\", \"abus\", \"aggress\", \"complicat\", \"toxic\", \"argu\"],\n },\n {\n style: \"cutoff\",\n needles: [\"estrang\", \"cut off\", \"cutoff\", \"no contact\", \"broken off\", \"sever\"],\n },\n ],\n negations: [\"not\", \"never\", \"no longer\", \"hardly\"],\n};\n\n/** Lowercase + strip diacritics so matching ignores accents. */\nexport function normalizeText(text: string): string {\n return text.normalize(\"NFD\").replace(/[̀-ͯ]/g, \"\").toLowerCase();\n}\n\nconst escapeRegExp = (s: string): string => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/**\n * Maps a free-text relationship quality to a neutral line style. Deterministic and\n * conservative: returns a specific style ONLY when exactly one lexical bucket matches;\n * null/empty/ambiguous/negated/unknown all fall back to \"plain\". The caller still\n * keeps the verbatim quality word, so nothing the author said is ever lost.\n */\nexport function qualityLineStyle(\n quality: string | null,\n lexicon: QualityLexicon = QUALITY_LEXICON_EN,\n): EdgeLineStyle {\n if (quality === null) return \"plain\";\n const haystack = normalizeText(quality);\n if (haystack.trim() === \"\") return \"plain\";\n\n if (lexicon.negations.length > 0) {\n const negation = new RegExp(`\\\\b(${lexicon.negations.map(escapeRegExp).join(\"|\")})\\\\b`);\n if (negation.test(haystack)) return \"plain\";\n }\n\n const matched: EdgeLineStyle[] = [];\n for (const { style, needles } of lexicon.buckets) {\n if (needles.some((n) => haystack.includes(n))) matched.push(style);\n }\n return matched.length === 1 ? matched[0]! : \"plain\";\n}\n","// A discreet, NEUTRAL \"this element was annotated by the caller\" marker, shared by every\n// diagram family. compasso never decides what an annotation MEANS — the caller asserts the\n// `annotated` flag from its own domain knowledge and supplies the legend label; the library\n// only draws a standardised mark. Pure presentation: literal SVG primitives, no <defs>, no\n// <marker>, no CSS. The mark is a DECORATION drawn inside an element's existing <g> (like a\n// genogram deceased slash) — never a layout box or routed segment, so it cannot create or\n// hide an overlap. Ink is the shared zinc-600 glyph stroke (#52525b) for cross-family unity.\nimport { LEGEND_SWATCH_W } from \"./legend\";\nimport type { Point } from \"./geometry\";\n\nconst round = (n: number): number => Math.round(n * 100) / 100;\n\nexport const ANNOTATION_INK = \"#52525b\";\nconst DOT_R = 3;\nconst TICK_HALF = 3;\n\n/**\n * A small filled dot marking an annotated NODE. Pass the point where it should sit — callers\n * place it at the node's upper-right (inset), the conventional \"has a note\" corner.\n */\nexport function annotationDot(cx: number, cy: number): string {\n return `<circle cx=\"${round(cx)}\" cy=\"${round(cy)}\" r=\"${DOT_R}\" fill=\"${ANNOTATION_INK}\" fill-opacity=\"0.6\"/>`;\n}\n\n/**\n * A short tick perpendicular to an annotated EDGE at the midpoint of its middle segment.\n * Org-chart / genogram polylines are axis-aligned, so the perpendicular is trivial; a tick on\n * a near-diagonal falls back to a vertical mark. Returns \"\" for a degenerate (<2-point) path.\n */\nexport function annotationTick(points: readonly Point[]): string {\n if (points.length < 2) return \"\";\n const i = Math.floor((points.length - 1) / 2);\n const a = points[i]!;\n const b = points[i + 1] ?? points[i]!;\n const mx = (a.x + b.x) / 2;\n const my = (a.y + b.y) / 2;\n const horizontal = Math.abs(a.y - b.y) <= Math.abs(a.x - b.x);\n const x1 = horizontal ? mx : mx - TICK_HALF;\n const x2 = horizontal ? mx : mx + TICK_HALF;\n const y1 = horizontal ? my - TICK_HALF : my;\n const y2 = horizontal ? my + TICK_HALF : my;\n return `<line x1=\"${round(x1)}\" y1=\"${round(y1)}\" x2=\"${round(x2)}\" y2=\"${round(y2)}\" stroke=\"${ANNOTATION_INK}\" stroke-width=\"1.5\"/>`;\n}\n\n/** Legend swatch for the annotation row: the same dot, centred in the swatch column. */\nexport function annotationSwatch(x: number, yCenter: number): string {\n return annotationDot(x + LEGEND_SWATCH_W / 2, yCenter);\n}\n","// Pure layout primitives shared across diagram families. Every function here is\n// deterministic and has zero references to any diagram-specific type (OrgNode,\n// GenogramPerson, etc.). Each was verified to have ≥2 real consumers before being\n// lifted; none is speculative.\n\n// ── packSubtree ────────────────────────────────────────────────────────────────\n// Moved VERBATIM from src/org-chart/layout.ts (was lines 180-223 before this lift).\n// See that file's \"PURE span-packer (Judge-1 seam)\" comment for the overlap-proof\n// and consumer notes.\n\n/** A node's own symmetric-or-asymmetric half-extents plus its children's half-extents. */\nexport interface PackNode {\n ownHalfL: number;\n ownHalfR: number;\n /** One entry per child, in placement order; empty = leaf. */\n children: { halfL: number; halfR: number }[];\n}\n\nexport interface PackGaps {\n siblingGap: number;\n}\n\nexport interface PackResult {\n /** Subtree half-extents (cover the ENTIRE subtree). */\n halfL: number;\n halfR: number;\n /** Center offset of each child relative to this node's center (parallel to children). */\n offsets: number[];\n}\n\n/**\n * Span-packs a node's children into disjoint horizontal intervals (the fault-tree `pack`\n * transposed top-down). Children c1..cn: x1 = 0; x_{i+1} = x_i + halfR_i + siblingGap +\n * halfL_{i+1}. Parent axis a = (x1 + xn)/2 — centered over its line-report block. The\n * returned offsets are each child's center MINUS the parent axis. Subtree halfL/halfR\n * extend ownHalf* to cover the children block. Pure + deterministic.\n */\nexport function packSubtree(node: PackNode, gaps: PackGaps): PackResult {\n const { ownHalfL, ownHalfR, children } = node;\n if (children.length === 0) {\n return { halfL: ownHalfL, halfR: ownHalfR, offsets: [] };\n }\n const xs: number[] = [0];\n for (let i = 1; i < children.length; i++) {\n xs.push(xs[i - 1]! + children[i - 1]!.halfR + gaps.siblingGap + children[i]!.halfL);\n }\n const first = children[0]!;\n const last = children[children.length - 1]!;\n const axis = (xs[0]! + xs[xs.length - 1]!) / 2;\n const offsets = xs.map((x) => x - axis);\n const halfL = Math.max(ownHalfL, axis - (xs[0]! - first.halfL));\n const halfR = Math.max(ownHalfR, xs[xs.length - 1]! + last.halfR - axis);\n return { halfL, halfR, offsets };\n}\n\n// ── allocateLanes ──────────────────────────────────────────────────────────────\n// Moved VERBATIM from src/org-chart/layout.ts (was lines 939-959 before this lift).\n// A byte-identical copy exists in src/genogram/layout.ts — that copy is NOT removed\n// this release (separate zero-change follow-up per the shipped migration discipline).\n\n/** Allocate lanes for a set of y-intervals: each takes the lowest lane free over its span\n * (touching at an endpoint does NOT count as overlap, so abutting edges may share). Mirror\n * of the genogram allocateLanes (src/genogram/layout.ts) — keeps the gutter narrow. */\nexport function allocateLanes(items: { lo: number; hi: number; set: (lane: number) => void }[]): number {\n const lanes: { lo: number; hi: number }[][] = [];\n for (const it of items) {\n let chosen = -1;\n for (let l = 0; l < lanes.length; l++) {\n if (lanes[l]!.every((o) => it.hi <= o.lo || it.lo >= o.hi)) {\n chosen = l;\n break;\n }\n }\n if (chosen === -1) {\n chosen = lanes.length;\n lanes.push([]);\n }\n lanes[chosen]!.push({ lo: it.lo, hi: it.hi });\n it.set(chosen);\n }\n return lanes.length;\n}\n\n// ── bandStack ──────────────────────────────────────────────────────────────────\n// NEW — captures the row-stacking recurrence verified duplicated in\n// org-chart/layout.ts (rowTop/busY) and fault-tree/layout.ts (gateZone).\n// `zoneH` generalises assistZone / gateZone (pass 0 when no side-zone exists).\n\nexport interface BandRow {\n /** Height of the content row itself (tallest box, etc.). */\n rowH: number;\n /** Height of the side-zone hanging BELOW the row and ABOVE the corridor\n * (assistant stack, gate zone, …). Pass 0 when there is no zone. */\n zoneH: number;\n}\n\nexport interface BandStackOpts {\n /** Canvas padding placed above row 0 and below the last row. */\n padding: number;\n /** Vertical gap between rows (the bus lives at busY = next rowTop − corridor/2). */\n corridor: number;\n}\n\nexport interface BandStackResult {\n /** rowTop[d] = y of the top edge of row d. rowTop[0] = padding. */\n rowTop: number[];\n /** y of the bus (connector horizontal bar) between row d and row d+1. */\n busY: (d: number) => number;\n /** Total canvas height (last row bottom + last zoneH + padding). */\n height: number;\n}\n\n/**\n * Stacks rows top-down with a corridor between them.\n *\n * Recurrence:\n * rowTop[0] = padding\n * rowTop[d+1] = rowTop[d] + rows[d].rowH + rows[d].zoneH + corridor\n * busY(d) = rowTop[d+1] − corridor / 2\n * height = rowTop[last] + rows[last].rowH + rows[last].zoneH + padding\n *\n * An empty `rows` array returns `{ rowTop: [], busY: () => 0, height: padding * 2 }`.\n * Pure + deterministic.\n */\nexport function bandStack(rows: BandRow[], opts: BandStackOpts): BandStackResult {\n const { padding, corridor } = opts;\n if (rows.length === 0) {\n return { rowTop: [], busY: () => 0, height: padding * 2 };\n }\n const rowTop: number[] = [padding];\n for (let d = 0; d < rows.length - 1; d++) {\n rowTop.push(rowTop[d]! + rows[d]!.rowH + rows[d]!.zoneH + corridor);\n }\n const last = rows.length - 1;\n const busY = (d: number): number => rowTop[d + 1]! - corridor / 2;\n const height = rowTop[last]! + rows[last]!.rowH + rows[last]!.zoneH + padding;\n return { rowTop, busY, height };\n}\n","// Explicit-polygon glyph kit — cardinal arrowheads, triangles, diamonds.\n//\n// Rules (AGENTS.md):\n// - All functions PURE; return a `points` string only.\n// - Caller owns fill/stroke — this kit NEVER bakes presentation.\n// - Cardinal Dir only: rotation = sign-flips on size, NO trig.\n// - round() every coordinate to 2 decimals.\n// - No <defs>, no <marker>, no CSS.\n\nimport type { Point } from \"./geometry\";\n\n// ── Direction ─────────────────────────────────────────────────────────────────\n\n/** Cardinal direction; tip of the glyph points in this direction. */\nexport type Dir = \"up\" | \"down\" | \"left\" | \"right\";\n\n/** Unit vector components for each cardinal direction. */\nfunction dirVec(dir: Dir): readonly [ux: number, uy: number] {\n switch (dir) {\n case \"right\": return [1, 0];\n case \"left\": return [-1, 0];\n case \"down\": return [0, 1];\n case \"up\": return [0, -1];\n }\n}\n\n/** Format a single point pair to 2-decimal strings. */\nfunction r(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction pt(x: number, y: number): string {\n return `${r(x)},${r(y)}`;\n}\n\n// ── Size consts ───────────────────────────────────────────────────────────────\n\n/** Open/filled arrowhead length (from tip to base). */\nexport const GLYPH_ARROW_LEN = 10;\n/** Open/filled arrowhead half-width at the base. */\nexport const GLYPH_ARROW_HALF = 5;\n\n/** Generalization/realization triangle length (from tip to base). */\nexport const GLYPH_TRI_LEN = 14;\n/** Generalization/realization triangle half-width at the base. */\nexport const GLYPH_TRI_HALF = 8;\n\n/** Aggregation/composition diamond length (tip to base, full axis). */\nexport const GLYPH_DIAMOND_LEN = 16;\n/** Aggregation/composition diamond half-width at mid-point. */\nexport const GLYPH_DIAMOND_HALF = 6;\n\n// ── Arrowheads ────────────────────────────────────────────────────────────────\n\n/**\n * Three-point open arrowhead (\"<\" shape, 2-stroke polyline).\n * Caller should set fill=\"none\".\n *\n * @param tip - apex of the arrowhead (where the line ends)\n * @param dir - direction the tip points\n * @param len - depth of the arrowhead (default GLYPH_ARROW_LEN)\n * @param half - half-width at the base (default GLYPH_ARROW_HALF)\n */\nexport function arrowOpenPoints(\n tip: Point,\n dir: Dir,\n len: number = GLYPH_ARROW_LEN,\n half: number = GLYPH_ARROW_HALF,\n): string {\n return _arrowPoints(tip, dir, len, half);\n}\n\n/**\n * Three-point solid (filled) arrowhead.\n * Caller should set fill to the desired ink color.\n *\n * @param tip - apex of the arrowhead (where the line ends)\n * @param dir - direction the tip points\n * @param len - depth of the arrowhead (default GLYPH_ARROW_LEN)\n * @param half - half-width at the base (default GLYPH_ARROW_HALF)\n */\nexport function arrowFilledPoints(\n tip: Point,\n dir: Dir,\n len: number = GLYPH_ARROW_LEN,\n half: number = GLYPH_ARROW_HALF,\n): string {\n return _arrowPoints(tip, dir, len, half);\n}\n\n/**\n * Shared arrow geometry: 3 points — tip, base+perp, base-perp.\n * Identical for open and filled (caller controls fill/stroke).\n *\n * Formula matches the fishbone arrowHead function:\n * base = tip - (ux*len, uy*len)\n * perpendicular = (-uy, ux)\n * pt1 = tip\n * pt2 = base + perp * half\n * pt3 = base - perp * half\n */\nfunction _arrowPoints(tip: Point, dir: Dir, len: number, half: number): string {\n const [ux, uy] = dirVec(dir);\n const tx = tip.x;\n const ty = tip.y;\n // base center (back from tip along the direction)\n const bx = tx - ux * len;\n const by = ty - uy * len;\n // perpendicular unit vector\n const px = -uy;\n const py = ux;\n return [\n pt(tx, ty),\n pt(bx + px * half, by + py * half),\n pt(bx - px * half, by - py * half),\n ].join(\" \");\n}\n\n// ── Triangle ──────────────────────────────────────────────────────────────────\n\n/**\n * Three-point isoceles triangle (generalization/realization head).\n * Same geometry as the arrowhead; caller fills white (open triangle) or ink (realization).\n *\n * @param tip - apex of the triangle (where the line ends)\n * @param dir - direction the tip points\n * @param len - depth tip→base (default GLYPH_TRI_LEN)\n * @param half - half-width at the base (default GLYPH_TRI_HALF)\n */\nexport function trianglePoints(\n tip: Point,\n dir: Dir,\n len: number = GLYPH_TRI_LEN,\n half: number = GLYPH_TRI_HALF,\n): string {\n return _arrowPoints(tip, dir, len, half);\n}\n\n// ── Diamond ───────────────────────────────────────────────────────────────────\n\n/**\n * Four-point rhombus (aggregation / composition diamond).\n * Points in order: tip → left-side → base → right-side.\n *\n * The `tip` is the outer apex (the one on the LINE, away from the source box).\n * The diamond extends `len` in the `dir` direction (toward the source box).\n * Left/right side-points are `half` perpendicular units off the mid-axis.\n *\n * @param tip - outer apex (where the line ends, nearest the target)\n * @param dir - direction from tip toward the source box\n * @param len - length of the full diamond axis (default GLYPH_DIAMOND_LEN)\n * @param half - half-width at the widest point (default GLYPH_DIAMOND_HALF)\n */\nexport function diamondPoints(\n tip: Point,\n dir: Dir,\n len: number = GLYPH_DIAMOND_LEN,\n half: number = GLYPH_DIAMOND_HALF,\n): string {\n const [ux, uy] = dirVec(dir);\n const tx = tip.x;\n const ty = tip.y;\n // mid-point (halfway along the axis)\n const mx = tx + ux * (len / 2);\n const my = ty + uy * (len / 2);\n // base (far end, at the source box edge)\n const basex = tx + ux * len;\n const basey = ty + uy * len;\n // perpendicular unit vector (-uy, ux)\n const px = -uy;\n const py = ux;\n return [\n pt(tx, ty),\n pt(mx - px * half, my - py * half),\n pt(basex, basey),\n pt(mx + px * half, my + py * half),\n ].join(\" \");\n}\n\n// ── Inset metric ──────────────────────────────────────────────────────────────\n\n/**\n * How far the LINE must stop short of the box edge so it meets the glyph BASE\n * (not the box face). Layout reserves this space; svg draws the line to this\n * point and the polygon from it.\n *\n * For arrows and triangles: the line ends at the glyph base, which is `len`\n * from the tip (the tip sits at the box edge). Inset = len.\n *\n * For diamonds: the diamond BASE is at the box edge; the tip is `len` outward.\n * The line ends at the diamond tip = `len` from the box edge. Inset = len.\n *\n * Direction does not affect the scalar inset value (rotation is sign-flip only).\n */\nexport function glyphInset(_dir: Dir, kind: \"arrow\" | \"triangle\" | \"diamond\"): number {\n switch (kind) {\n case \"arrow\": return GLYPH_ARROW_LEN;\n case \"triangle\": return GLYPH_TRI_LEN;\n case \"diamond\": return GLYPH_DIAMOND_LEN;\n }\n}\n","// Pure, deterministic multi-compartment box measurer. Guarantees that what\n// layout reserves is exactly what svg draws: every caller reads geometry from\n// CompartmentMetrics and never re-derives it independently.\n\nimport { estimateTextWidth } from \"./text\";\n\nexport interface CompartmentMetrics {\n /** Shared box width (all compartments share straight vertical sides). */\n boxW: number;\n /** Total box height (sum of all compartment heights). */\n boxH: number;\n /** Per-compartment row info: the line strings, the y of the compartment's\n * first-line baseline region (top of the padY region above the first line),\n * and the font size carried through. */\n rows: { lines: string[]; top: number; font: number }[];\n /** Y-coordinates of internal horizontal dividers (one between each pair of\n * consecutive compartments). Length = compartments.length - 1. */\n dividerYs: number[];\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\n/**\n * Measures a multi-compartment UML-style box.\n *\n * @param compartments Ordered list of compartments (top→bottom). Each carries\n * its pre-wrapped `lines` and the `font` size for those lines.\n * An EMPTY compartment (`lines.length === 0`) still reserves one blank row of\n * `lineH` height so the abstract-class empty-operations divider is always drawn.\n * @param opts\n * - padX Horizontal padding inside the box (applied left + right).\n * - padY Vertical padding above the first line and below the last line of\n * each compartment.\n * - lineH Height of a single line (applies to every compartment uniformly).\n * - minW Minimum box width (shared across all compartments).\n * - sepPad Reserved for future per-separator padding; currently unused in\n * geometry (dividers are flush horizontal rules) but accepted in the\n * signature per the brief contract.\n */\nexport function measureCompartmentBox(\n compartments: { lines: string[]; font: number }[],\n opts: { padX: number; padY: number; lineH: number; minW: number; sepPad: number },\n): CompartmentMetrics {\n const { padX, padY, lineH, minW } = opts;\n\n // --- boxW: shared width, max over ALL lines in ALL compartments ---\n let maxLineW = 0;\n for (const c of compartments) {\n for (const line of c.lines) {\n const w = estimateTextWidth(line, c.font);\n if (w > maxLineW) maxLineW = w;\n }\n }\n const boxW = round(Math.max(minW, maxLineW + 2 * padX));\n\n // --- Per-compartment heights and divider positions ---\n const rows: CompartmentMetrics[\"rows\"] = [];\n const dividerYs: number[] = [];\n let y = 0;\n\n for (let i = 0; i < compartments.length; i++) {\n const c = compartments[i]!;\n // An empty compartment reserves one blank row.\n const lineCount = c.lines.length > 0 ? c.lines.length : 1;\n const compartmentH = padY + lineCount * lineH + padY;\n\n rows.push({\n lines: c.lines,\n top: round(y + padY),\n font: c.font,\n });\n\n y += compartmentH;\n\n if (i < compartments.length - 1) {\n dividerYs.push(round(y));\n }\n }\n\n const boxH = round(y);\n\n return { boxW, boxH, rows, dividerYs };\n}\n","// Pure 2-D grid packer. Guarantees disjoint cell AABBs by construction —\n// the UML box-overlap proof (2-D analog of packSubtree's disjoint-interval\n// induction). Every cell occupies exactly one (col, row) slot; colW[c] is\n// the widest cell in column c; rowH[r] is the tallest cell in row r. Column\n// x-origins accumulate left-to-right with colGap between columns; row\n// y-origins accumulate top-to-bottom with rowGap between rows. cellX/cellY\n// are the CENTER coordinates of each cell — callers subtract w/2 or h/2 to\n// get the top-left corner for drawing.\n\nexport interface GridCell {\n col: number;\n row: number;\n w: number;\n h: number;\n}\n\nexport interface GridResult {\n /** Center x of each cell (parallel to the input cells array). */\n cellX: number[];\n /** Center y of each cell (parallel to the input cells array). */\n cellY: number[];\n /** Width of each column (index = column index, 0 … maxCol). */\n colW: number[];\n /** Height of each row (index = row index, 0 … maxRow). */\n rowH: number[];\n}\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\n/**\n * Packs a set of cells into a declared 2-D grid.\n *\n * @param cells Each cell declares its (col, row) position and its own (w, h).\n * Multiple cells may share a column or row; no two cells may share BOTH\n * col and row (undefined behaviour — first-write wins for column/row maxima).\n * Columns and rows are identified by non-negative integer indices. Sparse\n * grids (gaps in column or row numbering) are legal; the skipped indices\n * get width/height 0 and contribute zero extent.\n * @param gaps colGap: horizontal gutter between adjacent columns;\n * rowGap: vertical gutter between adjacent rows.\n */\nexport function packGrid(\n cells: GridCell[],\n gaps: { colGap: number; rowGap: number },\n): GridResult {\n if (cells.length === 0) {\n return { cellX: [], cellY: [], colW: [], rowH: [] };\n }\n\n const { colGap, rowGap } = gaps;\n\n // ── 1. Find grid extents ───────────────────────────────────────────────────\n let maxCol = 0;\n let maxRow = 0;\n for (const c of cells) {\n if (c.col > maxCol) maxCol = c.col;\n if (c.row > maxRow) maxRow = c.row;\n }\n\n // ── 2. Compute per-column widths and per-row heights ──────────────────────\n // Initialise to 0 so sparse slots remain 0.\n const colW: number[] = Array.from({ length: maxCol + 1 }, () => 0);\n const rowH: number[] = Array.from({ length: maxRow + 1 }, () => 0);\n\n for (const c of cells) {\n if (c.w > colW[c.col]!) colW[c.col] = c.w;\n if (c.h > rowH[c.row]!) rowH[c.row] = c.h;\n }\n\n // ── 3. Accumulate column x-origins (left edge of each column) ────────────\n const colX: number[] = Array.from({ length: maxCol + 1 }, () => 0);\n for (let c = 1; c <= maxCol; c++) {\n colX[c] = round(colX[c - 1]! + colW[c - 1]! + colGap);\n }\n\n // ── 4. Accumulate row y-origins (top edge of each row) ────────────────────\n const rowY: number[] = Array.from({ length: maxRow + 1 }, () => 0);\n for (let r = 1; r <= maxRow; r++) {\n rowY[r] = round(rowY[r - 1]! + rowH[r - 1]! + rowGap);\n }\n\n // ── 5. Compute cell centers ────────────────────────────────────────────────\n // cellX[i] = left edge of column + half column width (CENTER x)\n // cellY[i] = top edge of row + half row height (CENTER y)\n const cellX: number[] = cells.map((c) =>\n round(colX[c.col]! + colW[c.col]! / 2),\n );\n const cellY: number[] = cells.map((c) =>\n round(rowY[c.row]! + rowH[c.row]! / 2),\n );\n\n return { cellX, cellY, colW, rowH };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clampLabel, romanNumeral, estimateTextWidth, FONT_FAMILY, xmlEscape, legendBlock, wrapLabelBalanced, LEGEND_SWATCH_W } from './chunk-
|
|
1
|
+
import { clampLabel, romanNumeral, estimateTextWidth, FONT_FAMILY, xmlEscape, legendBlock, wrapLabelBalanced, LEGEND_SWATCH_W } from './chunk-DVLWT565.js';
|
|
2
2
|
|
|
3
3
|
// src/pedigree/types.ts
|
|
4
4
|
var LIFE_STATUSES = ["alive", "stillbirth"];
|
|
@@ -1037,5 +1037,5 @@ function pedigreeSvg(input, opts = {}) {
|
|
|
1037
1037
|
}
|
|
1038
1038
|
|
|
1039
1039
|
export { LIFE_STATUSES, MAX_CONDITIONS_PER_INDIVIDUAL, PEDIGREE_SVG_LABELS_EN, PEDIGREE_TITLE_LABELS_EN, PED_ADDRESS_FONT, PED_CONDITION_FILLS, PED_DESCENT_ID_BASE, PED_GLYPH, PED_LABEL_FONT, PED_LABEL_GAP, PED_LABEL_LINE_H, PED_MATING_ID_BASE, PED_RISER_ID_BASE, PED_SIBBAR_ID_BASE, PED_TWINBAR_ID_BASE, PedigreeValidationError, computePedigreeLayout, pedigreeIssues, pedigreeLayoutSvg, pedigreeSvg, validatePedigree };
|
|
1040
|
-
//# sourceMappingURL=chunk-
|
|
1041
|
-
//# sourceMappingURL=chunk-
|
|
1040
|
+
//# sourceMappingURL=chunk-JBDA7E2O.js.map
|
|
1041
|
+
//# sourceMappingURL=chunk-JBDA7E2O.js.map
|