"use strict"; (function (global) { function buildGraph(nodes = [], opts = {}) { const idOf = opts.idOf || (n => n?.id); const edgesOf = opts.edgesOf || ((n) => [...(n?.parents || []), ...(n?.children || [])]); const byId = new Map(nodes.filter(Boolean).map(n => [idOf(n), n]).filter(([id]) => id)); const graph = new Map([...byId.keys()].map(id => [id, new Set()])); const connect = (a, b) => { if (!a || !b || a === b || !graph.has(a) || !graph.has(b)) return; graph.get(a).add(b); graph.get(b).add(a); }; for (const node of byId.values()) { const id = idOf(node); for (const next of edgesOf(node, byId)) connect(id, next); } return { graph, byId }; } function connectedComponents(nodes = [], opts = {}) { const { graph, byId } = buildGraph(nodes, opts); const sort = opts.sort || null; const nodeList = [...byId.values()].sort(sort || (() => 0)); const seen = new Set(); const comps = []; for (const node of nodeList) { const start = opts.idOf ? opts.idOf(node) : node.id; if (!start || seen.has(start)) continue; const stack = [start]; const comp = []; seen.add(start); while (stack.length) { const id = stack.pop(); const item = byId.get(id); if (item) comp.push(item); for (const next of graph.get(id) || []) { if (seen.has(next)) continue; seen.add(next); stack.push(next); } } if (!opts.filter || opts.filter(comp)) comps.push(sort ? comp.sort(sort) : comp); } return comps; } function addParentEdge(childId, parentId, known, parentsByChild, childrenByParent) { if (!childId || !parentId || childId === parentId || !known?.has?.(childId) || !known.has(parentId)) return false; if (!parentsByChild.has(childId)) parentsByChild.set(childId, new Set()); if (!childrenByParent.has(parentId)) childrenByParent.set(parentId, new Set()); parentsByChild.get(childId).add(parentId); childrenByParent.get(parentId).add(childId); return true; } function buildRelationIndex(family = {}) { const known = new Set(Object.keys(family || {})); const parentsByChild = new Map(); const childrenByParent = new Map(); const addParent = (childId, parentId) => addParentEdge(childId, parentId, known, parentsByChild, childrenByParent); for (const n of Object.values(family || {})) { if (!n?.id) continue; for (const parentId of n.parents || []) addParent(n.id, parentId); for (const childId of n.children || []) addParent(childId, n.id); } return { parentsByChild, childrenByParent }; } function relationAllowsParentChild(family = {}, childId, parentId) { const child = family?.[childId]; const parent = family?.[parentId]; if (!child || !parent) return false; const childListsParent = Array.isArray(child.parents) && child.parents.includes(parentId); const parentListsChild = Array.isArray(parent.children) && parent.children.includes(childId); return childListsParent || parentListsChild; } global.TarinaiFamilyGraph = { connectedComponents, addParentEdge, buildRelationIndex, relationAllowsParentChild, }; })(typeof window !== "undefined" ? window : globalThis);