function startsWithParenthesis(part: string) { return /^[({[<]/.test(part); } // Reuse a single Intl.Segmenter instance to avoid repeated allocations const GRAPHEME_SEGMENTER = typeof Intl.Segmenter === 'function' ? new Intl.Segmenter('en', { granularity: 'grapheme' }) : undefined; // Helper to split the string into grapheme clusters, which handles complex characters correctly function getGraphemes(str: string): string[] { if (GRAPHEME_SEGMENTER) { return Array.from(GRAPHEME_SEGMENTER.segment(str), (s) => s.segment); } // Fallback to still splitting by Unicode code points when Intl.Segmenter is not available (NOTE: Won't handle complex graphemes perfectly) return Array.from(str); } export function getInitials(name: string) { if (name.length === 2 && /^[A-Z]{2}$/.test(name)) { return name; } const allInitials = name .split(' ') .filter((part) => !startsWithParenthesis(part)) .map((part) => getGraphemes(part)[0]) .join('') .toUpperCase(); // Get graphemes of the initials string to handle complex characters correctly const graphemes = getGraphemes(allInitials); if (graphemes.length === 1) { return graphemes[0]; } return graphemes[0] + graphemes[graphemes.length - 1]; }