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
package/dist/chunk-2EDRPEYL.mjs
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useModalFocus
|
|
3
|
-
} from "./chunk-M2FN7CNS.mjs";
|
|
4
|
-
import {
|
|
5
|
-
Button_default
|
|
6
|
-
} from "./chunk-ZQZBOTZJ.mjs";
|
|
7
|
-
import {
|
|
8
|
-
cn
|
|
9
|
-
} from "./chunk-53ICLDGS.mjs";
|
|
10
|
-
|
|
11
|
-
// src/components/AlertDialog/AlertDialog.tsx
|
|
12
|
-
import {
|
|
13
|
-
forwardRef,
|
|
14
|
-
useEffect,
|
|
15
|
-
useId,
|
|
16
|
-
useRef
|
|
17
|
-
} from "react";
|
|
18
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
-
var SIZE_CLASSES = {
|
|
20
|
-
"extra-small": "w-screen max-w-[324px]",
|
|
21
|
-
small: "w-screen max-w-[378px]",
|
|
22
|
-
medium: "w-screen max-w-[459px]",
|
|
23
|
-
large: "w-screen max-w-[578px]",
|
|
24
|
-
"extra-large": "w-screen max-w-[912px]"
|
|
25
|
-
};
|
|
26
|
-
var AlertDialog = forwardRef(
|
|
27
|
-
({
|
|
28
|
-
description,
|
|
29
|
-
cancelButtonLabel = "Cancelar",
|
|
30
|
-
submitButtonLabel = "Deletar",
|
|
31
|
-
title,
|
|
32
|
-
isOpen,
|
|
33
|
-
closeOnBackdropClick = true,
|
|
34
|
-
closeOnEscape = true,
|
|
35
|
-
className = "",
|
|
36
|
-
onSubmit,
|
|
37
|
-
onChangeOpen,
|
|
38
|
-
submitValue,
|
|
39
|
-
onCancel,
|
|
40
|
-
cancelValue,
|
|
41
|
-
size = "medium",
|
|
42
|
-
submitAction = "negative",
|
|
43
|
-
...props
|
|
44
|
-
}, ref) => {
|
|
45
|
-
const dialogRef = useRef(null);
|
|
46
|
-
const titleId = useId();
|
|
47
|
-
const descriptionId = useId();
|
|
48
|
-
useModalFocus(isOpen, dialogRef);
|
|
49
|
-
const setDialogRef = (node) => {
|
|
50
|
-
dialogRef.current = node;
|
|
51
|
-
if (typeof ref === "function") {
|
|
52
|
-
ref(node);
|
|
53
|
-
} else if (ref) {
|
|
54
|
-
ref.current = node;
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
if (!isOpen || !closeOnEscape) return;
|
|
59
|
-
const handleEscape = (event) => {
|
|
60
|
-
if (event.key === "Escape") {
|
|
61
|
-
onChangeOpen(false);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
document.addEventListener("keydown", handleEscape);
|
|
65
|
-
return () => document.removeEventListener("keydown", handleEscape);
|
|
66
|
-
}, [isOpen, closeOnEscape]);
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
if (isOpen) {
|
|
69
|
-
document.body.style.overflow = "hidden";
|
|
70
|
-
} else {
|
|
71
|
-
document.body.style.overflow = "unset";
|
|
72
|
-
}
|
|
73
|
-
return () => {
|
|
74
|
-
document.body.style.overflow = "unset";
|
|
75
|
-
};
|
|
76
|
-
}, [isOpen]);
|
|
77
|
-
const handleBackdropClick = (event) => {
|
|
78
|
-
if (event.target === event.currentTarget && closeOnBackdropClick) {
|
|
79
|
-
onChangeOpen(false);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
const handleBackdropKeyDown = (event) => {
|
|
83
|
-
if (event.key === "Escape" && closeOnEscape) {
|
|
84
|
-
onChangeOpen(false);
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
const handleSubmit = () => {
|
|
88
|
-
onChangeOpen(false);
|
|
89
|
-
onSubmit?.(submitValue);
|
|
90
|
-
};
|
|
91
|
-
const handleCancel = () => {
|
|
92
|
-
onChangeOpen(false);
|
|
93
|
-
onCancel?.(cancelValue);
|
|
94
|
-
};
|
|
95
|
-
const sizeClasses = SIZE_CLASSES[size];
|
|
96
|
-
return /* @__PURE__ */ jsx(Fragment, { children: isOpen && /* @__PURE__ */ jsx(
|
|
97
|
-
"div",
|
|
98
|
-
{
|
|
99
|
-
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm",
|
|
100
|
-
onClick: handleBackdropClick,
|
|
101
|
-
onKeyDown: handleBackdropKeyDown,
|
|
102
|
-
"data-testid": "alert-dialog-overlay",
|
|
103
|
-
children: /* @__PURE__ */ jsxs(
|
|
104
|
-
"dialog",
|
|
105
|
-
{
|
|
106
|
-
ref: setDialogRef,
|
|
107
|
-
open: true,
|
|
108
|
-
"aria-modal": "true",
|
|
109
|
-
"aria-labelledby": titleId,
|
|
110
|
-
"aria-describedby": descriptionId,
|
|
111
|
-
tabIndex: -1,
|
|
112
|
-
className: cn(
|
|
113
|
-
// `static` anula o `position: absolute` que o navegador aplica
|
|
114
|
-
// a `<dialog>`; sem isso ele escapa da centralização do
|
|
115
|
-
// backdrop. As demais regras do UA (padding, borda, fundo) já
|
|
116
|
-
// são sobrescritas pelas classes abaixo.
|
|
117
|
-
"static bg-background border border-border-100 rounded-lg shadow-lg p-6 m-3",
|
|
118
|
-
sizeClasses,
|
|
119
|
-
className
|
|
120
|
-
),
|
|
121
|
-
...props,
|
|
122
|
-
children: [
|
|
123
|
-
/* @__PURE__ */ jsx(
|
|
124
|
-
"h2",
|
|
125
|
-
{
|
|
126
|
-
id: titleId,
|
|
127
|
-
className: "pb-3 text-xl font-semibold text-text-950",
|
|
128
|
-
children: title
|
|
129
|
-
}
|
|
130
|
-
),
|
|
131
|
-
/* @__PURE__ */ jsx("p", { id: descriptionId, className: "text-text-700 text-sm", children: description }),
|
|
132
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center justify-end pt-4 gap-3", children: [
|
|
133
|
-
/* @__PURE__ */ jsx(Button_default, { variant: "outline", size: "small", onClick: handleCancel, children: cancelButtonLabel }),
|
|
134
|
-
/* @__PURE__ */ jsx(
|
|
135
|
-
Button_default,
|
|
136
|
-
{
|
|
137
|
-
variant: "solid",
|
|
138
|
-
size: "small",
|
|
139
|
-
action: submitAction,
|
|
140
|
-
onClick: handleSubmit,
|
|
141
|
-
children: submitButtonLabel
|
|
142
|
-
}
|
|
143
|
-
)
|
|
144
|
-
] })
|
|
145
|
-
]
|
|
146
|
-
}
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
) });
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
AlertDialog.displayName = "AlertDialog";
|
|
153
|
-
|
|
154
|
-
export {
|
|
155
|
-
AlertDialog
|
|
156
|
-
};
|
|
157
|
-
//# sourceMappingURL=chunk-2EDRPEYL.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/AlertDialog/AlertDialog.tsx"],"sourcesContent":["import {\n forwardRef,\n HTMLAttributes,\n useEffect,\n useId,\n useRef,\n MouseEvent,\n KeyboardEvent,\n} from 'react';\nimport Button from '../Button/Button';\nimport { useModalFocus } from '../../hooks/useModalFocus';\nimport { cn } from '../../utils/utils';\n\n/**\n * Lookup table for size classes\n */\nconst SIZE_CLASSES = {\n 'extra-small': 'w-screen max-w-[324px]',\n small: 'w-screen max-w-[378px]',\n medium: 'w-screen max-w-[459px]',\n large: 'w-screen max-w-[578px]',\n 'extra-large': 'w-screen max-w-[912px]',\n} as const;\n\ninterface AlertDialogProps extends HTMLAttributes<HTMLDialogElement> {\n /** Title of the alert dialog */\n title: string;\n /** Whether the alert dialog is open (controlled mode) */\n isOpen: boolean;\n /** Function called when the alert dialog is opened or closed (controlled mode) */\n onChangeOpen: (open: boolean) => void;\n /** Whether clicking the backdrop should close the alert dialog */\n closeOnBackdropClick?: boolean;\n /** Whether pressing Escape should close the alert dialog */\n closeOnEscape?: boolean;\n /** Additional CSS classes for the alert dialog content */\n className?: string;\n /** Function called when submit button is clicked */\n onSubmit?: (value?: unknown) => void;\n /** Value to pass to onSubmit function */\n submitValue?: unknown;\n /** Function called when cancel button is clicked */\n onCancel?: (value?: unknown) => void;\n /** Value to pass to onCancel function */\n cancelValue?: unknown;\n /** Description of the alert dialog */\n description: string;\n /** Label of the cancel button */\n cancelButtonLabel?: string;\n /** Label of the submit button */\n submitButtonLabel?: string;\n /** Size of the alert dialog */\n size?: 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';\n /** Action type for the submit button (controls color/style). Defaults to 'negative' (destructive) */\n submitAction?: 'primary' | 'secondary' | 'positive' | 'negative';\n}\n\nconst AlertDialog = forwardRef<HTMLDialogElement, AlertDialogProps>(\n (\n {\n description,\n cancelButtonLabel = 'Cancelar',\n submitButtonLabel = 'Deletar',\n title,\n isOpen,\n closeOnBackdropClick = true,\n closeOnEscape = true,\n className = '',\n onSubmit,\n onChangeOpen,\n submitValue,\n onCancel,\n cancelValue,\n size = 'medium',\n submitAction = 'negative',\n ...props\n },\n ref\n ) => {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n /**\n * Ids por instância. Fixos, dois diálogos abertos ao mesmo tempo — ou um\n * diálogo convivendo com qualquer outro elemento da página que use o mesmo\n * id — fariam o `aria-labelledby` apontar para o nó errado, e o leitor de\n * tela anunciaria o título do outro.\n */\n const titleId = useId();\n const descriptionId = useId();\n\n /**\n * Leva o foco pro diálogo ao abrir, prende o Tab lá dentro e devolve o foco\n * a quem o abriu ao fechar. Sem isto o foco ficava no botão que está ATRÁS\n * do backdrop: o leitor de tela seguia lendo a página de trás, sem nunca\n * anunciar que um diálogo abriu, e o Tab passeava pelo conteúdo bloqueado.\n *\n * É o mesmo hook que o `Modal` usa — o `AlertDialog` é que tinha ficado de\n * fora quando o foco foi resolvido lá.\n */\n useModalFocus(isOpen, dialogRef);\n\n /**\n * O nó é preciso aqui (para o foco) e também no `ref` do consumidor, que\n * segue sendo encaminhado como antes.\n */\n const setDialogRef = (node: HTMLDialogElement | null) => {\n dialogRef.current = node;\n\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n (ref as { current: HTMLDialogElement | null }).current = node;\n }\n };\n\n // Handle escape key\n useEffect(() => {\n if (!isOpen || !closeOnEscape) return;\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n onChangeOpen(false);\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, closeOnEscape]);\n\n // Prevent body scroll when modal is open\n useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = 'unset';\n }\n\n return () => {\n document.body.style.overflow = 'unset';\n };\n }, [isOpen]);\n\n const handleBackdropClick = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget && closeOnBackdropClick) {\n onChangeOpen(false);\n }\n };\n\n const handleBackdropKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape' && closeOnEscape) {\n onChangeOpen(false);\n }\n };\n\n const handleSubmit = () => {\n onChangeOpen(false);\n onSubmit?.(submitValue);\n };\n\n const handleCancel = () => {\n onChangeOpen(false);\n onCancel?.(cancelValue);\n };\n\n const sizeClasses = SIZE_CLASSES[size];\n\n return (\n <>\n {/* Alert Dialog Overlay */}\n {isOpen && (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm\"\n onClick={handleBackdropClick}\n onKeyDown={handleBackdropKeyDown}\n data-testid=\"alert-dialog-overlay\"\n >\n {/* Alert Dialog Content */}\n <dialog\n ref={setDialogRef}\n // `<dialog>` em vez de `role=\"dialog\"`: o papel vem do elemento,\n // que é o que garante o tratamento correto em qualquer\n // navegador/leitor. Mesmo padrão do `Modal`.\n //\n // `open` (e não `showModal()`) porque o backdrop é nosso; em\n // troca, o navegador não gerencia foco — quem faz isso é o\n // `useModalFocus` acima, e é dele o requisito do `tabIndex={-1}`:\n // o foco inicial vai pro próprio diálogo, não pro primeiro botão,\n // para o leitor anunciar título e descrição antes das ações.\n open\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={descriptionId}\n tabIndex={-1}\n className={cn(\n // `static` anula o `position: absolute` que o navegador aplica\n // a `<dialog>`; sem isso ele escapa da centralização do\n // backdrop. As demais regras do UA (padding, borda, fundo) já\n // são sobrescritas pelas classes abaixo.\n 'static bg-background border border-border-100 rounded-lg shadow-lg p-6 m-3',\n sizeClasses,\n className\n )}\n {...props}\n >\n <h2\n id={titleId}\n className=\"pb-3 text-xl font-semibold text-text-950\"\n >\n {title}\n </h2>\n <p id={descriptionId} className=\"text-text-700 text-sm\">\n {description}\n </p>\n\n <div className=\"flex flex-row items-center justify-end pt-4 gap-3\">\n <Button variant=\"outline\" size=\"small\" onClick={handleCancel}>\n {cancelButtonLabel}\n </Button>\n\n <Button\n variant=\"solid\"\n size=\"small\"\n action={submitAction}\n onClick={handleSubmit}\n >\n {submitButtonLabel}\n </Button>\n </div>\n </dialog>\n </div>\n )}\n </>\n );\n }\n);\n\nAlertDialog.displayName = 'AlertDialog';\n\nexport { AlertDialog };\n"],"mappings":";;;;;;;;;;;AAAA;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AA+JD,mBAqCQ,KAUA,YA/CR;AAvJN,IAAM,eAAe;AAAA,EACnB,eAAe;AAAA,EACf,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,eAAe;AACjB;AAmCA,IAAM,cAAc;AAAA,EAClB,CACE;AAAA,IACE;AAAA,IACA,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB;AAAA,IACA;AAAA,IACA,uBAAuB;AAAA,IACvB,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,eAAe;AAAA,IACf,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,YAAY,OAA0B,IAAI;AAQhD,UAAM,UAAU,MAAM;AACtB,UAAM,gBAAgB,MAAM;AAW5B,kBAAc,QAAQ,SAAS;AAM/B,UAAM,eAAe,CAAC,SAAmC;AACvD,gBAAU,UAAU;AAEpB,UAAI,OAAO,QAAQ,YAAY;AAC7B,YAAI,IAAI;AAAA,MACV,WAAW,KAAK;AACd,QAAC,IAA8C,UAAU;AAAA,MAC3D;AAAA,IACF;AAGA,cAAU,MAAM;AACd,UAAI,CAAC,UAAU,CAAC,cAAe;AAE/B,YAAM,eAAe,CAAC,UAAoC;AACxD,YAAI,MAAM,QAAQ,UAAU;AAC1B,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF;AAEA,eAAS,iBAAiB,WAAW,YAAY;AACjD,aAAO,MAAM,SAAS,oBAAoB,WAAW,YAAY;AAAA,IACnE,GAAG,CAAC,QAAQ,aAAa,CAAC;AAG1B,cAAU,MAAM;AACd,UAAI,QAAQ;AACV,iBAAS,KAAK,MAAM,WAAW;AAAA,MACjC,OAAO;AACL,iBAAS,KAAK,MAAM,WAAW;AAAA,MACjC;AAEA,aAAO,MAAM;AACX,iBAAS,KAAK,MAAM,WAAW;AAAA,MACjC;AAAA,IACF,GAAG,CAAC,MAAM,CAAC;AAEX,UAAM,sBAAsB,CAAC,UAAsC;AACjE,UAAI,MAAM,WAAW,MAAM,iBAAiB,sBAAsB;AAChE,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,wBAAwB,CAAC,UAAyC;AACtE,UAAI,MAAM,QAAQ,YAAY,eAAe;AAC3C,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,eAAe,MAAM;AACzB,mBAAa,KAAK;AAClB,iBAAW,WAAW;AAAA,IACxB;AAEA,UAAM,eAAe,MAAM;AACzB,mBAAa,KAAK;AAClB,iBAAW,WAAW;AAAA,IACxB;AAEA,UAAM,cAAc,aAAa,IAAI;AAErC,WACE,gCAEG,oBACC;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS;AAAA,QACT,WAAW;AAAA,QACX,eAAY;AAAA,QAGZ;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YAUL,MAAI;AAAA,YACJ,cAAW;AAAA,YACX,mBAAiB;AAAA,YACjB,oBAAkB;AAAA,YAClB,UAAU;AAAA,YACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,cAKT;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YACC,GAAG;AAAA,YAEJ;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,IAAI;AAAA,kBACJ,WAAU;AAAA,kBAET;AAAA;AAAA,cACH;AAAA,cACA,oBAAC,OAAE,IAAI,eAAe,WAAU,yBAC7B,uBACH;AAAA,cAEA,qBAAC,SAAI,WAAU,qDACb;AAAA,oCAAC,kBAAO,SAAQ,WAAU,MAAK,SAAQ,SAAS,cAC7C,6BACH;AAAA,gBAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,QAAQ;AAAA,oBACR,SAAS;AAAA,oBAER;AAAA;AAAA,gBACH;AAAA,iBACF;AAAA;AAAA;AAAA,QACF;AAAA;AAAA,IACF,GAEJ;AAAA,EAEJ;AACF;AAEA,YAAY,cAAc;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-2VODGC76.js","../src/components/Quiz/Quiz.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-2VODGC76.js","sourcesContent":[null,"import { BookOpenIcon } from '@phosphor-icons/react/dist/csr/BookOpen';\nimport { CaretLeftIcon } from '@phosphor-icons/react/dist/csr/CaretLeft';\nimport { CaretRightIcon } from '@phosphor-icons/react/dist/csr/CaretRight';\nimport { SquaresFourIcon } from '@phosphor-icons/react/dist/csr/SquaresFour';\nimport { HeaderAlternative } from '../Alternative/Alternative';\nimport Button from '../Button/Button';\nimport IconButton from '../IconButton/IconButton';\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useRef,\n useState,\n ComponentType,\n} from 'react';\nimport {\n useQuizStore,\n QUESTION_TYPE,\n QUIZ_TYPE,\n AI_CORRECTION_STATUS,\n CORRECTION_SOURCE,\n} from './useQuizStore';\nimport CorrectionSourceTag from './CorrectionSourceTag';\nimport { resolveCorrectionText } from './correction.utils';\nimport { QuizVariant } from './Quiz.types';\nimport { AlertDialog } from '../AlertDialog/AlertDialog';\nimport Modal from '../Modal/Modal';\n\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport { cn } from '../../utils/utils';\nimport {\n QuizAlternative,\n QuizConnectDots,\n QuizDissertative,\n QuizFill,\n QuizImageQuestion,\n QuizMultipleChoice,\n QuizTrueOrFalse,\n} from './QuizContent';\nimport { CardStatus } from '../Card/Card';\nimport Text from '../Text/Text';\nimport HtmlMathRenderer from '../HtmlMathRenderer/HtmlMathRenderer';\nimport {\n formatExamInfo,\n getQuestionA11yIds,\n shouldShowExamInfo,\n} from './Quiz.utils';\nimport QuizTimer from '../QuizTimer/QuizTimer';\nimport { useMobile } from '../../hooks/useMobile';\n\n// Função para obter configuração do tipo de quiz\nexport const getQuizTypeConfig = (type: QUIZ_TYPE) => {\n // Configuração centralizada para cada tipo de quiz\n const QUIZ_TYPE_CONFIG = {\n [QUIZ_TYPE.SIMULADO]: {\n label: 'Simulado',\n article: 'o',\n preposition: 'do',\n },\n [QUIZ_TYPE.QUESTIONARIO]: {\n label: 'Questionário',\n article: 'o',\n preposition: 'do',\n },\n [QUIZ_TYPE.ATIVIDADE]: {\n label: 'Atividade',\n article: 'a',\n preposition: 'da',\n },\n [QUIZ_TYPE.AULA_RECOMENDADA]: {\n label: 'Aula recomendada',\n article: 'a',\n preposition: 'da',\n },\n } as const;\n\n const config = QUIZ_TYPE_CONFIG[type];\n return config || QUIZ_TYPE_CONFIG[QUIZ_TYPE.SIMULADO]; // fallback para simulado\n};\n\n// Função para obter o label do tipo\nexport const getTypeLabel = (type: QUIZ_TYPE) => {\n return getQuizTypeConfig(type).label;\n};\n\n// Função para obter o artigo (o/a)\nexport const getQuizArticle = (type: QUIZ_TYPE) => {\n return getQuizTypeConfig(type).article;\n};\n\n// Função para obter a preposição (do/da)\nexport const getQuizPreposition = (type: QUIZ_TYPE) => {\n return getQuizTypeConfig(type).preposition;\n};\n\n// Função para gerar título de conclusão\nexport const getCompletionTitle = (type: QUIZ_TYPE) => {\n const config = getQuizTypeConfig(type);\n return `Você concluiu ${config.article} ${config.label.toLowerCase()}!`;\n};\n\n// Função para gerar o rótulo do botão de retorno no modal de conclusão\nexport const getGoBackButtonLabel = (type: QUIZ_TYPE): string => {\n if (type === QUIZ_TYPE.SIMULADO) return 'Ir para simulados';\n if (type === QUIZ_TYPE.QUESTIONARIO) return 'Ir para aulas';\n if (type === QUIZ_TYPE.ATIVIDADE) return 'Ir para atividades';\n if (type === QUIZ_TYPE.AULA_RECOMENDADA) return 'Ir para aulas recomendadas';\n return 'Ir para simulados';\n};\n\n// Função para gerar texto de confirmação de saída\nexport const getExitConfirmationText = (type: QUIZ_TYPE) => {\n const config = getQuizTypeConfig(type);\n // QUESTIONARIO não tem rascunho: ao sair, as respostas são perdidas.\n // Demais tipos (SIMULADO, ATIVIDADE, AULA_RECOMENDADA e fallback) salvam o\n // progresso, então o aluno pode continuar depois de onde parou.\n if (type === QUIZ_TYPE.QUESTIONARIO) {\n return `Se você sair ${config.preposition} ${config.label.toLowerCase()} agora, todas as respostas serão perdidas.`;\n }\n return `Se você sair ${config.preposition} ${config.label.toLowerCase()} agora, poderá continuar de onde parou depois.`;\n};\n\n// Função para gerar texto de confirmação de finalização\nexport const getFinishConfirmationText = (type: QUIZ_TYPE) => {\n const config = getQuizTypeConfig(type);\n return `Tem certeza que deseja finalizar ${config.article} ${config.label.toLowerCase()}?`;\n};\n\nconst Quiz = forwardRef<\n HTMLDivElement,\n { children: ReactNode; className?: string; variant?: 'result' | 'default' }\n>(({ children, className, variant = QuizVariant.DEFAULT, ...props }, ref) => {\n const { setVariant } = useQuizStore();\n\n useEffect(() => {\n setVariant(variant as QuizVariant);\n }, [variant, setVariant]);\n\n return (\n <div ref={ref} className={cn('flex flex-col', className)} {...props}>\n {children}\n </div>\n );\n});\n\nconst QuizTitle = forwardRef<\n HTMLDivElement,\n { className?: string; onBack?: () => void; showTimer?: boolean }\n>(({ className, onBack, showTimer = false, ...props }, ref) => {\n const {\n quiz,\n currentQuestionIndex,\n getTotalQuestions,\n getQuizTitle,\n isStarted,\n } = useQuizStore();\n\n const [showExitConfirmation, setShowExitConfirmation] = useState(false);\n\n const totalQuestions = getTotalQuestions();\n const quizTitle = getQuizTitle();\n\n const handleBackClick = () => {\n if (isStarted) {\n setShowExitConfirmation(true);\n } else {\n actionOnBack();\n }\n };\n\n const handleConfirmExit = () => {\n setShowExitConfirmation(false);\n actionOnBack();\n };\n\n const actionOnBack = () => {\n if (onBack) {\n onBack();\n } else {\n globalThis.history.back();\n }\n };\n\n const handleCancelExit = () => {\n setShowExitConfirmation(false);\n };\n\n return (\n <>\n <div\n ref={ref}\n /*\n * Três colunas em vez de `justify-between`: as laterais são `1fr`\n * iguais, então o título fica centralizado na tela mesmo com o voltar\n * e o cronômetro tendo larguras diferentes. Com flex ele era empurrado\n * para a direita junto do cronômetro.\n */\n className={cn(\n 'grid grid-cols-[1fr_auto_1fr] items-center gap-2 relative p-2',\n className\n )}\n {...props}\n >\n <IconButton\n icon={<CaretLeftIcon size={24} />}\n size=\"md\"\n aria-label=\"Voltar\"\n onClick={handleBackClick}\n className=\"justify-self-start\"\n />\n <span className=\"flex flex-col gap-2 text-center\">\n <Text size=\"md\" weight=\"bold\" color=\"text-text-950\">\n {quizTitle}\n </Text>\n <Text size=\"xs\" color=\"text-text-600\">\n {totalQuestions > 0\n ? `${currentQuestionIndex + 1} de ${totalQuestions}`\n : '0 de 0'}\n </Text>\n </span>\n <div className=\"justify-self-end\">{showTimer && <QuizTimer />}</div>\n </div>\n\n <AlertDialog\n isOpen={showExitConfirmation}\n onChangeOpen={setShowExitConfirmation}\n title=\"Deseja sair?\"\n description={getExitConfirmationText(quiz?.type || QUIZ_TYPE.SIMULADO)}\n cancelButtonLabel=\"Voltar e revisar\"\n submitButtonLabel=\"Sair Mesmo Assim\"\n onSubmit={handleConfirmExit}\n onCancel={handleCancelExit}\n />\n </>\n );\n});\n\nconst QuizHeader = () => {\n const { getCurrentQuestion, getQuestionIndex, quiz, currentQuestionIndex } =\n useQuizStore();\n const currentQuestion = getCurrentQuestion();\n const titleRef = useRef<HTMLHeadingElement>(null);\n const previousIndexRef = useRef(currentQuestionIndex);\n\n // After \"Próxima\"/\"Anterior\" focus would stay on the footer button and the\n // new question would go unannounced. Moving it to the heading makes the\n // screen reader read it, and the next Tab lands on the answer controls.\n // The first render is skipped so opening the quiz does not steal focus.\n useEffect(() => {\n if (previousIndexRef.current === currentQuestionIndex) return;\n previousIndexRef.current = currentQuestionIndex;\n titleRef.current?.focus();\n }, [currentQuestionIndex]);\n let currentId =\n currentQuestion && 'questionId' in currentQuestion\n ? (currentQuestion.questionId as string)\n : currentQuestion?.id;\n const questionIndex = getQuestionIndex(currentId!);\n\n const questionNumber = currentQuestion\n ? `Questão ${questionIndex.toString().padStart(2, '0')}`\n : 'Questão';\n\n const showExamInfo = shouldShowExamInfo(quiz);\n const examInfo = showExamInfo\n ? formatExamInfo(currentQuestion?.examBoard, currentQuestion?.examYear)\n : '';\n\n const title = examInfo ? `${questionNumber} ${examInfo}` : questionNumber;\n\n const { titleId, statementId } = getQuestionA11yIds(currentQuestion?.id);\n\n return (\n <HeaderAlternative\n titleId={titleId}\n contentId={statementId}\n titleRef={titleRef}\n title={title}\n subTitle={currentQuestion?.knowledgeMatrix?.[0]?.topic?.name ?? ''}\n content={currentQuestion?.statement ?? ''}\n />\n );\n};\n\nconst QuizContent = ({ paddingBottom }: { paddingBottom?: string }) => {\n const { getCurrentQuestion } = useQuizStore();\n const { isMobile } = useMobile();\n const currentQuestion = getCurrentQuestion();\n\n // `QuizFooter` is `position: fixed`, so it sits on top of the content instead\n // of taking space in the flow — without room reserved here, the last\n // alternative ends up underneath it and unreadable. The bar is taller on a\n // phone, where its controls stack into two rows.\n const contentPaddingBottom = paddingBottom ?? (isMobile ? 'pb-32' : 'pb-24');\n const questionComponents: Record<\n string,\n ComponentType<QuizVariantInterface>\n > = {\n [QUESTION_TYPE.ALTERNATIVA]: QuizAlternative,\n [QUESTION_TYPE.MULTIPLA_ESCOLHA]: QuizMultipleChoice,\n [QUESTION_TYPE.DISSERTATIVA]: QuizDissertative,\n [QUESTION_TYPE.VERDADEIRO_FALSO]: QuizTrueOrFalse,\n [QUESTION_TYPE.RELACIONAR]: QuizConnectDots,\n [QUESTION_TYPE.PREENCHER_LACUNAS]: QuizFill,\n [QUESTION_TYPE.IMAGEM]: QuizImageQuestion,\n };\n\n const QuestionComponent = currentQuestion\n ? questionComponents[currentQuestion.questionType]\n : null;\n\n if (!QuestionComponent) {\n return (\n <Text size=\"md\" weight=\"medium\" className=\"text-text-950 text-md\">\n Tipo de questão não suportado\n </Text>\n );\n }\n\n // The teacher's comment is no longer echoed here: in the result variant it\n // lives behind the \"Ver comentário\" button in the footer, so it is not shown\n // twice on the same screen.\n return <QuestionComponent paddingBottom={contentPaddingBottom} />;\n};\n\ninterface QuizVariantInterface {\n paddingBottom?: string;\n}\n\nconst QuizQuestionList = ({\n filterType = 'all',\n onQuestionClick,\n}: {\n filterType?: string;\n onQuestionClick?: () => void;\n} = {}) => {\n const {\n getQuestionsGroupedBySubject,\n goToQuestion,\n getQuestionStatusFromUserAnswers,\n getQuestionIndex,\n quiz,\n } = useQuizStore();\n\n const showExamInfo = shouldShowExamInfo(quiz);\n\n const groupedQuestions = getQuestionsGroupedBySubject();\n const getQuestionStatus = (questionId: string) => {\n return getQuestionStatusFromUserAnswers(questionId);\n };\n const filteredGroupedQuestions = Object.entries(groupedQuestions).reduce(\n (acc, [subjectId, questions]) => {\n const filteredQuestions = questions.filter((question) => {\n const status = getQuestionStatus(question.id);\n switch (filterType) {\n case 'answered':\n return status === 'answered';\n case 'unanswered':\n return status === 'unanswered' || status === 'skipped';\n default:\n return true;\n }\n });\n\n if (filteredQuestions.length > 0) {\n acc[subjectId] = filteredQuestions;\n }\n\n return acc;\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n {} as { [key: string]: any[] }\n );\n\n const getStatusLabel = (status: string) => {\n switch (status) {\n case 'answered':\n return 'Respondida';\n case 'skipped':\n return 'Em branco';\n default:\n return 'Em branco';\n }\n };\n return (\n <div className=\"space-y-6 px-4 h-full\">\n {Object.entries(filteredGroupedQuestions).length == 0 && (\n <div className=\"flex items-center justify-center text-gray-500 py-8 h-full\">\n <p className=\"text-lg\">Nenhum resultado</p>\n </div>\n )}\n {Object.entries(filteredGroupedQuestions).map(\n ([subjectId, questions]) => (\n <section key={subjectId} className=\"flex flex-col gap-2\">\n <span className=\"pt-6 pb-4 flex flex-row gap-2\">\n <div className=\"bg-primary-500 p-1 rounded-sm flex items-center justify-center\">\n <BookOpenIcon size={17} className=\"text-white\" />\n </div>\n <p className=\"text-text-800 font-bold text-lg\">\n {questions?.[0]?.knowledgeMatrix?.[0]?.subject?.name ??\n 'Sem componente curricular'}\n </p>\n </span>\n\n <ul className=\"flex flex-col gap-2\">\n {questions.map((question) => {\n const status = getQuestionStatus(question.id);\n const questionNumber = getQuestionIndex(question.id);\n const examInfo = showExamInfo\n ? formatExamInfo(question.examBoard, question.examYear)\n : '';\n const questionTitle = `Questão ${questionNumber.toString().padStart(2, '0')}`;\n const header = examInfo\n ? `${questionTitle} ${examInfo}`\n : questionTitle;\n return (\n <CardStatus\n key={question.id}\n header={header}\n label={getStatusLabel(status)}\n onClick={() => {\n goToQuestion(questionNumber - 1);\n onQuestionClick?.();\n }}\n />\n );\n })}\n </ul>\n </section>\n )\n )}\n </div>\n );\n};\n\n/**\n * Shared layout for the quiz result modals (generic result, all-correct and\n * all-incorrect questionnaire variants): a centered image, a title and a\n * footer with action buttons.\n */\nconst QuizResultModal = ({\n isOpen,\n onClose,\n image,\n showImagePlaceholder = true,\n title,\n description,\n footer,\n}: {\n isOpen: boolean;\n onClose: () => void;\n image?: ReactNode;\n showImagePlaceholder?: boolean;\n title: ReactNode;\n description: ReactNode;\n footer: ReactNode;\n}) => (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n title=\"\"\n closeOnEscape={false}\n hideCloseButton\n size={'md'}\n >\n <div className=\"flex flex-col w-full h-full items-center justify-center gap-4\">\n {image ? (\n <div className=\"w-[282px] h-auto\">{image}</div>\n ) : (\n showImagePlaceholder && (\n <div className=\"w-[282px] h-[200px] bg-gray-100 rounded-md flex items-center justify-center\">\n <Text as=\"span\" size=\"sm\" color=\"text-gray-500\">\n Imagem de resultado\n </Text>\n </div>\n )\n )}\n <div className=\"flex flex-col gap-2 text-center\">\n <Text as=\"h2\" size=\"lg\" weight=\"bold\">\n {title}\n </Text>\n {description}\n </div>\n {footer}\n </div>\n </Modal>\n);\n\n/**\n * Correction of the question currently on screen, resolved once.\n *\n * A dissertativa may have been graded by the AI. The teacher's text wins when it\n * exists, the AI's stands otherwise; the two are never merged — the backend\n * keeps them in separate columns precisely so a review does not destroy the\n * original verdict — and `correctionSource` says which one is on screen.\n *\n * It lives here, and not inline in `QuizFooter`, because both the footer (for\n * the modal body and title) and `QuizReviewActions` (for the buttons) need the\n * same four values, and deriving them twice would be two chances to disagree.\n *\n * @returns The effective comment plus the fields the tag and the title read\n */\nconst useCurrentCorrection = () => {\n const { getCurrentQuestion, getQuestionResultByQuestionId } = useQuizStore();\n\n const currentQuestion = getCurrentQuestion();\n const result = currentQuestion\n ? getQuestionResultByQuestionId(currentQuestion.id)\n : null;\n\n return {\n comment: resolveCorrectionText({ ...result }),\n correctionSource: result?.correctionSource,\n aiCorrectionStatus: result?.aiCorrectionStatus,\n };\n};\n\n/**\n * Title for the per-question feedback modal, phrased for whoever wrote it.\n *\n * Calling an AI correction \"Comentário do professor\" would be a lie the tag\n * inside the modal immediately contradicts, so both are derived from the same\n * `correctionSource`.\n *\n * @param correctionSource - Who produced the correction on display\n * @returns The modal title\n */\nconst getCorrectionModalTitle = (\n correctionSource?: CORRECTION_SOURCE | null\n): string => {\n if (correctionSource === CORRECTION_SOURCE.IA) {\n return 'Correção por IA';\n }\n\n if (correctionSource === CORRECTION_SOURCE.IA_PROFESSOR) {\n return 'Correção revisada pelo professor';\n }\n\n return 'Comentário do professor';\n};\n\n/**\n * The review bar's question-scoped actions: see the resolution, see the correction.\n *\n * Split out of `QuizFooter` because the two bars do different jobs — the\n * `default` one navigates between questions, this one reads a question already\n * graded — and because the four conditions the correction needs pushed the\n * footer past the cognitive-complexity limit while sitting in the middle of\n * unrelated navigation markup.\n *\n * @param props - Callbacks that open the footer's modals\n * @returns JSX element\n */\nconst QuizReviewActions = ({\n onOpenResolution,\n onOpenComment,\n className,\n}: {\n onOpenResolution: () => void;\n onOpenComment: () => void;\n readonly className?: string;\n}) => {\n const { getCurrentQuestion } = useQuizStore();\n const { comment, correctionSource, aiCorrectionStatus } =\n useCurrentCorrection();\n\n const currentQuestion = getCurrentQuestion();\n const hasResolution = Boolean(currentQuestion?.solutionExplanation);\n const isAiCorrecting = aiCorrectionStatus === AI_CORRECTION_STATUS.PENDING;\n const commentLabel =\n correctionSource === CORRECTION_SOURCE.IA\n ? 'Ver correção da IA'\n : 'Ver comentário';\n\n return (\n <div className={className}>\n {hasResolution && (\n <Button\n variant=\"solid\"\n action=\"primary\"\n size=\"large\"\n onClick={onOpenResolution}\n >\n Ver resolução\n </Button>\n )}\n {comment && (\n <Button\n variant=\"outline\"\n action=\"primary\"\n size=\"large\"\n onClick={onOpenComment}\n >\n {commentLabel}\n </Button>\n )}\n {/* Sem comentário ainda, mas a IA está corrigindo: o aluno acaba de\n entregar e chegou aqui antes do feedback existir. Dizer que está a\n caminho é melhor do que não mostrar nada. */}\n {!comment && isAiCorrecting && (\n <CorrectionSourceTag\n aiCorrectionStatus={aiCorrectionStatus}\n className=\"self-center\"\n />\n )}\n </div>\n );\n};\n\n/**\n * What the completion modal shows instead of the score.\n *\n * Some exams are not corrected on the spot — the in-classroom ENEM simulation\n * is graded later — so telling the student how many they got right would be\n * wrong. With this set, finishing opens a modal with only this content and\n * one button.\n */\nexport interface QuizCompletionOverride {\n title: ReactNode;\n description: ReactNode;\n buttonLabel: string;\n onConfirm: () => void;\n}\n\nconst QuizFooter = forwardRef<\n HTMLDivElement,\n {\n className?: string;\n onGoToSimulated?: () => void;\n onDetailResult?: () => void;\n handleFinishSimulated?: () => void;\n onGoToNextModule?: () => void;\n onRepeat?: () => void;\n onTryLater?: () => void;\n resultImageComponent?: ReactNode;\n resultIncorrectImageComponent?: ReactNode;\n /** Replaces the score modal; see `QuizCompletionOverride`. */\n completionOverride?: QuizCompletionOverride;\n }\n>(\n (\n {\n className,\n onGoToSimulated,\n onDetailResult,\n handleFinishSimulated,\n onGoToNextModule,\n onRepeat,\n onTryLater,\n resultImageComponent,\n resultIncorrectImageComponent,\n completionOverride,\n ...props\n },\n ref\n ) => {\n const {\n quiz,\n currentQuestionIndex,\n getTotalQuestions,\n goToNextQuestion,\n goToPreviousQuestion,\n getUnansweredQuestionsFromUserAnswers,\n getCurrentAnswer,\n skipQuestion,\n skipCurrentQuestionIfUnanswered,\n getCurrentQuestion,\n getQuestionStatusFromUserAnswers,\n variant,\n getQuestionResultStatistics,\n } = useQuizStore();\n\n // The review bar carries four controls. Below ~500px they no longer fit on\n // one line, so the actions and the pagination stack into two centred rows.\n const { isMobile } = useMobile();\n\n const totalQuestions = getTotalQuestions();\n const isFirstQuestion = currentQuestionIndex === 0;\n const isLastQuestion = currentQuestionIndex === totalQuestions - 1;\n const currentAnswer = getCurrentAnswer();\n const currentQuestion = getCurrentQuestion();\n const {\n comment: teacherComment,\n correctionSource,\n aiCorrectionStatus,\n } = useCurrentCorrection();\n const isCurrentQuestionSkipped = currentQuestion\n ? getQuestionStatusFromUserAnswers(currentQuestion.id) === 'skipped'\n : false;\n // Sistema unificado de controle de modais\n const [activeModal, setActiveModal] = useState<string | null>(null);\n const [filterType, setFilterType] = useState<string>('all');\n\n // Funções para controlar modais\n const openModal = (modalName: string) => setActiveModal(modalName);\n const closeModal = () => setActiveModal(null);\n const isModalOpen = (modalName: string) => activeModal === modalName;\n const unansweredQuestions = getUnansweredQuestionsFromUserAnswers();\n const allQuestions = getTotalQuestions();\n const stats = getQuestionResultStatistics();\n const correctAnswers = stats?.correctAnswers;\n const quizType = quiz?.type || QUIZ_TYPE.SIMULADO;\n const quizTypeLabel = getTypeLabel(quizType);\n // Real subtopic name, used to label the questionnaire completion modals.\n // The backend always populates the question knowledge matrix, so this is\n // available as soon as the quiz is loaded.\n const moduleName =\n quiz?.questions?.[0]?.knowledgeMatrix?.[0]?.subtopic?.name;\n\n // Submits the answers and opens the correct result modal. Statistics must\n // be read AFTER handleFinishSimulated, which is what populates\n // questionsResult in the store (the render-time values are still empty).\n const submitAndOpenResultModal = async () => {\n if (handleFinishSimulated) {\n await Promise.resolve(handleFinishSimulated());\n }\n\n if (completionOverride) {\n openModal('modalCompletionOverride');\n return;\n }\n\n const latestStats = getQuestionResultStatistics();\n const latestCorrect = latestStats?.correctAnswers;\n const latestTotal = latestStats?.totalAnswered;\n\n if (\n quizType === QUIZ_TYPE.QUESTIONARIO &&\n typeof latestCorrect === 'number' &&\n typeof latestTotal === 'number' &&\n latestCorrect === latestTotal\n ) {\n openModal('modalQuestionnaireAllCorrect');\n return;\n }\n\n if (\n quizType === QUIZ_TYPE.QUESTIONARIO &&\n typeof latestCorrect === 'number' &&\n latestCorrect === 0\n ) {\n openModal('modalQuestionnaireAllIncorrect');\n return;\n }\n\n openModal('modalResult');\n };\n\n const handleFinishQuiz = async () => {\n // Marca a questão atual como pulada se não foi respondida\n skipCurrentQuestionIfUnanswered();\n\n if (unansweredQuestions.length > 0) {\n openModal('alertDialog');\n return;\n }\n\n try {\n await submitAndOpenResultModal();\n } catch (err) {\n console.error('handleFinishSimulated failed:', err);\n }\n };\n\n const handleAlertSubmit = async () => {\n try {\n await submitAndOpenResultModal();\n } catch (err) {\n console.error('handleFinishSimulated failed:', err);\n closeModal();\n }\n };\n\n return (\n <>\n <footer\n ref={ref}\n className={cn(\n 'w-full px-2 bg-background lg:max-w-[1000px] not-lg:max-w-[calc(100vw-32px)] border-t border-border-50 fixed bottom-0 min-h-[80px] flex flex-row justify-between items-center',\n className\n )}\n {...props}\n >\n {variant === 'default' ? (\n <>\n <div className=\"flex flex-row items-center gap-1\">\n <IconButton\n icon={<SquaresFourIcon size={24} className=\"text-text-950\" />}\n size=\"md\"\n onClick={() => openModal('modalNavigate')}\n />\n\n {isFirstQuestion ? (\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={() => {\n skipQuestion();\n goToNextQuestion();\n }}\n >\n Pular\n </Button>\n ) : (\n <Button\n size=\"medium\"\n variant=\"link\"\n action=\"primary\"\n iconLeft={<CaretLeftIcon size={18} />}\n onClick={() => {\n goToPreviousQuestion();\n }}\n >\n Voltar\n </Button>\n )}\n </div>\n\n {!isFirstQuestion && !isLastQuestion && (\n <Button\n size=\"small\"\n variant=\"outline\"\n action=\"primary\"\n onClick={() => {\n skipQuestion();\n goToNextQuestion();\n }}\n >\n Pular\n </Button>\n )}\n\n {isLastQuestion ? (\n <Button\n size=\"medium\"\n variant=\"solid\"\n action=\"primary\"\n onClick={handleFinishQuiz}\n >\n Finalizar\n </Button>\n ) : (\n <Button\n size=\"medium\"\n variant=\"link\"\n action=\"primary\"\n iconRight={<CaretRightIcon size={18} />}\n disabled={!currentAnswer && !isCurrentQuestionSkipped}\n onClick={() => {\n goToNextQuestion();\n }}\n >\n Avançar\n </Button>\n )}\n </>\n ) : (\n <div\n className={cn(\n 'flex w-full items-center gap-2',\n isMobile ? 'flex-col py-2' : 'flex-row'\n )}\n >\n <QuizReviewActions\n className={cn(\n 'flex flex-row items-center gap-2',\n isMobile && 'justify-center'\n )}\n onOpenResolution={() => openModal('modalResolution')}\n onOpenComment={() => openModal('modalTeacherComment')}\n />\n {/* On a wide bar the pagination sits at the far end, away from the\n actions that act on the question being read; stacked, it is\n centred under them. */}\n <div\n className={cn(\n 'flex flex-row items-center gap-2',\n isMobile ? 'justify-center' : 'flex-1 justify-end'\n )}\n >\n <Button\n variant=\"outline\"\n action=\"primary\"\n size=\"medium\"\n aria-label=\"Questão anterior\"\n disabled={isFirstQuestion}\n onClick={goToPreviousQuestion}\n >\n <CaretLeftIcon size={18} />\n </Button>\n <Button\n variant=\"outline\"\n action=\"primary\"\n size=\"medium\"\n aria-label=\"Próxima questão\"\n disabled={isLastQuestion}\n onClick={goToNextQuestion}\n >\n <CaretRightIcon size={18} />\n </Button>\n </div>\n </div>\n )}\n </footer>\n\n <AlertDialog\n isOpen={isModalOpen('alertDialog')}\n onChangeOpen={(open) =>\n open ? openModal('alertDialog') : closeModal()\n }\n title={`Finalizar ${quizTypeLabel.toLowerCase()}?`}\n description={\n unansweredQuestions.length > 0\n ? `Você deixou as questões ${unansweredQuestions.join(', ')} sem resposta. Finalizar agora pode impactar seu desempenho.`\n : getFinishConfirmationText(quizType)\n }\n cancelButtonLabel=\"Voltar e revisar\"\n submitButtonLabel=\"Finalizar Mesmo Assim\"\n onSubmit={handleAlertSubmit}\n />\n\n <QuizResultModal\n isOpen={isModalOpen('modalResult')}\n onClose={closeModal}\n image={resultImageComponent}\n title={getCompletionTitle(quizType)}\n description={\n <Text as=\"p\" size=\"sm\" color=\"text-text-500\">\n Você acertou {correctAnswers ?? '--'} de {allQuestions} questões.\n </Text>\n }\n footer={\n <div className=\"px-6 flex flex-row items-center gap-2 w-full\">\n <Button\n variant=\"outline\"\n className=\"w-full\"\n size=\"small\"\n onClick={onGoToSimulated}\n >\n {getGoBackButtonLabel(quizType)}\n </Button>\n\n <Button className=\"w-full\" onClick={onDetailResult}>\n Detalhar resultado\n </Button>\n </div>\n }\n />\n\n {completionOverride && (\n <QuizResultModal\n isOpen={isModalOpen('modalCompletionOverride')}\n onClose={closeModal}\n image={resultImageComponent}\n title={completionOverride.title}\n description={\n <Text as=\"p\" size=\"sm\" color=\"text-text-500\">\n {completionOverride.description}\n </Text>\n }\n footer={\n <div className=\"px-6 flex flex-row items-center w-full\">\n <Button\n className=\"w-full\"\n onClick={completionOverride.onConfirm}\n data-testid=\"quiz-completion-override-confirm\"\n >\n {completionOverride.buttonLabel}\n </Button>\n </div>\n }\n />\n )}\n\n <Modal\n isOpen={isModalOpen('modalNavigate')}\n onClose={closeModal}\n title=\"Questões\"\n size={'lg'}\n >\n <div className=\"flex flex-col w-full not-lg:h-[calc(100vh-200px)] lg:max-h-[687px] lg:h-[687px]\">\n <div className=\"flex flex-row justify-between items-center py-6 pt-6 pb-4 border-b border-border-200 flex-shrink-0\">\n <p className=\"text-text-950 font-bold text-lg\">Filtrar por</p>\n <span className=\"max-w-[266px]\">\n <Select value={filterType} onValueChange={setFilterType}>\n <SelectTrigger\n variant=\"rounded\"\n className=\"max-w-[266px] min-w-[160px]\"\n >\n <SelectValue placeholder=\"Selecione uma opção\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">Todas</SelectItem>\n <SelectItem value=\"unanswered\">Em branco</SelectItem>\n <SelectItem value=\"answered\">Respondidas</SelectItem>\n </SelectContent>\n </Select>\n </span>\n </div>\n\n <div className=\"flex flex-col gap-2 flex-1 min-h-0 overflow-y-auto\">\n <QuizQuestionList\n filterType={filterType}\n onQuestionClick={closeModal}\n />\n </div>\n </div>\n </Modal>\n\n <Modal\n isOpen={isModalOpen('modalResolution')}\n onClose={closeModal}\n title=\"Resolução\"\n size={'lg'}\n >\n <HtmlMathRenderer\n content={currentQuestion?.solutionExplanation || ''}\n className=\"text-text-950 text-base\"\n />\n </Modal>\n\n <Modal\n isOpen={isModalOpen('modalTeacherComment')}\n onClose={closeModal}\n title={getCorrectionModalTitle(correctionSource)}\n size={'lg'}\n >\n {/* A tag fica dentro do modal, junto do texto: é ela que diz se o que\n está sendo lido saiu da IA, do professor, ou da IA revisada por\n ele. Sem isso o título sozinho teria que carregar essa informação\n em toda variação. */}\n <CorrectionSourceTag\n correctionSource={correctionSource}\n aiCorrectionStatus={aiCorrectionStatus}\n className=\"mb-3\"\n />\n {/* Plain text on purpose: the teacher writes this in a bare textarea,\n so running it through the HTML/LaTeX renderer would change what\n they typed. `whitespace-pre-wrap` keeps their line breaks. The AI\n feedback is plain text for the same reason. */}\n <Text\n size=\"md\"\n className=\"text-text-950 whitespace-pre-wrap break-words\"\n >\n {teacherComment}\n </Text>\n </Modal>\n\n <QuizResultModal\n isOpen={isModalOpen('modalQuestionnaireAllCorrect')}\n onClose={closeModal}\n image={resultImageComponent}\n title=\"🎉 Parabéns!\"\n description={\n <Text as=\"p\" size=\"sm\" color=\"text-text-500\">\n {moduleName\n ? `Você concluiu o módulo ${moduleName}.`\n : 'Você concluiu o questionário!'}\n </Text>\n }\n footer={\n <div className=\"px-6 flex flex-row items-center gap-2 w-full\">\n <Button className=\"w-full\" onClick={onGoToNextModule}>\n {getGoBackButtonLabel(quizType)}\n </Button>\n </div>\n }\n />\n\n <QuizResultModal\n isOpen={isModalOpen('modalQuestionnaireAllIncorrect')}\n onClose={closeModal}\n image={resultIncorrectImageComponent}\n showImagePlaceholder={false}\n title=\"😕 Não foi dessa vez...\"\n description={\n <>\n <Text as=\"p\" size=\"sm\" color=\"text-text-500\">\n Você tirou 0 no questionário, mas não se preocupe! Isso é apenas\n uma oportunidade de aprendizado.\n </Text>\n\n <Text as=\"p\" size=\"sm\" color=\"text-text-500\">\n Que tal tentar novamente para melhorar sua nota? Estamos aqui\n para te ajudar a entender o conteúdo e evoluir.\n </Text>\n\n {quiz?.canRetry && (\n <Text as=\"p\" size=\"sm\" color=\"text-text-500\">\n Clique em Repetir Questionário e mostre do que você é capaz!\n 💪\n </Text>\n )}\n </>\n }\n footer={\n <div className=\"flex flex-row justify-center items-center gap-2 w-full\">\n {quiz?.canRetry && (\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"small\"\n className=\"w-auto\"\n onClick={() => {\n closeModal();\n openModal('alertDialogTryLater');\n }}\n >\n Tentar depois\n </Button>\n )}\n\n <Button\n variant=\"outline\"\n size=\"small\"\n className=\"w-auto\"\n onClick={onDetailResult}\n >\n Detalhar resultado\n </Button>\n\n {quiz?.canRetry ? (\n <Button className=\"w-auto\" size=\"small\" onClick={onRepeat}>\n Repetir questionário\n </Button>\n ) : (\n <Button\n className=\"w-auto\"\n size=\"small\"\n onClick={onGoToSimulated}\n >\n {getGoBackButtonLabel(quizType)}\n </Button>\n )}\n </div>\n }\n />\n\n <AlertDialog\n isOpen={isModalOpen('alertDialogTryLater')}\n onChangeOpen={(open) =>\n open ? openModal('alertDialogTryLater') : closeModal()\n }\n title=\"Tentar depois?\"\n description={\n 'Você optou por refazer o questionário mais tarde.\\n\\nLembre-se: enquanto não refazer o questionário, sua nota permanecerá 0 no sistema.'\n }\n cancelButtonLabel=\"Repetir questionário\"\n submitButtonLabel=\"Tentar depois\"\n onSubmit={() => {\n onTryLater?.();\n closeModal();\n }}\n onCancel={() => {\n onRepeat?.();\n closeModal();\n }}\n />\n </>\n );\n }\n);\n\nexport {\n QuizTitle,\n Quiz,\n QuizHeader,\n QuizContent,\n QuizFooter,\n QuizQuestionList,\n};\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-3LN5GQAC.js","../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"],"names":["jsx","PreviewSegmented","jsxs","useState","Fragment","useEffect"],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-3LN5GQAC.js","sourcesContent":[null,"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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-BVUPM6EY.js","../src/components/IconButton/IconButton.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACA;ACJA,8BAA4D;AAyHpD,+CAAA;AAxDR,IAAM,WAAA,EAAa,+BAAA;AAAA,EACjB,CACE,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,UAAA,EAAY,EAAA,EAAI,QAAA,EAAU,GAAG,MAAM,CAAA,EACxE,GAAA,EAAA,GACG;AAEH,IAAA,MAAM,YAAA,EAAc;AAAA,MAClB,aAAA;AAAA,MACA,cAAA;AAAA,MACA,gBAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAA;AAAA,MACA,gBAAA;AAAA,MACA,eAAA;AAAA,MACA,gBAAA;AAAA,MACA,sBAAA;AAAA,MACA,iBAAA;AAAA,MACA,4BAAA;AAAA,MACA,sBAAA;AAAA,MACA,6BAAA;AAAA,MACA,mCAAA;AAAA,MACA,qBAAA;AAAA,MACA,6BAAA;AAAA,MACA;AAAA,IACF,CAAA;AAGA,IAAA,MAAM,YAAA,EAAc;AAAA,MAClB,EAAA,EAAI,CAAC,KAAA,EAAO,KAAA,EAAO,SAAS,CAAA;AAAA,MAC5B,EAAA,EAAI,CAAC,MAAA,EAAQ,MAAA,EAAQ,WAAW;AAAA,IAClC,CAAA;AAGA,IAAA,MAAM,cAAA,EAAgB,OAAA,EAClB,CAAC,gBAAA,EAAkB,mBAAA,EAAqB,uBAAuB,EAAA,EAC/D,CAAC,CAAA;AAEL,IAAA,MAAM,WAAA,EAAa;AAAA,MACjB,GAAG,WAAA;AAAA,MACH,GAAG,WAAA,CAAY,IAAI,CAAA;AAAA,MACnB,GAAG;AAAA,IACL,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAGV,IAAA,MAAM,UAAA,mBAAY,KAAA,CAAM,YAAY,CAAA,UAAK,0BAAA;AAEzC,IAAA,uBACE,6BAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA,EAAK,QAAA;AAAA,QACL,SAAA,EAAW,iCAAA,UAAG,EAAY,SAAS,CAAA;AAAA,QACnC,QAAA;AAAA,QACA,cAAA,EAAc,MAAA;AAAA,QACd,YAAA,EAAY,SAAA;AAAA,QACX,GAAG,KAAA;AAAA,QAEJ,QAAA,kBAAA,6BAAA,MAAC,EAAA,EAAK,SAAA,EAAU,kCAAA,EAAoC,QAAA,EAAA,KAAA,CAAK;AAAA,MAAA;AAAA,IAC3D,CAAA;AAAA,EAEJ;AACF,CAAA;AAEA,UAAA,CAAW,YAAA,EAAc,YAAA;AAEzB,IAAO,mBAAA,EAAQ,UAAA;ADzEf;AACA;AACE;AACF,gDAAC","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-BVUPM6EY.js","sourcesContent":[null,"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 (\n { icon, size = 'md', active = false, className = '', disabled, ...props },\n ref\n ) => {\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 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"]}
|
package/dist/chunk-CH6BWMSQ.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/hooks/useEscapeToClose.ts
|
|
2
|
-
var _react = require('react');
|
|
3
|
-
var useEscapeToClose = (enabled, onClose) => {
|
|
4
|
-
_react.useEffect.call(void 0, () => {
|
|
5
|
-
if (!enabled) return;
|
|
6
|
-
const handleEscape = (event) => {
|
|
7
|
-
if (event.key === "Escape" && !event.defaultPrevented) onClose();
|
|
8
|
-
};
|
|
9
|
-
document.addEventListener("keydown", handleEscape);
|
|
10
|
-
return () => document.removeEventListener("keydown", handleEscape);
|
|
11
|
-
}, [enabled, onClose]);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
exports.useEscapeToClose = useEscapeToClose;
|
|
17
|
-
//# sourceMappingURL=chunk-CH6BWMSQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-CH6BWMSQ.js","../src/hooks/useEscapeToClose.ts"],"names":[],"mappings":"AAAA;ACAA,8BAA0B;AAWnB,IAAM,iBAAA,EAAmB,CAAC,OAAA,EAAkB,OAAA,EAAA,GAAwB;AACzE,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,CAAC,OAAA,EAAS,MAAA;AAEd,IAAA,MAAM,aAAA,EAAe,CAAC,KAAA,EAAA,GAAoC;AAIxD,MAAA,GAAA,CAAI,KAAA,CAAM,IAAA,IAAQ,SAAA,GAAY,CAAC,KAAA,CAAM,gBAAA,EAAkB,OAAA,CAAQ,CAAA;AAAA,IACjE,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,YAAY,CAAA;AACjD,IAAA,OAAO,CAAA,EAAA,GAAM,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,YAAY,CAAA;AAAA,EACnE,CAAA,EAAG,CAAC,OAAA,EAAS,OAAO,CAAC,CAAA;AACvB,CAAA;ADbA;AACA;AACE;AACF,4CAAC","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-CH6BWMSQ.js","sourcesContent":[null,"import { useEffect } from 'react';\n\n/**\n * Fecha um overlay (modal/dialog) ao pressionar Escape enquanto ele está aberto.\n *\n * Compartilhado pelos modais da lib pra evitar duplicar o mesmo `keydown`\n * listener em cada componente.\n *\n * @param enabled - Liga o listener. Normalmente `isOpen && closeOnEscape`.\n * @param onClose - Chamado quando o Escape é pressionado.\n */\nexport const useEscapeToClose = (enabled: boolean, onClose: () => void) => {\n useEffect(() => {\n if (!enabled) return;\n\n const handleEscape = (event: globalThis.KeyboardEvent) => {\n // A popup inside the overlay (Select, DropdownMenu...) that already\n // handled this Escape marks it with preventDefault: only the popup\n // closes, the overlay stays open.\n if (event.key === 'Escape' && !event.defaultPrevented) onClose();\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [enabled, onClose]);\n};\n"]}
|