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
JavaScript
(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.