export const MAX_NAME_LENGTH = 80; export function parseName(raw) { if (typeof raw !== "string") return undefined; const trimmed = raw.trim(); if (trimmed.length === 0 || trimmed.length > MAX_NAME_LENGTH) return undefined; return trimmed; } export function hasNameConflict(records, sameParent, name, exceptId) { const needle = name.toLowerCase(); return records.some((record) => sameParent(record) && record.id !== exceptId && record.name.toLowerCase() === needle ); } export function nextSortIndex(siblings) { return siblings.reduce((max, record) => Math.max(max, record.sortIndex ?? 0), 0) + 1; } export function isExactIdSet(ids, allowed) { if (ids.length !== allowed.size) return false; const seen = new Set(); for (const id of ids) { if (!allowed.has(id) || seen.has(id)) return false; seen.add(id); } return true; }