analytica-frontend-lib 1.6.76 → 1.6.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AccessReportModal/index.js +4 -5
- package/dist/AccessReportModal/index.js.map +1 -1
- package/dist/AccessReportModal/index.mjs +3 -4
- package/dist/AccessibilityWidget/index.js +4 -5
- package/dist/AccessibilityWidget/index.js.map +1 -1
- package/dist/AccessibilityWidget/index.mjs +3 -4
- package/dist/Accordation/index.js +4 -4
- package/dist/Accordation/index.mjs +3 -3
- package/dist/ActivitiesHistory/index.js +48 -49
- package/dist/ActivitiesHistory/index.js.map +1 -1
- package/dist/ActivitiesHistory/index.mjs +47 -48
- package/dist/ActivityCardQuestionBanks/index.d.ts.map +1 -1
- package/dist/ActivityCardQuestionBanks/index.js +48 -49
- package/dist/ActivityCardQuestionBanks/index.js.map +1 -1
- package/dist/ActivityCardQuestionBanks/index.mjs +47 -48
- package/dist/ActivityCardQuestionPreview/index.js +48 -49
- package/dist/ActivityCardQuestionPreview/index.js.map +1 -1
- package/dist/ActivityCardQuestionPreview/index.mjs +47 -48
- package/dist/ActivityCreate/ActivityCreateContent/index.js +48 -49
- package/dist/ActivityCreate/ActivityCreateContent/index.js.map +1 -1
- package/dist/ActivityCreate/ActivityCreateContent/index.mjs +47 -48
- package/dist/ActivityCreate/index.js +48 -49
- package/dist/ActivityCreate/index.js.map +1 -1
- package/dist/ActivityCreate/index.mjs +47 -48
- package/dist/ActivityDetails/index.js +48 -49
- package/dist/ActivityDetails/index.js.map +1 -1
- package/dist/ActivityDetails/index.mjs +47 -48
- package/dist/ActivityFilters/index.js +48 -49
- package/dist/ActivityFilters/index.js.map +1 -1
- package/dist/ActivityFilters/index.mjs +47 -48
- package/dist/ActivityPageLayout/index.js +48 -49
- package/dist/ActivityPageLayout/index.js.map +1 -1
- package/dist/ActivityPageLayout/index.mjs +47 -48
- package/dist/ActivityPreview/index.js +48 -49
- package/dist/ActivityPreview/index.js.map +1 -1
- package/dist/ActivityPreview/index.mjs +47 -48
- package/dist/AlertDialog/index.d.ts.map +1 -1
- package/dist/AlertDialog/index.js +3 -3
- package/dist/AlertDialog/index.mjs +2 -2
- package/dist/AlertManager/index.js +48 -49
- package/dist/AlertManager/index.js.map +1 -1
- package/dist/AlertManager/index.mjs +47 -48
- package/dist/AlertManagerView/index.js +4 -5
- package/dist/AlertManagerView/index.js.map +1 -1
- package/dist/AlertManagerView/index.mjs +3 -4
- package/dist/AnnouncementModal/index.js +4 -5
- package/dist/AnnouncementModal/index.js.map +1 -1
- package/dist/AnnouncementModal/index.mjs +3 -4
- package/dist/AnnouncementsGate/index.js +5 -6
- package/dist/AnnouncementsGate/index.js.map +1 -1
- package/dist/AnnouncementsGate/index.mjs +4 -5
- package/dist/AnswerKeyModal/index.js +4 -5
- package/dist/AnswerKeyModal/index.js.map +1 -1
- package/dist/AnswerKeyModal/index.mjs +3 -4
- package/dist/AppHeader/index.js +8 -9
- package/dist/AppHeader/index.js.map +1 -1
- package/dist/AppHeader/index.mjs +7 -8
- package/dist/CalendarCard/index.js +6 -7
- package/dist/CalendarCard/index.js.map +1 -1
- package/dist/CalendarCard/index.mjs +5 -6
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +3 -3
- package/dist/Card/index.mjs +2 -2
- package/dist/Chat/index.js +4 -5
- package/dist/Chat/index.js.map +1 -1
- package/dist/Chat/index.mjs +3 -4
- package/dist/Chatbot/index.js +4 -5
- package/dist/Chatbot/index.js.map +1 -1
- package/dist/Chatbot/index.mjs +3 -4
- package/dist/CheckBoxGroup/index.js +48 -49
- package/dist/CheckBoxGroup/index.js.map +1 -1
- package/dist/CheckBoxGroup/index.mjs +47 -48
- package/dist/ComparatorChart/ComparatorView/index.js +4 -5
- package/dist/ComparatorChart/ComparatorView/index.js.map +1 -1
- package/dist/ComparatorChart/ComparatorView/index.mjs +3 -4
- package/dist/CorrectActivityModal/index.js +9 -10
- package/dist/CorrectActivityModal/index.js.map +1 -1
- package/dist/CorrectActivityModal/index.mjs +8 -9
- package/dist/DownloadButton/index.js +6 -7
- package/dist/DownloadButton/index.js.map +1 -1
- package/dist/DownloadButton/index.mjs +5 -6
- package/dist/DownloadModal/index.js +4 -5
- package/dist/DownloadModal/index.js.map +1 -1
- package/dist/DownloadModal/index.mjs +3 -4
- package/dist/DropdownMenu/index.js +4 -5
- package/dist/DropdownMenu/index.js.map +1 -1
- package/dist/DropdownMenu/index.mjs +3 -4
- package/dist/EnemClassroomStartModal/index.js +8 -9
- package/dist/EnemClassroomStartModal/index.js.map +1 -1
- package/dist/EnemClassroomStartModal/index.mjs +7 -8
- package/dist/EnemMoment/index.js +110 -94
- package/dist/EnemMoment/index.js.map +1 -1
- package/dist/EnemMoment/index.mjs +74 -58
- package/dist/EnemMoment/index.mjs.map +1 -1
- package/dist/EnemMomentStudentModal/index.js +62 -63
- package/dist/EnemMomentStudentModal/index.js.map +1 -1
- package/dist/EnemMomentStudentModal/index.mjs +48 -49
- package/dist/EnemMomentStudentModal/index.mjs.map +1 -1
- package/dist/EssayThemePicker/index.js +3 -3
- package/dist/EssayThemePicker/index.mjs +2 -2
- package/dist/ExamDetailsLayout/ExamDetailsPage/index.js +48 -49
- package/dist/ExamDetailsLayout/ExamDetailsPage/index.js.map +1 -1
- package/dist/ExamDetailsLayout/ExamDetailsPage/index.mjs +47 -48
- package/dist/ExamPageLayout/index.js +48 -49
- package/dist/ExamPageLayout/index.js.map +1 -1
- package/dist/ExamPageLayout/index.mjs +47 -48
- package/dist/Forum/index.js +6 -7
- package/dist/Forum/index.js.map +1 -1
- package/dist/Forum/index.mjs +5 -6
- package/dist/IconButton/index.js +2 -2
- package/dist/IconButton/index.mjs +1 -1
- package/dist/LessonCardPreview/index.js +48 -49
- package/dist/LessonCardPreview/index.js.map +1 -1
- package/dist/LessonCardPreview/index.mjs +47 -48
- package/dist/LessonMediaSections/index.js +48 -49
- package/dist/LessonMediaSections/index.js.map +1 -1
- package/dist/LessonMediaSections/index.mjs +47 -48
- package/dist/LessonsCatalog/index.js +48 -49
- package/dist/LessonsCatalog/index.js.map +1 -1
- package/dist/LessonsCatalog/index.mjs +47 -48
- package/dist/Modal/index.d.ts +11 -1
- package/dist/Modal/index.d.ts.map +1 -1
- package/dist/Modal/index.js +3 -4
- package/dist/Modal/index.js.map +1 -1
- package/dist/Modal/index.mjs +2 -3
- package/dist/MultiCheckSelect/index.js +5 -6
- package/dist/MultiCheckSelect/index.js.map +1 -1
- package/dist/MultiCheckSelect/index.mjs +4 -5
- package/dist/NotificationCard/index.js +6 -7
- package/dist/NotificationCard/index.js.map +1 -1
- package/dist/NotificationCard/index.mjs +5 -6
- package/dist/PerformanceReportModal/index.js +4 -5
- package/dist/PerformanceReportModal/index.js.map +1 -1
- package/dist/PerformanceReportModal/index.mjs +3 -4
- package/dist/PrintableUsersTable/index.js +48 -49
- package/dist/PrintableUsersTable/index.js.map +1 -1
- package/dist/PrintableUsersTable/index.mjs +47 -48
- package/dist/ProgressModal/index.js +4 -5
- package/dist/ProgressModal/index.js.map +1 -1
- package/dist/ProgressModal/index.mjs +3 -4
- package/dist/QuestionsPerformanceCard/index.js +49 -50
- package/dist/QuestionsPerformanceCard/index.js.map +1 -1
- package/dist/QuestionsPerformanceCard/index.mjs +48 -49
- package/dist/Quiz/QuizResult/index.js +4 -4
- package/dist/Quiz/QuizResult/index.mjs +3 -3
- package/dist/Quiz/index.d.ts.map +1 -1
- package/dist/Quiz/index.js +8 -9
- package/dist/Quiz/index.js.map +1 -1
- package/dist/Quiz/index.mjs +7 -8
- package/dist/QuizTimer/index.d.ts +12 -0
- package/dist/QuizTimer/index.d.ts.map +1 -1
- package/dist/QuizTimer/index.js +4 -2
- package/dist/QuizTimer/index.js.map +1 -1
- package/dist/QuizTimer/index.mjs +4 -2
- package/dist/RecommendedLessonCreate/index.js +48 -49
- package/dist/RecommendedLessonCreate/index.js.map +1 -1
- package/dist/RecommendedLessonCreate/index.mjs +47 -48
- package/dist/RecommendedLessonDetails/index.js +11 -12
- package/dist/RecommendedLessonDetails/index.js.map +1 -1
- package/dist/RecommendedLessonDetails/index.mjs +10 -11
- package/dist/RecommendedLessonsHistory/index.js +48 -49
- package/dist/RecommendedLessonsHistory/index.js.map +1 -1
- package/dist/RecommendedLessonsHistory/index.mjs +47 -48
- package/dist/ReportDetailModal/index.js +5 -6
- package/dist/ReportDetailModal/index.js.map +1 -1
- package/dist/ReportDetailModal/index.mjs +4 -5
- package/dist/RichEditor/index.js +6 -7
- package/dist/RichEditor/index.js.map +1 -1
- package/dist/RichEditor/index.mjs +5 -6
- package/dist/{RichEditorCore-62NIM7PC.js → RichEditorCore-6OT3VNJR.js} +15 -16
- package/dist/RichEditorCore-6OT3VNJR.js.map +1 -0
- package/dist/{RichEditorCore-CCO3SSSU.mjs → RichEditorCore-IF6JQHEO.mjs} +6 -7
- package/dist/{RichEditorCore-CCO3SSSU.mjs.map → RichEditorCore-IF6JQHEO.mjs.map} +1 -1
- package/dist/Search/index.js +5 -6
- package/dist/Search/index.js.map +1 -1
- package/dist/Search/index.mjs +4 -5
- package/dist/SendActivityModal/SendActivityModal.js +48 -49
- package/dist/SendActivityModal/SendActivityModal.js.map +1 -1
- package/dist/SendActivityModal/SendActivityModal.mjs +47 -48
- package/dist/SendActivityModal/index.js +48 -49
- package/dist/SendActivityModal/index.js.map +1 -1
- package/dist/SendActivityModal/index.mjs +47 -48
- package/dist/SendLessonModal/index.js +48 -49
- package/dist/SendLessonModal/index.js.map +1 -1
- package/dist/SendLessonModal/index.mjs +47 -48
- package/dist/SimulatedPerformance/SimulatedPerformanceView/index.js +48 -49
- package/dist/SimulatedPerformance/SimulatedPerformanceView/index.js.map +1 -1
- package/dist/SimulatedPerformance/SimulatedPerformanceView/index.mjs +47 -48
- package/dist/SimulatedPerformance/useSimulatedPerformance/index.js +6 -7
- package/dist/SimulatedPerformance/useSimulatedPerformance/index.js.map +1 -1
- package/dist/SimulatedPerformance/useSimulatedPerformance/index.mjs +5 -6
- package/dist/SimulatedStudentSimulationsModal/index.js +8 -9
- package/dist/SimulatedStudentSimulationsModal/index.js.map +1 -1
- package/dist/SimulatedStudentSimulationsModal/index.mjs +7 -8
- package/dist/SimulationSummaryCards/index.js +5 -5
- package/dist/SimulationSummaryCards/index.mjs +4 -4
- package/dist/SimulationsPage/index.js +48 -49
- package/dist/SimulationsPage/index.js.map +1 -1
- package/dist/SimulationsPage/index.mjs +47 -48
- package/dist/StudentLessonProgressModal/index.js +6 -7
- package/dist/StudentLessonProgressModal/index.js.map +1 -1
- package/dist/StudentLessonProgressModal/index.mjs +5 -6
- package/dist/StudentPerformanceDetailsModal/index.js +9 -10
- package/dist/StudentPerformanceDetailsModal/index.js.map +1 -1
- package/dist/StudentPerformanceDetailsModal/index.mjs +8 -9
- package/dist/Support/TicketModal/index.js +4 -5
- package/dist/Support/TicketModal/index.js.map +1 -1
- package/dist/Support/TicketModal/index.mjs +3 -4
- package/dist/Support/index.js +5 -6
- package/dist/Support/index.js.map +1 -1
- package/dist/Support/index.mjs +4 -5
- package/dist/TableProvider/index.js +48 -49
- package/dist/TableProvider/index.js.map +1 -1
- package/dist/TableProvider/index.mjs +47 -48
- package/dist/UnifiedDraftModelPage/index.js +48 -49
- package/dist/UnifiedDraftModelPage/index.js.map +1 -1
- package/dist/UnifiedDraftModelPage/index.mjs +47 -48
- package/dist/UnifiedHistoryPage/index.js +48 -49
- package/dist/UnifiedHistoryPage/index.js.map +1 -1
- package/dist/UnifiedHistoryPage/index.mjs +47 -48
- package/dist/VideoPlayer/index.js +7 -8
- package/dist/VideoPlayer/index.js.map +1 -1
- package/dist/VideoPlayer/index.mjs +6 -7
- package/dist/Whiteboard/index.js +4 -5
- package/dist/Whiteboard/index.js.map +1 -1
- package/dist/Whiteboard/index.mjs +3 -4
- package/dist/{chunk-EVBQNVQW.mjs → chunk-233FSBU7.mjs} +5 -5
- package/dist/{chunk-JU63EMZM.js → chunk-24DQFREC.js} +3 -3
- package/dist/{chunk-JU63EMZM.js.map → chunk-24DQFREC.js.map} +1 -1
- package/dist/{chunk-QFXSQKW3.mjs → chunk-254EBPMW.mjs} +22 -22
- package/dist/{chunk-QFXSQKW3.mjs.map → chunk-254EBPMW.mjs.map} +1 -1
- package/dist/{chunk-SFQVZ4KQ.js → chunk-2ETPIOCD.js} +3 -3
- package/dist/{chunk-SFQVZ4KQ.js.map → chunk-2ETPIOCD.js.map} +1 -1
- package/dist/{chunk-RCNIBRZY.js → chunk-2VTJ2PKF.js} +10 -10
- package/dist/{chunk-RCNIBRZY.js.map → chunk-2VTJ2PKF.js.map} +1 -1
- package/dist/{chunk-B35D5S4G.js → chunk-2ZMGNCMI.js} +6 -6
- package/dist/{chunk-B35D5S4G.js.map → chunk-2ZMGNCMI.js.map} +1 -1
- package/dist/{chunk-QEPKR6ZF.js → chunk-3KSRDIS2.js} +20 -20
- package/dist/{chunk-QEPKR6ZF.js.map → chunk-3KSRDIS2.js.map} +1 -1
- package/dist/{chunk-MUCV5ZWZ.mjs → chunk-3YF7H577.mjs} +15 -9
- package/dist/chunk-3YF7H577.mjs.map +1 -0
- package/dist/{chunk-MADPP2PW.mjs → chunk-3ZSI2KI5.mjs} +2 -2
- package/dist/{chunk-2W7PTFXS.mjs → chunk-42XKJV56.mjs} +2 -2
- package/dist/{chunk-M6TC6XRQ.mjs → chunk-55ESXRRM.mjs} +2 -2
- package/dist/{chunk-4MURAKPC.mjs → chunk-5DJVOLVX.mjs} +3 -3
- package/dist/{chunk-YVT7CT3G.mjs → chunk-5P6CBDZ6.mjs} +2 -2
- package/dist/{chunk-BHKTJCFD.js → chunk-5QUP5HKB.js} +3 -3
- package/dist/{chunk-BHKTJCFD.js.map → chunk-5QUP5HKB.js.map} +1 -1
- package/dist/{chunk-SFEU7BMY.mjs → chunk-5SFNRXZB.mjs} +2 -2
- package/dist/{chunk-6ALEXGAN.js → chunk-6U4AI5SE.js} +6 -6
- package/dist/{chunk-6ALEXGAN.js.map → chunk-6U4AI5SE.js.map} +1 -1
- package/dist/{chunk-KYY4U5SN.mjs → chunk-6Z5W5J44.mjs} +3 -3
- package/dist/{chunk-XOKBMLW3.js → chunk-7IGUYLSF.js} +3 -3
- package/dist/{chunk-XOKBMLW3.js.map → chunk-7IGUYLSF.js.map} +1 -1
- package/dist/{chunk-GVYGPJH3.mjs → chunk-AU5M2766.mjs} +2 -2
- package/dist/{chunk-2VODGC76.js → chunk-AVEMHDN2.js} +66 -44
- package/dist/chunk-AVEMHDN2.js.map +1 -0
- package/dist/{chunk-HIIOADV4.js → chunk-AZSRKBYS.js} +63 -71
- package/dist/chunk-AZSRKBYS.js.map +1 -0
- package/dist/{chunk-CY2VKNCB.js → chunk-BQIBVC6X.js} +5 -5
- package/dist/{chunk-CY2VKNCB.js.map → chunk-BQIBVC6X.js.map} +1 -1
- package/dist/{chunk-M77TQ5JJ.mjs → chunk-BU32E6BR.mjs} +4 -6
- package/dist/{chunk-M77TQ5JJ.mjs.map → chunk-BU32E6BR.mjs.map} +1 -1
- package/dist/{chunk-5CQVDUDO.js → chunk-BUNF5POU.js} +5 -5
- package/dist/{chunk-5CQVDUDO.js.map → chunk-BUNF5POU.js.map} +1 -1
- package/dist/{chunk-Z6UN4ZPW.mjs → chunk-BVHVYC7Q.mjs} +4 -4
- package/dist/{chunk-WJENEFDG.js → chunk-CAFVLHDV.js} +3 -3
- package/dist/{chunk-WJENEFDG.js.map → chunk-CAFVLHDV.js.map} +1 -1
- package/dist/{chunk-BVUPM6EY.js → chunk-CAQ2Q3ON.js} +2 -2
- package/dist/chunk-CAQ2Q3ON.js.map +1 -0
- package/dist/{chunk-QMPOGLAR.js → chunk-CIASXVWX.js} +3 -3
- package/dist/{chunk-QMPOGLAR.js.map → chunk-CIASXVWX.js.map} +1 -1
- package/dist/{chunk-APKEYUJ3.js → chunk-CIQLC2ZZ.js} +3 -3
- package/dist/{chunk-APKEYUJ3.js.map → chunk-CIQLC2ZZ.js.map} +1 -1
- package/dist/{chunk-36XPNLGQ.js → chunk-CW3FCWR4.js} +16 -16
- package/dist/{chunk-36XPNLGQ.js.map → chunk-CW3FCWR4.js.map} +1 -1
- package/dist/{chunk-J5VEAJN5.mjs → chunk-CWVUGZNK.mjs} +2 -2
- package/dist/{chunk-BCMDP6GK.mjs → chunk-DV3N2K3Y.mjs} +4 -4
- package/dist/{chunk-PP7SEERV.mjs → chunk-DXYSEBK3.mjs} +9 -3
- package/dist/chunk-DXYSEBK3.mjs.map +1 -0
- package/dist/{chunk-754M6HQ5.js → chunk-EJN4OP3D.js} +5 -5
- package/dist/{chunk-754M6HQ5.js.map → chunk-EJN4OP3D.js.map} +1 -1
- package/dist/{chunk-3IM2SBPO.js → chunk-F5K3HMKT.js} +4 -4
- package/dist/{chunk-3IM2SBPO.js.map → chunk-F5K3HMKT.js.map} +1 -1
- package/dist/{chunk-WMDSGVZ7.mjs → chunk-GCGSAS2Z.mjs} +48 -63
- package/dist/chunk-GCGSAS2Z.mjs.map +1 -0
- package/dist/{chunk-EXHGEJ4P.mjs → chunk-GKARHTZ2.mjs} +2 -2
- package/dist/{chunk-2VDCEEXB.js → chunk-GNKFBVW4.js} +3 -3
- package/dist/{chunk-2VDCEEXB.js.map → chunk-GNKFBVW4.js.map} +1 -1
- package/dist/{chunk-CDLOMECB.js → chunk-GTBPMNTJ.js} +3 -3
- package/dist/{chunk-CDLOMECB.js.map → chunk-GTBPMNTJ.js.map} +1 -1
- package/dist/{chunk-YQKAASWM.js → chunk-GXXDSBN2.js} +10 -4
- package/dist/chunk-GXXDSBN2.js.map +1 -0
- package/dist/{chunk-FASVPU6N.js → chunk-H3F4OCXC.js} +10 -10
- package/dist/{chunk-FASVPU6N.js.map → chunk-H3F4OCXC.js.map} +1 -1
- package/dist/{chunk-JCFN6KRS.mjs → chunk-HGWDB73S.mjs} +2 -2
- package/dist/{chunk-JXXMO7PY.mjs → chunk-HN5RW4C3.mjs} +3 -3
- package/dist/{chunk-I2A4EQPH.mjs → chunk-HQ2GXFK5.mjs} +6 -6
- package/dist/{chunk-BIPC6F6D.js → chunk-IDJ37MOU.js} +115 -115
- package/dist/{chunk-BIPC6F6D.js.map → chunk-IDJ37MOU.js.map} +1 -1
- package/dist/{chunk-TBJLNIOY.mjs → chunk-JBLYYTHN.mjs} +2 -2
- package/dist/{chunk-G4NK66PM.js → chunk-JTWXQ267.js} +24 -18
- package/dist/chunk-JTWXQ267.js.map +1 -0
- package/dist/{chunk-V6IC74KH.js → chunk-JXGLDRDC.js} +34 -34
- package/dist/{chunk-V6IC74KH.js.map → chunk-JXGLDRDC.js.map} +1 -1
- package/dist/{chunk-DDFIRQI5.mjs → chunk-K3E5VEBF.mjs} +56 -34
- package/dist/chunk-K3E5VEBF.mjs.map +1 -0
- package/dist/{chunk-MSBEWG26.js → chunk-K5O2IOI4.js} +8 -8
- package/dist/{chunk-MSBEWG26.js.map → chunk-K5O2IOI4.js.map} +1 -1
- package/dist/{chunk-SB5YGKXR.js → chunk-KBMLGQ5J.js} +49 -64
- package/dist/chunk-KBMLGQ5J.js.map +1 -0
- package/dist/chunk-KCZEKV7M.mjs +81 -0
- package/dist/chunk-KCZEKV7M.mjs.map +1 -0
- package/dist/{chunk-GRSN76BV.mjs → chunk-KH2R4STU.mjs} +3 -3
- package/dist/{chunk-7DQM34JT.js → chunk-KHYSXYPO.js} +23 -23
- package/dist/{chunk-7DQM34JT.js.map → chunk-KHYSXYPO.js.map} +1 -1
- package/dist/{chunk-V2YHMPRR.js → chunk-KJHBQQYJ.js} +5 -5
- package/dist/{chunk-V2YHMPRR.js.map → chunk-KJHBQQYJ.js.map} +1 -1
- package/dist/{chunk-ZF5NMQJZ.mjs → chunk-KUKLN3CK.mjs} +4 -4
- package/dist/{chunk-6AYB7CZH.js → chunk-KZQVGSR2.js} +2 -2
- package/dist/{chunk-6AYB7CZH.js.map → chunk-KZQVGSR2.js.map} +1 -1
- package/dist/{chunk-UAKRBNW2.mjs → chunk-L4T76OKM.mjs} +2 -2
- package/dist/{chunk-AUCXJ7LG.js → chunk-M3LQH7Y7.js} +3 -3
- package/dist/{chunk-AUCXJ7LG.js.map → chunk-M3LQH7Y7.js.map} +1 -1
- package/dist/{chunk-FQNJJH7F.js → chunk-MCXRKD56.js} +13 -13
- package/dist/{chunk-FQNJJH7F.js.map → chunk-MCXRKD56.js.map} +1 -1
- package/dist/{chunk-PY5WCBKN.mjs → chunk-MERKXOSI.mjs} +4 -4
- package/dist/{chunk-D3YDZF2G.js → chunk-N472HQPZ.js} +3 -3
- package/dist/{chunk-D3YDZF2G.js.map → chunk-N472HQPZ.js.map} +1 -1
- package/dist/{chunk-UPMYCGXR.js → chunk-N4K4X34Z.js} +4 -4
- package/dist/{chunk-UPMYCGXR.js.map → chunk-N4K4X34Z.js.map} +1 -1
- package/dist/{chunk-RU43UMEH.js → chunk-NFCNAFUK.js} +3 -3
- package/dist/{chunk-RU43UMEH.js.map → chunk-NFCNAFUK.js.map} +1 -1
- package/dist/{chunk-APCB5HWT.mjs → chunk-NLSDZJRR.mjs} +3 -3
- package/dist/{chunk-EWYIXCNF.mjs → chunk-NLUTNCLH.mjs} +5 -5
- package/dist/{chunk-OP4Q2KDS.mjs → chunk-NMKKMY5P.mjs} +2 -2
- package/dist/{chunk-WDPFO4II.mjs → chunk-NMPK336K.mjs} +2 -2
- package/dist/{chunk-X6BZ5IEV.mjs → chunk-NU7O6YKR.mjs} +2 -2
- package/dist/{chunk-ZABDSRX3.js → chunk-NUZ5K3CB.js} +4 -4
- package/dist/{chunk-ZABDSRX3.js.map → chunk-NUZ5K3CB.js.map} +1 -1
- package/dist/{chunk-N5ZGFYLA.js → chunk-NZX3BA62.js} +3 -3
- package/dist/{chunk-N5ZGFYLA.js.map → chunk-NZX3BA62.js.map} +1 -1
- package/dist/{chunk-2TLSEAL2.js → chunk-O4TRDWXJ.js} +3 -3
- package/dist/{chunk-2TLSEAL2.js.map → chunk-O4TRDWXJ.js.map} +1 -1
- package/dist/{chunk-CBI5F4ME.mjs → chunk-OMSSA4NO.mjs} +2 -2
- package/dist/{chunk-YGEEWLGJ.js → chunk-PKKXCX5B.js} +3 -3
- package/dist/{chunk-YGEEWLGJ.js.map → chunk-PKKXCX5B.js.map} +1 -1
- package/dist/{chunk-GYHD6QEA.mjs → chunk-PQGQ3EH5.mjs} +2 -2
- package/dist/{chunk-3LN5GQAC.js → chunk-Q6UIUYNF.js} +6 -8
- package/dist/chunk-Q6UIUYNF.js.map +1 -0
- package/dist/chunk-QLWBGM7H.js +81 -0
- package/dist/chunk-QLWBGM7H.js.map +1 -0
- package/dist/{chunk-IF5GW6ID.js → chunk-QZ5DCDZ2.js} +6 -6
- package/dist/{chunk-IF5GW6ID.js.map → chunk-QZ5DCDZ2.js.map} +1 -1
- package/dist/{chunk-LSUCENYD.mjs → chunk-RBKGHUSR.mjs} +2 -2
- package/dist/{chunk-PIZTI5SJ.js → chunk-RMCZ7C2C.js} +3 -3
- package/dist/{chunk-PIZTI5SJ.js.map → chunk-RMCZ7C2C.js.map} +1 -1
- package/dist/{chunk-LGQNMQOT.mjs → chunk-ROS5XGTQ.mjs} +2 -2
- package/dist/chunk-ROS5XGTQ.mjs.map +1 -0
- package/dist/{chunk-TEUERRDG.mjs → chunk-RV45XVXE.mjs} +2 -2
- package/dist/{chunk-FW6ZI2MC.mjs → chunk-UAFSWXN5.mjs} +2 -2
- package/dist/{chunk-QUGKQYAJ.mjs → chunk-ULVFVLFE.mjs} +4 -6
- package/dist/{chunk-QUGKQYAJ.mjs.map → chunk-ULVFVLFE.mjs.map} +1 -1
- package/dist/{chunk-ANLL2EIX.mjs → chunk-UWCGTH3U.mjs} +2 -2
- package/dist/{chunk-6R2LEEEP.mjs → chunk-UZF2D2GG.mjs} +2 -2
- package/dist/{chunk-62L3PMYE.mjs → chunk-V3OVMHZD.mjs} +2 -2
- package/dist/{chunk-UDITT3N3.mjs → chunk-V6ELDZ2B.mjs} +2 -2
- package/dist/{chunk-G7NUCBD3.js → chunk-VDPV24JJ.js} +3 -3
- package/dist/{chunk-G7NUCBD3.js.map → chunk-VDPV24JJ.js.map} +1 -1
- package/dist/{chunk-IJQOTS5O.mjs → chunk-VJUS3GC4.mjs} +2 -2
- package/dist/{chunk-ZUPP7R2K.js → chunk-W7BBVDBI.js} +17 -3
- package/dist/chunk-W7BBVDBI.js.map +1 -0
- package/dist/{chunk-EHQDQ5RV.js → chunk-XARMPXRN.js} +10 -12
- package/dist/chunk-XARMPXRN.js.map +1 -0
- package/dist/{chunk-MQEAEU6G.mjs → chunk-XGMRYNER.mjs} +2 -2
- package/dist/{chunk-MMQMVVD6.mjs → chunk-XLTD5J74.mjs} +3 -3
- package/dist/{chunk-L3ST5GUJ.js → chunk-XQUK7R7L.js} +17 -17
- package/dist/{chunk-L3ST5GUJ.js.map → chunk-XQUK7R7L.js.map} +1 -1
- package/dist/{chunk-OMBUOOMD.mjs → chunk-XYT542WD.mjs} +2 -2
- package/dist/{chunk-IZNABVXE.js → chunk-Y4IGIWP4.js} +3 -3
- package/dist/{chunk-IZNABVXE.js.map → chunk-Y4IGIWP4.js.map} +1 -1
- package/dist/{chunk-COWOGT7U.mjs → chunk-YZWFDSTC.mjs} +2 -2
- package/dist/{chunk-M2FN7CNS.mjs → chunk-Z4L2DWMX.mjs} +17 -3
- package/dist/chunk-Z4L2DWMX.mjs.map +1 -0
- package/dist/chunk-Z75J66LL.mjs +149 -0
- package/dist/chunk-Z75J66LL.mjs.map +1 -0
- package/dist/{chunk-CWIJ7RXR.js → chunk-ZHUFICW3.js} +3 -3
- package/dist/{chunk-CWIJ7RXR.js.map → chunk-ZHUFICW3.js.map} +1 -1
- package/dist/{chunk-Q5XGBTOY.js → chunk-ZNITTMV5.js} +3 -3
- package/dist/{chunk-Q5XGBTOY.js.map → chunk-ZNITTMV5.js.map} +1 -1
- package/dist/components/EnemMoment/HeaderFilters.d.ts +12 -1
- package/dist/components/EnemMoment/HeaderFilters.d.ts.map +1 -1
- package/dist/components/EnemMoment/types.d.ts +10 -1
- package/dist/components/EnemMoment/types.d.ts.map +1 -1
- package/dist/hooks/useAppContent/index.js +48 -49
- package/dist/hooks/useAppContent/index.js.map +1 -1
- package/dist/hooks/useAppContent/index.mjs +47 -48
- package/dist/hooks/useResizableColumns.d.ts +20 -9
- package/dist/hooks/useResizableColumns.d.ts.map +1 -1
- package/dist/hooks/useScreen/index.js +2 -2
- package/dist/hooks/useScreen/index.mjs +1 -1
- package/dist/index.js +48 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -48
- package/dist/store/layoutPreferencesStore.d.ts +12 -24
- package/dist/store/layoutPreferencesStore.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/RichEditorCore-62NIM7PC.js.map +0 -1
- package/dist/chunk-2EDRPEYL.mjs +0 -157
- package/dist/chunk-2EDRPEYL.mjs.map +0 -1
- package/dist/chunk-2VODGC76.js.map +0 -1
- package/dist/chunk-3LN5GQAC.js.map +0 -1
- package/dist/chunk-BVUPM6EY.js.map +0 -1
- package/dist/chunk-CH6BWMSQ.js +0 -17
- package/dist/chunk-CH6BWMSQ.js.map +0 -1
- package/dist/chunk-DDFIRQI5.mjs.map +0 -1
- package/dist/chunk-EHQDQ5RV.js.map +0 -1
- package/dist/chunk-G4NK66PM.js.map +0 -1
- package/dist/chunk-HIIOADV4.js.map +0 -1
- package/dist/chunk-JSH3BQZ7.mjs +0 -17
- package/dist/chunk-JSH3BQZ7.mjs.map +0 -1
- package/dist/chunk-LGQNMQOT.mjs.map +0 -1
- package/dist/chunk-LMDAF6LA.mjs +0 -51
- package/dist/chunk-LMDAF6LA.mjs.map +0 -1
- package/dist/chunk-M2FN7CNS.mjs.map +0 -1
- package/dist/chunk-MUCV5ZWZ.mjs.map +0 -1
- package/dist/chunk-PJOBOBNJ.js +0 -51
- package/dist/chunk-PJOBOBNJ.js.map +0 -1
- package/dist/chunk-PP7SEERV.mjs.map +0 -1
- package/dist/chunk-SB5YGKXR.js.map +0 -1
- package/dist/chunk-WMDSGVZ7.mjs.map +0 -1
- package/dist/chunk-YQKAASWM.js.map +0 -1
- package/dist/chunk-ZUPP7R2K.js.map +0 -1
- /package/dist/{chunk-EVBQNVQW.mjs.map → chunk-233FSBU7.mjs.map} +0 -0
- /package/dist/{chunk-MADPP2PW.mjs.map → chunk-3ZSI2KI5.mjs.map} +0 -0
- /package/dist/{chunk-2W7PTFXS.mjs.map → chunk-42XKJV56.mjs.map} +0 -0
- /package/dist/{chunk-M6TC6XRQ.mjs.map → chunk-55ESXRRM.mjs.map} +0 -0
- /package/dist/{chunk-4MURAKPC.mjs.map → chunk-5DJVOLVX.mjs.map} +0 -0
- /package/dist/{chunk-YVT7CT3G.mjs.map → chunk-5P6CBDZ6.mjs.map} +0 -0
- /package/dist/{chunk-SFEU7BMY.mjs.map → chunk-5SFNRXZB.mjs.map} +0 -0
- /package/dist/{chunk-KYY4U5SN.mjs.map → chunk-6Z5W5J44.mjs.map} +0 -0
- /package/dist/{chunk-GVYGPJH3.mjs.map → chunk-AU5M2766.mjs.map} +0 -0
- /package/dist/{chunk-Z6UN4ZPW.mjs.map → chunk-BVHVYC7Q.mjs.map} +0 -0
- /package/dist/{chunk-J5VEAJN5.mjs.map → chunk-CWVUGZNK.mjs.map} +0 -0
- /package/dist/{chunk-BCMDP6GK.mjs.map → chunk-DV3N2K3Y.mjs.map} +0 -0
- /package/dist/{chunk-EXHGEJ4P.mjs.map → chunk-GKARHTZ2.mjs.map} +0 -0
- /package/dist/{chunk-JCFN6KRS.mjs.map → chunk-HGWDB73S.mjs.map} +0 -0
- /package/dist/{chunk-JXXMO7PY.mjs.map → chunk-HN5RW4C3.mjs.map} +0 -0
- /package/dist/{chunk-I2A4EQPH.mjs.map → chunk-HQ2GXFK5.mjs.map} +0 -0
- /package/dist/{chunk-TBJLNIOY.mjs.map → chunk-JBLYYTHN.mjs.map} +0 -0
- /package/dist/{chunk-GRSN76BV.mjs.map → chunk-KH2R4STU.mjs.map} +0 -0
- /package/dist/{chunk-ZF5NMQJZ.mjs.map → chunk-KUKLN3CK.mjs.map} +0 -0
- /package/dist/{chunk-UAKRBNW2.mjs.map → chunk-L4T76OKM.mjs.map} +0 -0
- /package/dist/{chunk-PY5WCBKN.mjs.map → chunk-MERKXOSI.mjs.map} +0 -0
- /package/dist/{chunk-APCB5HWT.mjs.map → chunk-NLSDZJRR.mjs.map} +0 -0
- /package/dist/{chunk-EWYIXCNF.mjs.map → chunk-NLUTNCLH.mjs.map} +0 -0
- /package/dist/{chunk-OP4Q2KDS.mjs.map → chunk-NMKKMY5P.mjs.map} +0 -0
- /package/dist/{chunk-WDPFO4II.mjs.map → chunk-NMPK336K.mjs.map} +0 -0
- /package/dist/{chunk-X6BZ5IEV.mjs.map → chunk-NU7O6YKR.mjs.map} +0 -0
- /package/dist/{chunk-CBI5F4ME.mjs.map → chunk-OMSSA4NO.mjs.map} +0 -0
- /package/dist/{chunk-GYHD6QEA.mjs.map → chunk-PQGQ3EH5.mjs.map} +0 -0
- /package/dist/{chunk-LSUCENYD.mjs.map → chunk-RBKGHUSR.mjs.map} +0 -0
- /package/dist/{chunk-TEUERRDG.mjs.map → chunk-RV45XVXE.mjs.map} +0 -0
- /package/dist/{chunk-FW6ZI2MC.mjs.map → chunk-UAFSWXN5.mjs.map} +0 -0
- /package/dist/{chunk-ANLL2EIX.mjs.map → chunk-UWCGTH3U.mjs.map} +0 -0
- /package/dist/{chunk-6R2LEEEP.mjs.map → chunk-UZF2D2GG.mjs.map} +0 -0
- /package/dist/{chunk-62L3PMYE.mjs.map → chunk-V3OVMHZD.mjs.map} +0 -0
- /package/dist/{chunk-UDITT3N3.mjs.map → chunk-V6ELDZ2B.mjs.map} +0 -0
- /package/dist/{chunk-IJQOTS5O.mjs.map → chunk-VJUS3GC4.mjs.map} +0 -0
- /package/dist/{chunk-MQEAEU6G.mjs.map → chunk-XGMRYNER.mjs.map} +0 -0
- /package/dist/{chunk-MMQMVVD6.mjs.map → chunk-XLTD5J74.mjs.map} +0 -0
- /package/dist/{chunk-OMBUOOMD.mjs.map → chunk-XYT542WD.mjs.map} +0 -0
- /package/dist/{chunk-COWOGT7U.mjs.map → chunk-YZWFDSTC.mjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Modal_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3YF7H577.mjs";
|
|
4
4
|
import {
|
|
5
5
|
cn
|
|
6
6
|
} from "./chunk-53ICLDGS.mjs";
|
|
@@ -172,4 +172,4 @@ var Whiteboard_default = Whiteboard;
|
|
|
172
172
|
export {
|
|
173
173
|
Whiteboard_default
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
175
|
+
//# sourceMappingURL=chunk-RBKGHUSR.mjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkJTWXQ267js = require('./chunk-JTWXQ267.js');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var _chunkTN3AYOMVjs = require('./chunk-TN3AYOMV.js');
|
|
@@ -147,7 +147,7 @@ var Whiteboard = ({
|
|
|
147
147
|
image.id
|
|
148
148
|
)) }),
|
|
149
149
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
150
|
-
|
|
150
|
+
_chunkJTWXQ267js.Modal_default,
|
|
151
151
|
{
|
|
152
152
|
isOpen: previewImage !== null,
|
|
153
153
|
onClose: () => setPreviewImageId(null),
|
|
@@ -172,4 +172,4 @@ var Whiteboard_default = Whiteboard;
|
|
|
172
172
|
|
|
173
173
|
|
|
174
174
|
exports.Whiteboard_default = Whiteboard_default;
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
175
|
+
//# sourceMappingURL=chunk-RMCZ7C2C.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-PIZTI5SJ.js","../src/components/Whiteboard/Whiteboard.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-PIZTI5SJ.js","sourcesContent":[null,"import { HTMLAttributes, useCallback, useState } from 'react';\nimport { DownloadSimpleIcon } from '@phosphor-icons/react/dist/csr/DownloadSimple';\nimport Modal from '../Modal/Modal';\nimport { cn } from '../../utils/utils';\n\n// Design constants for critical layout dimensions\nconst IMAGE_WIDTH = 225;\nconst IMAGE_HEIGHT = 90;\n\n/**\n * Whiteboard image item interface\n */\nexport interface WhiteboardImage {\n id: string;\n imageUrl: string;\n title?: string;\n}\n\n/**\n * Whiteboard component props interface\n */\nexport interface WhiteboardProps extends HTMLAttributes<HTMLDivElement> {\n /** Array of images to display in the whiteboard */\n images: WhiteboardImage[];\n /** Whether to show download button on images */\n showDownload?: boolean;\n /** Custom className for the container */\n className?: string;\n /** Callback when download button is clicked */\n onDownload?: (image: WhiteboardImage) => void;\n /**\n * Called when the user activates an image — ao ampliar OU ao baixar.\n * Lets a consumer observe the interaction (marking a board as viewed, say)\n * without wrapping these buttons in an outer control of its own.\n */\n onImageActivate?: (image: WhiteboardImage) => void;\n /** Maximum number of images to display per row on desktop */\n imagesPerRow?: 2 | 3 | 4;\n}\n\n/**\n * Whiteboard component for displaying classroom board images\n * @param props Component properties\n * @returns Whiteboard component\n */\nconst Whiteboard = ({\n images,\n showDownload = true,\n className,\n onDownload,\n onImageActivate,\n imagesPerRow = 2,\n ...rest\n}: WhiteboardProps) => {\n // State to track images that failed to load\n const [imageErrors, setImageErrors] = useState<Set<string>>(new Set());\n /**\n * Quadro aberto em tamanho grande, guardado pelo ID e resolvido na lista\n * ATUAL — não pelo objeto.\n *\n * Guardar o objeto deixava o preview exibindo uma imagem que já não está mais\n * em `images` (a aula muda, a lista é trocada e o modal segue mostrando a\n * antiga). Resolvendo por ID, o preview fecha sozinho quando o quadro sai da\n * lista, e uma lista vazia não deixa o diálogo armado para reabrir sozinho\n * depois.\n */\n const [previewImageId, setPreviewImageId] = useState<string | null>(null);\n const previewImage =\n images?.find((image) => image.id === previewImageId) ?? null;\n\n /**\n * Handle image download\n */\n const handleDownload = useCallback(\n (image: WhiteboardImage) => {\n if (onDownload) {\n onDownload(image);\n } else {\n const link = document.createElement('a');\n link.href = image.imageUrl;\n link.download = image.title || `whiteboard-${image.id}`;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n },\n [onDownload]\n );\n\n /**\n * Clique na imagem: abre o quadro ampliado.\n *\n * Antes isto baixava o arquivo, igual ao botão do canto — o rótulo dizia\n * \"Ampliar\" e nada ampliava. Cada um dos dois botões agora faz o que o seu\n * rótulo promete, e os dois seguem avisando o consumidor: `onImageActivate` é\n * \"o aluno interagiu com este quadro\" (quem marca progresso de quadro visto),\n * então ampliar e baixar continuam valendo igual.\n */\n const handleExpand = useCallback(\n (image: WhiteboardImage) => {\n setPreviewImageId(image.id);\n onImageActivate?.(image);\n },\n [onImageActivate]\n );\n\n /** Clique no botão do canto: baixa o arquivo. */\n const handleDownloadClick = useCallback(\n (image: WhiteboardImage) => {\n handleDownload(image);\n onImageActivate?.(image);\n },\n [handleDownload, onImageActivate]\n );\n\n /**\n * Handle image loading error\n */\n const handleImageError = useCallback((imageId: string) => {\n setImageErrors((prev) => new Set(prev).add(imageId));\n }, []);\n\n const gridColsClass =\n images?.length === 1\n ? 'grid-cols-1'\n : {\n 2: 'grid-cols-1 sm:grid-cols-2',\n 3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n 4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',\n }[imagesPerRow];\n\n // Let CSS handle sizing responsively\n\n if (!images || images.length === 0) {\n return (\n <div\n className={cn(\n 'flex items-center justify-center p-8 bg-background border border-border-50 rounded-xl',\n className\n )}\n {...rest}\n >\n <p className=\"text-gray-400 text-sm\">Nenhuma imagem disponível</p>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'flex flex-col bg-background border border-border-50 p-4 gap-2 rounded-xl w-fit mx-auto',\n className\n )}\n {...rest}\n >\n <div className={cn('grid gap-4', gridColsClass)}>\n {images.map((image) => (\n <div\n key={image.id}\n className=\"relative group overflow-hidden bg-gray-100 rounded-lg\"\n style={{\n width: `${IMAGE_WIDTH}px`,\n }}\n >\n <div\n className=\"relative\"\n style={{\n width: `${IMAGE_WIDTH}px`,\n height: `${IMAGE_HEIGHT}px`,\n }}\n >\n {imageErrors.has(image.id) ? (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gray-200\">\n <p className=\"text-gray-500 text-sm text-center px-2\">\n Imagem indisponível\n </p>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => handleExpand(image)}\n className=\"absolute inset-0 w-full h-full cursor-pointer border-none p-0 bg-transparent\"\n aria-label={`Ampliar ${image.title || 'imagem'}`}\n >\n <img\n src={image.imageUrl}\n alt={image.title || `Whiteboard ${image.id}`}\n className=\"w-full h-full object-cover\"\n loading=\"lazy\"\n onError={() => handleImageError(image.id)}\n />\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/20 to-transparent pointer-events-none\" />\n </button>\n )}\n </div>\n {showDownload && (\n <button\n type=\"button\"\n onClick={() => handleDownloadClick(image)}\n className=\"cursor-pointer absolute bottom-3 right-3 flex items-center justify-center bg-black/20 backdrop-blur-sm rounded hover:bg-black/30 transition-colors duration-200 group/button w-6 h-6\"\n aria-label={`Baixar ${image.title || 'imagem'}`}\n >\n {/* Ícone de download. Era o `ArrowsOut` (expandir) num botão que\n baixava — quem olhava esperava ampliar. Decorativo: o rótulo\n do botão já diz o que ele faz. */}\n <DownloadSimpleIcon\n size={24}\n weight=\"regular\"\n aria-hidden=\"true\"\n className=\"text-white group-hover/button:scale-110 transition-transform duration-200\"\n />\n </button>\n )}\n </div>\n ))}\n </div>\n\n {/* Quadro ampliado. Usa o `Modal` da lib, que já traz Escape, trava de\n scroll e gerenciamento de foco (`useModalFocus`). */}\n <Modal\n isOpen={previewImage !== null}\n onClose={() => setPreviewImageId(null)}\n title={previewImage?.title || 'Quadro da aula'}\n size=\"xl\"\n >\n {previewImage && (\n <img\n src={previewImage.imageUrl}\n alt={previewImage.title ? '' : 'Quadro da aula ampliado'}\n className=\"w-full h-auto rounded-lg\"\n />\n )}\n </Modal>\n </div>\n );\n};\n\nexport default Whiteboard;\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-RMCZ7C2C.js","../src/components/Whiteboard/Whiteboard.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-RMCZ7C2C.js","sourcesContent":[null,"import { HTMLAttributes, useCallback, useState } from 'react';\nimport { DownloadSimpleIcon } from '@phosphor-icons/react/dist/csr/DownloadSimple';\nimport Modal from '../Modal/Modal';\nimport { cn } from '../../utils/utils';\n\n// Design constants for critical layout dimensions\nconst IMAGE_WIDTH = 225;\nconst IMAGE_HEIGHT = 90;\n\n/**\n * Whiteboard image item interface\n */\nexport interface WhiteboardImage {\n id: string;\n imageUrl: string;\n title?: string;\n}\n\n/**\n * Whiteboard component props interface\n */\nexport interface WhiteboardProps extends HTMLAttributes<HTMLDivElement> {\n /** Array of images to display in the whiteboard */\n images: WhiteboardImage[];\n /** Whether to show download button on images */\n showDownload?: boolean;\n /** Custom className for the container */\n className?: string;\n /** Callback when download button is clicked */\n onDownload?: (image: WhiteboardImage) => void;\n /**\n * Called when the user activates an image — ao ampliar OU ao baixar.\n * Lets a consumer observe the interaction (marking a board as viewed, say)\n * without wrapping these buttons in an outer control of its own.\n */\n onImageActivate?: (image: WhiteboardImage) => void;\n /** Maximum number of images to display per row on desktop */\n imagesPerRow?: 2 | 3 | 4;\n}\n\n/**\n * Whiteboard component for displaying classroom board images\n * @param props Component properties\n * @returns Whiteboard component\n */\nconst Whiteboard = ({\n images,\n showDownload = true,\n className,\n onDownload,\n onImageActivate,\n imagesPerRow = 2,\n ...rest\n}: WhiteboardProps) => {\n // State to track images that failed to load\n const [imageErrors, setImageErrors] = useState<Set<string>>(new Set());\n /**\n * Quadro aberto em tamanho grande, guardado pelo ID e resolvido na lista\n * ATUAL — não pelo objeto.\n *\n * Guardar o objeto deixava o preview exibindo uma imagem que já não está mais\n * em `images` (a aula muda, a lista é trocada e o modal segue mostrando a\n * antiga). Resolvendo por ID, o preview fecha sozinho quando o quadro sai da\n * lista, e uma lista vazia não deixa o diálogo armado para reabrir sozinho\n * depois.\n */\n const [previewImageId, setPreviewImageId] = useState<string | null>(null);\n const previewImage =\n images?.find((image) => image.id === previewImageId) ?? null;\n\n /**\n * Handle image download\n */\n const handleDownload = useCallback(\n (image: WhiteboardImage) => {\n if (onDownload) {\n onDownload(image);\n } else {\n const link = document.createElement('a');\n link.href = image.imageUrl;\n link.download = image.title || `whiteboard-${image.id}`;\n link.target = '_blank';\n link.rel = 'noopener noreferrer';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n },\n [onDownload]\n );\n\n /**\n * Clique na imagem: abre o quadro ampliado.\n *\n * Antes isto baixava o arquivo, igual ao botão do canto — o rótulo dizia\n * \"Ampliar\" e nada ampliava. Cada um dos dois botões agora faz o que o seu\n * rótulo promete, e os dois seguem avisando o consumidor: `onImageActivate` é\n * \"o aluno interagiu com este quadro\" (quem marca progresso de quadro visto),\n * então ampliar e baixar continuam valendo igual.\n */\n const handleExpand = useCallback(\n (image: WhiteboardImage) => {\n setPreviewImageId(image.id);\n onImageActivate?.(image);\n },\n [onImageActivate]\n );\n\n /** Clique no botão do canto: baixa o arquivo. */\n const handleDownloadClick = useCallback(\n (image: WhiteboardImage) => {\n handleDownload(image);\n onImageActivate?.(image);\n },\n [handleDownload, onImageActivate]\n );\n\n /**\n * Handle image loading error\n */\n const handleImageError = useCallback((imageId: string) => {\n setImageErrors((prev) => new Set(prev).add(imageId));\n }, []);\n\n const gridColsClass =\n images?.length === 1\n ? 'grid-cols-1'\n : {\n 2: 'grid-cols-1 sm:grid-cols-2',\n 3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n 4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',\n }[imagesPerRow];\n\n // Let CSS handle sizing responsively\n\n if (!images || images.length === 0) {\n return (\n <div\n className={cn(\n 'flex items-center justify-center p-8 bg-background border border-border-50 rounded-xl',\n className\n )}\n {...rest}\n >\n <p className=\"text-gray-400 text-sm\">Nenhuma imagem disponível</p>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'flex flex-col bg-background border border-border-50 p-4 gap-2 rounded-xl w-fit mx-auto',\n className\n )}\n {...rest}\n >\n <div className={cn('grid gap-4', gridColsClass)}>\n {images.map((image) => (\n <div\n key={image.id}\n className=\"relative group overflow-hidden bg-gray-100 rounded-lg\"\n style={{\n width: `${IMAGE_WIDTH}px`,\n }}\n >\n <div\n className=\"relative\"\n style={{\n width: `${IMAGE_WIDTH}px`,\n height: `${IMAGE_HEIGHT}px`,\n }}\n >\n {imageErrors.has(image.id) ? (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gray-200\">\n <p className=\"text-gray-500 text-sm text-center px-2\">\n Imagem indisponível\n </p>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => handleExpand(image)}\n className=\"absolute inset-0 w-full h-full cursor-pointer border-none p-0 bg-transparent\"\n aria-label={`Ampliar ${image.title || 'imagem'}`}\n >\n <img\n src={image.imageUrl}\n alt={image.title || `Whiteboard ${image.id}`}\n className=\"w-full h-full object-cover\"\n loading=\"lazy\"\n onError={() => handleImageError(image.id)}\n />\n <div className=\"absolute inset-0 bg-gradient-to-t from-black/20 to-transparent pointer-events-none\" />\n </button>\n )}\n </div>\n {showDownload && (\n <button\n type=\"button\"\n onClick={() => handleDownloadClick(image)}\n className=\"cursor-pointer absolute bottom-3 right-3 flex items-center justify-center bg-black/20 backdrop-blur-sm rounded hover:bg-black/30 transition-colors duration-200 group/button w-6 h-6\"\n aria-label={`Baixar ${image.title || 'imagem'}`}\n >\n {/* Ícone de download. Era o `ArrowsOut` (expandir) num botão que\n baixava — quem olhava esperava ampliar. Decorativo: o rótulo\n do botão já diz o que ele faz. */}\n <DownloadSimpleIcon\n size={24}\n weight=\"regular\"\n aria-hidden=\"true\"\n className=\"text-white group-hover/button:scale-110 transition-transform duration-200\"\n />\n </button>\n )}\n </div>\n ))}\n </div>\n\n {/* Quadro ampliado. Usa o `Modal` da lib, que já traz Escape, trava de\n scroll e gerenciamento de foco (`useModalFocus`). */}\n <Modal\n isOpen={previewImage !== null}\n onClose={() => setPreviewImageId(null)}\n title={previewImage?.title || 'Quadro da aula'}\n size=\"xl\"\n >\n {previewImage && (\n <img\n src={previewImage.imageUrl}\n alt={previewImage.title ? '' : 'Quadro da aula ampliado'}\n className=\"w-full h-auto rounded-lg\"\n />\n )}\n </Modal>\n </div>\n );\n};\n\nexport default Whiteboard;\n"]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import { forwardRef } from "react";
|
|
7
7
|
import { jsx } from "react/jsx-runtime";
|
|
8
8
|
var IconButton = forwardRef(
|
|
9
|
-
({ icon, size = "md", active
|
|
9
|
+
({ icon, size = "md", active, className = "", disabled, ...props }, ref) => {
|
|
10
10
|
const baseClasses = [
|
|
11
11
|
"inline-flex",
|
|
12
12
|
"items-center",
|
|
@@ -58,4 +58,4 @@ var IconButton_default = IconButton;
|
|
|
58
58
|
export {
|
|
59
59
|
IconButton_default
|
|
60
60
|
};
|
|
61
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
//# sourceMappingURL=chunk-ROS5XGTQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/IconButton/IconButton.tsx"],"sourcesContent":["import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\nimport { cn } from '../../utils/utils';\n\n/**\n * IconButton component props interface\n */\nexport type IconButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Tamanho do botão */\n size?: 'sm' | 'md';\n /** Estado de seleção/ativo do botão - permanece ativo até ser clicado novamente ou outro botão ser ativado */\n active?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * IconButton component for Analytica Ensino platforms\n *\n * Um botão compacto apenas com ícone, ideal para menus dropdown,\n * barras de ferramentas e ações secundárias.\n * Oferece dois tamanhos com estilo consistente.\n * Estado ativo permanece até ser clicado novamente ou outro botão ser ativado.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param size - Tamanho do botão (sm, md)\n * @param active - Estado ativo/selecionado do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button compacto estilizado apenas com ícone\n *\n * @example\n * ```tsx\n * <IconButton\n * icon={<MoreVerticalIcon />}\n * size=\"sm\"\n * onClick={() => openMenu()}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Botão ativo em uma barra de ferramentas - permanece ativo até outro clique\n * <IconButton\n * icon={<BoldIcon />}\n * active={isBold}\n * onClick={toggleBold}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para controle programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * <IconButton\n * ref={buttonRef}\n * icon={<EditIcon />}\n * size=\"md\"\n * onClick={() => startEditing()}\n * />\n * ```\n */\nconst IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ icon, size = 'md', active, className = '', disabled, ...props }, ref) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'inline-flex',\n 'items-center',\n 'justify-center',\n 'rounded-lg',\n 'font-medium',\n 'bg-transparent',\n 'text-text-950',\n 'cursor-pointer',\n 'hover:bg-primary-600',\n 'hover:text-text',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-0',\n 'focus-visible:ring-indicator-info',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n 'disabled:pointer-events-none',\n ];\n\n // Classes de tamanho\n const sizeClasses = {\n sm: ['w-6', 'h-6', 'text-sm'],\n md: ['w-10', 'h-10', 'text-base'],\n };\n\n // Classes de estado ativo\n const activeClasses = active\n ? ['!bg-primary-50', '!text-primary-950', 'hover:!bg-primary-100']\n : [];\n\n const allClasses = [\n ...baseClasses,\n ...sizeClasses[size],\n ...activeClasses,\n ].join(' ');\n\n // Garantir acessibilidade com aria-label padrão\n const ariaLabel = props['aria-label'] ?? 'Botão de ação';\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(allClasses, className)}\n disabled={disabled}\n // Only expose toggle semantics when the caller actually controls the\n // state; a hardcoded `false` makes screen readers announce every\n // icon button as a toggle (\"botão alternar\").\n aria-pressed={active}\n aria-label={ariaLabel}\n {...props}\n >\n <span className=\"flex items-center justify-center\">{icon}</span>\n </button>\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n\nexport default IconButton;\n"],"mappings":";;;;;AAAA,SAA0C,kBAAkB;AAyHpD;AAxDR,IAAM,aAAa;AAAA,EACjB,CAAC,EAAE,MAAM,OAAO,MAAM,QAAQ,YAAY,IAAI,UAAU,GAAG,MAAM,GAAG,QAAQ;AAE1E,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,cAAc;AAAA,MAClB,IAAI,CAAC,OAAO,OAAO,SAAS;AAAA,MAC5B,IAAI,CAAC,QAAQ,QAAQ,WAAW;AAAA,IAClC;AAGA,UAAM,gBAAgB,SAClB,CAAC,kBAAkB,qBAAqB,uBAAuB,IAC/D,CAAC;AAEL,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,GAAG,YAAY,IAAI;AAAA,MACnB,GAAG;AAAA,IACL,EAAE,KAAK,GAAG;AAGV,UAAM,YAAY,MAAM,YAAY,KAAK;AAEzC,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW,GAAG,YAAY,SAAS;AAAA,QACnC;AAAA,QAIA,gBAAc;AAAA,QACd,cAAY;AAAA,QACX,GAAG;AAAA,QAEJ,8BAAC,UAAK,WAAU,oCAAoC,gBAAK;AAAA;AAAA,IAC3D;AAAA,EAEJ;AACF;AAEA,WAAW,cAAc;AAEzB,IAAO,qBAAQ;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SimulationStatCard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YZWFDSTC.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Tooltip
|
|
6
6
|
} from "./chunk-QBKJAKGY.mjs";
|
|
@@ -207,4 +207,4 @@ export {
|
|
|
207
207
|
numberedExamScores,
|
|
208
208
|
answerTiles
|
|
209
209
|
};
|
|
210
|
-
//# sourceMappingURL=chunk-
|
|
210
|
+
//# sourceMappingURL=chunk-RV45XVXE.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
escapeHtmlText,
|
|
3
3
|
processLatexInHtml
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NU7O6YKR.mjs";
|
|
5
5
|
import {
|
|
6
6
|
normalizeLineBreaksInHtml
|
|
7
7
|
} from "./chunk-ZWMOGGGE.mjs";
|
|
@@ -3292,4 +3292,4 @@ var MathNode = Node2.create({
|
|
|
3292
3292
|
export {
|
|
3293
3293
|
MathNode
|
|
3294
3294
|
};
|
|
3295
|
-
//# sourceMappingURL=chunk-
|
|
3295
|
+
//# sourceMappingURL=chunk-UAFSWXN5.mjs.map
|
|
@@ -26,13 +26,11 @@ import {
|
|
|
26
26
|
} from "./chunk-QBKJAKGY.mjs";
|
|
27
27
|
import {
|
|
28
28
|
IconButton_default
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
import {
|
|
31
|
-
useEscapeToClose
|
|
32
|
-
} from "./chunk-JSH3BQZ7.mjs";
|
|
29
|
+
} from "./chunk-ROS5XGTQ.mjs";
|
|
33
30
|
import {
|
|
31
|
+
useEscapeToClose,
|
|
34
32
|
useModalFocus
|
|
35
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-Z4L2DWMX.mjs";
|
|
36
34
|
import {
|
|
37
35
|
Button_default
|
|
38
36
|
} from "./chunk-ZQZBOTZJ.mjs";
|
|
@@ -1248,4 +1246,4 @@ export {
|
|
|
1248
1246
|
VLibrasLoader,
|
|
1249
1247
|
AccessibilityWidget
|
|
1250
1248
|
};
|
|
1251
|
-
//# sourceMappingURL=chunk-
|
|
1249
|
+
//# sourceMappingURL=chunk-ULVFVLFE.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/AccessibilityWidget/AccessibilityWidget.tsx","../src/components/AccessibilityWidget/AccessibilityFab.tsx","../src/components/AccessibilityWidget/fabPositioning.ts","../src/components/AccessibilityWidget/AccessibilityPanel.tsx","../src/components/AccessibilityWidget/AccessibilityToggleRow.tsx","../src/components/AccessibilityWidget/TTSSection.tsx","../src/components/AccessibilityWidget/LibrasFab.tsx","../src/components/AccessibilityWidget/ReadingAid.tsx","../src/components/AccessibilityWidget/ColorBlindFilters.tsx","../src/components/AccessibilityWidget/TTSController.tsx","../src/components/AccessibilityWidget/VLibrasLoader.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport AccessibilityFab, {\n type AccessibilityFabPosition,\n} from './AccessibilityFab';\nimport AccessibilityPanel from './AccessibilityPanel';\nimport LibrasFab from './LibrasFab';\nimport ReadingAid from './ReadingAid';\nimport ColorBlindFilters from './ColorBlindFilters';\nimport TTSController from './TTSController';\nimport VLibrasLoader from './VLibrasLoader';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\nimport { useA11yPreferences } from '../../hooks/useA11yPreferences';\nimport { useA11yKeyboardShortcut } from '../../hooks/useA11yKeyboardShortcut';\nimport './accessibility.css';\n\nexport interface AccessibilityWidgetProps {\n /** Lado da viewport onde o botão fica colado (default: 'right') */\n position?: AccessibilityFabPosition;\n /** Classes extras para o botão flutuante */\n fabClassName?: string;\n /** Classes extras para o painel */\n panelClassName?: string;\n /**\n * Mostra o botão de Libras empilhado abaixo do botão de\n * acessibilidade (default: true). Plataformas que já injetam o\n * VLibras de forma própria podem desabilitar passando `false`.\n */\n showLibras?: boolean;\n}\n\n/**\n * Widget de acessibilidade — botão flutuante que abre um painel\n * com controles de contraste, fonte, espaçamento e outras\n * preferências visuais. As preferências são persistidas em\n * localStorage e aplicadas via classes no `<html>`.\n *\n * Renderize uma única instância no shell da aplicação. Tudo fica\n * dentro de `.a11y-widget-root` para que o próprio widget não\n * sofra com os filtros que aplica na página.\n *\n * @example\n * ```tsx\n * <AccessibilityWidget position=\"left\" />\n * ```\n */\nexport default function AccessibilityWidget({\n position = 'right',\n fabClassName,\n panelClassName,\n showLibras = true,\n}: Readonly<AccessibilityWidgetProps>) {\n useA11yPreferences();\n useA11yKeyboardShortcut();\n\n const isPanelOpen = useAccessibilityStore((s) => s.isPanelOpen);\n const togglePanel = useAccessibilityStore((s) => s.togglePanel);\n const closePanel = useAccessibilityStore((s) => s.closePanel);\n const librasEnabled = useAccessibilityStore((s) => s.librasEnabled);\n const setLibrasEnabled = useAccessibilityStore((s) => s.setLibrasEnabled);\n\n // Quando o Libras é exibido, os dois FABs ficam empilhados\n // (acessibilidade acima do meio, libras abaixo). Sem Libras,\n // o de acessibilidade ocupa o centro como antes.\n const accessibilityVerticalAlign = showLibras ? 'above-center' : 'center';\n\n /**\n * Clique no FAB de Libras:\n * - Primeira vez (não ativado): ativa o widget VLibras (que se\n * auto-abre no painel pela primeira vez).\n * - Demais vezes: dispara o click no botão de acesso nativo do\n * VLibras, que abre/fecha o painel sem precisar reinjetar o widget.\n * Isso evita o ciclo de remoção/reinjeção que deixava o VLibras\n * em estado inconsistente após fechá-lo.\n */\n const handleLibrasClick = () => {\n if (!librasEnabled) {\n setLibrasEnabled(true);\n return;\n }\n document.querySelector<HTMLElement>('[vw-access-button]')?.click();\n };\n\n const fabRef = useRef<HTMLButtonElement>(null);\n const wasPanelOpenRef = useRef(false);\n\n /**\n * Devolve o foco ao FAB quando o painel fecha.\n *\n * O painel já faz isso sozinho (`useModalFocus` guarda quem o abriu), mas\n * quando quem abriu foi o próprio FAB o nó guardado não existe mais: o FAB é\n * desmontado enquanto o painel está aberto, e o hook — que só devolve o foco\n * se o elemento ainda está na página — deixa o foco no `<body>`. Daí o Tab\n * recomeçava do topo da página.\n *\n * A guarda do `<body>` é o que mantém o caminho do atalho `Alt+A` intacto:\n * ali quem tinha o foco era um elemento qualquer da página, que sobrevive à\n * abertura e recebe o foco de volta do próprio hook. Nesse caso o foco não\n * está no `<body>` e este efeito sai do caminho.\n */\n useEffect(() => {\n if (isPanelOpen) {\n wasPanelOpenRef.current = true;\n return;\n }\n\n if (!wasPanelOpenRef.current) return;\n wasPanelOpenRef.current = false;\n\n const active = document.activeElement;\n if (!active || active === document.body) {\n fabRef.current?.focus();\n }\n }, [isPanelOpen]);\n\n return (\n <>\n {!isPanelOpen && (\n <AccessibilityFab\n ref={fabRef}\n onClick={togglePanel}\n isOpen={isPanelOpen}\n position={position}\n verticalAlign={accessibilityVerticalAlign}\n className={fabClassName}\n />\n )}\n {!isPanelOpen && showLibras && (\n <LibrasFab onClick={handleLibrasClick} position={position} />\n )}\n <AccessibilityPanel\n isOpen={isPanelOpen}\n onClose={closePanel}\n position={position}\n className={panelClassName}\n />\n <ReadingAid />\n <ColorBlindFilters />\n <TTSController />\n {showLibras && <VLibrasLoader />}\n </>\n );\n}\n","import { forwardRef } from 'react';\nimport Button from '../Button/Button';\nimport { Tooltip } from '../Tooltip/Tooltip';\nimport { cn } from '../../utils/utils';\nimport accessibilityIcon from '../../assets/img/accessibility.png';\nimport {\n FAB_POSITION_CLASSES,\n FAB_TOOLTIP_POSITION,\n FAB_VERTICAL_ALIGN_CLASSES,\n type FabPosition,\n type FabVerticalAlign,\n} from './fabPositioning';\n\n/** Re-exports mantidos para compatibilidade com a API pública do widget. */\nexport type AccessibilityFabPosition = FabPosition;\nexport type AccessibilityFabVerticalAlign = FabVerticalAlign;\n\nexport interface AccessibilityFabProps {\n /** Click handler — alterna o painel */\n onClick: () => void;\n /** Indica se o painel está aberto (controla aria-expanded) */\n isOpen?: boolean;\n /** Lado da viewport onde o botão fica colado */\n position?: AccessibilityFabPosition;\n /** Alinhamento vertical (default: `center`) */\n verticalAlign?: AccessibilityFabVerticalAlign;\n /** Classes extras */\n className?: string;\n}\n\n/**\n * Botão flutuante (FAB) que abre o painel de acessibilidade.\n * Inspirado no padrão HandTalk: quadrado azul escuro colado na\n * lateral da viewport (direita por padrão), com o ícone universal\n * de acessibilidade. Verticalmente centralizado.\n *\n * A ref vai pro `<button>` em si: o FAB é desmontado enquanto o painel está\n * aberto, então quem devolve o foco pra ele no fechamento é o\n * `AccessibilityWidget`, que precisa alcançar o nó recém-remontado.\n */\nconst AccessibilityFab = forwardRef<HTMLButtonElement, AccessibilityFabProps>(\n (\n {\n onClick,\n isOpen = false,\n position = 'right',\n verticalAlign = 'center',\n className,\n },\n ref\n ) => {\n const label = isOpen\n ? 'Fechar opções de acessibilidade'\n : 'Opções de acessibilidade';\n\n return (\n <Tooltip\n content={label}\n position={FAB_TOOLTIP_POSITION[position]}\n className={cn(\n 'fixed z-40',\n FAB_VERTICAL_ALIGN_CLASSES[verticalAlign],\n FAB_POSITION_CLASSES[position]\n )}\n >\n <Button\n ref={ref}\n variant=\"raw\"\n onClick={onClick}\n aria-label={label}\n aria-expanded={isOpen}\n data-testid=\"accessibility-fab\"\n className={cn(\n 'a11y-widget-shield',\n FAB_POSITION_CLASSES[position],\n 'flex h-10 w-10 cursor-pointer items-center justify-center',\n // `text-text-50` flipa junto com `bg-info-900` (claro no light,\n // escuro no dark). `text-white` deixaria o ícone branco sumindo\n // no tema escuro, onde `bg-info-900` resolve pra azul-claro.\n 'bg-info-900 text-text-50 shadow-lg',\n 'transition-all duration-200 hover:scale-110 hover:bg-info-800',\n 'focus:outline-none focus:ring-4 focus:ring-info-300',\n className\n )}\n >\n <img\n src={accessibilityIcon}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"h-7 w-7\"\n />\n </Button>\n </Tooltip>\n );\n }\n);\n\nAccessibilityFab.displayName = 'AccessibilityFab';\n\nexport default AccessibilityFab;\n","/**\n * Constantes de posicionamento compartilhadas entre os FABs do widget\n * (`AccessibilityFab` e `LibrasFab`). Centralizadas aqui para evitar\n * que mudanças de gap/lateral precisem ser replicadas em cada FAB.\n */\n\nexport type FabPosition = 'right' | 'left';\n\n/**\n * Alinhamento vertical do FAB. Quando o widget renderiza só um botão\n * (sem Libras), `center` deixa-o no meio da viewport. Quando há também\n * o LibrasFab empilhado abaixo, o de acessibilidade fica `above-center`\n * e o Libras fica `below-center` — formando um par grudado no meio.\n */\nexport type FabVerticalAlign = 'center' | 'above-center' | 'below-center';\n\nexport const FAB_POSITION_CLASSES: Record<FabPosition, string> = {\n right: 'right-0 rounded-l-lg',\n left: 'left-0 rounded-r-lg',\n};\n\nexport const FAB_VERTICAL_ALIGN_CLASSES: Record<FabVerticalAlign, string> = {\n center: 'top-1/2 -translate-y-1/2',\n // Pares empilhados (acessibilidade + Libras) com gap mínimo entre si,\n // como no widget do HandTalk. Cada FAB tem 40px (h-10).\n 'above-center': 'top-[calc(50%-1px)] -translate-y-full',\n 'below-center': 'top-[calc(50%+1px)]',\n};\n\n/** Tooltip aparece do lado oposto à borda em que o FAB está colado. */\nexport const FAB_TOOLTIP_POSITION: Record<FabPosition, 'left' | 'right'> = {\n right: 'left',\n left: 'right',\n};\n","import { useRef, useState, type ReactNode } from 'react';\nimport {\n ArrowCounterClockwiseIcon,\n CaretDownIcon,\n EyeIcon,\n FilmReelIcon,\n KeyboardIcon,\n NavigationArrowIcon,\n SpeakerHighIcon,\n TextTIcon,\n XIcon,\n} from '@phosphor-icons/react';\nimport accessibilityIcon from '../../assets/img/accessibility.png';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport IconButton from '../IconButton/IconButton';\nimport AccessibilityToggleRow from './AccessibilityToggleRow';\nimport TTSSection from './TTSSection';\nimport { cn } from '../../utils/utils';\nimport { useModalFocus } from '../../hooks/useModalFocus';\nimport { useEscapeToClose } from '../../hooks/useEscapeToClose';\nimport {\n useAccessibilityStore,\n type ContrastMode,\n type SaturationMode,\n type ReadingAid,\n} from '../../store/accessibilityStore';\nimport type { AccessibilityFabPosition } from './AccessibilityFab';\n\nconst CONTRAST_OPTIONS: { value: ContrastMode; label: string }[] = [\n { value: 'normal', label: 'Normal' },\n { value: 'high', label: 'Alto' },\n { value: 'inverted', label: 'Invertido' },\n];\n\nconst SATURATION_OPTIONS: { value: SaturationMode; label: string }[] = [\n { value: 'normal', label: 'Normal' },\n { value: 'low', label: 'Baixa' },\n { value: 'grayscale', label: 'Tons de cinza' },\n];\n\nconst READING_AID_OPTIONS: { value: ReadingAid; label: string }[] = [\n { value: 'none', label: 'Nenhum' },\n { value: 'ruler', label: 'Régua' },\n { value: 'mask', label: 'Máscara' },\n];\n\nconst LEVEL_LABELS = ['Padrão', 'Pequeno', 'Médio', 'Grande'] as const;\n\n/** Tamanho de fonte do preview \"Aa\" em cada botão (Padrão → Grande). */\nconst FONT_SIZE_PREVIEW_CLASSES = [\n 'text-base', // Padrão\n 'text-lg', // Pequeno (= maior que Padrão, segue a escala incremental do widget)\n 'text-2xl', // Médio\n 'text-4xl', // Grande\n] as const;\n\n/** Letter-spacing do preview \"Aa\" em cada botão. */\nconst LETTER_SPACING_PREVIEW_CLASSES = [\n 'tracking-tighter', // Padrão (junto)\n 'tracking-normal',\n 'tracking-wider',\n 'tracking-widest',\n] as const;\n\n/** Gap vertical entre as 3 barras do preview de espaçamento entre linhas. */\nconst LINE_SPACING_PREVIEW_GAPS = [\n 'gap-0.5', // Padrão (2px) — linhas próximas\n 'gap-1.5', // Pequeno (6px)\n 'gap-2.5', // Médio (10px)\n 'gap-3.5', // Grande (14px)\n] as const;\n\n/**\n * `<dialog open>` aplica `left: 0; right: 0` como user-agent style. Sem\n * resetar o lado oposto para `auto`, o painel acaba grudando no lado\n * errado mesmo com `right-6` ou `left-6` aplicado.\n */\nconst PANEL_EDGE_CLASSES: Record<AccessibilityFabPosition, string> = {\n right: 'right-10 left-auto',\n left: 'left-10 right-auto',\n};\n\ninterface AccordionSectionProps {\n title: string;\n icon: ReactNode;\n defaultExpanded?: boolean;\n testId?: string;\n children: ReactNode;\n}\n\n/**\n * Item de accordion estilo lista (sem cantos arredondados nem card),\n * com ícone + título à esquerda e caret à direita. Cada item separado\n * do próximo por uma linha fina. Mantém a estrutura visual do design\n * do Figma sem usar o `CardAccordation` da lib (que tem visual de card).\n */\nconst AccordionSection = ({\n title,\n icon,\n defaultExpanded = false,\n testId,\n children,\n}: Readonly<AccordionSectionProps>) => {\n const [expanded, setExpanded] = useState(defaultExpanded);\n return (\n <section className=\"border-b border-background-200 last:border-b-0\">\n <Button\n variant=\"raw\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n data-testid={testId}\n className={cn(\n 'flex w-full cursor-pointer items-center justify-between gap-2 px-4 py-3',\n 'text-left transition-colors hover:bg-background-50',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-info-500 focus-visible:ring-inset'\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span className=\"text-text-800\" aria-hidden=\"true\">\n {icon}\n </span>\n <Text\n size=\"md\"\n weight=\"semibold\"\n className=\"leading-none text-text-800\"\n >\n {title}\n </Text>\n </span>\n <CaretDownIcon\n size={16}\n weight=\"bold\"\n aria-hidden=\"true\"\n className={cn(\n 'text-text-700 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0'\n )}\n />\n </Button>\n {expanded && (\n <div className=\"flex flex-col gap-6 px-4 pb-4 pt-2\">{children}</div>\n )}\n </section>\n );\n};\n\ninterface SubControlProps {\n label: string;\n children: ReactNode;\n}\n\n/**\n * Wrapper para uma control (segmented/toggle) com título dentro do\n * accordion. Tipografia do label segue o Figma: Roboto 12px/500/100%\n * uppercase, cor `text-text-600` (#737373).\n */\nconst SubControl = ({ label, children }: Readonly<SubControlProps>) => (\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n {label}\n </Text>\n {children}\n </div>\n);\n\ninterface SegmentedProps<T extends string | number> {\n value: T;\n options: { value: T; label: string }[];\n onChange: (value: T) => void;\n ariaLabel: string;\n}\n\n/**\n * Estilo de segmented baseado no `SelectionButton` da lib: cada opção é\n * um botão independente com `border` + `bg-background`, e o selecionado\n * ganha `ring-primary-950` (mesma identidade visual do componente da lib,\n * sem o overhead de ícone obrigatório do SelectionButton).\n */\nconst Segmented = <T extends string | number>({\n value,\n options,\n onChange,\n ariaLabel,\n}: Readonly<SegmentedProps<T>>) => (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className=\"flex flex-wrap gap-2\"\n >\n {options.map((opt) => {\n const isActive = opt.value === value;\n return (\n <Button\n key={String(opt.value)}\n variant=\"raw\"\n role=\"radio\"\n aria-checked={isActive}\n onClick={() => onChange(opt.value)}\n className={cn(\n 'flex-1 cursor-pointer rounded-xl border border-border-50 bg-background',\n // Texto segue spec do Figma: Roboto 14px/700/100%/0.2px, cor\n // #525252 (text-700). Quando ativo, troca pra primary-950\n // (azul escuro), mas mantém a mesma typography.\n 'px-4 py-4 text-sm font-bold leading-none tracking-[0.2px] text-text-700',\n 'shadow-soft-shadow-1 transition-all duration-150',\n 'hover:bg-background-100',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indicator-info',\n isActive &&\n 'ring-2 ring-primary-950 ring-offset-0 shadow-none text-primary-950'\n )}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n);\n\ninterface PreviewSegmentedOption<T extends string | number> {\n value: T;\n label: string;\n /** Conteúdo visual exibido DENTRO do botão (preview do efeito). */\n preview: ReactNode;\n}\n\ninterface PreviewSegmentedProps<T extends string | number> {\n value: T;\n options: PreviewSegmentedOption<T>[];\n onChange: (value: T) => void;\n ariaLabel: string;\n}\n\n/**\n * Variante do Segmented onde o botão mostra um preview visual do efeito\n * (ex.: \"Aa\" em tamanhos diferentes para \"Tamanho da fonte\") e o label\n * textual fica abaixo do botão como legenda.\n */\nconst PreviewSegmented = <T extends string | number>({\n value,\n options,\n onChange,\n ariaLabel,\n}: Readonly<PreviewSegmentedProps<T>>) => (\n <div role=\"radiogroup\" aria-label={ariaLabel} className=\"flex gap-2\">\n {options.map((opt) => {\n const isActive = opt.value === value;\n return (\n <div\n key={String(opt.value)}\n className=\"flex flex-1 flex-col items-center gap-2\"\n >\n <Button\n variant=\"raw\"\n role=\"radio\"\n aria-checked={isActive}\n aria-label={opt.label}\n onClick={() => onChange(opt.value)}\n className={cn(\n 'flex aspect-square w-full items-center justify-center',\n 'cursor-pointer rounded-xl border border-border-50 bg-background',\n 'text-text-700 shadow-soft-shadow-1 transition-all duration-150',\n 'hover:bg-background-100',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indicator-info',\n isActive &&\n 'ring-2 ring-primary-950 ring-offset-0 shadow-none text-primary-950'\n )}\n >\n {opt.preview}\n </Button>\n <Text\n size=\"xs\"\n weight=\"normal\"\n className=\"leading-none text-text-700\"\n >\n {opt.label}\n </Text>\n </div>\n );\n })}\n </div>\n);\n\nexport interface AccessibilityPanelProps {\n isOpen: boolean;\n onClose: () => void;\n /** Lado da viewport onde o painel aparece (default: 'right') */\n position?: AccessibilityFabPosition;\n className?: string;\n}\n\n/**\n * Painel lateral com os controles de acessibilidade organizados em\n * accordions colapsáveis (Visão, Leitura, Leitor de texto, Animação,\n * Navegação, Atalho de teclado).\n *\n * O próprio painel fica dentro de `.a11y-widget-shield`, então\n * filtros aplicados no `<html>` (alto contraste, etc.) não afetam\n * sua legibilidade.\n */\nexport default function AccessibilityPanel({\n isOpen,\n onClose,\n position = 'right',\n className,\n}: Readonly<AccessibilityPanelProps>) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n const {\n contrastMode,\n saturationMode,\n fontSize,\n letterSpacing,\n lineSpacing,\n highlightLinks,\n pauseAnimations,\n bigCursor,\n dyslexiaFont,\n readingAid,\n keyboardShortcut,\n setContrastMode,\n setSaturationMode,\n setFontSize,\n setLetterSpacing,\n setLineSpacing,\n setHighlightLinks,\n setPauseAnimations,\n setBigCursor,\n setDyslexiaFont,\n setReadingAid,\n setKeyboardShortcut,\n resetPreferences,\n } = useAccessibilityStore();\n\n /**\n * Foco e navegação, pelos mesmos hooks que o `Modal` e o `AlertDialog` usam.\n * O `useModalFocus` leva o foco pro diálogo ao abrir, prende Tab e Shift+Tab\n * no ciclo (de \"Redefinir ajustes\" volta pro \"Fechar opções de\n * acessibilidade\", e vice-versa) e torna o resto da página `inert` —\n * necessário porque este é um `<dialog open>` sem top layer: sem isso o\n * cursor virtual do VoiceOver continua passeando pelo menu atrás, e o Tab\n * escapa pra ele. Também devolve o foco a quem abriu o painel.\n *\n * O foco inicial vai pro próprio diálogo (daí o `tabIndex={-1}` abaixo), e\n * não pro botão de fechar: assim o leitor anuncia \"Opções de acessibilidade,\n * diálogo\" antes de cair nos controles.\n *\n * `useEscapeToClose` em vez do listener manual de antes: ele ignora um\n * Escape já tratado (`defaultPrevented`), então fechar o `Select` de voz do\n * TTS não fecha mais o painel inteiro junto.\n *\n * Sem `useBodyScrollLock` de propósito: ele cobre a faixa da scrollbar com um\n * overlay escuro combinando com o backdrop dos modais, e este painel não tem\n * backdrop — a tarja apareceria solta na borda da tela.\n */\n useModalFocus(isOpen, dialogRef);\n useEscapeToClose(isOpen, onClose);\n\n if (!isOpen) return null;\n\n const levelOptions = LEVEL_LABELS.map((label, index) => ({\n value: index as 0 | 1 | 2 | 3,\n label,\n }));\n\n return (\n <dialog\n ref={dialogRef}\n open\n // Requisito do `useModalFocus` (ver a nota acima): o foco inicial vai pro\n // próprio diálogo, que precisa ser focável sem entrar no ciclo de Tab.\n tabIndex={-1}\n // `open` sem `showModal()` não cria top layer nem marca o diálogo como\n // modal, então o papel é declarado aqui — como no `Modal` e no\n // `AlertDialog`. Quem realmente prende a navegação é o `inert` aplicado\n // pelo hook; o atributo é o que anuncia ao leitor que a página atrás\n // saiu do caminho.\n aria-modal=\"true\"\n aria-label=\"Opções de acessibilidade\"\n data-testid=\"accessibility-panel\"\n // `<dialog>` não estica automaticamente com `top` + `bottom`, por\n // isso a altura fica explícita: `100vh - 5rem` (80px de respiro do\n // topo). Combinado com `bottom-0` no className, o painel encosta\n // na base da viewport como no Figma.\n style={{ height: 'calc(100vh - 5rem)' }}\n className={cn(\n 'a11y-widget-shield',\n 'fixed bottom-0 z-40 m-0',\n PANEL_EDGE_CLASSES[position],\n 'flex w-[calc(100vw-3rem)] max-w-110 flex-col overflow-hidden rounded-2xl p-0',\n 'border border-background-200 bg-background shadow-2xl',\n className\n )}\n >\n {/* Header — visual do Figma: bg azul-claro (Paraná) / rosa-claro\n (Paraíba) usando `primary-50`. Preferido em vez de `map-attention`\n porque `primary-50` flipa corretamente no dark mode em todos os\n temas (ex.: Paraná dark = #27344a), enquanto `map-attention`\n ficou idêntico em light/dark no theme do Paraná, deixando o\n texto branco invisível sobre o azul-claro no dark. */}\n <header className=\"flex items-center justify-between gap-3 bg-primary-50 px-4 py-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <img\n src={accessibilityIcon}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"h-10 w-10 shrink-0\"\n />\n <div className=\"flex min-w-0 flex-col gap-1\">\n <Text\n size=\"md\"\n weight=\"bold\"\n className=\"leading-none tracking-[0.2px] text-text-950\"\n >\n Acessibilidade\n </Text>\n <Text\n size=\"xs\"\n weight=\"normal\"\n className=\"leading-none text-text-800\"\n >\n Personalize a leitura e navegação\n </Text>\n </div>\n </div>\n <IconButton\n size=\"sm\"\n aria-label=\"Fechar opções de acessibilidade\"\n onClick={onClose}\n icon={<XIcon size={18} />}\n />\n </header>\n\n <div className=\"flex-1 overflow-y-auto\">\n <AccordionSection\n title=\"Visão\"\n icon={<EyeIcon size={18} />}\n testId=\"a11y-section-vision\"\n >\n <SubControl label=\"Contraste\">\n <Segmented\n ariaLabel=\"Modo de contraste\"\n value={contrastMode}\n options={CONTRAST_OPTIONS}\n onChange={setContrastMode}\n />\n </SubControl>\n <SubControl label=\"Saturação\">\n <Segmented\n ariaLabel=\"Modo de saturação\"\n value={saturationMode}\n options={SATURATION_OPTIONS}\n onChange={setSaturationMode}\n />\n </SubControl>\n {/* Daltonismo removido por enquanto — store/store actions\n mantidos para reativação futura sem refactor. */}\n </AccordionSection>\n\n <AccordionSection\n title=\"Leitura\"\n icon={<TextTIcon size={18} />}\n testId=\"a11y-section-reading\"\n >\n <SubControl label=\"Fonte para dislexia\">\n <AccessibilityToggleRow\n ariaLabel=\"Trocar para Comic Sans MS\"\n rowTestId=\"a11y-toggle-dyslexia-font-row\"\n switchTestId=\"a11y-toggle-dyslexia-font\"\n checked={dyslexiaFont}\n onChange={() => setDyslexiaFont(!dyslexiaFont)}\n label={\n <>\n Trocar para{' '}\n <span style={{ fontFamily: '\"Comic Sans MS\", cursive' }}>\n Comic Sans MS\n </span>\n </>\n }\n />\n </SubControl>\n\n <SubControl label=\"Tamanho da fonte\">\n <PreviewSegmented\n ariaLabel=\"Tamanho da fonte\"\n value={fontSize}\n options={levelOptions.map((opt) => ({\n ...opt,\n preview: (\n <span\n className={cn(\n 'font-semibold leading-none',\n FONT_SIZE_PREVIEW_CLASSES[opt.value]\n )}\n >\n Aa\n </span>\n ),\n }))}\n onChange={setFontSize}\n />\n </SubControl>\n\n <SubControl label=\"Espaçamento entre letras\">\n <PreviewSegmented\n ariaLabel=\"Espaçamento entre letras\"\n value={letterSpacing}\n options={levelOptions.map((opt) => ({\n ...opt,\n preview: (\n <span\n className={cn(\n // Mesmo tamanho do \"Aa\" no botão Padrão de \"Tamanho\n // da fonte\" (text-base), pra que essa scale visualize\n // só a variação de letter-spacing.\n 'text-base font-semibold leading-none',\n LETTER_SPACING_PREVIEW_CLASSES[opt.value]\n )}\n >\n Aa\n </span>\n ),\n }))}\n onChange={setLetterSpacing}\n />\n </SubControl>\n\n <SubControl label=\"Espaçamento entre linhas\">\n <PreviewSegmented\n ariaLabel=\"Espaçamento entre linhas\"\n value={lineSpacing}\n options={levelOptions.map((opt) => ({\n ...opt,\n preview: (\n <span\n className={cn(\n 'flex flex-col items-stretch',\n LINE_SPACING_PREVIEW_GAPS[opt.value]\n )}\n >\n <span className=\"h-0.5 w-7 rounded-full bg-current\" />\n <span className=\"h-0.5 w-7 rounded-full bg-current\" />\n <span className=\"h-0.5 w-7 rounded-full bg-current\" />\n </span>\n ),\n }))}\n onChange={setLineSpacing}\n />\n </SubControl>\n\n <SubControl label=\"Auxiliar de leitura\">\n <Segmented\n ariaLabel=\"Auxiliar de leitura\"\n value={readingAid}\n options={READING_AID_OPTIONS}\n onChange={setReadingAid}\n />\n </SubControl>\n </AccordionSection>\n\n <AccordionSection\n title=\"Leitor de texto\"\n icon={<SpeakerHighIcon size={18} />}\n testId=\"a11y-section-tts\"\n >\n <TTSSection PreviewSegmented={PreviewSegmented} />\n </AccordionSection>\n\n <AccordionSection\n title=\"Animação\"\n icon={<FilmReelIcon size={18} />}\n testId=\"a11y-section-animation\"\n >\n <AccessibilityToggleRow\n label=\"Pausar animações para conforto visual\"\n checked={pauseAnimations}\n onChange={() => setPauseAnimations(!pauseAnimations)}\n switchTestId=\"a11y-toggle-pause-animations\"\n />\n </AccordionSection>\n\n <AccordionSection\n title=\"Navegação\"\n icon={<NavigationArrowIcon size={18} />}\n testId=\"a11y-section-navigation\"\n >\n <SubControl label=\"Destacar links e botões\">\n <AccessibilityToggleRow\n label=\"Adicionar contorno em elementos clicáveis\"\n checked={highlightLinks}\n onChange={() => setHighlightLinks(!highlightLinks)}\n switchTestId=\"a11y-toggle-highlight-links\"\n />\n </SubControl>\n <SubControl label=\"Cursor maior\">\n <AccessibilityToggleRow\n label=\"Aumentar e escurecer cursor\"\n checked={bigCursor}\n onChange={() => setBigCursor(!bigCursor)}\n switchTestId=\"a11y-toggle-big-cursor\"\n />\n </SubControl>\n </AccordionSection>\n\n <AccordionSection\n title=\"Atalho de teclado\"\n icon={<KeyboardIcon size={18} />}\n testId=\"a11y-section-shortcut\"\n >\n <AccessibilityToggleRow\n label=\"Alt+A para abrir o painel\"\n checked={keyboardShortcut}\n onChange={() => setKeyboardShortcut(!keyboardShortcut)}\n switchTestId=\"a11y-toggle-keyboard-shortcut\"\n />\n </AccordionSection>\n </div>\n\n <footer className=\"border-t border-background-200 px-4 py-3\">\n <Button\n variant=\"outline\"\n action=\"primary\"\n size=\"medium\"\n iconLeft={\n <ArrowCounterClockwiseIcon\n size={16}\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n }\n onClick={resetPreferences}\n data-testid=\"a11y-reset\"\n className=\"w-full justify-center\"\n >\n Redefinir ajustes\n </Button>\n </footer>\n </dialog>\n );\n}\n","import type { ReactNode } from 'react';\nimport Text from '../Text/Text';\nimport ToggleSwitch from '../ToggleSwitch/ToggleSwitch';\nimport { cn } from '../../utils/utils';\n\nexport interface AccessibilityToggleRowProps {\n /** Conteúdo principal da linha (texto ou JSX, ex.: trecho em Comic Sans). */\n label: ReactNode;\n /** Aria-label do row quando `label` é JSX e não pode ser usado como texto. */\n ariaLabel?: string;\n /** Texto auxiliar abaixo do label. */\n description?: string;\n checked: boolean;\n onChange: () => void;\n /** Testid no wrapper interativo (toda a linha). */\n rowTestId?: string;\n /** Testid no `<ToggleSwitch>` interno — usado pelos testes que ainda\n * clicam diretamente no botão de switch. */\n switchTestId?: string;\n}\n\n/**\n * Linha clicável \"label à esquerda + ToggleSwitch à direita\" usada nos\n * accordions de Animação, Navegação, Atalho, dislexia e leitor de texto.\n *\n * O wrapper inteiro responde a click/Enter/Space; o `ToggleSwitch` interno\n * é apenas decorativo (`tabIndex={-1}`, `aria-hidden`) pra que toda a área\n * vire alvo de clique sem dupla-ativação do switch.\n */\nexport default function AccessibilityToggleRow({\n label,\n ariaLabel,\n description,\n checked,\n onChange,\n rowTestId,\n switchTestId,\n}: Readonly<AccessibilityToggleRowProps>) {\n const computedAriaLabel =\n ariaLabel ?? (typeof label === 'string' ? label : undefined);\n return (\n <div\n role=\"switch\"\n tabIndex={0}\n aria-checked={checked}\n aria-label={computedAriaLabel}\n data-testid={rowTestId}\n className={cn(\n 'flex items-center justify-between gap-3 rounded-md py-1.5',\n 'cursor-pointer transition-colors duration-150 hover:bg-background-100',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-info-500'\n )}\n onClick={onChange}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onChange();\n }\n }}\n >\n <div className=\"flex flex-col\">\n <Text size=\"sm\" className=\"text-text-900\">\n {label}\n </Text>\n {description && (\n <Text size=\"2xs\" className=\"text-text-600\">\n {description}\n </Text>\n )}\n </div>\n <ToggleSwitch\n checked={checked}\n onChange={() => undefined}\n checkedColor=\"bg-info-600\"\n data-testid={switchTestId}\n tabIndex={-1}\n aria-hidden\n />\n </div>\n );\n}\n","import { useMemo, type ReactElement, type ReactNode } from 'react';\nimport { PauseIcon, PlayIcon, StopIcon } from '@phosphor-icons/react';\nimport Button from '../Button/Button';\nimport Text from '../Text/Text';\nimport Select, {\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n} from '../Select/Select';\nimport AccessibilityToggleRow from './AccessibilityToggleRow';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\nimport { useTTS } from '../../hooks/useTTS';\n\n/**\n * Opções de velocidade da fala. O `preview` mostra o valor numérico\n * dentro do botão (1.0, 1.25, etc.) e o `label` aparece como caption\n * abaixo. Valores escolhidos para casarem com o que o Web Speech API\n * aceita (0.5–2.0) — `0.75` foi mantido para \"Lento\" em vez de algo\n * mais agressivo porque vozes nativas ficam ininteligíveis abaixo disso.\n */\nconst RATE_OPTIONS: {\n value: string;\n label: string;\n preview: ReactNode;\n}[] = [\n { value: '0.75', label: 'Lento', preview: '0.75' },\n { value: '1', label: 'Normal', preview: '1.0' },\n { value: '1.25', label: 'Rápido', preview: '1.25' },\n { value: '2', label: 'Muito rápido', preview: '2.0' },\n];\n\nexport interface TTSSectionProps {\n /** Componente de segmented com preview visual + label abaixo */\n PreviewSegmented: <T extends string | number>(props: {\n value: T;\n options: { value: T; label: string; preview: ReactNode }[];\n ariaLabel: string;\n onChange: (value: T) => void;\n }) => ReactElement;\n}\n\n/**\n * Bloco de controles do leitor de texto dentro do painel.\n * Estrutura segue o design do Figma:\n * 1. \"Texto para voz\" — toggle que ativa/desativa o modo click-to-read\n * 2. \"Voz\" — seletor de voz\n * 3. \"Velocidade\" — PreviewSegmented com valor numérico\n */\nexport default function TTSSection({\n PreviewSegmented,\n}: Readonly<TTSSectionProps>) {\n const ttsMode = useAccessibilityStore((s) => s.ttsMode);\n const ttsStatus = useAccessibilityStore((s) => s.ttsStatus);\n const ttsRate = useAccessibilityStore((s) => s.ttsRate);\n const ttsVoiceId = useAccessibilityStore((s) => s.ttsVoiceId);\n const setTTSMode = useAccessibilityStore((s) => s.setTTSMode);\n const setTTSRate = useAccessibilityStore((s) => s.setTTSRate);\n const setTTSVoiceId = useAccessibilityStore((s) => s.setTTSVoiceId);\n\n const { isSupported, voices, hasPortugueseVoice, pause, resume, stop } =\n useTTS();\n\n // Preferimos vozes em português; demais ficam ao final.\n const sortedVoices = useMemo(() => {\n return [...voices].sort((a, b) => {\n const aPt = a.lang.toLowerCase().startsWith('pt') ? 0 : 1;\n const bPt = b.lang.toLowerCase().startsWith('pt') ? 0 : 1;\n if (aPt !== bPt) return aPt - bPt;\n return a.name.localeCompare(b.name);\n });\n }, [voices]);\n\n if (!isSupported) {\n return (\n <Text size=\"2xs\" className=\"text-text-600\">\n Síntese de voz não está disponível neste navegador.\n </Text>\n );\n }\n\n const isClickToReadOn = ttsMode === 'click-to-read';\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Texto para voz: toggle row */}\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n Texto para voz\n </Text>\n <AccessibilityToggleRow\n label=\"Ative a leitura e clique no texto para ouvir\"\n rowTestId=\"a11y-tts-mode-toggle\"\n checked={isClickToReadOn}\n onChange={() => setTTSMode(isClickToReadOn ? 'off' : 'click-to-read')}\n />\n </div>\n\n {!hasPortugueseVoice && (\n <Text size=\"2xs\" className=\"text-warning-700\">\n Nenhuma voz em português foi encontrada no seu sistema. A leitura será\n feita com a voz padrão disponível.\n </Text>\n )}\n\n {/* Voz: pill select */}\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n Voz\n </Text>\n <Select\n size=\"small\"\n value={ttsVoiceId ?? ''}\n onValueChange={(value) => setTTSVoiceId(value || null)}\n >\n <SelectTrigger\n variant=\"rounded\"\n aria-label=\"Voz da síntese de fala\"\n data-testid=\"a11y-tts-voice-select\"\n >\n <SelectValue placeholder=\"Padrão do navegador\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"\">Padrão do navegador</SelectItem>\n {sortedVoices.map((v) => (\n <SelectItem key={v.id} value={v.id}>\n {v.name} — {v.lang}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Velocidade: preview segmented com valor numérico no botão */}\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n Velocidade\n </Text>\n <PreviewSegmented\n ariaLabel=\"Velocidade da fala\"\n value={String(ttsRate)}\n options={RATE_OPTIONS.map((opt) => ({\n value: opt.value,\n label: opt.label,\n preview: (\n <span className=\"text-base font-bold leading-none\">\n {opt.preview}\n </span>\n ),\n }))}\n onChange={(v) => setTTSRate(Number(v))}\n />\n </div>\n\n {/* Ações: pause/resume/stop conforme status — só visíveis durante a fala */}\n {ttsStatus !== 'idle' && (\n <div className=\"flex items-center gap-2\">\n {ttsStatus === 'speaking' && (\n <Button\n variant=\"outline\"\n action=\"secondary\"\n size=\"small\"\n iconLeft={\n <PauseIcon size={14} weight=\"bold\" aria-hidden=\"true\" />\n }\n onClick={pause}\n data-testid=\"a11y-tts-pause\"\n >\n Pausar\n </Button>\n )}\n\n {ttsStatus === 'paused' && (\n <Button\n variant=\"outline\"\n action=\"secondary\"\n size=\"small\"\n iconLeft={<PlayIcon size={14} weight=\"bold\" aria-hidden=\"true\" />}\n onClick={resume}\n data-testid=\"a11y-tts-resume\"\n >\n Retomar\n </Button>\n )}\n\n <Button\n variant=\"outline\"\n action=\"negative\"\n size=\"small\"\n iconLeft={<StopIcon size={14} weight=\"bold\" aria-hidden=\"true\" />}\n onClick={stop}\n data-testid=\"a11y-tts-stop\"\n className=\"ml-auto\"\n >\n Parar\n </Button>\n </div>\n )}\n </div>\n );\n}\n","import { HandWavingIcon } from '@phosphor-icons/react';\nimport Button from '../Button/Button';\nimport { Tooltip } from '../Tooltip/Tooltip';\nimport { cn } from '../../utils/utils';\nimport {\n FAB_POSITION_CLASSES,\n FAB_TOOLTIP_POSITION,\n FAB_VERTICAL_ALIGN_CLASSES,\n type FabPosition,\n type FabVerticalAlign,\n} from './fabPositioning';\n\ntype AccessibilityFabPosition = FabPosition;\ntype AccessibilityFabVerticalAlign = FabVerticalAlign;\n\nexport interface LibrasFabProps {\n /** Click handler — alterna o painel do VLibras (abrir/fechar) */\n onClick: () => void;\n /** Lado da viewport onde o botão fica colado */\n position?: AccessibilityFabPosition;\n /** Alinhamento vertical (default: `below-center`) */\n verticalAlign?: AccessibilityFabVerticalAlign;\n /** Classes extras */\n className?: string;\n}\n\n/**\n * Segundo botão flutuante (FAB), posicionado abaixo do `AccessibilityFab`.\n * Aciona o widget oficial do VLibras (gov.br) que faz tradução automática\n * de português para Libras via avatar 3D.\n *\n * O botão tem visual constante — não mantemos um indicador de estado\n * \"ativo\" porque o painel do VLibras já reflete visualmente se está\n * aberto ou fechado. Cada clique alterna o painel.\n *\n * Mesma identidade visual do FAB principal (azul escuro, quadrado com\n * canto interno arredondado, colado na lateral).\n */\nexport default function LibrasFab({\n onClick,\n position = 'right',\n verticalAlign = 'below-center',\n className,\n}: Readonly<LibrasFabProps>) {\n const label = 'Tradução em Libras';\n\n return (\n <Tooltip\n content={label}\n position={FAB_TOOLTIP_POSITION[position]}\n className={cn(\n 'fixed z-40',\n FAB_VERTICAL_ALIGN_CLASSES[verticalAlign],\n FAB_POSITION_CLASSES[position]\n )}\n >\n <Button\n variant=\"raw\"\n onClick={onClick}\n aria-label={label}\n data-testid=\"libras-fab\"\n className={cn(\n 'a11y-widget-shield',\n FAB_POSITION_CLASSES[position],\n 'flex h-10 w-10 cursor-pointer items-center justify-center',\n // `text-text-50` flipa junto com `bg-info-900`: claro no light,\n // escuro no dark. Como o ícone usa `currentColor`, com `text-white`\n // a mãozinha sumiria no tema escuro (branco em fundo azul-claro).\n 'bg-info-900 text-text-50 shadow-lg',\n 'transition-all duration-200 hover:scale-110 hover:bg-info-800',\n 'focus:outline-none focus:ring-4 focus:ring-info-300',\n className\n )}\n >\n <HandWavingIcon size={25} weight=\"fill\" aria-hidden=\"true\" />\n </Button>\n </Tooltip>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\n\nconst RULER_HEIGHT_PX = 32;\nconst MASK_GAP_PX = 80; // metade da altura da janela visível\n\n/**\n * Renderiza auxiliares de leitura (régua ou máscara) que acompanham\n * a posição vertical do mouse. Só monta listener de `mousemove` quando\n * algum auxiliar está ativo, para não pagar custo quando desligado.\n */\nexport default function ReadingAid() {\n const readingAid = useAccessibilityStore((s) => s.readingAid);\n const [mouseY, setMouseY] = useState<number | null>(null);\n\n useEffect(() => {\n if (readingAid === 'none') {\n setMouseY(null);\n return;\n }\n\n let frame = 0;\n const handleMouseMove = (event: MouseEvent) => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(() => setMouseY(event.clientY));\n };\n\n document.addEventListener('mousemove', handleMouseMove, { passive: true });\n return () => {\n cancelAnimationFrame(frame);\n document.removeEventListener('mousemove', handleMouseMove);\n };\n }, [readingAid]);\n\n if (readingAid === 'none' || mouseY === null) return null;\n\n if (readingAid === 'ruler') {\n return (\n <div\n aria-hidden=\"true\"\n data-testid=\"a11y-reading-ruler\"\n className=\"a11y-widget-shield pointer-events-none fixed left-0 right-0 z-30\"\n style={{\n top: mouseY - RULER_HEIGHT_PX / 2,\n height: RULER_HEIGHT_PX,\n background: 'rgba(255, 235, 59, 0.25)',\n borderTop: '2px solid #facc15',\n borderBottom: '2px solid #facc15',\n }}\n />\n );\n }\n\n // Máscara: dois retângulos escurecendo acima e abaixo do cursor\n return (\n <>\n <div\n aria-hidden=\"true\"\n data-testid=\"a11y-reading-mask-top\"\n className=\"a11y-widget-shield pointer-events-none fixed left-0 right-0 top-0 z-30 bg-black/90\"\n style={{ height: Math.max(0, mouseY - MASK_GAP_PX) }}\n />\n <div\n aria-hidden=\"true\"\n data-testid=\"a11y-reading-mask-bottom\"\n className=\"a11y-widget-shield pointer-events-none fixed left-0 right-0 bottom-0 z-30 bg-black/90\"\n style={{ top: mouseY + MASK_GAP_PX }}\n />\n </>\n );\n}\n","import {\n ColorBlindMode,\n getColorBlindFilterId,\n} from '../../store/accessibilityStore';\n\n/**\n * SVG escondido com matrizes `<feColorMatrix>` que simulam/auxiliam\n * cada tipo de daltonismo. As classes em `accessibility.css` aplicam\n * `filter: url(#a11y-cb-...)` no `<html>` para colorir a página.\n *\n * Os IDs dos filters são derivados do enum `ColorBlindMode` via\n * `getColorBlindFilterId` — mesma fonte da verdade que o hook usa\n * para aplicar a classe.\n *\n * Matrizes baseadas em Brettel/Vienot/Mollon — padrão amplamente\n * utilizado em ferramentas de acessibilidade como AXE, Daltonize e\n * widget oficial do HandTalk.\n */\nexport default function ColorBlindFilters() {\n return (\n <svg\n aria-hidden=\"true\"\n data-testid=\"a11y-colorblind-filters\"\n style={{\n position: 'absolute',\n width: 0,\n height: 0,\n overflow: 'hidden',\n }}\n >\n <defs>\n <filter id={getColorBlindFilterId(ColorBlindMode.Protanopia)}>\n <feColorMatrix\n type=\"matrix\"\n values=\"0.567 0.433 0 0 0\n 0.558 0.442 0 0 0\n 0 0.242 0.758 0 0\n 0 0 0 1 0\"\n />\n </filter>\n <filter id={getColorBlindFilterId(ColorBlindMode.Deuteranopia)}>\n <feColorMatrix\n type=\"matrix\"\n values=\"0.625 0.375 0 0 0\n 0.700 0.300 0 0 0\n 0 0.300 0.7 0 0\n 0 0 0 1 0\"\n />\n </filter>\n <filter id={getColorBlindFilterId(ColorBlindMode.Tritanopia)}>\n <feColorMatrix\n type=\"matrix\"\n values=\"0.95 0.05 0 0 0\n 0 0.433 0.567 0 0\n 0 0.475 0.525 0 0\n 0 0 0 1 0\"\n />\n </filter>\n </defs>\n </svg>\n );\n}\n","import { useEffect } from 'react';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\nimport { useTTS } from '../../hooks/useTTS';\n\nconst HIGHLIGHT_CLASS = 'a11y-tts-target';\n\n/**\n * Controller invisível que conecta o `ttsMode` do store ao DOM:\n * - `click-to-read`: registra um listener global de clique. Ao clicar\n * em qualquer elemento (exceto o próprio widget), lê seu texto.\n * - `read-selection`: lê o texto atualmente selecionado quando o store\n * sinaliza (via `pendingReadSelection`). UI/atalho disparam isso.\n *\n * Aplica a classe `.a11y-tts-target` no elemento sendo lido para\n * destaque visual; remove ao terminar/parar.\n */\nexport default function TTSController() {\n const ttsMode = useAccessibilityStore((s) => s.ttsMode);\n const ttsStatus = useAccessibilityStore((s) => s.ttsStatus);\n const { speak, stop, isSupported } = useTTS();\n\n // Click-to-read: ouve cliques globais enquanto o modo está ativo\n useEffect(() => {\n if (!isSupported || ttsMode !== 'click-to-read') return;\n\n const handler = (event: MouseEvent) => {\n const initialTarget = event.target as HTMLElement | null;\n if (!initialTarget) return;\n\n // Ignora cliques dentro do próprio widget\n if (initialTarget.closest('.a11y-widget-shield')) return;\n\n // Sobe pela árvore até achar o ancestral que tem texto legível.\n // Cobre o caso comum de IconButtons com `<svg>` interno: clicar no\n // SVG não retorna texto, mas o botão pai tem aria-label.\n const found = findReadableAncestor(initialTarget);\n if (!found) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n // Limpa highlight anterior e marca o novo alvo\n document\n .querySelectorAll(`.${HIGHLIGHT_CLASS}`)\n .forEach((el) => el.classList.remove(HIGHLIGHT_CLASS));\n found.node.classList.add(HIGHLIGHT_CLASS);\n\n speak(found.text);\n };\n\n // capture: true → pegamos o clique antes do handler do app/link\n document.addEventListener('click', handler, true);\n return () => {\n document.removeEventListener('click', handler, true);\n document\n .querySelectorAll(`.${HIGHLIGHT_CLASS}`)\n .forEach((el) => el.classList.remove(HIGHLIGHT_CLASS));\n // Interrompe qualquer fala em curso ao sair do modo. Sem isso,\n // desligar o \"Clique para ler\" deixaria a leitura terminando\n // sozinha, contrariando a expectativa do usuário.\n stop();\n };\n }, [isSupported, ttsMode, speak, stop]);\n\n // Quando a fala termina (ttsStatus volta a 'idle'), limpa highlight\n useEffect(() => {\n if (ttsStatus === 'idle') {\n document\n .querySelectorAll(`.${HIGHLIGHT_CLASS}`)\n .forEach((el) => el.classList.remove(HIGHLIGHT_CLASS));\n }\n }, [ttsStatus]);\n\n // Para qualquer fala em curso quando o componente desmonta\n useEffect(() => () => stop(), [stop]);\n\n return null;\n}\n\n/**\n * Extrai texto legível do elemento clicado. Prioriza:\n * 1. `aria-label` se presente\n * 2. `title`\n * 3. `innerText` truncado\n *\n * `innerText` (e não `textContent`) respeita estilos como `display: none`\n * e quebras de linha visuais — leitura mais natural.\n */\nconst extractReadableText = (el: HTMLElement): string => {\n const aria = el.getAttribute('aria-label')?.trim();\n if (aria) return aria;\n const title = el.getAttribute('title')?.trim();\n if (title) return title;\n const text = el.innerText?.trim() ?? '';\n // Limita comprimento para evitar leitura infinita ao clicar em\n // contêineres grandes (ex.: <main>). 600 chars ≈ 1min de fala.\n return text.length > 600 ? `${text.slice(0, 600)}...` : text;\n};\n\n/** Quantos níveis de ancestralidade subimos buscando um nó legível. */\nconst MAX_ANCESTOR_LOOKUP = 8;\n\n/**\n * Caminha pela árvore a partir do elemento clicado até achar o ancestral\n * mais próximo que tenha texto legível (`aria-label`, `title` ou\n * `innerText`). Limita a profundidade e nunca retorna o `<body>` para\n * evitar ler a página inteira ao clicar em ícones soltos.\n */\nconst findReadableAncestor = (\n start: HTMLElement\n): { node: HTMLElement; text: string } | null => {\n let node: HTMLElement | null = start;\n let depth = 0;\n while (node && depth < MAX_ANCESTOR_LOOKUP && node !== document.body) {\n const text = extractReadableText(node);\n if (text) return { node, text };\n node = node.parentElement;\n depth++;\n }\n return null;\n};\n","import { useEffect } from 'react';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\n\nconst SCRIPT_ID = 'a11y-vlibras-script';\nconst SCRIPT_URL = 'https://vlibras.gov.br/app/vlibras-plugin.js';\nconst APP_URL = 'https://vlibras.gov.br/app';\nconst WRAPPER_ID = 'a11y-vlibras-wrapper';\n\ninterface VLibrasGlobal {\n Widget: new (appUrl: string) => unknown;\n}\n\n/**\n * Carrega e ativa o widget oficial de Libras do governo brasileiro\n * (gov.br/vlibras) sob demanda. Estratégia:\n *\n * - Quando `librasEnabled === true`:\n * 1. Injeta o esqueleto DOM esperado pelo VLibras (`<div vw>` etc.)\n * no `<body>` (precisa estar no body, não dentro do React tree).\n * 2. Carrega o script oficial uma única vez (cacheado por id).\n * 3. Instancia `new window.VLibras.Widget(...)` para inicializar o\n * avatar e os assets 3D.\n *\n * - Quando `librasEnabled === false`:\n * - Apenas OCULTA o esqueleto DOM (não remove). O plugin do VLibras\n * registra um listener de `resize` no `window` que ele nunca desanexa;\n * se removêssemos o wrapper, esse listener rodaria `d(\"[vp]\").closest(...)`\n * sobre um `null` (nós já removidos) e lançaria\n * `Cannot read properties of null (reading 'closest')` no próximo resize\n * (rotação de tela / teclado virtual no mobile). Mantendo o esqueleto\n * oculto no DOM, `[vp]`/`[vw]` continuam existindo e o handler órfão não\n * quebra. O script permanece em cache para reativações rápidas.\n *\n * O script é pesado (~MBs de avatares 3D), por isso só carregamos quando\n * o usuário clica para ativar — fluxo opt-in.\n */\nexport default function VLibrasLoader() {\n const enabled = useAccessibilityStore((s) => s.librasEnabled);\n\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n if (!enabled) {\n hideWrapper();\n return;\n }\n\n injectWrapper();\n loadScript()\n .then(() => {\n const VLibras = (globalThis as unknown as { VLibras?: VLibrasGlobal })\n .VLibras;\n if (!VLibras?.Widget) return;\n\n // ATENÇÃO: o construtor do VLibras Widget registra a lógica de\n // inicialização DENTRO de `window.onload = () => {...}`. Como\n // nesta integração o widget é ativado depois da página já ter\n // carregado, o evento `load` já disparou e o handler nunca\n // executa sozinho. Capturamos o handler que o construtor\n // instalou e chamamos manualmente para popular o DOM (avatar,\n // botão de acesso, painel) imediatamente.\n const previousOnload = globalThis.onload;\n // A instanciação importa pelos efeitos colaterais: o construtor\n // do VLibras registra `window.onload` com a lógica de inicialização\n // do widget. O retorno não é usado e é descartado de propósito.\n new VLibras.Widget(APP_URL); // NOSONAR — instantiation by side effect\n const installed = globalThis.onload;\n if (typeof installed === 'function' && installed !== previousOnload) {\n // `onload` espera tipo Window — usamos `as` porque o construtor\n // do VLibras só lê `event.target` (que ignoramos) e não toca em\n // propriedades específicas do Window.\n (installed as (this: Window, ev: Event) => unknown).call(\n globalThis as unknown as Window,\n new Event('load')\n );\n }\n\n // Após popular o DOM, abre direto o painel do VLibras — caso\n // contrário o usuário precisaria clicar duas vezes (nosso FAB\n // + botão de acesso do VLibras). Aguarda um frame para garantir\n // que o handler de click do botão já foi anexado pelo plugin.\n requestAnimationFrame(() => {\n const accessButton =\n document.querySelector<HTMLElement>('[vw-access-button]');\n accessButton?.click();\n });\n })\n .catch(() => {\n // Falha de rede ou bloqueio: desabilita silenciosamente o estado\n // para o usuário não ficar preso achando que vai funcionar.\n useAccessibilityStore.getState().setLibrasEnabled(false);\n });\n\n return () => {\n // Não removemos o wrapper aqui: a remoção real fica no ramo\n // `!enabled` acima. Manter aqui causaria flicker em re-renders.\n };\n }, [enabled]);\n\n return null;\n}\n\nconst injectWrapper = () => {\n const existing = document.getElementById(WRAPPER_ID);\n if (existing) {\n // Wrapper já foi criado numa ativação anterior e apenas ocultado ao\n // desativar. Basta reexibi-lo em vez de recriar (o que reinjetaria os\n // nós e recriaria o listener órfão do plugin).\n existing.style.removeProperty('display');\n return;\n }\n\n const wrapper = document.createElement('div');\n wrapper.id = WRAPPER_ID;\n wrapper.setAttribute('vw', '');\n wrapper.className = 'enabled';\n\n const accessButton = document.createElement('div');\n accessButton.setAttribute('vw-access-button', '');\n accessButton.className = 'active';\n wrapper.appendChild(accessButton);\n\n const pluginWrapper = document.createElement('div');\n pluginWrapper.setAttribute('vw-plugin-wrapper', '');\n const top = document.createElement('div');\n top.className = 'vw-plugin-top-wrapper';\n pluginWrapper.appendChild(top);\n wrapper.appendChild(pluginWrapper);\n\n document.body.appendChild(wrapper);\n};\n\nconst hideWrapper = () => {\n const wrapper = document.getElementById(WRAPPER_ID);\n if (wrapper) {\n // Oculta sem remover: preserva os nós [vp]/[vw] que o listener de resize\n // órfão do plugin do VLibras consulta via `.closest()`.\n wrapper.style.display = 'none';\n }\n};\n\nconst loadScript = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (document.getElementById(SCRIPT_ID)) {\n resolve();\n return;\n }\n\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = SCRIPT_URL;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () =>\n reject(new Error('Falha ao carregar o script do VLibras'));\n document.head.appendChild(script);\n });\n};\n\nexport const __testing = {\n SCRIPT_ID,\n SCRIPT_URL,\n WRAPPER_ID,\n injectWrapper,\n hideWrapper,\n};\n"],"mappings":"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","names":["useEffect","useRef","jsx","jsx","jsxs","PreviewSegmented","jsx","jsxs","jsx","useState","Fragment","jsx","jsxs","useState","jsx","jsxs","useEffect","useEffect","useEffect","useEffect","Fragment","jsx","jsxs","useRef","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/AccessibilityWidget/AccessibilityWidget.tsx","../src/components/AccessibilityWidget/AccessibilityFab.tsx","../src/components/AccessibilityWidget/fabPositioning.ts","../src/components/AccessibilityWidget/AccessibilityPanel.tsx","../src/components/AccessibilityWidget/AccessibilityToggleRow.tsx","../src/components/AccessibilityWidget/TTSSection.tsx","../src/components/AccessibilityWidget/LibrasFab.tsx","../src/components/AccessibilityWidget/ReadingAid.tsx","../src/components/AccessibilityWidget/ColorBlindFilters.tsx","../src/components/AccessibilityWidget/TTSController.tsx","../src/components/AccessibilityWidget/VLibrasLoader.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport AccessibilityFab, {\n type AccessibilityFabPosition,\n} from './AccessibilityFab';\nimport AccessibilityPanel from './AccessibilityPanel';\nimport LibrasFab from './LibrasFab';\nimport ReadingAid from './ReadingAid';\nimport ColorBlindFilters from './ColorBlindFilters';\nimport TTSController from './TTSController';\nimport VLibrasLoader from './VLibrasLoader';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\nimport { useA11yPreferences } from '../../hooks/useA11yPreferences';\nimport { useA11yKeyboardShortcut } from '../../hooks/useA11yKeyboardShortcut';\nimport './accessibility.css';\n\nexport interface AccessibilityWidgetProps {\n /** Lado da viewport onde o botão fica colado (default: 'right') */\n position?: AccessibilityFabPosition;\n /** Classes extras para o botão flutuante */\n fabClassName?: string;\n /** Classes extras para o painel */\n panelClassName?: string;\n /**\n * Mostra o botão de Libras empilhado abaixo do botão de\n * acessibilidade (default: true). Plataformas que já injetam o\n * VLibras de forma própria podem desabilitar passando `false`.\n */\n showLibras?: boolean;\n}\n\n/**\n * Widget de acessibilidade — botão flutuante que abre um painel\n * com controles de contraste, fonte, espaçamento e outras\n * preferências visuais. As preferências são persistidas em\n * localStorage e aplicadas via classes no `<html>`.\n *\n * Renderize uma única instância no shell da aplicação. Tudo fica\n * dentro de `.a11y-widget-root` para que o próprio widget não\n * sofra com os filtros que aplica na página.\n *\n * @example\n * ```tsx\n * <AccessibilityWidget position=\"left\" />\n * ```\n */\nexport default function AccessibilityWidget({\n position = 'right',\n fabClassName,\n panelClassName,\n showLibras = true,\n}: Readonly<AccessibilityWidgetProps>) {\n useA11yPreferences();\n useA11yKeyboardShortcut();\n\n const isPanelOpen = useAccessibilityStore((s) => s.isPanelOpen);\n const togglePanel = useAccessibilityStore((s) => s.togglePanel);\n const closePanel = useAccessibilityStore((s) => s.closePanel);\n const librasEnabled = useAccessibilityStore((s) => s.librasEnabled);\n const setLibrasEnabled = useAccessibilityStore((s) => s.setLibrasEnabled);\n\n // Quando o Libras é exibido, os dois FABs ficam empilhados\n // (acessibilidade acima do meio, libras abaixo). Sem Libras,\n // o de acessibilidade ocupa o centro como antes.\n const accessibilityVerticalAlign = showLibras ? 'above-center' : 'center';\n\n /**\n * Clique no FAB de Libras:\n * - Primeira vez (não ativado): ativa o widget VLibras (que se\n * auto-abre no painel pela primeira vez).\n * - Demais vezes: dispara o click no botão de acesso nativo do\n * VLibras, que abre/fecha o painel sem precisar reinjetar o widget.\n * Isso evita o ciclo de remoção/reinjeção que deixava o VLibras\n * em estado inconsistente após fechá-lo.\n */\n const handleLibrasClick = () => {\n if (!librasEnabled) {\n setLibrasEnabled(true);\n return;\n }\n document.querySelector<HTMLElement>('[vw-access-button]')?.click();\n };\n\n const fabRef = useRef<HTMLButtonElement>(null);\n const wasPanelOpenRef = useRef(false);\n\n /**\n * Devolve o foco ao FAB quando o painel fecha.\n *\n * O painel já faz isso sozinho (`useModalFocus` guarda quem o abriu), mas\n * quando quem abriu foi o próprio FAB o nó guardado não existe mais: o FAB é\n * desmontado enquanto o painel está aberto, e o hook — que só devolve o foco\n * se o elemento ainda está na página — deixa o foco no `<body>`. Daí o Tab\n * recomeçava do topo da página.\n *\n * A guarda do `<body>` é o que mantém o caminho do atalho `Alt+A` intacto:\n * ali quem tinha o foco era um elemento qualquer da página, que sobrevive à\n * abertura e recebe o foco de volta do próprio hook. Nesse caso o foco não\n * está no `<body>` e este efeito sai do caminho.\n */\n useEffect(() => {\n if (isPanelOpen) {\n wasPanelOpenRef.current = true;\n return;\n }\n\n if (!wasPanelOpenRef.current) return;\n wasPanelOpenRef.current = false;\n\n const active = document.activeElement;\n if (!active || active === document.body) {\n fabRef.current?.focus();\n }\n }, [isPanelOpen]);\n\n return (\n <>\n {!isPanelOpen && (\n <AccessibilityFab\n ref={fabRef}\n onClick={togglePanel}\n isOpen={isPanelOpen}\n position={position}\n verticalAlign={accessibilityVerticalAlign}\n className={fabClassName}\n />\n )}\n {!isPanelOpen && showLibras && (\n <LibrasFab onClick={handleLibrasClick} position={position} />\n )}\n <AccessibilityPanel\n isOpen={isPanelOpen}\n onClose={closePanel}\n position={position}\n className={panelClassName}\n />\n <ReadingAid />\n <ColorBlindFilters />\n <TTSController />\n {showLibras && <VLibrasLoader />}\n </>\n );\n}\n","import { forwardRef } from 'react';\nimport Button from '../Button/Button';\nimport { Tooltip } from '../Tooltip/Tooltip';\nimport { cn } from '../../utils/utils';\nimport accessibilityIcon from '../../assets/img/accessibility.png';\nimport {\n FAB_POSITION_CLASSES,\n FAB_TOOLTIP_POSITION,\n FAB_VERTICAL_ALIGN_CLASSES,\n type FabPosition,\n type FabVerticalAlign,\n} from './fabPositioning';\n\n/** Re-exports mantidos para compatibilidade com a API pública do widget. */\nexport type AccessibilityFabPosition = FabPosition;\nexport type AccessibilityFabVerticalAlign = FabVerticalAlign;\n\nexport interface AccessibilityFabProps {\n /** Click handler — alterna o painel */\n onClick: () => void;\n /** Indica se o painel está aberto (controla aria-expanded) */\n isOpen?: boolean;\n /** Lado da viewport onde o botão fica colado */\n position?: AccessibilityFabPosition;\n /** Alinhamento vertical (default: `center`) */\n verticalAlign?: AccessibilityFabVerticalAlign;\n /** Classes extras */\n className?: string;\n}\n\n/**\n * Botão flutuante (FAB) que abre o painel de acessibilidade.\n * Inspirado no padrão HandTalk: quadrado azul escuro colado na\n * lateral da viewport (direita por padrão), com o ícone universal\n * de acessibilidade. Verticalmente centralizado.\n *\n * A ref vai pro `<button>` em si: o FAB é desmontado enquanto o painel está\n * aberto, então quem devolve o foco pra ele no fechamento é o\n * `AccessibilityWidget`, que precisa alcançar o nó recém-remontado.\n */\nconst AccessibilityFab = forwardRef<HTMLButtonElement, AccessibilityFabProps>(\n (\n {\n onClick,\n isOpen = false,\n position = 'right',\n verticalAlign = 'center',\n className,\n },\n ref\n ) => {\n const label = isOpen\n ? 'Fechar opções de acessibilidade'\n : 'Opções de acessibilidade';\n\n return (\n <Tooltip\n content={label}\n position={FAB_TOOLTIP_POSITION[position]}\n className={cn(\n 'fixed z-40',\n FAB_VERTICAL_ALIGN_CLASSES[verticalAlign],\n FAB_POSITION_CLASSES[position]\n )}\n >\n <Button\n ref={ref}\n variant=\"raw\"\n onClick={onClick}\n aria-label={label}\n aria-expanded={isOpen}\n data-testid=\"accessibility-fab\"\n className={cn(\n 'a11y-widget-shield',\n FAB_POSITION_CLASSES[position],\n 'flex h-10 w-10 cursor-pointer items-center justify-center',\n // `text-text-50` flipa junto com `bg-info-900` (claro no light,\n // escuro no dark). `text-white` deixaria o ícone branco sumindo\n // no tema escuro, onde `bg-info-900` resolve pra azul-claro.\n 'bg-info-900 text-text-50 shadow-lg',\n 'transition-all duration-200 hover:scale-110 hover:bg-info-800',\n 'focus:outline-none focus:ring-4 focus:ring-info-300',\n className\n )}\n >\n <img\n src={accessibilityIcon}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"h-7 w-7\"\n />\n </Button>\n </Tooltip>\n );\n }\n);\n\nAccessibilityFab.displayName = 'AccessibilityFab';\n\nexport default AccessibilityFab;\n","/**\n * Constantes de posicionamento compartilhadas entre os FABs do widget\n * (`AccessibilityFab` e `LibrasFab`). Centralizadas aqui para evitar\n * que mudanças de gap/lateral precisem ser replicadas em cada FAB.\n */\n\nexport type FabPosition = 'right' | 'left';\n\n/**\n * Alinhamento vertical do FAB. Quando o widget renderiza só um botão\n * (sem Libras), `center` deixa-o no meio da viewport. Quando há também\n * o LibrasFab empilhado abaixo, o de acessibilidade fica `above-center`\n * e o Libras fica `below-center` — formando um par grudado no meio.\n */\nexport type FabVerticalAlign = 'center' | 'above-center' | 'below-center';\n\nexport const FAB_POSITION_CLASSES: Record<FabPosition, string> = {\n right: 'right-0 rounded-l-lg',\n left: 'left-0 rounded-r-lg',\n};\n\nexport const FAB_VERTICAL_ALIGN_CLASSES: Record<FabVerticalAlign, string> = {\n center: 'top-1/2 -translate-y-1/2',\n // Pares empilhados (acessibilidade + Libras) com gap mínimo entre si,\n // como no widget do HandTalk. Cada FAB tem 40px (h-10).\n 'above-center': 'top-[calc(50%-1px)] -translate-y-full',\n 'below-center': 'top-[calc(50%+1px)]',\n};\n\n/** Tooltip aparece do lado oposto à borda em que o FAB está colado. */\nexport const FAB_TOOLTIP_POSITION: Record<FabPosition, 'left' | 'right'> = {\n right: 'left',\n left: 'right',\n};\n","import { useRef, useState, type ReactNode } from 'react';\nimport {\n ArrowCounterClockwiseIcon,\n CaretDownIcon,\n EyeIcon,\n FilmReelIcon,\n KeyboardIcon,\n NavigationArrowIcon,\n SpeakerHighIcon,\n TextTIcon,\n XIcon,\n} from '@phosphor-icons/react';\nimport accessibilityIcon from '../../assets/img/accessibility.png';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport IconButton from '../IconButton/IconButton';\nimport AccessibilityToggleRow from './AccessibilityToggleRow';\nimport TTSSection from './TTSSection';\nimport { cn } from '../../utils/utils';\nimport { useModalFocus } from '../../hooks/useModalFocus';\nimport { useEscapeToClose } from '../../hooks/useEscapeToClose';\nimport {\n useAccessibilityStore,\n type ContrastMode,\n type SaturationMode,\n type ReadingAid,\n} from '../../store/accessibilityStore';\nimport type { AccessibilityFabPosition } from './AccessibilityFab';\n\nconst CONTRAST_OPTIONS: { value: ContrastMode; label: string }[] = [\n { value: 'normal', label: 'Normal' },\n { value: 'high', label: 'Alto' },\n { value: 'inverted', label: 'Invertido' },\n];\n\nconst SATURATION_OPTIONS: { value: SaturationMode; label: string }[] = [\n { value: 'normal', label: 'Normal' },\n { value: 'low', label: 'Baixa' },\n { value: 'grayscale', label: 'Tons de cinza' },\n];\n\nconst READING_AID_OPTIONS: { value: ReadingAid; label: string }[] = [\n { value: 'none', label: 'Nenhum' },\n { value: 'ruler', label: 'Régua' },\n { value: 'mask', label: 'Máscara' },\n];\n\nconst LEVEL_LABELS = ['Padrão', 'Pequeno', 'Médio', 'Grande'] as const;\n\n/** Tamanho de fonte do preview \"Aa\" em cada botão (Padrão → Grande). */\nconst FONT_SIZE_PREVIEW_CLASSES = [\n 'text-base', // Padrão\n 'text-lg', // Pequeno (= maior que Padrão, segue a escala incremental do widget)\n 'text-2xl', // Médio\n 'text-4xl', // Grande\n] as const;\n\n/** Letter-spacing do preview \"Aa\" em cada botão. */\nconst LETTER_SPACING_PREVIEW_CLASSES = [\n 'tracking-tighter', // Padrão (junto)\n 'tracking-normal',\n 'tracking-wider',\n 'tracking-widest',\n] as const;\n\n/** Gap vertical entre as 3 barras do preview de espaçamento entre linhas. */\nconst LINE_SPACING_PREVIEW_GAPS = [\n 'gap-0.5', // Padrão (2px) — linhas próximas\n 'gap-1.5', // Pequeno (6px)\n 'gap-2.5', // Médio (10px)\n 'gap-3.5', // Grande (14px)\n] as const;\n\n/**\n * `<dialog open>` aplica `left: 0; right: 0` como user-agent style. Sem\n * resetar o lado oposto para `auto`, o painel acaba grudando no lado\n * errado mesmo com `right-6` ou `left-6` aplicado.\n */\nconst PANEL_EDGE_CLASSES: Record<AccessibilityFabPosition, string> = {\n right: 'right-10 left-auto',\n left: 'left-10 right-auto',\n};\n\ninterface AccordionSectionProps {\n title: string;\n icon: ReactNode;\n defaultExpanded?: boolean;\n testId?: string;\n children: ReactNode;\n}\n\n/**\n * Item de accordion estilo lista (sem cantos arredondados nem card),\n * com ícone + título à esquerda e caret à direita. Cada item separado\n * do próximo por uma linha fina. Mantém a estrutura visual do design\n * do Figma sem usar o `CardAccordation` da lib (que tem visual de card).\n */\nconst AccordionSection = ({\n title,\n icon,\n defaultExpanded = false,\n testId,\n children,\n}: Readonly<AccordionSectionProps>) => {\n const [expanded, setExpanded] = useState(defaultExpanded);\n return (\n <section className=\"border-b border-background-200 last:border-b-0\">\n <Button\n variant=\"raw\"\n aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}\n data-testid={testId}\n className={cn(\n 'flex w-full cursor-pointer items-center justify-between gap-2 px-4 py-3',\n 'text-left transition-colors hover:bg-background-50',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-info-500 focus-visible:ring-inset'\n )}\n >\n <span className=\"flex items-center gap-2\">\n <span className=\"text-text-800\" aria-hidden=\"true\">\n {icon}\n </span>\n <Text\n size=\"md\"\n weight=\"semibold\"\n className=\"leading-none text-text-800\"\n >\n {title}\n </Text>\n </span>\n <CaretDownIcon\n size={16}\n weight=\"bold\"\n aria-hidden=\"true\"\n className={cn(\n 'text-text-700 transition-transform duration-200',\n expanded ? 'rotate-180' : 'rotate-0'\n )}\n />\n </Button>\n {expanded && (\n <div className=\"flex flex-col gap-6 px-4 pb-4 pt-2\">{children}</div>\n )}\n </section>\n );\n};\n\ninterface SubControlProps {\n label: string;\n children: ReactNode;\n}\n\n/**\n * Wrapper para uma control (segmented/toggle) com título dentro do\n * accordion. Tipografia do label segue o Figma: Roboto 12px/500/100%\n * uppercase, cor `text-text-600` (#737373).\n */\nconst SubControl = ({ label, children }: Readonly<SubControlProps>) => (\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n {label}\n </Text>\n {children}\n </div>\n);\n\ninterface SegmentedProps<T extends string | number> {\n value: T;\n options: { value: T; label: string }[];\n onChange: (value: T) => void;\n ariaLabel: string;\n}\n\n/**\n * Estilo de segmented baseado no `SelectionButton` da lib: cada opção é\n * um botão independente com `border` + `bg-background`, e o selecionado\n * ganha `ring-primary-950` (mesma identidade visual do componente da lib,\n * sem o overhead de ícone obrigatório do SelectionButton).\n */\nconst Segmented = <T extends string | number>({\n value,\n options,\n onChange,\n ariaLabel,\n}: Readonly<SegmentedProps<T>>) => (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className=\"flex flex-wrap gap-2\"\n >\n {options.map((opt) => {\n const isActive = opt.value === value;\n return (\n <Button\n key={String(opt.value)}\n variant=\"raw\"\n role=\"radio\"\n aria-checked={isActive}\n onClick={() => onChange(opt.value)}\n className={cn(\n 'flex-1 cursor-pointer rounded-xl border border-border-50 bg-background',\n // Texto segue spec do Figma: Roboto 14px/700/100%/0.2px, cor\n // #525252 (text-700). Quando ativo, troca pra primary-950\n // (azul escuro), mas mantém a mesma typography.\n 'px-4 py-4 text-sm font-bold leading-none tracking-[0.2px] text-text-700',\n 'shadow-soft-shadow-1 transition-all duration-150',\n 'hover:bg-background-100',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indicator-info',\n isActive &&\n 'ring-2 ring-primary-950 ring-offset-0 shadow-none text-primary-950'\n )}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n);\n\ninterface PreviewSegmentedOption<T extends string | number> {\n value: T;\n label: string;\n /** Conteúdo visual exibido DENTRO do botão (preview do efeito). */\n preview: ReactNode;\n}\n\ninterface PreviewSegmentedProps<T extends string | number> {\n value: T;\n options: PreviewSegmentedOption<T>[];\n onChange: (value: T) => void;\n ariaLabel: string;\n}\n\n/**\n * Variante do Segmented onde o botão mostra um preview visual do efeito\n * (ex.: \"Aa\" em tamanhos diferentes para \"Tamanho da fonte\") e o label\n * textual fica abaixo do botão como legenda.\n */\nconst PreviewSegmented = <T extends string | number>({\n value,\n options,\n onChange,\n ariaLabel,\n}: Readonly<PreviewSegmentedProps<T>>) => (\n <div role=\"radiogroup\" aria-label={ariaLabel} className=\"flex gap-2\">\n {options.map((opt) => {\n const isActive = opt.value === value;\n return (\n <div\n key={String(opt.value)}\n className=\"flex flex-1 flex-col items-center gap-2\"\n >\n <Button\n variant=\"raw\"\n role=\"radio\"\n aria-checked={isActive}\n aria-label={opt.label}\n onClick={() => onChange(opt.value)}\n className={cn(\n 'flex aspect-square w-full items-center justify-center',\n 'cursor-pointer rounded-xl border border-border-50 bg-background',\n 'text-text-700 shadow-soft-shadow-1 transition-all duration-150',\n 'hover:bg-background-100',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indicator-info',\n isActive &&\n 'ring-2 ring-primary-950 ring-offset-0 shadow-none text-primary-950'\n )}\n >\n {opt.preview}\n </Button>\n <Text\n size=\"xs\"\n weight=\"normal\"\n className=\"leading-none text-text-700\"\n >\n {opt.label}\n </Text>\n </div>\n );\n })}\n </div>\n);\n\nexport interface AccessibilityPanelProps {\n isOpen: boolean;\n onClose: () => void;\n /** Lado da viewport onde o painel aparece (default: 'right') */\n position?: AccessibilityFabPosition;\n className?: string;\n}\n\n/**\n * Painel lateral com os controles de acessibilidade organizados em\n * accordions colapsáveis (Visão, Leitura, Leitor de texto, Animação,\n * Navegação, Atalho de teclado).\n *\n * O próprio painel fica dentro de `.a11y-widget-shield`, então\n * filtros aplicados no `<html>` (alto contraste, etc.) não afetam\n * sua legibilidade.\n */\nexport default function AccessibilityPanel({\n isOpen,\n onClose,\n position = 'right',\n className,\n}: Readonly<AccessibilityPanelProps>) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n const {\n contrastMode,\n saturationMode,\n fontSize,\n letterSpacing,\n lineSpacing,\n highlightLinks,\n pauseAnimations,\n bigCursor,\n dyslexiaFont,\n readingAid,\n keyboardShortcut,\n setContrastMode,\n setSaturationMode,\n setFontSize,\n setLetterSpacing,\n setLineSpacing,\n setHighlightLinks,\n setPauseAnimations,\n setBigCursor,\n setDyslexiaFont,\n setReadingAid,\n setKeyboardShortcut,\n resetPreferences,\n } = useAccessibilityStore();\n\n /**\n * Foco e navegação, pelos mesmos hooks que o `Modal` e o `AlertDialog` usam.\n * O `useModalFocus` leva o foco pro diálogo ao abrir, prende Tab e Shift+Tab\n * no ciclo (de \"Redefinir ajustes\" volta pro \"Fechar opções de\n * acessibilidade\", e vice-versa) e torna o resto da página `inert` —\n * necessário porque este é um `<dialog open>` sem top layer: sem isso o\n * cursor virtual do VoiceOver continua passeando pelo menu atrás, e o Tab\n * escapa pra ele. Também devolve o foco a quem abriu o painel.\n *\n * O foco inicial vai pro próprio diálogo (daí o `tabIndex={-1}` abaixo), e\n * não pro botão de fechar: assim o leitor anuncia \"Opções de acessibilidade,\n * diálogo\" antes de cair nos controles.\n *\n * `useEscapeToClose` em vez do listener manual de antes: ele ignora um\n * Escape já tratado (`defaultPrevented`), então fechar o `Select` de voz do\n * TTS não fecha mais o painel inteiro junto.\n *\n * Sem `useBodyScrollLock` de propósito: ele cobre a faixa da scrollbar com um\n * overlay escuro combinando com o backdrop dos modais, e este painel não tem\n * backdrop — a tarja apareceria solta na borda da tela.\n */\n useModalFocus(isOpen, dialogRef);\n useEscapeToClose(isOpen, onClose);\n\n if (!isOpen) return null;\n\n const levelOptions = LEVEL_LABELS.map((label, index) => ({\n value: index as 0 | 1 | 2 | 3,\n label,\n }));\n\n return (\n <dialog\n ref={dialogRef}\n open\n // Requisito do `useModalFocus` (ver a nota acima): o foco inicial vai pro\n // próprio diálogo, que precisa ser focável sem entrar no ciclo de Tab.\n tabIndex={-1}\n // `open` sem `showModal()` não cria top layer nem marca o diálogo como\n // modal, então o papel é declarado aqui — como no `Modal` e no\n // `AlertDialog`. Quem realmente prende a navegação é o `inert` aplicado\n // pelo hook; o atributo é o que anuncia ao leitor que a página atrás\n // saiu do caminho.\n aria-modal=\"true\"\n aria-label=\"Opções de acessibilidade\"\n data-testid=\"accessibility-panel\"\n // `<dialog>` não estica automaticamente com `top` + `bottom`, por\n // isso a altura fica explícita: `100vh - 5rem` (80px de respiro do\n // topo). Combinado com `bottom-0` no className, o painel encosta\n // na base da viewport como no Figma.\n style={{ height: 'calc(100vh - 5rem)' }}\n className={cn(\n 'a11y-widget-shield',\n 'fixed bottom-0 z-40 m-0',\n PANEL_EDGE_CLASSES[position],\n 'flex w-[calc(100vw-3rem)] max-w-110 flex-col overflow-hidden rounded-2xl p-0',\n 'border border-background-200 bg-background shadow-2xl',\n className\n )}\n >\n {/* Header — visual do Figma: bg azul-claro (Paraná) / rosa-claro\n (Paraíba) usando `primary-50`. Preferido em vez de `map-attention`\n porque `primary-50` flipa corretamente no dark mode em todos os\n temas (ex.: Paraná dark = #27344a), enquanto `map-attention`\n ficou idêntico em light/dark no theme do Paraná, deixando o\n texto branco invisível sobre o azul-claro no dark. */}\n <header className=\"flex items-center justify-between gap-3 bg-primary-50 px-4 py-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <img\n src={accessibilityIcon}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"h-10 w-10 shrink-0\"\n />\n <div className=\"flex min-w-0 flex-col gap-1\">\n <Text\n size=\"md\"\n weight=\"bold\"\n className=\"leading-none tracking-[0.2px] text-text-950\"\n >\n Acessibilidade\n </Text>\n <Text\n size=\"xs\"\n weight=\"normal\"\n className=\"leading-none text-text-800\"\n >\n Personalize a leitura e navegação\n </Text>\n </div>\n </div>\n <IconButton\n size=\"sm\"\n aria-label=\"Fechar opções de acessibilidade\"\n onClick={onClose}\n icon={<XIcon size={18} />}\n />\n </header>\n\n <div className=\"flex-1 overflow-y-auto\">\n <AccordionSection\n title=\"Visão\"\n icon={<EyeIcon size={18} />}\n testId=\"a11y-section-vision\"\n >\n <SubControl label=\"Contraste\">\n <Segmented\n ariaLabel=\"Modo de contraste\"\n value={contrastMode}\n options={CONTRAST_OPTIONS}\n onChange={setContrastMode}\n />\n </SubControl>\n <SubControl label=\"Saturação\">\n <Segmented\n ariaLabel=\"Modo de saturação\"\n value={saturationMode}\n options={SATURATION_OPTIONS}\n onChange={setSaturationMode}\n />\n </SubControl>\n {/* Daltonismo removido por enquanto — store/store actions\n mantidos para reativação futura sem refactor. */}\n </AccordionSection>\n\n <AccordionSection\n title=\"Leitura\"\n icon={<TextTIcon size={18} />}\n testId=\"a11y-section-reading\"\n >\n <SubControl label=\"Fonte para dislexia\">\n <AccessibilityToggleRow\n ariaLabel=\"Trocar para Comic Sans MS\"\n rowTestId=\"a11y-toggle-dyslexia-font-row\"\n switchTestId=\"a11y-toggle-dyslexia-font\"\n checked={dyslexiaFont}\n onChange={() => setDyslexiaFont(!dyslexiaFont)}\n label={\n <>\n Trocar para{' '}\n <span style={{ fontFamily: '\"Comic Sans MS\", cursive' }}>\n Comic Sans MS\n </span>\n </>\n }\n />\n </SubControl>\n\n <SubControl label=\"Tamanho da fonte\">\n <PreviewSegmented\n ariaLabel=\"Tamanho da fonte\"\n value={fontSize}\n options={levelOptions.map((opt) => ({\n ...opt,\n preview: (\n <span\n className={cn(\n 'font-semibold leading-none',\n FONT_SIZE_PREVIEW_CLASSES[opt.value]\n )}\n >\n Aa\n </span>\n ),\n }))}\n onChange={setFontSize}\n />\n </SubControl>\n\n <SubControl label=\"Espaçamento entre letras\">\n <PreviewSegmented\n ariaLabel=\"Espaçamento entre letras\"\n value={letterSpacing}\n options={levelOptions.map((opt) => ({\n ...opt,\n preview: (\n <span\n className={cn(\n // Mesmo tamanho do \"Aa\" no botão Padrão de \"Tamanho\n // da fonte\" (text-base), pra que essa scale visualize\n // só a variação de letter-spacing.\n 'text-base font-semibold leading-none',\n LETTER_SPACING_PREVIEW_CLASSES[opt.value]\n )}\n >\n Aa\n </span>\n ),\n }))}\n onChange={setLetterSpacing}\n />\n </SubControl>\n\n <SubControl label=\"Espaçamento entre linhas\">\n <PreviewSegmented\n ariaLabel=\"Espaçamento entre linhas\"\n value={lineSpacing}\n options={levelOptions.map((opt) => ({\n ...opt,\n preview: (\n <span\n className={cn(\n 'flex flex-col items-stretch',\n LINE_SPACING_PREVIEW_GAPS[opt.value]\n )}\n >\n <span className=\"h-0.5 w-7 rounded-full bg-current\" />\n <span className=\"h-0.5 w-7 rounded-full bg-current\" />\n <span className=\"h-0.5 w-7 rounded-full bg-current\" />\n </span>\n ),\n }))}\n onChange={setLineSpacing}\n />\n </SubControl>\n\n <SubControl label=\"Auxiliar de leitura\">\n <Segmented\n ariaLabel=\"Auxiliar de leitura\"\n value={readingAid}\n options={READING_AID_OPTIONS}\n onChange={setReadingAid}\n />\n </SubControl>\n </AccordionSection>\n\n <AccordionSection\n title=\"Leitor de texto\"\n icon={<SpeakerHighIcon size={18} />}\n testId=\"a11y-section-tts\"\n >\n <TTSSection PreviewSegmented={PreviewSegmented} />\n </AccordionSection>\n\n <AccordionSection\n title=\"Animação\"\n icon={<FilmReelIcon size={18} />}\n testId=\"a11y-section-animation\"\n >\n <AccessibilityToggleRow\n label=\"Pausar animações para conforto visual\"\n checked={pauseAnimations}\n onChange={() => setPauseAnimations(!pauseAnimations)}\n switchTestId=\"a11y-toggle-pause-animations\"\n />\n </AccordionSection>\n\n <AccordionSection\n title=\"Navegação\"\n icon={<NavigationArrowIcon size={18} />}\n testId=\"a11y-section-navigation\"\n >\n <SubControl label=\"Destacar links e botões\">\n <AccessibilityToggleRow\n label=\"Adicionar contorno em elementos clicáveis\"\n checked={highlightLinks}\n onChange={() => setHighlightLinks(!highlightLinks)}\n switchTestId=\"a11y-toggle-highlight-links\"\n />\n </SubControl>\n <SubControl label=\"Cursor maior\">\n <AccessibilityToggleRow\n label=\"Aumentar e escurecer cursor\"\n checked={bigCursor}\n onChange={() => setBigCursor(!bigCursor)}\n switchTestId=\"a11y-toggle-big-cursor\"\n />\n </SubControl>\n </AccordionSection>\n\n <AccordionSection\n title=\"Atalho de teclado\"\n icon={<KeyboardIcon size={18} />}\n testId=\"a11y-section-shortcut\"\n >\n <AccessibilityToggleRow\n label=\"Alt+A para abrir o painel\"\n checked={keyboardShortcut}\n onChange={() => setKeyboardShortcut(!keyboardShortcut)}\n switchTestId=\"a11y-toggle-keyboard-shortcut\"\n />\n </AccordionSection>\n </div>\n\n <footer className=\"border-t border-background-200 px-4 py-3\">\n <Button\n variant=\"outline\"\n action=\"primary\"\n size=\"medium\"\n iconLeft={\n <ArrowCounterClockwiseIcon\n size={16}\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n }\n onClick={resetPreferences}\n data-testid=\"a11y-reset\"\n className=\"w-full justify-center\"\n >\n Redefinir ajustes\n </Button>\n </footer>\n </dialog>\n );\n}\n","import type { ReactNode } from 'react';\nimport Text from '../Text/Text';\nimport ToggleSwitch from '../ToggleSwitch/ToggleSwitch';\nimport { cn } from '../../utils/utils';\n\nexport interface AccessibilityToggleRowProps {\n /** Conteúdo principal da linha (texto ou JSX, ex.: trecho em Comic Sans). */\n label: ReactNode;\n /** Aria-label do row quando `label` é JSX e não pode ser usado como texto. */\n ariaLabel?: string;\n /** Texto auxiliar abaixo do label. */\n description?: string;\n checked: boolean;\n onChange: () => void;\n /** Testid no wrapper interativo (toda a linha). */\n rowTestId?: string;\n /** Testid no `<ToggleSwitch>` interno — usado pelos testes que ainda\n * clicam diretamente no botão de switch. */\n switchTestId?: string;\n}\n\n/**\n * Linha clicável \"label à esquerda + ToggleSwitch à direita\" usada nos\n * accordions de Animação, Navegação, Atalho, dislexia e leitor de texto.\n *\n * O wrapper inteiro responde a click/Enter/Space; o `ToggleSwitch` interno\n * é apenas decorativo (`tabIndex={-1}`, `aria-hidden`) pra que toda a área\n * vire alvo de clique sem dupla-ativação do switch.\n */\nexport default function AccessibilityToggleRow({\n label,\n ariaLabel,\n description,\n checked,\n onChange,\n rowTestId,\n switchTestId,\n}: Readonly<AccessibilityToggleRowProps>) {\n const computedAriaLabel =\n ariaLabel ?? (typeof label === 'string' ? label : undefined);\n return (\n <div\n role=\"switch\"\n tabIndex={0}\n aria-checked={checked}\n aria-label={computedAriaLabel}\n data-testid={rowTestId}\n className={cn(\n 'flex items-center justify-between gap-3 rounded-md py-1.5',\n 'cursor-pointer transition-colors duration-150 hover:bg-background-100',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-info-500'\n )}\n onClick={onChange}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onChange();\n }\n }}\n >\n <div className=\"flex flex-col\">\n <Text size=\"sm\" className=\"text-text-900\">\n {label}\n </Text>\n {description && (\n <Text size=\"2xs\" className=\"text-text-600\">\n {description}\n </Text>\n )}\n </div>\n <ToggleSwitch\n checked={checked}\n onChange={() => undefined}\n checkedColor=\"bg-info-600\"\n data-testid={switchTestId}\n tabIndex={-1}\n aria-hidden\n />\n </div>\n );\n}\n","import { useMemo, type ReactElement, type ReactNode } from 'react';\nimport { PauseIcon, PlayIcon, StopIcon } from '@phosphor-icons/react';\nimport Button from '../Button/Button';\nimport Text from '../Text/Text';\nimport Select, {\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n} from '../Select/Select';\nimport AccessibilityToggleRow from './AccessibilityToggleRow';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\nimport { useTTS } from '../../hooks/useTTS';\n\n/**\n * Opções de velocidade da fala. O `preview` mostra o valor numérico\n * dentro do botão (1.0, 1.25, etc.) e o `label` aparece como caption\n * abaixo. Valores escolhidos para casarem com o que o Web Speech API\n * aceita (0.5–2.0) — `0.75` foi mantido para \"Lento\" em vez de algo\n * mais agressivo porque vozes nativas ficam ininteligíveis abaixo disso.\n */\nconst RATE_OPTIONS: {\n value: string;\n label: string;\n preview: ReactNode;\n}[] = [\n { value: '0.75', label: 'Lento', preview: '0.75' },\n { value: '1', label: 'Normal', preview: '1.0' },\n { value: '1.25', label: 'Rápido', preview: '1.25' },\n { value: '2', label: 'Muito rápido', preview: '2.0' },\n];\n\nexport interface TTSSectionProps {\n /** Componente de segmented com preview visual + label abaixo */\n PreviewSegmented: <T extends string | number>(props: {\n value: T;\n options: { value: T; label: string; preview: ReactNode }[];\n ariaLabel: string;\n onChange: (value: T) => void;\n }) => ReactElement;\n}\n\n/**\n * Bloco de controles do leitor de texto dentro do painel.\n * Estrutura segue o design do Figma:\n * 1. \"Texto para voz\" — toggle que ativa/desativa o modo click-to-read\n * 2. \"Voz\" — seletor de voz\n * 3. \"Velocidade\" — PreviewSegmented com valor numérico\n */\nexport default function TTSSection({\n PreviewSegmented,\n}: Readonly<TTSSectionProps>) {\n const ttsMode = useAccessibilityStore((s) => s.ttsMode);\n const ttsStatus = useAccessibilityStore((s) => s.ttsStatus);\n const ttsRate = useAccessibilityStore((s) => s.ttsRate);\n const ttsVoiceId = useAccessibilityStore((s) => s.ttsVoiceId);\n const setTTSMode = useAccessibilityStore((s) => s.setTTSMode);\n const setTTSRate = useAccessibilityStore((s) => s.setTTSRate);\n const setTTSVoiceId = useAccessibilityStore((s) => s.setTTSVoiceId);\n\n const { isSupported, voices, hasPortugueseVoice, pause, resume, stop } =\n useTTS();\n\n // Preferimos vozes em português; demais ficam ao final.\n const sortedVoices = useMemo(() => {\n return [...voices].sort((a, b) => {\n const aPt = a.lang.toLowerCase().startsWith('pt') ? 0 : 1;\n const bPt = b.lang.toLowerCase().startsWith('pt') ? 0 : 1;\n if (aPt !== bPt) return aPt - bPt;\n return a.name.localeCompare(b.name);\n });\n }, [voices]);\n\n if (!isSupported) {\n return (\n <Text size=\"2xs\" className=\"text-text-600\">\n Síntese de voz não está disponível neste navegador.\n </Text>\n );\n }\n\n const isClickToReadOn = ttsMode === 'click-to-read';\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Texto para voz: toggle row */}\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n Texto para voz\n </Text>\n <AccessibilityToggleRow\n label=\"Ative a leitura e clique no texto para ouvir\"\n rowTestId=\"a11y-tts-mode-toggle\"\n checked={isClickToReadOn}\n onChange={() => setTTSMode(isClickToReadOn ? 'off' : 'click-to-read')}\n />\n </div>\n\n {!hasPortugueseVoice && (\n <Text size=\"2xs\" className=\"text-warning-700\">\n Nenhuma voz em português foi encontrada no seu sistema. A leitura será\n feita com a voz padrão disponível.\n </Text>\n )}\n\n {/* Voz: pill select */}\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n Voz\n </Text>\n <Select\n size=\"small\"\n value={ttsVoiceId ?? ''}\n onValueChange={(value) => setTTSVoiceId(value || null)}\n >\n <SelectTrigger\n variant=\"rounded\"\n aria-label=\"Voz da síntese de fala\"\n data-testid=\"a11y-tts-voice-select\"\n >\n <SelectValue placeholder=\"Padrão do navegador\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"\">Padrão do navegador</SelectItem>\n {sortedVoices.map((v) => (\n <SelectItem key={v.id} value={v.id}>\n {v.name} — {v.lang}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Velocidade: preview segmented com valor numérico no botão */}\n <div className=\"flex flex-col gap-2\">\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"uppercase leading-none text-text-600\"\n >\n Velocidade\n </Text>\n <PreviewSegmented\n ariaLabel=\"Velocidade da fala\"\n value={String(ttsRate)}\n options={RATE_OPTIONS.map((opt) => ({\n value: opt.value,\n label: opt.label,\n preview: (\n <span className=\"text-base font-bold leading-none\">\n {opt.preview}\n </span>\n ),\n }))}\n onChange={(v) => setTTSRate(Number(v))}\n />\n </div>\n\n {/* Ações: pause/resume/stop conforme status — só visíveis durante a fala */}\n {ttsStatus !== 'idle' && (\n <div className=\"flex items-center gap-2\">\n {ttsStatus === 'speaking' && (\n <Button\n variant=\"outline\"\n action=\"secondary\"\n size=\"small\"\n iconLeft={\n <PauseIcon size={14} weight=\"bold\" aria-hidden=\"true\" />\n }\n onClick={pause}\n data-testid=\"a11y-tts-pause\"\n >\n Pausar\n </Button>\n )}\n\n {ttsStatus === 'paused' && (\n <Button\n variant=\"outline\"\n action=\"secondary\"\n size=\"small\"\n iconLeft={<PlayIcon size={14} weight=\"bold\" aria-hidden=\"true\" />}\n onClick={resume}\n data-testid=\"a11y-tts-resume\"\n >\n Retomar\n </Button>\n )}\n\n <Button\n variant=\"outline\"\n action=\"negative\"\n size=\"small\"\n iconLeft={<StopIcon size={14} weight=\"bold\" aria-hidden=\"true\" />}\n onClick={stop}\n data-testid=\"a11y-tts-stop\"\n className=\"ml-auto\"\n >\n Parar\n </Button>\n </div>\n )}\n </div>\n );\n}\n","import { HandWavingIcon } from '@phosphor-icons/react';\nimport Button from '../Button/Button';\nimport { Tooltip } from '../Tooltip/Tooltip';\nimport { cn } from '../../utils/utils';\nimport {\n FAB_POSITION_CLASSES,\n FAB_TOOLTIP_POSITION,\n FAB_VERTICAL_ALIGN_CLASSES,\n type FabPosition,\n type FabVerticalAlign,\n} from './fabPositioning';\n\ntype AccessibilityFabPosition = FabPosition;\ntype AccessibilityFabVerticalAlign = FabVerticalAlign;\n\nexport interface LibrasFabProps {\n /** Click handler — alterna o painel do VLibras (abrir/fechar) */\n onClick: () => void;\n /** Lado da viewport onde o botão fica colado */\n position?: AccessibilityFabPosition;\n /** Alinhamento vertical (default: `below-center`) */\n verticalAlign?: AccessibilityFabVerticalAlign;\n /** Classes extras */\n className?: string;\n}\n\n/**\n * Segundo botão flutuante (FAB), posicionado abaixo do `AccessibilityFab`.\n * Aciona o widget oficial do VLibras (gov.br) que faz tradução automática\n * de português para Libras via avatar 3D.\n *\n * O botão tem visual constante — não mantemos um indicador de estado\n * \"ativo\" porque o painel do VLibras já reflete visualmente se está\n * aberto ou fechado. Cada clique alterna o painel.\n *\n * Mesma identidade visual do FAB principal (azul escuro, quadrado com\n * canto interno arredondado, colado na lateral).\n */\nexport default function LibrasFab({\n onClick,\n position = 'right',\n verticalAlign = 'below-center',\n className,\n}: Readonly<LibrasFabProps>) {\n const label = 'Tradução em Libras';\n\n return (\n <Tooltip\n content={label}\n position={FAB_TOOLTIP_POSITION[position]}\n className={cn(\n 'fixed z-40',\n FAB_VERTICAL_ALIGN_CLASSES[verticalAlign],\n FAB_POSITION_CLASSES[position]\n )}\n >\n <Button\n variant=\"raw\"\n onClick={onClick}\n aria-label={label}\n data-testid=\"libras-fab\"\n className={cn(\n 'a11y-widget-shield',\n FAB_POSITION_CLASSES[position],\n 'flex h-10 w-10 cursor-pointer items-center justify-center',\n // `text-text-50` flipa junto com `bg-info-900`: claro no light,\n // escuro no dark. Como o ícone usa `currentColor`, com `text-white`\n // a mãozinha sumiria no tema escuro (branco em fundo azul-claro).\n 'bg-info-900 text-text-50 shadow-lg',\n 'transition-all duration-200 hover:scale-110 hover:bg-info-800',\n 'focus:outline-none focus:ring-4 focus:ring-info-300',\n className\n )}\n >\n <HandWavingIcon size={25} weight=\"fill\" aria-hidden=\"true\" />\n </Button>\n </Tooltip>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\n\nconst RULER_HEIGHT_PX = 32;\nconst MASK_GAP_PX = 80; // metade da altura da janela visível\n\n/**\n * Renderiza auxiliares de leitura (régua ou máscara) que acompanham\n * a posição vertical do mouse. Só monta listener de `mousemove` quando\n * algum auxiliar está ativo, para não pagar custo quando desligado.\n */\nexport default function ReadingAid() {\n const readingAid = useAccessibilityStore((s) => s.readingAid);\n const [mouseY, setMouseY] = useState<number | null>(null);\n\n useEffect(() => {\n if (readingAid === 'none') {\n setMouseY(null);\n return;\n }\n\n let frame = 0;\n const handleMouseMove = (event: MouseEvent) => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(() => setMouseY(event.clientY));\n };\n\n document.addEventListener('mousemove', handleMouseMove, { passive: true });\n return () => {\n cancelAnimationFrame(frame);\n document.removeEventListener('mousemove', handleMouseMove);\n };\n }, [readingAid]);\n\n if (readingAid === 'none' || mouseY === null) return null;\n\n if (readingAid === 'ruler') {\n return (\n <div\n aria-hidden=\"true\"\n data-testid=\"a11y-reading-ruler\"\n className=\"a11y-widget-shield pointer-events-none fixed left-0 right-0 z-30\"\n style={{\n top: mouseY - RULER_HEIGHT_PX / 2,\n height: RULER_HEIGHT_PX,\n background: 'rgba(255, 235, 59, 0.25)',\n borderTop: '2px solid #facc15',\n borderBottom: '2px solid #facc15',\n }}\n />\n );\n }\n\n // Máscara: dois retângulos escurecendo acima e abaixo do cursor\n return (\n <>\n <div\n aria-hidden=\"true\"\n data-testid=\"a11y-reading-mask-top\"\n className=\"a11y-widget-shield pointer-events-none fixed left-0 right-0 top-0 z-30 bg-black/90\"\n style={{ height: Math.max(0, mouseY - MASK_GAP_PX) }}\n />\n <div\n aria-hidden=\"true\"\n data-testid=\"a11y-reading-mask-bottom\"\n className=\"a11y-widget-shield pointer-events-none fixed left-0 right-0 bottom-0 z-30 bg-black/90\"\n style={{ top: mouseY + MASK_GAP_PX }}\n />\n </>\n );\n}\n","import {\n ColorBlindMode,\n getColorBlindFilterId,\n} from '../../store/accessibilityStore';\n\n/**\n * SVG escondido com matrizes `<feColorMatrix>` que simulam/auxiliam\n * cada tipo de daltonismo. As classes em `accessibility.css` aplicam\n * `filter: url(#a11y-cb-...)` no `<html>` para colorir a página.\n *\n * Os IDs dos filters são derivados do enum `ColorBlindMode` via\n * `getColorBlindFilterId` — mesma fonte da verdade que o hook usa\n * para aplicar a classe.\n *\n * Matrizes baseadas em Brettel/Vienot/Mollon — padrão amplamente\n * utilizado em ferramentas de acessibilidade como AXE, Daltonize e\n * widget oficial do HandTalk.\n */\nexport default function ColorBlindFilters() {\n return (\n <svg\n aria-hidden=\"true\"\n data-testid=\"a11y-colorblind-filters\"\n style={{\n position: 'absolute',\n width: 0,\n height: 0,\n overflow: 'hidden',\n }}\n >\n <defs>\n <filter id={getColorBlindFilterId(ColorBlindMode.Protanopia)}>\n <feColorMatrix\n type=\"matrix\"\n values=\"0.567 0.433 0 0 0\n 0.558 0.442 0 0 0\n 0 0.242 0.758 0 0\n 0 0 0 1 0\"\n />\n </filter>\n <filter id={getColorBlindFilterId(ColorBlindMode.Deuteranopia)}>\n <feColorMatrix\n type=\"matrix\"\n values=\"0.625 0.375 0 0 0\n 0.700 0.300 0 0 0\n 0 0.300 0.7 0 0\n 0 0 0 1 0\"\n />\n </filter>\n <filter id={getColorBlindFilterId(ColorBlindMode.Tritanopia)}>\n <feColorMatrix\n type=\"matrix\"\n values=\"0.95 0.05 0 0 0\n 0 0.433 0.567 0 0\n 0 0.475 0.525 0 0\n 0 0 0 1 0\"\n />\n </filter>\n </defs>\n </svg>\n );\n}\n","import { useEffect } from 'react';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\nimport { useTTS } from '../../hooks/useTTS';\n\nconst HIGHLIGHT_CLASS = 'a11y-tts-target';\n\n/**\n * Controller invisível que conecta o `ttsMode` do store ao DOM:\n * - `click-to-read`: registra um listener global de clique. Ao clicar\n * em qualquer elemento (exceto o próprio widget), lê seu texto.\n * - `read-selection`: lê o texto atualmente selecionado quando o store\n * sinaliza (via `pendingReadSelection`). UI/atalho disparam isso.\n *\n * Aplica a classe `.a11y-tts-target` no elemento sendo lido para\n * destaque visual; remove ao terminar/parar.\n */\nexport default function TTSController() {\n const ttsMode = useAccessibilityStore((s) => s.ttsMode);\n const ttsStatus = useAccessibilityStore((s) => s.ttsStatus);\n const { speak, stop, isSupported } = useTTS();\n\n // Click-to-read: ouve cliques globais enquanto o modo está ativo\n useEffect(() => {\n if (!isSupported || ttsMode !== 'click-to-read') return;\n\n const handler = (event: MouseEvent) => {\n const initialTarget = event.target as HTMLElement | null;\n if (!initialTarget) return;\n\n // Ignora cliques dentro do próprio widget\n if (initialTarget.closest('.a11y-widget-shield')) return;\n\n // Sobe pela árvore até achar o ancestral que tem texto legível.\n // Cobre o caso comum de IconButtons com `<svg>` interno: clicar no\n // SVG não retorna texto, mas o botão pai tem aria-label.\n const found = findReadableAncestor(initialTarget);\n if (!found) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n // Limpa highlight anterior e marca o novo alvo\n document\n .querySelectorAll(`.${HIGHLIGHT_CLASS}`)\n .forEach((el) => el.classList.remove(HIGHLIGHT_CLASS));\n found.node.classList.add(HIGHLIGHT_CLASS);\n\n speak(found.text);\n };\n\n // capture: true → pegamos o clique antes do handler do app/link\n document.addEventListener('click', handler, true);\n return () => {\n document.removeEventListener('click', handler, true);\n document\n .querySelectorAll(`.${HIGHLIGHT_CLASS}`)\n .forEach((el) => el.classList.remove(HIGHLIGHT_CLASS));\n // Interrompe qualquer fala em curso ao sair do modo. Sem isso,\n // desligar o \"Clique para ler\" deixaria a leitura terminando\n // sozinha, contrariando a expectativa do usuário.\n stop();\n };\n }, [isSupported, ttsMode, speak, stop]);\n\n // Quando a fala termina (ttsStatus volta a 'idle'), limpa highlight\n useEffect(() => {\n if (ttsStatus === 'idle') {\n document\n .querySelectorAll(`.${HIGHLIGHT_CLASS}`)\n .forEach((el) => el.classList.remove(HIGHLIGHT_CLASS));\n }\n }, [ttsStatus]);\n\n // Para qualquer fala em curso quando o componente desmonta\n useEffect(() => () => stop(), [stop]);\n\n return null;\n}\n\n/**\n * Extrai texto legível do elemento clicado. Prioriza:\n * 1. `aria-label` se presente\n * 2. `title`\n * 3. `innerText` truncado\n *\n * `innerText` (e não `textContent`) respeita estilos como `display: none`\n * e quebras de linha visuais — leitura mais natural.\n */\nconst extractReadableText = (el: HTMLElement): string => {\n const aria = el.getAttribute('aria-label')?.trim();\n if (aria) return aria;\n const title = el.getAttribute('title')?.trim();\n if (title) return title;\n const text = el.innerText?.trim() ?? '';\n // Limita comprimento para evitar leitura infinita ao clicar em\n // contêineres grandes (ex.: <main>). 600 chars ≈ 1min de fala.\n return text.length > 600 ? `${text.slice(0, 600)}...` : text;\n};\n\n/** Quantos níveis de ancestralidade subimos buscando um nó legível. */\nconst MAX_ANCESTOR_LOOKUP = 8;\n\n/**\n * Caminha pela árvore a partir do elemento clicado até achar o ancestral\n * mais próximo que tenha texto legível (`aria-label`, `title` ou\n * `innerText`). Limita a profundidade e nunca retorna o `<body>` para\n * evitar ler a página inteira ao clicar em ícones soltos.\n */\nconst findReadableAncestor = (\n start: HTMLElement\n): { node: HTMLElement; text: string } | null => {\n let node: HTMLElement | null = start;\n let depth = 0;\n while (node && depth < MAX_ANCESTOR_LOOKUP && node !== document.body) {\n const text = extractReadableText(node);\n if (text) return { node, text };\n node = node.parentElement;\n depth++;\n }\n return null;\n};\n","import { useEffect } from 'react';\nimport { useAccessibilityStore } from '../../store/accessibilityStore';\n\nconst SCRIPT_ID = 'a11y-vlibras-script';\nconst SCRIPT_URL = 'https://vlibras.gov.br/app/vlibras-plugin.js';\nconst APP_URL = 'https://vlibras.gov.br/app';\nconst WRAPPER_ID = 'a11y-vlibras-wrapper';\n\ninterface VLibrasGlobal {\n Widget: new (appUrl: string) => unknown;\n}\n\n/**\n * Carrega e ativa o widget oficial de Libras do governo brasileiro\n * (gov.br/vlibras) sob demanda. Estratégia:\n *\n * - Quando `librasEnabled === true`:\n * 1. Injeta o esqueleto DOM esperado pelo VLibras (`<div vw>` etc.)\n * no `<body>` (precisa estar no body, não dentro do React tree).\n * 2. Carrega o script oficial uma única vez (cacheado por id).\n * 3. Instancia `new window.VLibras.Widget(...)` para inicializar o\n * avatar e os assets 3D.\n *\n * - Quando `librasEnabled === false`:\n * - Apenas OCULTA o esqueleto DOM (não remove). O plugin do VLibras\n * registra um listener de `resize` no `window` que ele nunca desanexa;\n * se removêssemos o wrapper, esse listener rodaria `d(\"[vp]\").closest(...)`\n * sobre um `null` (nós já removidos) e lançaria\n * `Cannot read properties of null (reading 'closest')` no próximo resize\n * (rotação de tela / teclado virtual no mobile). Mantendo o esqueleto\n * oculto no DOM, `[vp]`/`[vw]` continuam existindo e o handler órfão não\n * quebra. O script permanece em cache para reativações rápidas.\n *\n * O script é pesado (~MBs de avatares 3D), por isso só carregamos quando\n * o usuário clica para ativar — fluxo opt-in.\n */\nexport default function VLibrasLoader() {\n const enabled = useAccessibilityStore((s) => s.librasEnabled);\n\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n if (!enabled) {\n hideWrapper();\n return;\n }\n\n injectWrapper();\n loadScript()\n .then(() => {\n const VLibras = (globalThis as unknown as { VLibras?: VLibrasGlobal })\n .VLibras;\n if (!VLibras?.Widget) return;\n\n // ATENÇÃO: o construtor do VLibras Widget registra a lógica de\n // inicialização DENTRO de `window.onload = () => {...}`. Como\n // nesta integração o widget é ativado depois da página já ter\n // carregado, o evento `load` já disparou e o handler nunca\n // executa sozinho. Capturamos o handler que o construtor\n // instalou e chamamos manualmente para popular o DOM (avatar,\n // botão de acesso, painel) imediatamente.\n const previousOnload = globalThis.onload;\n // A instanciação importa pelos efeitos colaterais: o construtor\n // do VLibras registra `window.onload` com a lógica de inicialização\n // do widget. O retorno não é usado e é descartado de propósito.\n new VLibras.Widget(APP_URL); // NOSONAR — instantiation by side effect\n const installed = globalThis.onload;\n if (typeof installed === 'function' && installed !== previousOnload) {\n // `onload` espera tipo Window — usamos `as` porque o construtor\n // do VLibras só lê `event.target` (que ignoramos) e não toca em\n // propriedades específicas do Window.\n (installed as (this: Window, ev: Event) => unknown).call(\n globalThis as unknown as Window,\n new Event('load')\n );\n }\n\n // Após popular o DOM, abre direto o painel do VLibras — caso\n // contrário o usuário precisaria clicar duas vezes (nosso FAB\n // + botão de acesso do VLibras). Aguarda um frame para garantir\n // que o handler de click do botão já foi anexado pelo plugin.\n requestAnimationFrame(() => {\n const accessButton =\n document.querySelector<HTMLElement>('[vw-access-button]');\n accessButton?.click();\n });\n })\n .catch(() => {\n // Falha de rede ou bloqueio: desabilita silenciosamente o estado\n // para o usuário não ficar preso achando que vai funcionar.\n useAccessibilityStore.getState().setLibrasEnabled(false);\n });\n\n return () => {\n // Não removemos o wrapper aqui: a remoção real fica no ramo\n // `!enabled` acima. Manter aqui causaria flicker em re-renders.\n };\n }, [enabled]);\n\n return null;\n}\n\nconst injectWrapper = () => {\n const existing = document.getElementById(WRAPPER_ID);\n if (existing) {\n // Wrapper já foi criado numa ativação anterior e apenas ocultado ao\n // desativar. Basta reexibi-lo em vez de recriar (o que reinjetaria os\n // nós e recriaria o listener órfão do plugin).\n existing.style.removeProperty('display');\n return;\n }\n\n const wrapper = document.createElement('div');\n wrapper.id = WRAPPER_ID;\n wrapper.setAttribute('vw', '');\n wrapper.className = 'enabled';\n\n const accessButton = document.createElement('div');\n accessButton.setAttribute('vw-access-button', '');\n accessButton.className = 'active';\n wrapper.appendChild(accessButton);\n\n const pluginWrapper = document.createElement('div');\n pluginWrapper.setAttribute('vw-plugin-wrapper', '');\n const top = document.createElement('div');\n top.className = 'vw-plugin-top-wrapper';\n pluginWrapper.appendChild(top);\n wrapper.appendChild(pluginWrapper);\n\n document.body.appendChild(wrapper);\n};\n\nconst hideWrapper = () => {\n const wrapper = document.getElementById(WRAPPER_ID);\n if (wrapper) {\n // Oculta sem remover: preserva os nós [vp]/[vw] que o listener de resize\n // órfão do plugin do VLibras consulta via `.closest()`.\n wrapper.style.display = 'none';\n }\n};\n\nconst loadScript = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (document.getElementById(SCRIPT_ID)) {\n resolve();\n return;\n }\n\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = SCRIPT_URL;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () =>\n reject(new Error('Falha ao carregar o script do VLibras'));\n document.head.appendChild(script);\n });\n};\n\nexport const __testing = {\n SCRIPT_ID,\n SCRIPT_URL,\n WRAPPER_ID,\n injectWrapper,\n hideWrapper,\n};\n"],"mappings":"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","names":["useEffect","useRef","jsx","jsx","jsxs","PreviewSegmented","jsx","jsxs","jsx","useState","Fragment","jsx","jsxs","useState","jsx","jsxs","useEffect","useEffect","useEffect","useEffect","Fragment","jsx","jsxs","useRef","useEffect"]}
|