react-text-to-speech
Version:
An easy-to-use React.js library that leverages the Web Speech API to convert text to speech.
67 lines (64 loc) • 3.88 kB
JavaScript
import { composeProps, idPrefix, highlightedTextIdSuffix, useSpeechInternal, hideElement, showElement } from './chunk-A4O2Q4ZN.js';
import { HiVolumeUp, HiVolumeOff, HiMiniStop } from './chunk-KE4WPWBB.js';
import { __objRest, __spreadValues } from './chunk-FZ4QVG4I.js';
import React, { useRef, useLayoutEffect } from 'react';
function HighlightedText(_a) {
var _b = _a, { id, children } = _b, props = __objRest(_b, ["id", "children"]);
const uniqueId = `${idPrefix}${id}`;
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", __spreadValues({}, composeProps(uniqueId, props))), /* @__PURE__ */ React.createElement("div", __spreadValues({}, composeProps(`${uniqueId}${highlightedTextIdSuffix}`, props))));
}
function Speech(_a) {
var _b = _a, {
startBtn = /* @__PURE__ */ React.createElement(HiVolumeUp, null),
pauseBtn = /* @__PURE__ */ React.createElement(HiVolumeOff, null),
stopBtn = /* @__PURE__ */ React.createElement(HiMiniStop, null),
useStopOverPause = false,
enableConditionalHighlight = false,
props = {},
children
} = _b, hookProps = __objRest(_b, [
"startBtn",
"pauseBtn",
"stopBtn",
"useStopOverPause",
"enableConditionalHighlight",
"props",
"children"
]);
const _a2 = useSpeechInternal(hookProps), { uniqueId, normalizedText, reactContent, Text, speechStatus } = _a2, childrenOptions = __objRest(_a2, ["uniqueId", "normalizedText", "reactContent", "Text", "speechStatus"]);
const { isInQueue, start, pause, stop } = childrenOptions;
const sourceRef = useRef(null);
useLayoutEffect(() => {
const containers = Array.from(document.getElementsByClassName(uniqueId)).filter((container) => container !== sourceRef.current);
if (!containers.length) return;
const sourceHTML = sourceRef.current.innerHTML;
containers.forEach((container) => container.innerHTML = sourceHTML);
if (!enableConditionalHighlight) return;
const observer = new MutationObserver(() => {
const observedContainers = Array.from(document.getElementsByClassName(uniqueId));
observedContainers.forEach((container) => {
if (!container.innerHTML) container.innerHTML = sourceHTML;
});
});
observer.observe(document.body, { childList: true, subtree: true });
return () => observer.disconnect();
}, [normalizedText, uniqueId]);
useLayoutEffect(() => {
const containers = Array.from(document.getElementsByClassName(uniqueId)).filter((container) => container !== sourceRef.current);
if (!containers.length) return;
const highlightedTextContainers = Array.from(document.getElementsByClassName(`${uniqueId}${highlightedTextIdSuffix}`));
if (hookProps.showOnlyHighlightedText) {
const sourceHTML = sourceRef.current.innerHTML;
containers.forEach(hideElement);
highlightedTextContainers.forEach((container) => {
container.innerHTML = sourceHTML;
showElement(container);
});
} else {
highlightedTextContainers.forEach(hideElement);
containers.forEach(showElement);
}
}, [reactContent, uniqueId]);
return typeof children === "function" ? children(childrenOptions) : /* @__PURE__ */ React.createElement("div", __spreadValues({ style: { display: "flex", columnGap: "1rem" } }, props), !isInQueue ? /* @__PURE__ */ React.createElement("span", { role: "button", onClick: start }, startBtn) : useStopOverPause ? /* @__PURE__ */ React.createElement("span", { role: "button", onClick: stop }, stopBtn) : /* @__PURE__ */ React.createElement("span", { role: "button", onClick: pause }, pauseBtn), !useStopOverPause && stopBtn && /* @__PURE__ */ React.createElement("span", { role: "button", onClick: stop }, stopBtn), /* @__PURE__ */ React.createElement(Text, { ref: sourceRef, style: { display: "none" } }));
}
export { HighlightedText, Speech };