/** Split a group name into normalized hierarchy segments. */ export function splitSampleGroupPath(groupName: string, separator: string): string[] { const parts = groupName .split(separator) .map(part => part.trim()) .filter(part => part.length > 0) return parts.length > 0 ? parts : [groupName] } /** First normalized hierarchy segment, used as the reorderable family key. */ export function getSampleGroupMajorPrefix(groupName: string, separator: string): string { return splitSampleGroupPath(groupName, separator)[0] } /** Normalized path above a concrete leaf group. */ export function getSampleGroupParentPath(groupName: string, separator: string): string { const parts = splitSampleGroupPath(groupName, separator) return parts.length > 1 ? parts.slice(0, -1).join(separator) : '' }