vevet
Version:
Vevet is a JavaScript library for creative development that simplifies crafting rich interactions like split text animations, carousels, marquees, preloading, and more.
71 lines (53 loc) • 1.83 kB
text/typescript
import split from 'lodash.split';
import { cnAdd } from '@/internal/cn';
import { doc } from '@/internal/env';
import {
ISplitTextLetterMeta,
ISplitTextStaticProps,
ISplitTextWordMeta,
} from '../types';
import { isIgnored } from './isIgnored';
interface IProps {
wordsMeta: ISplitTextWordMeta[];
classname: string;
tagName: keyof HTMLElementTagNameMap;
ignore: ISplitTextStaticProps['ignore'];
}
/**
* Wraps each letter in every word inside the container with the specified HTML tag and class name.
*/
export function wrapLetters({ wordsMeta, classname, tagName, ignore }: IProps) {
const lettersMeta: ISplitTextLetterMeta[] = [];
const baseElement = doc.createElement(tagName);
baseElement.style.display = 'inline-block';
cnAdd(baseElement, classname);
// Iterate over each word to wrap its letters
wordsMeta.forEach((wordMeta) => {
if (isIgnored(wordMeta.element, ignore)) {
return;
}
const textNode = wordMeta.element.childNodes[0];
if (!textNode) {
return;
}
const text = textNode.textContent;
if (!text) {
return;
}
// Split the word into individual letters
const splitLetters = split(text, '');
splitLetters.forEach((letterContents) => {
const element = baseElement.cloneNode(false) as HTMLElement;
element.appendChild(doc.createTextNode(letterContents));
// Append the letter element to the word's container
wordMeta.element.insertBefore(element, textNode);
const letter: ISplitTextLetterMeta = { element };
// Add the letter to the word's letters array and the global letters array
wordMeta.letters.push(letter);
lettersMeta.push(letter);
});
// Remove the original text node after wrapping the letters
textNode.remove();
});
return { lettersMeta };
}