UNPKG

animatry

Version:
127 lines (122 loc) 5.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.splitText = factory()); })(this, (function () { 'use strict'; const select = (input) => { if (typeof input === 'string') { const match = input.match(/\w+\[(\d+)\]/); if (match) { const index = parseInt(match[1], 10); const elements = document.querySelectorAll(input.replace(`[${match[1]}]`, '')); return [elements[index]]; } return Array.from(document.querySelectorAll(input)); } else if (input instanceof Element) { return [input]; } else if (input instanceof NodeList || input instanceof Array) { return Array.from(input).flatMap(entry => select(entry)); } else if (input instanceof Document) { return [input.documentElement]; } warn('Could not collect these elements:' + input); return []; }; const _p = 'background-color:rgba(0,0,0,0.5);padding:3px 7.5px;'; const warn = (m) => { console.warn(`%cAnimatry%c ${m}`, _p, ''); }; function splitText(elements, options) { elements = select(elements); const splitChars = /char/.test(options); const splitWords = /word/.test(options); const splitLines = /line/.test(options); const lines = []; const words = []; const chars = []; elements.forEach((element) => { element.style.minWidth = element.clientWidth + 'px'; const clone = element.cloneNode(true); const processNode = (node) => { var _a; if (node.nodeType === Node.TEXT_NODE) { const textContent = (_a = node.textContent) !== null && _a !== void 0 ? _a : ''; if (textContent.trim() === '') return; const wordsArray = textContent.split(/(\s+)/); const container = document.createDocumentFragment(); wordsArray.forEach((wordString) => { if (wordString.trim() !== '') { const word = document.createElement('span'); word.classList.add('word'); word.style.display = 'inline-block'; if (splitChars) { wordString.split('').forEach((charString) => { const char = document.createElement('span'); char.classList.add('char'); char.style.display = 'inline-block'; char.textContent = charString; word.appendChild(char); chars.push(char); }); } else { word.textContent = wordString; } container.appendChild(word); words.push(word); } else { container.appendChild(document.createTextNode(' ')); } }); node.replaceWith(container); } else if (node.nodeType === Node.ELEMENT_NODE) { Array.from(node.childNodes).forEach(processNode); } }; if (splitWords || splitChars || splitLines) { processNode(clone); } const processLines = () => { const nodes = Array.from(clone.childNodes); element.innerHTML = ''; const lineFragments = []; let currentHeight = 0; function createLine(node) { const lineFragment = document.createElement('div'); lineFragment.classList.add('line'); lineFragment.appendChild(node); element.appendChild(lineFragment); currentHeight = lineFragment.clientHeight; lineFragments.push(lineFragment); } if (nodes.length > 0) { createLine(nodes.shift()); } while (nodes.length > 0) { const lastLine = lineFragments[lineFragments.length - 1]; lastLine.appendChild(nodes.shift()); if (lastLine.clientHeight > currentHeight) { createLine(lastLine.lastChild); } } return lineFragments; }; if (splitLines) { lines.push(...processLines()); } else { element.replaceWith(clone); } }); return { lines, words, chars, }; } return splitText; }));