wotsui-vue-directives
Version:
Vue Directives for WotsUI
108 lines (107 loc) • 3.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const intersection_1 = require("../hooks/intersection");
const baseSettings = {
interval: 20,
ignorePunctuation: false,
};
function typewrite(el, binding) {
const typewriteData = parseData(el);
const settings = initSettings(binding);
const observer = new IntersectionObserver(handleIntersection, {
threshold: settings.treshold,
});
intersection_1.setIntersectionClasses(el, settings, false);
bindsMap.set(el, { data: typewriteData, settings });
observer.observe(el);
}
exports.default = typewrite;
function parseData(el) {
let data = [];
const nodes = el.childNodes;
nodes.forEach((node) => {
if (!node.textContent) {
return;
}
if (node.nodeType === 3) {
data.push({
node,
textContent: node.textContent,
});
node.textContent = '';
}
else {
data = data.concat(parseData(node));
}
});
return data;
}
function initSettings(binding) {
const settings = { ...intersection_1.intersectionSettings, ...baseSettings };
if (typeof binding.value === 'number') {
settings.interval = binding.value;
}
if (typeof binding.value === 'object') {
Object.assign(settings, binding.value);
}
if (binding.modifiers.ignorePunctuation) {
settings.ignorePunctuation = true;
}
return settings;
}
function handleIntersection(entries, observer) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const el = entry.target;
const { data, settings } = bindsMap.get(el);
if (!settings) {
observer.unobserve(el);
return;
}
intersection_1.setIntersectionClasses(el, settings, true);
typeText(data, settings);
bindsMap.delete(el);
observer.unobserve(el);
}
});
}
async function typeText(data, settings) {
for (const nodeData of data) {
try {
const { node, textContent } = nodeData;
if (!textContent) {
continue;
}
for (const char of textContent) {
node.textContent += char;
let estimatedTime = settings.interval;
if (!settings.ignorePunctuation) {
estimatedTime *= getCharMultiplier(char);
}
try {
await new Promise((resolve) => {
setTimeout(() => {
resolve(null);
}, estimatedTime);
});
}
catch (error) {
continue;
}
}
}
catch (error) {
continue;
}
}
}
function getCharMultiplier(char) {
if (char.match(/\.!\?/)) {
return 10;
}
if (char.match(/[;:]/)) {
return 5;
}
return 1;
}
const bindsMap = new Map();