import React from 'react'; type SplitWordsProps = { children: React.ReactNode; wrapper: React.ReactElement; delimiter?: string; }; type SplitCharsProps = { children: React.ReactNode; wrapper: React.ReactElement; }; const escapeRegExp = (regExp: string) => { var specialChars = ['$', '^', '*', '(', ')', '+', '[', ']', '{', '}', '\\', '|', '.', '?', '/']; var regex = new RegExp('(\\' + specialChars.join('|\\') + ')', 'g'); return regExp.replace(regex, '\\$1'); }; // TODO: possible or better to output all the refs as one array? export const SplitWords = React.forwardRef( ({ children, wrapper, delimiter = ' ' }, ref) => { if (typeof children !== 'string') { throw new Error('SplitWords only accepts a string as child.'); } const words = children.split(new RegExp(`(${escapeRegExp(delimiter)})`, 'g')); return ( <> {words.map((word: string, i: number) => { if (delimiter === ' ' && word === delimiter) { return ; } return React.cloneElement(wrapper, { ref, key: i }, word); })} ); } ); // TODO: possible or better to output all the refs as one array? export const SplitChars = React.forwardRef(({ children, wrapper }, ref) => { if (typeof children !== 'string') { throw new Error('SplitChars only accepts a string as child.'); } return ( <> {children .split( /(?=(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/ ) .map((char: string, i: number) => { // TODO: enhance check for space if (char === ' ') { return ; } return React.cloneElement(wrapper, { ref, key: i }, char); })} ); }); export const SplitLetters = React.forwardRef((props: any, ref) => { console.warn('Deprecation warning: Use SplitChars instead of SplitLetters'); return ; });