UNPKG

accessibility-sidebar

Version:

A comprehensive, lightweight accessibility widget for web and mobile apps with WCAG 2.1 AA compliance

1,441 lines (1,247 loc) 804 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("react")); else if(typeof define === 'function' && define.amd) define(["React"], factory); else if(typeof exports === 'object') exports["AccessibilitySidebar"] = factory(require("react")); else root["AccessibilitySidebar"] = factory(root["React"]); })(typeof self !== 'undefined' ? self : this, (__WEBPACK_EXTERNAL_MODULE__156__) => { return /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ 14: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports["default"] = isPrefixedValue; var RE = /-webkit-|-moz-|-ms-/; function isPrefixedValue(value) { return typeof value === 'string' && RE.test(value); } /***/ }), /***/ 20: /***/ ((__unused_webpack_module, exports) => { "use strict"; var __webpack_unused_export__; __webpack_unused_export__ = ({ value: true }); exports.A = logical; var alternativeProps = { marginBlockStart: ['WebkitMarginBefore'], marginBlockEnd: ['WebkitMarginAfter'], marginInlineStart: ['WebkitMarginStart', 'MozMarginStart'], marginInlineEnd: ['WebkitMarginEnd', 'MozMarginEnd'], paddingBlockStart: ['WebkitPaddingBefore'], paddingBlockEnd: ['WebkitPaddingAfter'], paddingInlineStart: ['WebkitPaddingStart', 'MozPaddingStart'], paddingInlineEnd: ['WebkitPaddingEnd', 'MozPaddingEnd'], borderBlockStart: ['WebkitBorderBefore'], borderBlockStartColor: ['WebkitBorderBeforeColor'], borderBlockStartStyle: ['WebkitBorderBeforeStyle'], borderBlockStartWidth: ['WebkitBorderBeforeWidth'], borderBlockEnd: ['WebkitBorderAfter'], borderBlockEndColor: ['WebkitBorderAfterColor'], borderBlockEndStyle: ['WebkitBorderAfterStyle'], borderBlockEndWidth: ['WebkitBorderAfterWidth'], borderInlineStart: ['WebkitBorderStart', 'MozBorderStart'], borderInlineStartColor: ['WebkitBorderStartColor', 'MozBorderStartColor'], borderInlineStartStyle: ['WebkitBorderStartStyle', 'MozBorderStartStyle'], borderInlineStartWidth: ['WebkitBorderStartWidth', 'MozBorderStartWidth'], borderInlineEnd: ['WebkitBorderEnd', 'MozBorderEnd'], borderInlineEndColor: ['WebkitBorderEndColor', 'MozBorderEndColor'], borderInlineEndStyle: ['WebkitBorderEndStyle', 'MozBorderEndStyle'], borderInlineEndWidth: ['WebkitBorderEndWidth', 'MozBorderEndWidth'] }; function logical(property, value, style) { if (Object.prototype.hasOwnProperty.call(alternativeProps, property)) { var alternativePropList = alternativeProps[property]; for (var i = 0, len = alternativePropList.length; i < len; ++i) { style[alternativePropList[i]] = value; } } } /***/ }), /***/ 49: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports["default"] = prefixProperty; var _capitalizeString = __webpack_require__(91); var _capitalizeString2 = _interopRequireDefault(_capitalizeString); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function prefixProperty(prefixProperties, property, style) { var requiredPrefixes = prefixProperties[property]; if (requiredPrefixes && style.hasOwnProperty(property)) { var capitalizedProperty = (0, _capitalizeString2.default)(property); for (var i = 0; i < requiredPrefixes.length; ++i) { var prefixedProperty = requiredPrefixes[i] + capitalizedProperty; if (!style[prefixedProperty]) { style[prefixedProperty] = style[property]; } } } return style; } /***/ }), /***/ 91: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports["default"] = capitalizeString; function capitalizeString(str) { return str.charAt(0).toUpperCase() + str.slice(1); } /***/ }), /***/ 99: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports["default"] = isObject; function isObject(value) { return value instanceof Object && !Array.isArray(value); } /***/ }), /***/ 129: /***/ ((__unused_webpack_module, exports) => { "use strict"; var __webpack_unused_export__; __webpack_unused_export__ = ({ value: true }); exports.A = sizing; var prefixes = ['-webkit-', '-moz-', '']; var properties = { maxHeight: true, maxWidth: true, width: true, height: true, columnWidth: true, minWidth: true, minHeight: true }; var values = { 'min-content': true, 'max-content': true, 'fill-available': true, 'fit-content': true, 'contain-floats': true }; function sizing(property, value) { if (properties.hasOwnProperty(property) && values.hasOwnProperty(value)) { return prefixes.map(function (prefix) { return prefix + value; }); } } /***/ }), /***/ 147: /***/ (() => { function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } // Enhanced Accessibility Sidebar with Narrator - Standalone JSX Component window.AccessibilitySidebar = function () { // State for panel visibility and settings var _React$useState = React.useState(false), _React$useState2 = _slicedToArray(_React$useState, 2), isPanelOpen = _React$useState2[0], setIsPanelOpen = _React$useState2[1]; var _React$useState3 = React.useState(false), _React$useState4 = _slicedToArray(_React$useState3, 2), isDragging = _React$useState4[0], setIsDragging = _React$useState4[1]; var _React$useState5 = React.useState({ x: 16, y: 100 }), _React$useState6 = _slicedToArray(_React$useState5, 2), position = _React$useState6[0], setPosition = _React$useState6[1]; var _React$useState7 = React.useState({ x: 0, y: 0 }), _React$useState8 = _slicedToArray(_React$useState7, 2), startPos = _React$useState8[0], setStartPos = _React$useState8[1]; var _React$useState9 = React.useState(false), _React$useState0 = _slicedToArray(_React$useState9, 2), isMobile = _React$useState0[0], setIsMobile = _React$useState0[1]; // Voice and narrator states var _React$useState1 = React.useState([]), _React$useState10 = _slicedToArray(_React$useState1, 2), availableRomanianVoices = _React$useState10[0], setAvailableRomanianVoices = _React$useState10[1]; var _React$useState11 = React.useState(null), _React$useState12 = _slicedToArray(_React$useState11, 2), selectedVoice = _React$useState12[0], setSelectedVoice = _React$useState12[1]; var _React$useState13 = React.useState(0), _React$useState14 = _slicedToArray(_React$useState13, 2), readingProgress = _React$useState14[0], setReadingProgress = _React$useState14[1]; var _React$useState15 = React.useState(null), _React$useState16 = _slicedToArray(_React$useState15, 2), currentUtterance = _React$useState16[0], setCurrentUtterance = _React$useState16[1]; var _React$useState17 = React.useState(0.8), _React$useState18 = _slicedToArray(_React$useState17, 2), speechRate = _React$useState18[0], setSpeechRate = _React$useState18[1]; var _React$useState19 = React.useState(1.0), _React$useState20 = _slicedToArray(_React$useState19, 2), speechPitch = _React$useState20[0], setSpeechPitch = _React$useState20[1]; // Accessibility states var _React$useState21 = React.useState(0), _React$useState22 = _slicedToArray(_React$useState21, 2), fontSize = _React$useState22[0], setFontSize = _React$useState22[1]; // 0: normal, 1: larger, 2: largest var _React$useState23 = React.useState(false), _React$useState24 = _slicedToArray(_React$useState23, 2), highContrast = _React$useState24[0], setHighContrast = _React$useState24[1]; var _React$useState25 = React.useState(0), _React$useState26 = _slicedToArray(_React$useState25, 2), lineHeight = _React$useState26[0], setLineHeight = _React$useState26[1]; // 0: normal, 1: larger, 2: largest var _React$useState27 = React.useState(false), _React$useState28 = _slicedToArray(_React$useState27, 2), isReading = _React$useState28[0], setIsReading = _React$useState28[1]; // Check for mobile devices React.useEffect(function () { var checkMobile = function checkMobile() { setIsMobile(window.innerWidth <= 768); }; checkMobile(); window.addEventListener('resize', checkMobile); return function () { return window.removeEventListener('resize', checkMobile); }; }, []); // Voice setup and management React.useEffect(function () { var updateVoices = function updateVoices() { var voices = window.speechSynthesis.getVoices(); var romanianVoices = voices.filter(function (voice) { return voice.lang.includes('ro') || voice.name.toLowerCase().includes('romanian') || voice.name.toLowerCase().includes('română'); }); setAvailableRomanianVoices(romanianVoices); // Auto-select the best Romanian voice if (romanianVoices.length > 0 && !selectedVoice) { var bestVoice = romanianVoices.find(function (v) { return !v.name.toLowerCase().includes('standard') && !v.name.toLowerCase().includes('compact'); }) || romanianVoices[0]; setSelectedVoice(bestVoice); } }; updateVoices(); if (window.speechSynthesis.onvoiceschanged !== undefined) { window.speechSynthesis.onvoiceschanged = updateVoices; } return function () { if (window.speechSynthesis.onvoiceschanged !== undefined) { window.speechSynthesis.onvoiceschanged = null; } }; }, [selectedVoice]); // Handle font size changes var handleFontSizeChange = function handleFontSizeChange() { var newSize = (fontSize + 1) % 3; setFontSize(newSize); // Remove existing classes document.body.classList.remove('font-size-larger', 'font-size-largest'); // Add appropriate class if (newSize === 1) { document.body.classList.add('font-size-larger'); } else if (newSize === 2) { document.body.classList.add('font-size-largest'); } }; // Handle contrast toggle var handleContrastToggle = function handleContrastToggle() { var newState = !highContrast; setHighContrast(newState); if (newState) { document.body.classList.add('high-contrast'); } else { document.body.classList.remove('high-contrast'); } }; // Handle line height changes var handleLineHeightChange = function handleLineHeightChange() { var newHeight = (lineHeight + 1) % 3; setLineHeight(newHeight); // Remove existing classes document.body.classList.remove('line-height-larger', 'line-height-largest'); // Add appropriate class if (newHeight === 1) { document.body.classList.add('line-height-larger'); } else if (newHeight === 2) { document.body.classList.add('line-height-largest'); } }; // Enhanced text-to-speech with narrator features var handleReadAloud = function handleReadAloud() { if (!('speechSynthesis' in window)) { alert('Browserul dvs. nu suportă citirea cu voce tare'); return; } if (isReading) { window.speechSynthesis.cancel(); setIsReading(false); setReadingProgress(0); setCurrentUtterance(null); } else { // Get all the text from the main content var contentArea = document.querySelector('.content-area') || document.querySelector('main') || document.body; // Get text content from relevant elements, excluding navigation and controls var textElements = contentArea.querySelectorAll('p, li, h1, h2, h3, h4, h5, h6, blockquote, td'); var textContent = Array.from(textElements).filter(function (el) { // Exclude navigation, accessibility controls, and other UI elements return !el.closest('.toc') && !el.closest('.content-nav') && !el.closest('.accessibility-sidebar') && !el.closest('.back-to-top') && !el.closest('.search-container') && !el.closest('nav') && !el.closest('header') && !el.closest('footer') && !el.classList.contains('sr-only'); }).map(function (el) { return el.textContent.trim(); }).filter(function (text) { return text.length > 0; }).join('. '); if (!textContent) { alert('Nu s-a găsit conținut pentru citire'); return; } // Split into manageable chunks for better speech synthesis var sentences = textContent.match(/[^\.!?]+[\.!?]+/g) || [textContent]; var chunks = []; var currentChunk = ''; sentences.forEach(function (sentence) { if ((currentChunk + sentence).length > 200) { if (currentChunk) chunks.push(currentChunk.trim()); currentChunk = sentence; } else { currentChunk += sentence; } }); if (currentChunk) chunks.push(currentChunk.trim()); var currentIndex = 0; var _speakNext = function speakNext() { if (currentIndex < chunks.length && isReading) { var utterance = new SpeechSynthesisUtterance(chunks[currentIndex]); utterance.lang = 'ro-RO'; utterance.rate = speechRate; utterance.pitch = speechPitch; utterance.volume = 1.0; // Use selected voice if available if (selectedVoice) { utterance.voice = selectedVoice; } utterance.onstart = function () { var progress = Math.round(currentIndex / chunks.length * 100); setReadingProgress(progress); }; utterance.onend = function () { currentIndex++; if (currentIndex < chunks.length) { // Small pause between chunks setTimeout(_speakNext, 300); } else { setIsReading(false); setReadingProgress(100); // Reset progress after completion setTimeout(function () { return setReadingProgress(0); }, 2000); } }; utterance.onerror = function (event) { console.error('Speech synthesis error:', event.error); setIsReading(false); setReadingProgress(0); alert('Eroare la citirea cu voce tare: ' + event.error); }; setCurrentUtterance(utterance); window.speechSynthesis.speak(utterance); } }; setIsReading(true); setReadingProgress(0); // Cancel any previous speech window.speechSynthesis.cancel(); // Start speaking setTimeout(_speakNext, 100); // Small delay to ensure cancellation is complete } }; // Handle speech rate change var handleSpeechRateChange = function handleSpeechRateChange() { var rates = [0.6, 0.8, 1.0, 1.2]; var currentIndex = rates.indexOf(speechRate); var newRate = rates[(currentIndex + 1) % rates.length]; setSpeechRate(newRate); }; // Handle voice selection var handleVoiceChange = function handleVoiceChange() { if (availableRomanianVoices.length <= 1) return; var currentIndex = availableRomanianVoices.indexOf(selectedVoice); var nextIndex = (currentIndex + 1) % availableRomanianVoices.length; setSelectedVoice(availableRomanianVoices[nextIndex]); }; // Handle panel dragging var handleMouseDown = function handleMouseDown(e) { if (isMobile) return; // No dragging on mobile setIsDragging(true); setStartPos({ x: e.clientX - position.x, y: e.clientY - position.y }); // Prevent text selection during drag e.preventDefault(); }; var handleMouseMove = function handleMouseMove(e) { if (!isDragging) return; // Calculate new position with bounds checking var newX = Math.max(0, Math.min(window.innerWidth - 60, e.clientX - startPos.x)); var newY = Math.max(0, Math.min(window.innerHeight - 60, e.clientY - startPos.y)); setPosition({ x: newX, y: newY }); }; var handleMouseUp = function handleMouseUp() { setIsDragging(false); }; // Set up mouse event listeners for dragging React.useEffect(function () { if (isDragging) { document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); } else { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); } return function () { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; }, [isDragging]); // Reset position when switching between mobile and desktop React.useEffect(function () { if (isMobile) { setPosition({ x: 16, y: window.innerHeight - 80 }); } else { setPosition({ x: 16, y: 100 }); } }, [isMobile]); // Handle keyboard accessibility var handleKeyDown = function handleKeyDown(e, action) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); action(); } }; // Reset all settings var resetAllSettings = function resetAllSettings() { setFontSize(0); setHighContrast(false); setLineHeight(0); setSpeechRate(0.8); setSpeechPitch(1.0); if (isReading) { window.speechSynthesis.cancel(); setIsReading(false); setReadingProgress(0); } // Remove all classes document.body.classList.remove('font-size-larger', 'font-size-largest', 'high-contrast', 'line-height-larger', 'line-height-largest'); }; // Get current voice name for display var getCurrentVoiceName = function getCurrentVoiceName() { if (!selectedVoice) return 'Implicit'; return selectedVoice.name.length > 20 ? selectedVoice.name.substring(0, 20) + '...' : selectedVoice.name; }; // Get speech rate label var getSpeechRateLabel = function getSpeechRateLabel() { switch (speechRate) { case 0.6: return 'Încet'; case 0.8: return 'Normal'; case 1.0: return 'Mediu'; case 1.2: return 'Rapid'; default: return 'Normal'; } }; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, "\n @keyframes pulse {\n 0% { opacity: 0.4; }\n 50% { opacity: 1; }\n 100% { opacity: 0.4; }\n }\n\n @keyframes reading-progress {\n 0% { transform: scaleX(0); }\n 100% { transform: scaleX(1); }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .accessibility-sidebar {\n transition: none !important;\n }\n\n @keyframes pulse {\n 0%, 50%, 100% { opacity: 1; }\n }\n }\n\n .a11y-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n }\n\n .a11y-icon.large {\n width: 24px;\n height: 24px;\n }\n\n .reading-progress-indicator {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 3px;\n background: linear-gradient(90deg, #4CAF50, #2196F3);\n border-radius: 0 0 12px 12px;\n transition: width 0.3s ease;\n }\n\n .voice-indicator {\n font-size: 10px;\n opacity: 0.7;\n margin-top: 2px;\n line-height: 1;\n }\n "), /*#__PURE__*/React.createElement("div", { className: "accessibility-sidebar ".concat(isPanelOpen ? 'expanded' : 'collapsed', " ").concat(isMobile ? 'mobile' : 'desktop'), style: _defineProperty({ position: 'fixed', top: isMobile ? 'auto' : "".concat(position.y, "px"), left: isMobile ? 'auto' : "".concat(position.x, "px"), bottom: isMobile ? '20px' : 'auto', right: isMobile ? '20px' : 'auto', zIndex: 9999, transition: 'all 0.3s ease', background: highContrast ? '#000' : 'white', color: highContrast ? '#fff' : '#333', border: "2px solid ".concat(highContrast ? '#fff' : '#2196F3'), borderRadius: '12px', boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', padding: isPanelOpen ? '16px' : '8px', width: isPanelOpen ? isMobile ? '300px' : '300px' : '56px', maxWidth: '90vw', display: 'flex', flexDirection: 'column', gap: '12px', cursor: isDragging ? 'grabbing' : 'auto' }, "position", 'relative') }, isReading && readingProgress > 0 && /*#__PURE__*/React.createElement("div", { className: "reading-progress-indicator", style: { width: "".concat(readingProgress, "%") } }), /*#__PURE__*/React.createElement("div", { className: "accessibility-header", style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px', cursor: isMobile ? 'auto' : 'grab', padding: '4px' }, onMouseDown: handleMouseDown, role: "presentation" }, isPanelOpen && /*#__PURE__*/React.createElement("div", { className: "title", style: { fontWeight: 'bold', display: 'flex', alignItems: 'center', gap: '8px' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-universal-access", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("span", null, "Accesibilitate")), /*#__PURE__*/React.createElement("button", { "aria-label": isPanelOpen ? "Închide panoul de accesibilitate" : "Deschide panoul de accesibilitate", title: isPanelOpen ? "Închide panoul" : "Opțiuni de accesibilitate", onClick: function onClick() { return setIsPanelOpen(!isPanelOpen); }, style: { background: 'transparent', border: 'none', cursor: 'pointer', padding: '8px', borderRadius: '8px', color: highContrast ? '#fff' : '#2196F3', marginLeft: isPanelOpen ? '0' : 'auto', marginRight: isPanelOpen ? '0' : 'auto', display: 'flex', alignItems: 'center', justifyContent: 'center' }, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, function () { return setIsPanelOpen(!isPanelOpen); }); } }, isPanelOpen ? /*#__PURE__*/React.createElement("div", { className: "a11y-icon large" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-compress", "aria-hidden": "true" })) : /*#__PURE__*/React.createElement("div", { className: "a11y-icon large" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-universal-access", "aria-hidden": "true" })))), isPanelOpen && /*#__PURE__*/React.createElement("div", { className: "control-buttons", style: { display: 'flex', flexDirection: 'column', gap: '12px' }, role: "group", "aria-label": "Controale de accesibilitate" }, /*#__PURE__*/React.createElement("button", { "aria-label": "M\u0103rime text: ".concat(fontSize === 0 ? 'normal' : fontSize === 1 ? 'mare' : 'foarte mare'), "aria-pressed": fontSize > 0, className: "control-button ".concat(fontSize > 0 ? 'active' : ''), onClick: handleFontSizeChange, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, handleFontSizeChange); }, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: fontSize > 0 ? highContrast ? '#fff' : '#e3f2fd' : highContrast ? '#333' : '#f5f5f5', color: fontSize > 0 ? highContrast ? '#000' : '#2196F3' : highContrast ? '#fff' : '#333', cursor: 'pointer', textAlign: 'left', fontWeight: fontSize > 0 ? 'bold' : 'normal', transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-font", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } }, /*#__PURE__*/React.createElement("span", null, "M\u0103rime text"), /*#__PURE__*/React.createElement("small", { style: { fontSize: '12px', opacity: '0.8' } }, fontSize === 0 ? 'Normal' : fontSize === 1 ? 'Mare' : 'Foarte mare'))), /*#__PURE__*/React.createElement("button", { "aria-label": "Contrast: ".concat(highContrast ? 'ridicat' : 'normal'), "aria-pressed": highContrast, className: "control-button ".concat(highContrast ? 'active' : ''), onClick: handleContrastToggle, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, handleContrastToggle); }, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: highContrast ? highContrast ? '#fff' : '#e3f2fd' : highContrast ? '#333' : '#f5f5f5', color: highContrast ? highContrast ? '#000' : '#2196F3' : highContrast ? '#fff' : '#333', cursor: 'pointer', textAlign: 'left', fontWeight: highContrast ? 'bold' : 'normal', transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: highContrast ? "fas fa-sun" : "fas fa-moon", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } }, /*#__PURE__*/React.createElement("span", null, "Contrast"), /*#__PURE__*/React.createElement("small", { style: { fontSize: '12px', opacity: '0.8' } }, highContrast ? 'Ridicat' : 'Normal'))), /*#__PURE__*/React.createElement("button", { "aria-label": "Spa\u021Biu \xEEntre r\xE2nduri: ".concat(lineHeight === 0 ? 'normal' : lineHeight === 1 ? 'mare' : 'foarte mare'), "aria-pressed": lineHeight > 0, className: "control-button ".concat(lineHeight > 0 ? 'active' : ''), onClick: handleLineHeightChange, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, handleLineHeightChange); }, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: lineHeight > 0 ? highContrast ? '#fff' : '#e3f2fd' : highContrast ? '#333' : '#f5f5f5', color: lineHeight > 0 ? highContrast ? '#000' : '#2196F3' : highContrast ? '#fff' : '#333', cursor: 'pointer', textAlign: 'left', fontWeight: lineHeight > 0 ? 'bold' : 'normal', transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-align-justify", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } }, /*#__PURE__*/React.createElement("span", null, "Spa\u021Biu \xEEntre r\xE2nduri"), /*#__PURE__*/React.createElement("small", { style: { fontSize: '12px', opacity: '0.8' } }, lineHeight === 0 ? 'Normal' : lineHeight === 1 ? 'Mare' : 'Foarte mare'))), /*#__PURE__*/React.createElement("button", { "aria-label": isReading ? "Oprește citirea" : "Citește cu voce tare", "aria-pressed": isReading, className: "control-button ".concat(isReading ? 'active' : ''), onClick: handleReadAloud, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, handleReadAloud); }, disabled: !('speechSynthesis' in window), style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: isReading ? highContrast ? '#fff' : '#e3f2fd' : highContrast ? '#333' : '#f5f5f5', color: isReading ? highContrast ? '#000' : '#2196F3' : highContrast ? '#fff' : '#333', cursor: 'speechSynthesis' in window ? 'pointer' : 'not-allowed', textAlign: 'left', fontWeight: isReading ? 'bold' : 'normal', opacity: 'speechSynthesis' in window ? 1 : 0.7, transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: isReading ? "fas fa-volume-mute" : "fas fa-volume-up", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } }, /*#__PURE__*/React.createElement("span", null, isReading ? "Oprește citirea" : "Citește cu voce tare"), /*#__PURE__*/React.createElement("small", { style: { fontSize: '12px', opacity: '0.8' } }, 'speechSynthesis' in window ? isReading ? "Progres: ".concat(readingProgress, "%") : 'Inactiv' : 'Indisponibil'))), availableRomanianVoices.length > 0 && /*#__PURE__*/React.createElement("button", { "aria-label": "Viteza citirii: ".concat(getSpeechRateLabel()), onClick: handleSpeechRateChange, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, handleSpeechRateChange); }, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: highContrast ? '#333' : '#f5f5f5', color: highContrast ? '#fff' : '#333', cursor: 'pointer', textAlign: 'left', transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-tachometer-alt", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } }, /*#__PURE__*/React.createElement("span", null, "Viteza citirii"), /*#__PURE__*/React.createElement("small", { style: { fontSize: '12px', opacity: '0.8' } }, getSpeechRateLabel()))), availableRomanianVoices.length > 1 && /*#__PURE__*/React.createElement("button", { "aria-label": "Voce: ".concat(getCurrentVoiceName()), onClick: handleVoiceChange, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, handleVoiceChange); }, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: highContrast ? '#333' : '#f5f5f5', color: highContrast ? '#fff' : '#333', cursor: 'pointer', textAlign: 'left', transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-microphone", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start' } }, /*#__PURE__*/React.createElement("span", null, "Voce narrator"), /*#__PURE__*/React.createElement("small", { style: { fontSize: '12px', opacity: '0.8' } }, getCurrentVoiceName()))), /*#__PURE__*/React.createElement("button", { "aria-label": "Reseteaz\u0103 toate set\u0103rile", className: "control-button reset", onClick: resetAllSettings, onKeyDown: function onKeyDown(e) { return handleKeyDown(e, resetAllSettings); }, style: { display: 'flex', alignItems: 'center', gap: '12px', padding: '10px 12px', borderRadius: '8px', border: 'none', background: highContrast ? '#444' : '#f5f5f5', color: highContrast ? '#fff' : '#666', cursor: 'pointer', textAlign: 'left', marginTop: '8px', transition: 'all 0.2s ease', width: '100%' } }, /*#__PURE__*/React.createElement("div", { className: "a11y-icon" }, /*#__PURE__*/React.createElement("i", { className: "fas fa-undo", "aria-hidden": "true" })), /*#__PURE__*/React.createElement("span", null, "Reseteaz\u0103 set\u0103rile"))), !isPanelOpen && /*#__PURE__*/React.createElement("div", { className: "status-indicators", style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px', marginTop: '8px' } }, fontSize > 0 && /*#__PURE__*/React.createElement("div", { "aria-hidden": "true", title: "M\u0103rime text m\u0103rit\u0103", style: { width: '8px', height: '8px', borderRadius: '50%', background: highContrast ? '#fff' : '#2196F3' } }), highContrast && /*#__PURE__*/React.createElement("div", { "aria-hidden": "true", title: "Contrast ridicat activat", style: { width: '8px', height: '8px', borderRadius: '50%', background: highContrast ? '#fff' : '#2196F3' } }), lineHeight > 0 && /*#__PURE__*/React.createElement("div", { "aria-hidden": "true", title: "Spa\u021Biu \xEEntre r\xE2nduri m\u0103rit", style: { width: '8px', height: '8px', borderRadius: '50%', background: highContrast ? '#fff' : '#2196F3' } }), isReading && /*#__PURE__*/React.createElement("div", { "aria-hidden": "true", title: "Citire vocal\u0103 activ\u0103", style: { width: '8px', height: '8px', borderRadius: '50%', background: highContrast ? '#fff' : '#2196F3', animation: 'pulse 1.5s infinite' } })))); }; /***/ }), /***/ 156: /***/ ((module) => { "use strict"; module.exports = __WEBPACK_EXTERNAL_MODULE__156__; /***/ }), /***/ 176: /***/ ((__unused_webpack_module, exports) => { "use strict"; var __webpack_unused_export__; /** * Copyright (c) Nicolas Gallagher * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * */ __webpack_unused_export__ = ({ value: true }); exports.P = void 0; var cache = new WeakMap(); var compiledKey = '$$css'; function createStyleq(options) { var disableCache; var disableMix; var transform; if (options != null) { disableCache = options.disableCache === true; disableMix = options.disableMix === true; transform = options.transform; } return function styleq() { // Keep track of property commits to the className var definedProperties = []; // The className and inline style to build up var className = ''; var inlineStyle = null; // The current position in the cache graph var nextCache = disableCache ? null : cache; // This way of creating an array from arguments is fastest var styles = new Array(arguments.length); for (var i = 0; i < arguments.length; i++) { styles[i] = arguments[i]; } // Iterate over styles from last to first while (styles.length > 0) { var possibleStyle = styles.pop(); // Skip empty items if (possibleStyle == null || possibleStyle === false) { continue; } // Push nested styles back onto the stack to be processed if (Array.isArray(possibleStyle)) { for (var _i = 0; _i < possibleStyle.length; _i++) { styles.push(possibleStyle[_i]); } continue; } // Process an individual style object var style = transform != null ? transform(possibleStyle) : possibleStyle; if (style.$$css) { // Build up the class names defined by this object var classNameChunk = ''; // Check the cache to see if we've already done this work if (nextCache != null && nextCache.has(style)) { // Cache: read var cacheEntry = nextCache.get(style); if (cacheEntry != null) { classNameChunk = cacheEntry[0]; // $FlowIgnore definedProperties.push.apply(definedProperties, cacheEntry[1]); nextCache = cacheEntry[2]; } } // Update the chunks with data from this object else { // The properties defined by this object var definedPropertiesChunk = []; for (var prop in style) { var value = style[prop]; if (prop === compiledKey) continue; // Each property value is used as an HTML class name // { 'debug.string': 'debug.string', opacity: 's-jskmnoqp' } if (typeof value === 'string' || value === null) { // Only add to chunks if this property hasn't already been seen if (!definedProperties.includes(prop)) { definedProperties.push(prop); if (nextCache != null) { definedPropertiesChunk.push(prop); } if (typeof value === 'string') { classNameChunk += classNameChunk ? ' ' + value : value; } } } // If we encounter a value that isn't a string or `null` else { console.error("styleq: ".concat(prop, " typeof ").concat(String(value), " is not \"string\" or \"null\".")); } } // Cache: write if (nextCache != null) { // Create the next WeakMap for this sequence of styles var weakMap = new WeakMap(); nextCache.set(style, [classNameChunk, definedPropertiesChunk, weakMap]); nextCache = weakMap; } } // Order of classes in chunks matches property-iteration order of style // object. Order of chunks matches passed order of styles from first to // last (which we iterate over in reverse). if (classNameChunk) { className = className ? classNameChunk + ' ' + className : classNameChunk; } } // ----- DYNAMIC: Process inline style object ----- else { if (disableMix) { if (inlineStyle == null) { inlineStyle = {}; } inlineStyle = Object.assign({}, style, inlineStyle); } else { var subStyle = null; for (var _prop in style) { var _value = style[_prop]; if (_value !== undefined) { if (!definedProperties.includes(_prop)) { if (_value != null) { if (inlineStyle == null) { inlineStyle = {}; } if (subStyle == null) { subStyle = {}; } subStyle[_prop] = _value; } definedProperties.push(_prop); // Cache is unnecessary overhead if results can't be reused. nextCache = null; } } } if (subStyle != null) { inlineStyle = Object.assign(subStyle, inlineStyle); } } } } var styleProps = [className, inlineStyle]; return styleProps; }; } var styleq = createStyleq(); exports.P = styleq; styleq.factory = createStyleq; /***/ }), /***/ 261: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; var __webpack_unused_export__; __webpack_unused_export__ = ({ value: true }); exports.A = crossFade; var _cssInJsUtils = __webpack_require__(486); var CROSS_FADE_REGEX = /cross-fade\(/g; // http://caniuse.com/#search=cross-fade var prefixes = ['-webkit-', '']; function crossFade(property, value) { if (typeof value === 'string' && !(0, _cssInJsUtils.isPrefixedValue)(value) && value.indexOf('cross-fade(') !== -1) { return prefixes.map(function (prefix) { return value.replace(CROSS_FADE_REGEX, prefix + 'cross-fade('); }); } } /***/ }), /***/ 336: /***/ ((__unused_webpack_module, exports) => { "use strict"; var __webpack_unused_export__; /** * Copyright (c) Nicolas Gallagher * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ __webpack_unused_export__ = ({ value: true }); exports.n = localizeStyle; var cache = new WeakMap(); var markerProp = '$$css$localize'; /** * The compiler polyfills logical properties and values, generating a class * name for both writing directions. The style objects are annotated by * the compiler as needing this runtime transform. The results are memoized. * * { '$$css$localize': true, float: [ 'float-left', 'float-right' ] } * => { float: 'float-left' } */ function compileStyle(style, isRTL) { // Create a new compiled style for styleq var compiledStyle = {}; for (var prop in style) { if (prop !== markerProp) { var value = style[prop]; if (Array.isArray(value)) { compiledStyle[prop] = isRTL ? value[1] : value[0]; } else { compiledStyle[prop] = value; } } } return compiledStyle; } function localizeStyle(style, isRTL) { if (style[markerProp] != null) { var compiledStyleIndex = isRTL ? 1 : 0; // Check the cache in case we've already seen this object if (cache.has(style)) { var _cachedStyles = cache.get(style); var _compiledStyle = _cachedStyles[compiledStyleIndex]; if (_compiledStyle == null) { // Update the missing cache entry _compiledStyle = compileStyle(style, isRTL); _cachedStyles[compiledStyleIndex] = _compiledStyle; cache.set(style, _cachedStyles); } return _compiledStyle; } // Create a new compiled style for styleq var compiledStyle = compileStyle(style, isRTL); var cachedStyles = new Array(2); cachedStyles[compiledStyleIndex] = compiledStyle; cache.set(style, cachedStyles); return compiledStyle; } return style; } /***/ }), /***/ 368: /***/ ((module) => { "use strict"; module.exports = value => { if (Object.prototype.toString.call(value) !== '[object Object]') { return false; } const prototype = Object.getPrototypeOf(value); return prototype === null || prototype === Object.prototype; }; /***/ }), /***/ 395: /***/ ((module) => { "use strict"; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * */ function makeEmptyFunction(arg) { return function () { return arg; }; } /** * This function accepts and discards inputs; it has no side effects. This is * primarily useful idiomatically for overridable function endpoints which * always need to be callable, since JS lacks a null-call idiom ala Cocoa. */ var emptyFunction = function emptyFunction() {}; emptyFunction.thatReturns = makeEmptyFunction; emptyFunction.thatReturnsFalse = makeEmptyFunction(false); emptyFunction.thatReturnsTrue = makeEmptyFunction(true); emptyFunction.thatReturnsNull = makeEmptyFunction(null); emptyFunction.thatReturnsThis = function () { return this; }; emptyFunction.thatReturnsArgument = function (arg) { return arg; }; module.exports = emptyFunction; /***/ }), /***/ 485: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; var __webpack_unused_export__; __webpack_unused_export__ = ({ value: true }); exports.A = createPrefixer; var _prefixProperty = __webpack_require__(49); var _prefixProperty2 = _interopRequireDefault(_prefixProperty); var _prefixValue = __webpack_require__(971); var _prefixValue2 = _interopRequireDefault(_prefixValue); var _addNewValuesOnly = __webpack_require__(863); var _addNewValuesOnly2 = _interopRequireDefault(_addNewValuesOnly); var _isObject = __webpack_require__(99); var _isObject2 = _interopRequireDefault(_isObject); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function createPrefixer(_ref) { var prefixMap = _ref.prefixMap, plugins = _ref.plugins; return function prefix(style) { for (var property in style) { var value = style[property]; // handle nested objects if ((0, _isObject2.default)(value)) { style[property] = prefix(value); // handle array values } else if (Array.isArray(value)) { var combinedValue = []; for (var i = 0, len = value.length; i < len; ++i) { var processedValue = (0, _prefixValue2.default)(plugins, property, value[i], style, prefixMap); (0, _addNewValuesOnly2.default)(combinedValue, processedValue || value[i]); } // only modify the value if it was touched // by any plugin to prevent unnecessary mutations if (combinedValue.length > 0) { style[property] = combinedValue; } } else { var _processedValue = (0, _prefixValue2.default)(plugins, property, value, style, prefixMap); // only modify the value if it was touched // by any plugin to prevent unnecessary mutations if (_processedValue) { style[property] = _processedValue; } style = (0, _prefixProperty2.default)(prefixMap, property, style); } } return style; }; } /***/ }), /***/ 486: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXPORTS __webpack_require__.d(__webpack_exports__, { assignStyle: () => (/* reexport */ assignStyle), camelCaseProperty: () => (/* reexport */ camelCaseProperty), cssifyDeclaration: () => (/* reexport */ cssifyDeclaration), cssifyObject: () => (/* reexport */ cssifyObject), hyphenateProperty: () => (/* reexport */ hyphenateProperty), isPrefixedProperty: () => (/* reexport */ isPrefixedProperty), isPrefixedValue: () => (/* reexport */ isPrefixedValue), isUnitlessProperty: () => (/* reexport */ isUnitlessProperty), normalizeProperty: () => (/* reexport */ normalizeProperty), resolveArrayValue: () => (/* reexport */ resolveArrayValue), unprefixProperty: () => (/* reexport */ unprefixProperty), unprefixValue: () => (/* reexport */ unprefixValue) }); ;// ./node_modules/css-in-js-utils/es/assignStyle.js function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.