analytica-frontend-lib 1.7.21 → 1.7.23

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.
Files changed (384) hide show
  1. package/dist/AccessReportModal/index.js +3 -3
  2. package/dist/AccessReportModal/index.mjs +2 -2
  3. package/dist/ActivitiesHistory/index.js +49 -49
  4. package/dist/ActivitiesHistory/index.mjs +48 -48
  5. package/dist/ActivityCardQuestionBanks/index.js +49 -49
  6. package/dist/ActivityCardQuestionBanks/index.mjs +48 -48
  7. package/dist/ActivityCardQuestionPreview/index.js +49 -49
  8. package/dist/ActivityCardQuestionPreview/index.mjs +48 -48
  9. package/dist/ActivityCreate/ActivityCreateContent/index.js +49 -49
  10. package/dist/ActivityCreate/ActivityCreateContent/index.mjs +48 -48
  11. package/dist/ActivityCreate/index.js +49 -49
  12. package/dist/ActivityCreate/index.mjs +48 -48
  13. package/dist/ActivityDetails/index.js +49 -49
  14. package/dist/ActivityDetails/index.mjs +48 -48
  15. package/dist/ActivityFilters/index.js +49 -49
  16. package/dist/ActivityFilters/index.mjs +48 -48
  17. package/dist/ActivityPageLayout/index.js +49 -49
  18. package/dist/ActivityPageLayout/index.mjs +48 -48
  19. package/dist/ActivityPreview/index.js +49 -49
  20. package/dist/ActivityPreview/index.mjs +48 -48
  21. package/dist/AlertManager/index.js +49 -49
  22. package/dist/AlertManager/index.mjs +48 -48
  23. package/dist/AlertManagerView/index.js +3 -3
  24. package/dist/AlertManagerView/index.mjs +2 -2
  25. package/dist/AnnouncementModal/index.js +3 -3
  26. package/dist/AnnouncementModal/index.mjs +2 -2
  27. package/dist/AnnouncementsGate/index.js +4 -4
  28. package/dist/AnnouncementsGate/index.mjs +3 -3
  29. package/dist/AnswerKeyModal/index.js +3 -3
  30. package/dist/AnswerKeyModal/index.mjs +2 -2
  31. package/dist/AppHeader/index.js +6 -6
  32. package/dist/AppHeader/index.mjs +5 -5
  33. package/dist/CalendarCard/index.js +4 -4
  34. package/dist/CalendarCard/index.mjs +3 -3
  35. package/dist/Chat/index.js +3 -3
  36. package/dist/Chat/index.mjs +2 -2
  37. package/dist/CheckBox/index.d.ts.map +1 -1
  38. package/dist/CheckBox/index.js +2 -2
  39. package/dist/CheckBox/index.mjs +1 -1
  40. package/dist/CheckBoxGroup/index.js +49 -49
  41. package/dist/CheckBoxGroup/index.mjs +48 -48
  42. package/dist/ComparatorChart/ComparatorView/index.js +3 -3
  43. package/dist/ComparatorChart/ComparatorView/index.mjs +2 -2
  44. package/dist/CorrectActivityModal/index.js +7 -7
  45. package/dist/CorrectActivityModal/index.mjs +6 -6
  46. package/dist/DownloadButton/index.js +4 -4
  47. package/dist/DownloadButton/index.mjs +3 -3
  48. package/dist/DownloadModal/index.js +3 -3
  49. package/dist/DownloadModal/index.mjs +2 -2
  50. package/dist/DropdownMenu/index.js +3 -3
  51. package/dist/DropdownMenu/index.mjs +2 -2
  52. package/dist/EnemClassroomStartModal/index.d.ts.map +1 -1
  53. package/dist/EnemClassroomStartModal/index.js +7 -7
  54. package/dist/EnemClassroomStartModal/index.mjs +6 -6
  55. package/dist/EnemMoment/index.js +57 -57
  56. package/dist/EnemMoment/index.mjs +51 -51
  57. package/dist/EnemMomentStudentModal/index.js +50 -50
  58. package/dist/EnemMomentStudentModal/index.mjs +48 -48
  59. package/dist/ExamDetailsLayout/ExamDetailsPage/index.js +49 -49
  60. package/dist/ExamDetailsLayout/ExamDetailsPage/index.mjs +48 -48
  61. package/dist/ExamPageLayout/index.js +49 -49
  62. package/dist/ExamPageLayout/index.mjs +48 -48
  63. package/dist/Forum/index.js +5 -5
  64. package/dist/Forum/index.mjs +4 -4
  65. package/dist/KnowledgePerformanceCard/index.js +51 -51
  66. package/dist/KnowledgePerformanceCard/index.mjs +50 -50
  67. package/dist/LessonCardPreview/index.js +49 -49
  68. package/dist/LessonCardPreview/index.mjs +48 -48
  69. package/dist/LessonMediaSections/index.js +49 -49
  70. package/dist/LessonMediaSections/index.mjs +48 -48
  71. package/dist/LessonsCatalog/index.js +49 -49
  72. package/dist/LessonsCatalog/index.mjs +48 -48
  73. package/dist/Modal/index.d.ts.map +1 -1
  74. package/dist/Modal/index.js +2 -2
  75. package/dist/Modal/index.mjs +1 -1
  76. package/dist/MultiCheckSelect/index.js +5 -5
  77. package/dist/MultiCheckSelect/index.mjs +4 -4
  78. package/dist/MultiSearchSelect/index.js +3 -3
  79. package/dist/MultiSearchSelect/index.mjs +2 -2
  80. package/dist/MultipleChoice/index.js +3 -3
  81. package/dist/MultipleChoice/index.mjs +2 -2
  82. package/dist/NotificationCard/index.js +4 -4
  83. package/dist/NotificationCard/index.mjs +3 -3
  84. package/dist/PerformanceReportModal/index.js +3 -3
  85. package/dist/PerformanceReportModal/index.mjs +2 -2
  86. package/dist/PrintableUsersTable/index.js +49 -49
  87. package/dist/PrintableUsersTable/index.mjs +48 -48
  88. package/dist/ProgressModal/index.js +3 -3
  89. package/dist/ProgressModal/index.mjs +2 -2
  90. package/dist/QuestionsPerformanceCard/index.js +50 -50
  91. package/dist/QuestionsPerformanceCard/index.mjs +49 -49
  92. package/dist/Quiz/index.js +6 -6
  93. package/dist/Quiz/index.mjs +5 -5
  94. package/dist/RecommendedLessonCreate/index.js +49 -49
  95. package/dist/RecommendedLessonCreate/index.mjs +48 -48
  96. package/dist/RecommendedLessonDetails/index.js +7 -7
  97. package/dist/RecommendedLessonDetails/index.mjs +6 -6
  98. package/dist/RecommendedLessonsHistory/index.js +49 -49
  99. package/dist/RecommendedLessonsHistory/index.mjs +48 -48
  100. package/dist/ReportDetailModal/index.js +4 -4
  101. package/dist/ReportDetailModal/index.mjs +3 -3
  102. package/dist/RichEditor/index.js +5 -5
  103. package/dist/RichEditor/index.mjs +4 -4
  104. package/dist/{RichEditorCore-6MTYSSKS.mjs → RichEditorCore-2S5YUAOI.mjs} +5 -5
  105. package/dist/{RichEditorCore-KDARBEK4.js → RichEditorCore-N7A2445B.js} +16 -16
  106. package/dist/{RichEditorCore-KDARBEK4.js.map → RichEditorCore-N7A2445B.js.map} +1 -1
  107. package/dist/Search/index.js +4 -4
  108. package/dist/Search/index.mjs +3 -3
  109. package/dist/SendActivityModal/SendActivityModal.js +49 -49
  110. package/dist/SendActivityModal/SendActivityModal.mjs +48 -48
  111. package/dist/SendActivityModal/index.js +49 -49
  112. package/dist/SendActivityModal/index.mjs +48 -48
  113. package/dist/SendLessonModal/index.js +49 -49
  114. package/dist/SendLessonModal/index.mjs +48 -48
  115. package/dist/SimulatedPerformance/SimulatedPerformanceView/index.js +49 -49
  116. package/dist/SimulatedPerformance/SimulatedPerformanceView/index.mjs +48 -48
  117. package/dist/SimulatedPerformance/useSimulatedPerformance/index.js +5 -5
  118. package/dist/SimulatedPerformance/useSimulatedPerformance/index.mjs +4 -4
  119. package/dist/SimulatedStudentSimulationsModal/index.js +6 -6
  120. package/dist/SimulatedStudentSimulationsModal/index.mjs +5 -5
  121. package/dist/SimulationsPage/index.js +49 -49
  122. package/dist/SimulationsPage/index.mjs +48 -48
  123. package/dist/StudentLessonProgressModal/index.js +3 -3
  124. package/dist/StudentLessonProgressModal/index.mjs +2 -2
  125. package/dist/StudentPerformanceDetailsModal/index.js +5 -5
  126. package/dist/StudentPerformanceDetailsModal/index.mjs +4 -4
  127. package/dist/Support/TicketModal/index.js +3 -3
  128. package/dist/Support/TicketModal/index.mjs +2 -2
  129. package/dist/Support/index.js +4 -4
  130. package/dist/Support/index.mjs +3 -3
  131. package/dist/SupportChatComposer/index.js +3 -3
  132. package/dist/SupportChatComposer/index.mjs +2 -2
  133. package/dist/SupportChatEvent/index.js +3 -3
  134. package/dist/SupportChatEvent/index.mjs +2 -2
  135. package/dist/SupportChatMessage/index.js +3 -3
  136. package/dist/SupportChatMessage/index.mjs +2 -2
  137. package/dist/SupportChatWidget/index.js +3 -3
  138. package/dist/SupportChatWidget/index.mjs +2 -2
  139. package/dist/SupportConcludeModal/index.js +4 -4
  140. package/dist/SupportConcludeModal/index.mjs +3 -3
  141. package/dist/SupportConversationHeader/index.js +4 -4
  142. package/dist/SupportConversationHeader/index.mjs +3 -3
  143. package/dist/SupportConversationMessages/index.js +5 -5
  144. package/dist/SupportConversationMessages/index.mjs +4 -4
  145. package/dist/SupportTicketConversation/index.js +12 -12
  146. package/dist/SupportTicketConversation/index.mjs +11 -11
  147. package/dist/TableProvider/index.js +49 -49
  148. package/dist/TableProvider/index.mjs +48 -48
  149. package/dist/UnifiedDraftModelPage/index.js +49 -49
  150. package/dist/UnifiedDraftModelPage/index.mjs +48 -48
  151. package/dist/UnifiedHistoryPage/index.js +49 -49
  152. package/dist/UnifiedHistoryPage/index.mjs +48 -48
  153. package/dist/VideoPlayer/index.js +5 -5
  154. package/dist/VideoPlayer/index.mjs +4 -4
  155. package/dist/Whiteboard/index.js +3 -3
  156. package/dist/Whiteboard/index.mjs +2 -2
  157. package/dist/{chunk-B6QOBHZM.mjs → chunk-24BEZK43.mjs} +2 -2
  158. package/dist/{chunk-CYSODZGX.js → chunk-27Y6V3GM.js} +169 -66
  159. package/dist/chunk-27Y6V3GM.js.map +1 -0
  160. package/dist/{chunk-OQTXTDSK.mjs → chunk-2OJ3QSLU.mjs} +3 -3
  161. package/dist/{chunk-VDUO65VK.mjs → chunk-3EGJJDIM.mjs} +2 -2
  162. package/dist/{chunk-VDUO65VK.mjs.map → chunk-3EGJJDIM.mjs.map} +1 -1
  163. package/dist/{chunk-4OUBPEVS.mjs → chunk-3HKLGNUE.mjs} +3 -3
  164. package/dist/{chunk-YA7XLH7D.js → chunk-3MFACEZ2.js} +3 -3
  165. package/dist/{chunk-YA7XLH7D.js.map → chunk-3MFACEZ2.js.map} +1 -1
  166. package/dist/{chunk-IHBWJM4C.mjs → chunk-3Q7RJKUP.mjs} +2 -2
  167. package/dist/{chunk-PY6WD6SB.mjs → chunk-3WRB4WCD.mjs} +4 -4
  168. package/dist/{chunk-4RHCBMMP.js → chunk-46VHAL4S.js} +3 -3
  169. package/dist/{chunk-4RHCBMMP.js.map → chunk-46VHAL4S.js.map} +1 -1
  170. package/dist/{chunk-POT3ALY3.js → chunk-5DINXU6W.js} +1 -1
  171. package/dist/{chunk-POT3ALY3.js.map → chunk-5DINXU6W.js.map} +1 -1
  172. package/dist/{chunk-L52NFNFK.mjs → chunk-5VC4BK65.mjs} +3 -3
  173. package/dist/{chunk-B67RLIUM.js → chunk-72D7G6YQ.js} +3 -3
  174. package/dist/{chunk-B67RLIUM.js.map → chunk-72D7G6YQ.js.map} +1 -1
  175. package/dist/{chunk-C65DG2RI.mjs → chunk-7FSBWUOM.mjs} +2 -2
  176. package/dist/{chunk-QWMFWYII.js → chunk-7IZNLARX.js} +3 -3
  177. package/dist/{chunk-QWMFWYII.js.map → chunk-7IZNLARX.js.map} +1 -1
  178. package/dist/{chunk-ZCBT2BUZ.js → chunk-7RFHXFFV.js} +13 -13
  179. package/dist/{chunk-ZCBT2BUZ.js.map → chunk-7RFHXFFV.js.map} +1 -1
  180. package/dist/{chunk-EMWX6IKP.js → chunk-7VJP5D26.js} +13 -13
  181. package/dist/{chunk-EMWX6IKP.js.map → chunk-7VJP5D26.js.map} +1 -1
  182. package/dist/{chunk-HCQJR5CE.mjs → chunk-7ZWEBNFB.mjs} +2 -2
  183. package/dist/{chunk-3RHNJUXU.mjs → chunk-ACSEJOW6.mjs} +2 -2
  184. package/dist/{chunk-WQZHUW7C.mjs → chunk-ANFHLSDB.mjs} +3 -3
  185. package/dist/{chunk-H6NQOLQY.mjs → chunk-ANFLWCVD.mjs} +2 -2
  186. package/dist/{chunk-BKBDQXZX.js → chunk-AOYPUZRO.js} +3 -3
  187. package/dist/{chunk-BKBDQXZX.js.map → chunk-AOYPUZRO.js.map} +1 -1
  188. package/dist/{chunk-5WS6IENQ.mjs → chunk-AU2HLQDJ.mjs} +2 -2
  189. package/dist/{chunk-P6FX3NT6.mjs → chunk-AZGDHAP5.mjs} +2 -2
  190. package/dist/{chunk-NCGO7FPB.js → chunk-AZKNYREH.js} +8 -8
  191. package/dist/{chunk-NCGO7FPB.js.map → chunk-AZKNYREH.js.map} +1 -1
  192. package/dist/{chunk-R6MTPYYW.js → chunk-AZTBNERQ.js} +3 -3
  193. package/dist/{chunk-R6MTPYYW.js.map → chunk-AZTBNERQ.js.map} +1 -1
  194. package/dist/{chunk-NPB2JTYC.mjs → chunk-BO3QVQ37.mjs} +4 -4
  195. package/dist/{chunk-2WI4Q2I2.mjs → chunk-BPMWRFSI.mjs} +4 -4
  196. package/dist/{chunk-TEW33GLR.mjs → chunk-BXN3VO6I.mjs} +2 -2
  197. package/dist/{chunk-7ZB3YHF2.mjs → chunk-C6LC5LD5.mjs} +1 -1
  198. package/dist/{chunk-7ZB3YHF2.mjs.map → chunk-C6LC5LD5.mjs.map} +1 -1
  199. package/dist/{chunk-5HONWYQA.js → chunk-C7ILTLT5.js} +3 -3
  200. package/dist/{chunk-5HONWYQA.js.map → chunk-C7ILTLT5.js.map} +1 -1
  201. package/dist/{chunk-OES54VU6.mjs → chunk-CFV2OZ3P.mjs} +116 -13
  202. package/dist/chunk-CFV2OZ3P.mjs.map +1 -0
  203. package/dist/{chunk-4OVIHZ3I.js → chunk-CGXWWPEA.js} +6 -6
  204. package/dist/{chunk-4OVIHZ3I.js.map → chunk-CGXWWPEA.js.map} +1 -1
  205. package/dist/{chunk-MNU45FM3.js → chunk-COT4KW3H.js} +2 -2
  206. package/dist/{chunk-MNU45FM3.js.map → chunk-COT4KW3H.js.map} +1 -1
  207. package/dist/{chunk-JDQUXG75.js → chunk-CVDNCU6L.js} +3 -3
  208. package/dist/{chunk-JDQUXG75.js.map → chunk-CVDNCU6L.js.map} +1 -1
  209. package/dist/{chunk-HBZHWSMZ.mjs → chunk-D46PJSQ7.mjs} +13 -13
  210. package/dist/{chunk-ARYIJ4RU.js → chunk-DDORKDQO.js} +3 -3
  211. package/dist/{chunk-ARYIJ4RU.js.map → chunk-DDORKDQO.js.map} +1 -1
  212. package/dist/{chunk-7YQTDJFA.js → chunk-DKXSR2V3.js} +3 -3
  213. package/dist/{chunk-7YQTDJFA.js.map → chunk-DKXSR2V3.js.map} +1 -1
  214. package/dist/{chunk-I6EAPPBL.mjs → chunk-DZMYIOKZ.mjs} +5 -5
  215. package/dist/{chunk-SKM7NFPY.js → chunk-EPXAFJVW.js} +6 -6
  216. package/dist/{chunk-SKM7NFPY.js.map → chunk-EPXAFJVW.js.map} +1 -1
  217. package/dist/{chunk-AYYMS23L.js → chunk-ESIQ2GB4.js} +7 -7
  218. package/dist/{chunk-AYYMS23L.js.map → chunk-ESIQ2GB4.js.map} +1 -1
  219. package/dist/{chunk-NU2WNYOD.js → chunk-EW7HGUFV.js} +87 -87
  220. package/dist/{chunk-NU2WNYOD.js.map → chunk-EW7HGUFV.js.map} +1 -1
  221. package/dist/{chunk-I4QGQMXI.mjs → chunk-EXYXZFNK.mjs} +2 -2
  222. package/dist/{chunk-RBJAO57A.js → chunk-FAAR4XC5.js} +3 -3
  223. package/dist/{chunk-RBJAO57A.js.map → chunk-FAAR4XC5.js.map} +1 -1
  224. package/dist/{chunk-N2VNE3ON.js → chunk-FDTDJDZI.js} +13 -13
  225. package/dist/{chunk-N2VNE3ON.js.map → chunk-FDTDJDZI.js.map} +1 -1
  226. package/dist/{chunk-SU5Q64TW.mjs → chunk-FVCTKS33.mjs} +6 -5
  227. package/dist/chunk-FVCTKS33.mjs.map +1 -0
  228. package/dist/{chunk-AVHZHWI3.js → chunk-GBIFSFWJ.js} +15 -15
  229. package/dist/{chunk-AVHZHWI3.js.map → chunk-GBIFSFWJ.js.map} +1 -1
  230. package/dist/{chunk-KSUPPAKH.js → chunk-GIQSHTB5.js} +9 -9
  231. package/dist/{chunk-KSUPPAKH.js.map → chunk-GIQSHTB5.js.map} +1 -1
  232. package/dist/{chunk-4QBKD4JN.js → chunk-GUUJYGXF.js} +3 -3
  233. package/dist/{chunk-4QBKD4JN.js.map → chunk-GUUJYGXF.js.map} +1 -1
  234. package/dist/{chunk-M4O46VDY.mjs → chunk-GX2PKLN2.mjs} +2 -2
  235. package/dist/{chunk-5BUTINIM.mjs → chunk-HLVLSWKD.mjs} +3 -3
  236. package/dist/{chunk-FU23WOTY.js → chunk-HSV5VZ4Z.js} +6 -6
  237. package/dist/{chunk-FU23WOTY.js.map → chunk-HSV5VZ4Z.js.map} +1 -1
  238. package/dist/{chunk-MMS2ELDK.mjs → chunk-IIQCS3A2.mjs} +2 -2
  239. package/dist/{chunk-NKWLCZUZ.mjs → chunk-JGGUMHM6.mjs} +2 -2
  240. package/dist/{chunk-HT2GREFH.js → chunk-JLD46DL7.js} +11 -11
  241. package/dist/{chunk-HT2GREFH.js.map → chunk-JLD46DL7.js.map} +1 -1
  242. package/dist/{chunk-NVL5TKWD.mjs → chunk-JYFLOQYT.mjs} +2 -2
  243. package/dist/{chunk-DWGDEUEW.mjs → chunk-KG563P7F.mjs} +5 -5
  244. package/dist/{chunk-TCIC5556.mjs → chunk-KH4TEDGD.mjs} +2 -2
  245. package/dist/{chunk-23PAYKWB.js → chunk-KM27ZDHZ.js} +2 -2
  246. package/dist/{chunk-23PAYKWB.js.map → chunk-KM27ZDHZ.js.map} +1 -1
  247. package/dist/{chunk-XZUMD3CB.mjs → chunk-LODDYDTP.mjs} +2 -2
  248. package/dist/{chunk-XZUMD3CB.mjs.map → chunk-LODDYDTP.mjs.map} +1 -1
  249. package/dist/{chunk-E6CGJBID.mjs → chunk-LUHKMY56.mjs} +2 -2
  250. package/dist/{chunk-TVLEUNKE.mjs → chunk-LZP5VZCO.mjs} +2 -2
  251. package/dist/{chunk-EHNEBXS7.mjs → chunk-M6DXZ2FM.mjs} +2 -2
  252. package/dist/{chunk-B4C5DWAP.mjs → chunk-MMMJDO75.mjs} +2 -2
  253. package/dist/{chunk-AFCWMJQO.js → chunk-MOUPNP53.js} +3 -3
  254. package/dist/{chunk-AFCWMJQO.js.map → chunk-MOUPNP53.js.map} +1 -1
  255. package/dist/{chunk-36KFIZ43.js → chunk-MYPUZ6EG.js} +3 -3
  256. package/dist/{chunk-36KFIZ43.js.map → chunk-MYPUZ6EG.js.map} +1 -1
  257. package/dist/{chunk-6JHIKIPA.js → chunk-NUGLTWEA.js} +23 -23
  258. package/dist/{chunk-6JHIKIPA.js.map → chunk-NUGLTWEA.js.map} +1 -1
  259. package/dist/{chunk-KWXOYHYK.mjs → chunk-P7MORXSE.mjs} +2 -2
  260. package/dist/{chunk-YG4IZ5Q3.mjs → chunk-Q2OSEROT.mjs} +2 -2
  261. package/dist/{chunk-L5SXG6T6.mjs → chunk-QQKOHKO2.mjs} +3 -3
  262. package/dist/{chunk-SADSJ2MV.js → chunk-QVGUYPXO.js} +3 -3
  263. package/dist/{chunk-SADSJ2MV.js.map → chunk-QVGUYPXO.js.map} +1 -1
  264. package/dist/{chunk-K45PTE7F.mjs → chunk-RBKQXT73.mjs} +4 -4
  265. package/dist/{chunk-JZFISWTP.js → chunk-RIN2IN7E.js} +2 -2
  266. package/dist/{chunk-JZFISWTP.js.map → chunk-RIN2IN7E.js.map} +1 -1
  267. package/dist/{chunk-BXLAOYAG.mjs → chunk-RIUVPTG7.mjs} +2 -2
  268. package/dist/{chunk-QVB54LBS.mjs → chunk-RNZGX6MX.mjs} +3 -3
  269. package/dist/{chunk-VSVLIRO2.js → chunk-RXEU77VN.js} +15 -15
  270. package/dist/{chunk-VSVLIRO2.js.map → chunk-RXEU77VN.js.map} +1 -1
  271. package/dist/{chunk-ZRIYCU2V.js → chunk-S2BZPPAI.js} +5 -5
  272. package/dist/{chunk-ZRIYCU2V.js.map → chunk-S2BZPPAI.js.map} +1 -1
  273. package/dist/{chunk-MES2BP4T.mjs → chunk-SGL5IUCV.mjs} +2 -2
  274. package/dist/{chunk-7LS5UQCQ.mjs → chunk-STKUPDHG.mjs} +2 -2
  275. package/dist/{chunk-PPYCCT2K.js → chunk-SWDVSCQJ.js} +9 -8
  276. package/dist/chunk-SWDVSCQJ.js.map +1 -0
  277. package/dist/{chunk-JCA76TCX.mjs → chunk-SZKLJOTN.mjs} +2 -2
  278. package/dist/{chunk-F5WR6XZZ.js → chunk-T73HPYF2.js} +3 -3
  279. package/dist/{chunk-F5WR6XZZ.js.map → chunk-T73HPYF2.js.map} +1 -1
  280. package/dist/{chunk-ZB6HDDE4.js → chunk-TQO37PVW.js} +14 -14
  281. package/dist/{chunk-ZB6HDDE4.js.map → chunk-TQO37PVW.js.map} +1 -1
  282. package/dist/{chunk-VKQ5AJDT.mjs → chunk-UENZQF2Y.mjs} +2 -2
  283. package/dist/{chunk-DCG7EUBC.js → chunk-UWLW5YVB.js} +6 -6
  284. package/dist/{chunk-DCG7EUBC.js.map → chunk-UWLW5YVB.js.map} +1 -1
  285. package/dist/{chunk-37AJ2GVO.mjs → chunk-UXJIZDXQ.mjs} +2 -2
  286. package/dist/{chunk-PLLPFCN3.js → chunk-UXMDPRAI.js} +14 -14
  287. package/dist/{chunk-PLLPFCN3.js.map → chunk-UXMDPRAI.js.map} +1 -1
  288. package/dist/{chunk-7BOTKRY6.mjs → chunk-V55DG5B4.mjs} +2 -2
  289. package/dist/{chunk-YRTIDZTN.js → chunk-VHEDMUAW.js} +4 -4
  290. package/dist/{chunk-YRTIDZTN.js.map → chunk-VHEDMUAW.js.map} +1 -1
  291. package/dist/{chunk-4RD55E4R.js → chunk-VWLWSO4J.js} +3 -3
  292. package/dist/{chunk-4RD55E4R.js.map → chunk-VWLWSO4J.js.map} +1 -1
  293. package/dist/{chunk-VJQIKFMG.mjs → chunk-W3CWEZDB.mjs} +3 -3
  294. package/dist/{chunk-JM6SLU7D.js → chunk-W7NNH4VY.js} +6 -6
  295. package/dist/{chunk-JM6SLU7D.js.map → chunk-W7NNH4VY.js.map} +1 -1
  296. package/dist/{chunk-VQ7MSYIH.js → chunk-WUN5NHZE.js} +4 -4
  297. package/dist/{chunk-VQ7MSYIH.js.map → chunk-WUN5NHZE.js.map} +1 -1
  298. package/dist/{chunk-AAU7ABJN.js → chunk-WWTRSQ3X.js} +3 -3
  299. package/dist/{chunk-AAU7ABJN.js.map → chunk-WWTRSQ3X.js.map} +1 -1
  300. package/dist/{chunk-BR6D2TGF.js → chunk-WZOA2PVJ.js} +3 -3
  301. package/dist/{chunk-BR6D2TGF.js.map → chunk-WZOA2PVJ.js.map} +1 -1
  302. package/dist/{chunk-TZKR5Z4J.mjs → chunk-XJF2F36N.mjs} +2 -2
  303. package/dist/{chunk-P6ACVNQK.mjs → chunk-YD2XBEKO.mjs} +2 -2
  304. package/dist/{chunk-LMXWIPGR.js → chunk-YWPLHFAK.js} +3 -3
  305. package/dist/{chunk-LMXWIPGR.js.map → chunk-YWPLHFAK.js.map} +1 -1
  306. package/dist/{chunk-DCEWWHV5.mjs → chunk-Z3HGYPH7.mjs} +2 -2
  307. package/dist/{chunk-Q3PKW6TH.js → chunk-ZCV3HWI2.js} +6 -6
  308. package/dist/{chunk-Q3PKW6TH.js.map → chunk-ZCV3HWI2.js.map} +1 -1
  309. package/dist/{chunk-OSA3YVDZ.mjs → chunk-ZF46DCAC.mjs} +2 -2
  310. package/dist/{chunk-5T6IDXSB.js → chunk-ZO2GA23I.js} +3 -3
  311. package/dist/{chunk-5T6IDXSB.js.map → chunk-ZO2GA23I.js.map} +1 -1
  312. package/dist/{chunk-ZN3763VZ.js → chunk-ZQLW4EJB.js} +9 -9
  313. package/dist/{chunk-ZN3763VZ.js.map → chunk-ZQLW4EJB.js.map} +1 -1
  314. package/dist/{chunk-CM5R4SPF.js → chunk-ZQQJTO6T.js} +3 -3
  315. package/dist/{chunk-CM5R4SPF.js.map → chunk-ZQQJTO6T.js.map} +1 -1
  316. package/dist/{chunk-SEL4QDCO.js → chunk-ZSXSAE3D.js} +3 -3
  317. package/dist/{chunk-SEL4QDCO.js.map → chunk-ZSXSAE3D.js.map} +1 -1
  318. package/dist/components/SupportChatWidget/guestSupportChatAdapter.d.ts +6 -1
  319. package/dist/components/SupportChatWidget/guestSupportChatAdapter.d.ts.map +1 -1
  320. package/dist/hooks/useAppContent/index.js +49 -49
  321. package/dist/hooks/useAppContent/index.mjs +48 -48
  322. package/dist/hooks/useSupportChat.d.ts +2 -0
  323. package/dist/hooks/useSupportChat.d.ts.map +1 -1
  324. package/dist/index.js +49 -49
  325. package/dist/index.mjs +48 -48
  326. package/dist/types/supportChat/index.d.ts +14 -0
  327. package/dist/types/supportChat/index.d.ts.map +1 -1
  328. package/dist/types/supportChat/index.js +2 -2
  329. package/dist/types/supportChat/index.mjs +1 -1
  330. package/dist/types/supportChat.d.ts +14 -0
  331. package/dist/types/supportChat.d.ts.map +1 -1
  332. package/package.json +1 -1
  333. package/dist/chunk-CYSODZGX.js.map +0 -1
  334. package/dist/chunk-OES54VU6.mjs.map +0 -1
  335. package/dist/chunk-PPYCCT2K.js.map +0 -1
  336. package/dist/chunk-SU5Q64TW.mjs.map +0 -1
  337. /package/dist/{RichEditorCore-6MTYSSKS.mjs.map → RichEditorCore-2S5YUAOI.mjs.map} +0 -0
  338. /package/dist/{chunk-B6QOBHZM.mjs.map → chunk-24BEZK43.mjs.map} +0 -0
  339. /package/dist/{chunk-OQTXTDSK.mjs.map → chunk-2OJ3QSLU.mjs.map} +0 -0
  340. /package/dist/{chunk-4OUBPEVS.mjs.map → chunk-3HKLGNUE.mjs.map} +0 -0
  341. /package/dist/{chunk-IHBWJM4C.mjs.map → chunk-3Q7RJKUP.mjs.map} +0 -0
  342. /package/dist/{chunk-PY6WD6SB.mjs.map → chunk-3WRB4WCD.mjs.map} +0 -0
  343. /package/dist/{chunk-L52NFNFK.mjs.map → chunk-5VC4BK65.mjs.map} +0 -0
  344. /package/dist/{chunk-C65DG2RI.mjs.map → chunk-7FSBWUOM.mjs.map} +0 -0
  345. /package/dist/{chunk-HCQJR5CE.mjs.map → chunk-7ZWEBNFB.mjs.map} +0 -0
  346. /package/dist/{chunk-3RHNJUXU.mjs.map → chunk-ACSEJOW6.mjs.map} +0 -0
  347. /package/dist/{chunk-WQZHUW7C.mjs.map → chunk-ANFHLSDB.mjs.map} +0 -0
  348. /package/dist/{chunk-H6NQOLQY.mjs.map → chunk-ANFLWCVD.mjs.map} +0 -0
  349. /package/dist/{chunk-5WS6IENQ.mjs.map → chunk-AU2HLQDJ.mjs.map} +0 -0
  350. /package/dist/{chunk-P6FX3NT6.mjs.map → chunk-AZGDHAP5.mjs.map} +0 -0
  351. /package/dist/{chunk-NPB2JTYC.mjs.map → chunk-BO3QVQ37.mjs.map} +0 -0
  352. /package/dist/{chunk-2WI4Q2I2.mjs.map → chunk-BPMWRFSI.mjs.map} +0 -0
  353. /package/dist/{chunk-TEW33GLR.mjs.map → chunk-BXN3VO6I.mjs.map} +0 -0
  354. /package/dist/{chunk-HBZHWSMZ.mjs.map → chunk-D46PJSQ7.mjs.map} +0 -0
  355. /package/dist/{chunk-I6EAPPBL.mjs.map → chunk-DZMYIOKZ.mjs.map} +0 -0
  356. /package/dist/{chunk-I4QGQMXI.mjs.map → chunk-EXYXZFNK.mjs.map} +0 -0
  357. /package/dist/{chunk-M4O46VDY.mjs.map → chunk-GX2PKLN2.mjs.map} +0 -0
  358. /package/dist/{chunk-5BUTINIM.mjs.map → chunk-HLVLSWKD.mjs.map} +0 -0
  359. /package/dist/{chunk-MMS2ELDK.mjs.map → chunk-IIQCS3A2.mjs.map} +0 -0
  360. /package/dist/{chunk-NKWLCZUZ.mjs.map → chunk-JGGUMHM6.mjs.map} +0 -0
  361. /package/dist/{chunk-NVL5TKWD.mjs.map → chunk-JYFLOQYT.mjs.map} +0 -0
  362. /package/dist/{chunk-DWGDEUEW.mjs.map → chunk-KG563P7F.mjs.map} +0 -0
  363. /package/dist/{chunk-TCIC5556.mjs.map → chunk-KH4TEDGD.mjs.map} +0 -0
  364. /package/dist/{chunk-E6CGJBID.mjs.map → chunk-LUHKMY56.mjs.map} +0 -0
  365. /package/dist/{chunk-TVLEUNKE.mjs.map → chunk-LZP5VZCO.mjs.map} +0 -0
  366. /package/dist/{chunk-EHNEBXS7.mjs.map → chunk-M6DXZ2FM.mjs.map} +0 -0
  367. /package/dist/{chunk-B4C5DWAP.mjs.map → chunk-MMMJDO75.mjs.map} +0 -0
  368. /package/dist/{chunk-KWXOYHYK.mjs.map → chunk-P7MORXSE.mjs.map} +0 -0
  369. /package/dist/{chunk-YG4IZ5Q3.mjs.map → chunk-Q2OSEROT.mjs.map} +0 -0
  370. /package/dist/{chunk-L5SXG6T6.mjs.map → chunk-QQKOHKO2.mjs.map} +0 -0
  371. /package/dist/{chunk-K45PTE7F.mjs.map → chunk-RBKQXT73.mjs.map} +0 -0
  372. /package/dist/{chunk-BXLAOYAG.mjs.map → chunk-RIUVPTG7.mjs.map} +0 -0
  373. /package/dist/{chunk-QVB54LBS.mjs.map → chunk-RNZGX6MX.mjs.map} +0 -0
  374. /package/dist/{chunk-MES2BP4T.mjs.map → chunk-SGL5IUCV.mjs.map} +0 -0
  375. /package/dist/{chunk-7LS5UQCQ.mjs.map → chunk-STKUPDHG.mjs.map} +0 -0
  376. /package/dist/{chunk-JCA76TCX.mjs.map → chunk-SZKLJOTN.mjs.map} +0 -0
  377. /package/dist/{chunk-VKQ5AJDT.mjs.map → chunk-UENZQF2Y.mjs.map} +0 -0
  378. /package/dist/{chunk-37AJ2GVO.mjs.map → chunk-UXJIZDXQ.mjs.map} +0 -0
  379. /package/dist/{chunk-7BOTKRY6.mjs.map → chunk-V55DG5B4.mjs.map} +0 -0
  380. /package/dist/{chunk-VJQIKFMG.mjs.map → chunk-W3CWEZDB.mjs.map} +0 -0
  381. /package/dist/{chunk-TZKR5Z4J.mjs.map → chunk-XJF2F36N.mjs.map} +0 -0
  382. /package/dist/{chunk-P6ACVNQK.mjs.map → chunk-YD2XBEKO.mjs.map} +0 -0
  383. /package/dist/{chunk-DCEWWHV5.mjs.map → chunk-Z3HGYPH7.mjs.map} +0 -0
  384. /package/dist/{chunk-OSA3YVDZ.mjs.map → chunk-ZF46DCAC.mjs.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/SupportChatWidget/SupportChatWidget.tsx","../src/hooks/useSupportChat.ts","../src/components/SupportChatWidget/SupportChatContactForm.tsx","../src/components/SupportChatWidget/SupportChatArticleView.tsx","../src/components/SupportChatWidget/supportChatContent.tsx","../src/components/SupportChatWidget/NativeSupportChat.tsx","../src/components/SupportChatWidget/guestSupportChatAdapter.ts","../src/components/SupportChatWidget/mockSupportChatAdapter.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type KeyboardEvent,\n} from 'react';\nimport {\n ChatCircleDotsIcon,\n MinusIcon,\n PaperclipIcon,\n PaperPlaneTiltIcon,\n XIcon,\n} from '@phosphor-icons/react';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport { useSupportChat } from '../../hooks/useSupportChat';\nimport { SupportChatContactForm } from './SupportChatContactForm';\nimport { SupportChatArticleView } from './SupportChatArticleView';\nimport {\n AttachmentList,\n MessageText,\n PendingAttachment,\n SUPPORT_CHAT_ACCEPT,\n pickAttachments,\n} from './supportChatContent';\nimport { SupportType } from '../../types/support';\nimport {\n SUPPORT_CHAT_AUTHOR,\n SUPPORT_CHAT_MAX_ATTACHMENTS,\n type SupportChatAdapter,\n type SupportChatFlags,\n type SupportChatMessage,\n type SupportChatTheme,\n type SupportChatUser,\n} from '../../types/supportChat';\nimport { cn } from '../../utils/utils';\n\n/** Visibility of the chat window */\nexport type SupportChatWindowState = 'closed' | 'open' | 'minimized';\n\nexport interface SupportChatWidgetProps {\n /** Data layer (createMockSupportChatAdapter for now) */\n adapter: SupportChatAdapter;\n /** App the widget runs in, sent with the ticket (e.g. \"login\", \"backoffice\") */\n channel: string;\n institutionId?: string;\n /** Logged user; omit for visitors */\n user?: SupportChatUser;\n flags?: SupportChatFlags;\n theme?: SupportChatTheme;\n onOpen?: () => void;\n onSend?: (message: SupportChatMessage) => void;\n /**\n * Called when the window is closed with X. Closing only hides it: the\n * conversation stays connected and new replies count as unread.\n */\n onClose?: () => void;\n /**\n * Link of a FAQ article, e.g. `(id) => '/artigo/' + id`. With it, the\n * \"Baseado na FAQ\" line under an AI answer opens the article; without it\n * the line only names the article.\n */\n faqArticleUrl?: (articleId: string) => string;\n}\n\n/** Label read by screen readers on the unread badge of the launcher */\nconst formatNewMessagesLabel = (count: number): string =>\n count === 1 ? '1 nova mensagem' : `${count} novas mensagens`;\n\n/** The requester side of the conversation (user or visitor) */\nconst isOwnMessage = (message: SupportChatMessage) =>\n message.senderRole === SUPPORT_CHAT_AUTHOR.USER ||\n message.senderRole === SUPPORT_CHAT_AUTHOR.GUEST;\n\nconst formatTime = (createdAt: string) =>\n new Date(createdAt).toLocaleTimeString('pt-BR', {\n hour: '2-digit',\n minute: '2-digit',\n });\n\n/** \"Baseado na FAQ: <title>\" under an AI answer, linked when possible */\nconst FaqReference = ({\n faq,\n faqArticleUrl,\n onOpenArticle,\n}: {\n faq: { id: string; title: string };\n faqArticleUrl?: (articleId: string) => string;\n onOpenArticle?: (article: { id: string; title: string }) => void;\n}) => {\n const linked = !!onOpenArticle || !!faqArticleUrl;\n const label = (\n <Text\n as=\"span\"\n size=\"xs\"\n color=\"text-primary-700\"\n className={cn(linked && 'underline')}\n >\n Baseado na FAQ: {faq.title}\n </Text>\n );\n let content = label;\n if (onOpenArticle) {\n // Opens inside the chat, like the Zendesk messenger (no new tab)\n content = (\n <a\n href={faqArticleUrl?.(faq.id) ?? '#'}\n onClick={(event) => {\n event.preventDefault();\n onOpenArticle(faq);\n }}\n >\n {label}\n </a>\n );\n } else if (faqArticleUrl) {\n content = (\n <a href={faqArticleUrl(faq.id)} target=\"_blank\" rel=\"noreferrer\">\n {label}\n </a>\n );\n }\n return (\n <div data-testid=\"support-chat-faq\" className=\"mt-1 max-w-[80%]\">\n {content}\n </div>\n );\n};\n\nconst MessageBubble = ({\n message,\n faqArticleUrl,\n onOpenArticle,\n}: {\n message: SupportChatMessage;\n faqArticleUrl?: (articleId: string) => string;\n onOpenArticle?: (article: { id: string; title?: string }) => void;\n}) => {\n const own = isOwnMessage(message);\n return (\n <div\n className={cn(\n 'flex flex-col mb-3 transition-opacity',\n own ? 'items-end' : 'items-start',\n message.pending && 'opacity-60'\n )}\n aria-busy={message.pending || undefined}\n >\n {!own && (\n <Text size=\"xs\" className=\"text-text-500 mb-1\">\n {message.senderName}\n </Text>\n )}\n <div\n className={cn(\n 'max-w-[80%] rounded-2xl whitespace-pre-wrap break-words',\n // Image-only messages show the image without the colored bubble\n message.content\n ? cn(\n 'px-4 py-2',\n own\n ? 'bg-primary-500 text-white rounded-br-md'\n : 'bg-background-100 text-text-900 rounded-bl-md'\n )\n : 'text-text-900'\n )}\n >\n {message.content && (\n <MessageText\n text={message.content}\n onOpenArticle={\n onOpenArticle ? (id) => onOpenArticle({ id }) : undefined\n }\n />\n )}\n {message.attachments.length > 0 && (\n <AttachmentList items={message.attachments} />\n )}\n </div>\n {message.faq && (\n <FaqReference\n faq={message.faq}\n faqArticleUrl={faqArticleUrl}\n onOpenArticle={onOpenArticle}\n />\n )}\n <Text size=\"xs\" className=\"text-text-400 mt-1\">\n {message.pending ? 'Enviando…' : formatTime(message.createdAt)}\n </Text>\n </div>\n );\n};\n\n/**\n * Floating support chat (native support, the Zendesk replacement).\n * Renders nothing when disabled or when the institution uses Zendesk.\n */\nexport const SupportChatWidget = ({\n flags,\n ...props\n}: SupportChatWidgetProps) => {\n const hidden =\n flags?.enabled === false ||\n flags?.chat === false ||\n flags?.supportType === SupportType.ZENDESK;\n\n if (hidden) return null;\n return <SupportChatWidgetContent {...props} />;\n};\n\nconst SupportChatWidgetContent = ({\n adapter,\n channel,\n institutionId,\n user,\n theme,\n onOpen,\n onSend,\n onClose,\n faqArticleUrl,\n}: Omit<SupportChatWidgetProps, 'flags'>) => {\n const [windowState, setWindowState] =\n useState<SupportChatWindowState>('closed');\n const [draft, setDraft] = useState('');\n const [files, setFiles] = useState<File[]>([]);\n const [fileError, setFileError] = useState<string | null>(null);\n const [unread, setUnread] = useState(0);\n // FAQ article open inside the chat (the conversation stays as it was)\n const [article, setArticle] = useState<{ id: string; title?: string } | null>(\n null\n );\n const [expanded, setExpanded] = useState(false);\n const listRef = useRef<HTMLDivElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const seenCount = useRef(0);\n\n const {\n messages,\n sending,\n error,\n closed,\n restored,\n send,\n updateContact,\n reset,\n } = useSupportChat({\n adapter,\n channel,\n institutionId,\n user,\n });\n const [savedContactRequests, setSavedContactRequests] = useState<string[]>(\n []\n );\n\n // Latest AI request for name/e-mail: the form goes under it, and the\n // composer waits until it is sent\n const contactRequest = updateContact\n ? [...messages].reverse().find((message) => message.contactRequest?.length)\n : undefined;\n const awaitingContact =\n !!contactRequest && !savedContactRequests.includes(contactRequest.id);\n\n const isOpen = windowState === 'open';\n\n const canOpenArticle = !!adapter.getArticle && !!institutionId;\n const loadArticle = useCallback(\n (articleId: string) => {\n if (!adapter.getArticle || !institutionId) {\n return Promise.reject(new Error('Artigo indisponível'));\n }\n // Called on the adapter so a class-based adapter keeps its `this`\n return adapter.getArticle(institutionId, articleId);\n },\n [adapter, institutionId]\n );\n const openArticle = canOpenArticle\n ? (target: { id: string; title?: string }) => {\n setArticle(target);\n setExpanded(true);\n }\n : undefined;\n const closeArticle = () => {\n setArticle(null);\n setExpanded(false);\n };\n const title = theme?.title ?? 'Suporte';\n const left = theme?.position === 'bottom-left';\n const accentStyle = theme?.primaryColor\n ? { backgroundColor: theme.primaryColor }\n : undefined;\n\n // Count the support replies that arrive while the window is not visible\n useEffect(() => {\n const fresh = messages.slice(seenCount.current);\n seenCount.current = messages.length;\n // A resumed conversation was already read before the reload\n if (isOpen || (restored && fresh.length === messages.length)) return;\n const replies = fresh.filter((message) => !isOwnMessage(message)).length;\n if (replies) setUnread((count) => count + replies);\n }, [messages, isOpen, restored]);\n\n useEffect(() => {\n if (!isOpen || article) return;\n setUnread(0);\n listRef.current?.scrollTo?.({ top: listRef.current.scrollHeight });\n }, [isOpen, messages, article]);\n\n const open = () => {\n setWindowState('open');\n onOpen?.();\n };\n\n const close = () => {\n setWindowState('closed');\n onClose?.();\n };\n\n /** Drop a finished conversation so the next message opens a new ticket */\n const startOver = () => {\n setDraft('');\n setFiles([]);\n setFileError(null);\n setUnread(0);\n seenCount.current = 0;\n setSavedContactRequests([]);\n reset();\n };\n\n const submit = async () => {\n const content = draft;\n const pending = files;\n if (!content.trim() && pending.length === 0) return;\n setDraft('');\n setFiles([]);\n setFileError(null);\n const message = await send(content, pending);\n if (message) {\n onSend?.(message);\n } else {\n setDraft(content);\n setFiles(pending);\n }\n };\n\n const handleFiles = (event: ChangeEvent<HTMLInputElement>) => {\n const { accepted, problem } = pickAttachments(\n files,\n Array.from(event.target.files ?? [])\n );\n setFiles(accepted);\n setFileError(problem);\n event.target.value = '';\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n void submit();\n }\n };\n\n return (\n <div\n className={cn(\n 'fixed bottom-4 z-50 flex flex-col gap-3',\n left ? 'left-4 items-start' : 'right-4 items-end'\n )}\n >\n {isOpen && (\n <section\n role=\"dialog\"\n aria-label={title}\n className={cn(\n 'max-w-[calc(100vw-2rem)] max-h-[calc(100vh-6rem)] flex flex-col bg-background rounded-2xl shadow-lg border border-border-100 overflow-hidden transition-[width,height]',\n expanded ? 'w-[720px] h-[615px]' : 'w-[360px] h-[520px]'\n )}\n >\n {article ? (\n <SupportChatArticleView\n articleId={article.id}\n initialTitle={article.title}\n loadArticle={loadArticle}\n expanded={expanded}\n onToggleExpanded={() => setExpanded((value) => !value)}\n onBack={closeArticle}\n externalUrl={faqArticleUrl?.(article.id)}\n accentStyle={accentStyle}\n />\n ) : (\n <>\n <header\n className=\"flex items-center justify-between px-4 py-3 bg-primary-500 text-white\"\n style={accentStyle}\n >\n <Text size=\"md\" weight=\"semibold\" color=\"\">\n {title}\n </Text>\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"raw\"\n aria-label=\"Minimizar\"\n onClick={() => setWindowState('minimized')}\n className=\"p-1 rounded hover:bg-white/20\"\n >\n <MinusIcon size={18} />\n </Button>\n <Button\n variant=\"raw\"\n aria-label=\"Fechar\"\n onClick={close}\n className=\"p-1 rounded hover:bg-white/20\"\n >\n <XIcon size={18} />\n </Button>\n </div>\n </header>\n\n <div ref={listRef} className=\"flex-1 overflow-y-auto px-4 py-3\">\n {messages.length === 0 ? (\n <Text size=\"sm\" className=\"text-text-500 text-center mt-8\">\n Olá! Como podemos te ajudar?\n </Text>\n ) : (\n messages.map((message) => (\n <div key={message.id}>\n <MessageBubble\n message={message}\n faqArticleUrl={faqArticleUrl}\n onOpenArticle={openArticle}\n />\n {updateContact &&\n message.id === contactRequest?.id &&\n message.contactRequest && (\n <SupportChatContactForm\n fields={message.contactRequest}\n accentColor={theme?.primaryColor}\n onSubmit={async (contact) => {\n const ok = await updateContact(contact);\n if (ok) {\n setSavedContactRequests((ids) => [\n ...ids,\n message.id,\n ]);\n }\n return ok;\n }}\n />\n )}\n </div>\n ))\n )}\n </div>\n\n {(fileError || error) && (\n <Text\n size=\"xs\"\n role=\"alert\"\n className=\"px-4 py-2 text-error-700 bg-error-50\"\n >\n {fileError ?? error}\n </Text>\n )}\n\n {closed ? (\n <div className=\"flex flex-col items-center gap-2 px-4 py-3 border-t border-border-100\">\n <Text size=\"sm\" color=\"text-text-500\" className=\"text-center\">\n Este atendimento foi encerrado.\n </Text>\n <Button variant=\"link\" size=\"small\" onClick={startOver}>\n Iniciar nova conversa\n </Button>\n </div>\n ) : (\n <form\n className=\"flex flex-col gap-2 px-3 py-3 border-t border-border-100\"\n onSubmit={(event) => {\n event.preventDefault();\n void submit();\n }}\n >\n {files.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {files.map((file, index) => (\n <PendingAttachment\n key={`${file.name}-${index}`}\n file={file}\n onRemove={() =>\n setFiles((list) =>\n list.filter((_, i) => i !== index)\n )\n }\n />\n ))}\n </div>\n )}\n <div className=\"flex items-end gap-2\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={SUPPORT_CHAT_ACCEPT}\n multiple\n hidden\n data-testid=\"support-chat-file-input\"\n onChange={handleFiles}\n />\n <Button\n variant=\"raw\"\n aria-label=\"Anexar arquivo\"\n disabled={\n sending ||\n awaitingContact ||\n files.length >= SUPPORT_CHAT_MAX_ATTACHMENTS\n }\n onClick={() => fileInputRef.current?.click()}\n className=\"p-2 rounded-full text-text-600 hover:bg-background-100 disabled:opacity-50\"\n >\n <PaperclipIcon size={20} />\n </Button>\n <textarea\n aria-label=\"Mensagem\"\n placeholder={\n awaitingContact\n ? 'Preencha seus dados acima'\n : 'Digite sua mensagem'\n }\n disabled={awaitingContact}\n rows={1}\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={handleKeyDown}\n className=\"flex-1 resize-none rounded-xl border border-border-300 px-3 py-2 text-sm text-text-900 focus:outline-none focus:border-primary-500 max-h-28\"\n />\n <Button\n variant=\"raw\"\n type=\"submit\"\n aria-label=\"Enviar\"\n disabled={\n sending ||\n awaitingContact ||\n (!draft.trim() && files.length === 0)\n }\n className=\"p-2 rounded-full bg-primary-500 text-white disabled:opacity-50\"\n style={accentStyle}\n >\n <PaperPlaneTiltIcon size={18} />\n </Button>\n </div>\n </form>\n )}\n </>\n )}\n </section>\n )}\n\n {!isOpen && (\n <Button\n variant=\"raw\"\n aria-label={`Abrir ${title.toLowerCase()}`}\n onClick={open}\n className=\"relative w-14 h-14 rounded-full bg-primary-500 text-white shadow-lg flex items-center justify-center hover:brightness-110\"\n style={accentStyle}\n >\n <ChatCircleDotsIcon size={28} />\n {unread > 0 && (\n <Text\n as=\"span\"\n size=\"xs\"\n color=\"text-white\"\n aria-label={formatNewMessagesLabel(unread)}\n className=\"absolute -top-1 -right-1 min-w-5 h-5 px-1 rounded-full bg-error-500 flex items-center justify-center\"\n >\n {unread}\n </Text>\n )}\n </Button>\n )}\n </div>\n );\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n SUPPORT_CHAT_AUTHOR,\n SUPPORT_CHAT_GUEST_SENDER_ID,\n SUPPORT_CHAT_STATUS,\n type SupportChatAdapter,\n type SupportChatContact,\n type SupportChatEvent,\n type SupportChatMessage,\n type SupportChatTicket,\n type SupportChatUser,\n} from '../types/supportChat';\n\nexport interface UseSupportChatConfig {\n adapter: SupportChatAdapter;\n channel: string;\n institutionId?: string;\n user?: SupportChatUser;\n}\n\nexport interface UseSupportChatReturn {\n ticket: SupportChatTicket | null;\n messages: SupportChatMessage[];\n sending: boolean;\n error: string | null;\n /** Ticket resolved: no more messages can be sent */\n closed: boolean;\n /** The conversation was resumed from an earlier page load */\n restored: boolean;\n /** Send a message (text and/or files); the first one opens the ticket */\n send: (content: string, files?: File[]) => Promise<SupportChatMessage | null>;\n /**\n * Save the contact typed in the form shown under the AI request. Resolves\n * false (and sets `error`) when it fails. Undefined when the adapter cannot\n * save it.\n */\n updateContact?: (contact: SupportChatContact) => Promise<boolean>;\n /** Forget the current conversation */\n reset: () => void;\n}\n\nlet pendingSequence = 0;\n\n/**\n * Message shown right away while it is being sent (optimistic rendering).\n * Images use local object URLs, released when the real message arrives.\n */\nconst buildPendingMessage = (\n content: string,\n files: File[],\n user?: SupportChatUser\n): SupportChatMessage => {\n pendingSequence += 1;\n return {\n id: `pending-${pendingSequence}`,\n senderId: SUPPORT_CHAT_GUEST_SENDER_ID,\n senderName: user?.name || 'Você',\n senderPhoto: null,\n senderRole: user?.email\n ? SUPPORT_CHAT_AUTHOR.USER\n : SUPPORT_CHAT_AUTHOR.GUEST,\n content,\n messageType: 'text',\n createdAt: new Date().toISOString(),\n attachments: files.map((file, index) => ({\n id: `pending-${pendingSequence}-${index}`,\n url: URL.createObjectURL(file),\n fileName: file.name,\n mimeType: file.type,\n size: file.size,\n })),\n pending: true,\n };\n};\n\nconst releasePending = (message: SupportChatMessage) =>\n message.attachments.forEach((item) => URL.revokeObjectURL(item.url));\n\nconst getErrorMessage = (error: unknown) =>\n error instanceof Error ? error.message : 'Não foi possível enviar a mensagem';\n\n/** Add or replace a message, keeping the list ordered by arrival */\nconst upsertMessage = (\n list: SupportChatMessage[],\n message: SupportChatMessage\n): SupportChatMessage[] =>\n list.some((item) => item.id === message.id)\n ? list.map((item) => (item.id === message.id ? message : item))\n : [...list, message];\n\n/**\n * State of a support conversation on top of a SupportChatAdapter.\n * The REST-like calls write; the subscription only applies the events,\n * so a message received both ways is stored once.\n */\nexport const useSupportChat = ({\n adapter,\n channel,\n institutionId,\n user,\n}: UseSupportChatConfig): UseSupportChatReturn => {\n const [ticket, setTicket] = useState<SupportChatTicket | null>(null);\n const [messages, setMessages] = useState<SupportChatMessage[]>([]);\n const [sending, setSending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [restored, setRestored] = useState(false);\n const sendingRef = useRef(false);\n\n const ticketId = ticket?.id;\n const userEmail = user?.email;\n // Read by the restore, which must not replace a conversation started meanwhile\n const ticketRef = useRef(ticket);\n ticketRef.current = ticket;\n\n // Resume the unresolved conversation of an earlier page load, unless the\n // person already started a new one meanwhile\n useEffect(() => {\n if (!adapter.restoreConversation) return;\n let active = true;\n adapter\n .restoreConversation({ email: userEmail })\n .then((resumed) => {\n if (!active || !resumed) return;\n if (ticketRef.current || sendingRef.current) return;\n setTicket(resumed.ticket);\n setMessages(resumed.messages);\n setRestored(true);\n })\n .catch(() => {\n // Not resumed: the next message opens a new ticket\n });\n return () => {\n active = false;\n };\n }, [adapter, userEmail]);\n\n const closed = ticket?.status === SUPPORT_CHAT_STATUS.FECHADO;\n\n // A resolved conversation is not resumed on the next load\n useEffect(() => {\n if (closed) adapter.forgetConversation?.();\n }, [adapter, closed]);\n\n useEffect(() => {\n if (!ticketId) return;\n\n const handleEvent = (event: SupportChatEvent) => {\n switch (event.type) {\n case 'new_message':\n setMessages((list) => upsertMessage(list, event.payload.message));\n break;\n case 'message_updated':\n setMessages((list) =>\n list.map((item) =>\n item.id === event.payload.messageId\n ? { ...item, content: event.payload.content }\n : item\n )\n );\n break;\n case 'ticket_updated': {\n const { ticketId: id, ...rest } = event.payload;\n setTicket((current) =>\n current?.id === id ? { ...current, ...rest } : current\n );\n break;\n }\n case 'error':\n setError(event.payload.message);\n break;\n }\n };\n\n return adapter.subscribe(ticketId, handleEvent);\n }, [adapter, ticketId]);\n\n const send = useCallback(\n async (content: string, files: File[] = []) => {\n const text = content.trim();\n if ((!text && files.length === 0) || sendingRef.current) return null;\n\n sendingRef.current = true;\n setSending(true);\n setError(null);\n\n const pending = buildPendingMessage(text, files, user);\n setMessages((list) => [...list, pending]);\n // Swap the optimistic message for the confirmed ones\n const confirm = (confirmed: SupportChatMessage[]) =>\n setMessages((list) =>\n confirmed.reduce(\n upsertMessage,\n list.filter((item) => item.id !== pending.id)\n )\n );\n\n try {\n if (ticketId) {\n const message = await adapter.sendMessage(ticketId, text, files);\n confirm([message]);\n return message;\n }\n\n const started = await adapter.startConversation({\n message: text,\n channel,\n institutionId,\n requesterName: user?.name,\n email: user?.email,\n files,\n });\n setTicket(started.ticket);\n confirm(started.messages);\n return started.messages[started.messages.length - 1] ?? null;\n } catch (sendError) {\n setMessages((list) => list.filter((item) => item.id !== pending.id));\n setError(getErrorMessage(sendError));\n return null;\n } finally {\n releasePending(pending);\n sendingRef.current = false;\n setSending(false);\n }\n },\n [adapter, channel, institutionId, ticketId, user]\n );\n\n const updateContact = useCallback(\n async (contact: SupportChatContact) => {\n if (!ticketId || !adapter.updateContact) return false;\n setError(null);\n try {\n await adapter.updateContact(ticketId, contact);\n return true;\n } catch (contactError) {\n setError(\n (contactError as { response?: { status?: number } } | null)?.response\n ?.status === 409\n ? 'O e-mail deste atendimento já foi informado'\n : 'Não foi possível salvar seus dados. Tente de novo.'\n );\n return false;\n }\n },\n [adapter, ticketId]\n );\n\n const reset = useCallback(() => {\n adapter.forgetConversation?.();\n setTicket(null);\n setMessages([]);\n setError(null);\n setRestored(false);\n }, [adapter]);\n\n return {\n ticket,\n messages,\n sending,\n error,\n closed,\n restored,\n send,\n updateContact: adapter.updateContact ? updateContact : undefined,\n reset,\n };\n};\n","import { useState, type FormEvent } from 'react';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport Input from '../Input/Input';\nimport type {\n SupportChatContact,\n SupportChatContactField,\n} from '../../types/supportChat';\n\nexport interface SupportChatContactFormProps {\n /** Fields the AI asked for, in order (one step each) */\n fields: SupportChatContactField[];\n /** Saves the contact; resolves true when it worked */\n onSubmit: (contact: SupportChatContact) => Promise<boolean>;\n /** Accent color of the theme, for the button */\n accentColor?: string;\n}\n\nconst STEPS: Record<\n SupportChatContactField,\n { label: string; type: string; autoComplete: string; placeholder: string }\n> = {\n name: {\n label: 'Seu nome',\n type: 'text',\n autoComplete: 'name',\n placeholder: 'Como podemos te chamar?',\n },\n email: {\n label: 'Seu e-mail',\n type: 'email',\n autoComplete: 'email',\n placeholder: 'nome@exemplo.com',\n },\n};\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/** Problem with a typed value, or null when it can be sent */\nconst validate = (\n field: SupportChatContactField,\n value: string\n): string | null => {\n if (field === 'name') {\n return value.length >= 2 ? null : 'Digite seu nome';\n }\n return EMAIL_PATTERN.test(value) ? null : 'Digite um e-mail válido';\n};\n\n/**\n * Step-by-step form for the contact the AI asks on the first contact (name,\n * then e-mail), shown under the AI message like the Zendesk pre-chat form.\n * The values go to the backend as fields, not as a chat message. Once sent,\n * it shows what was saved.\n */\nexport const SupportChatContactForm = ({\n fields,\n onSubmit,\n accentColor,\n}: SupportChatContactFormProps) => {\n const [step, setStep] = useState(0);\n const [values, setValues] = useState<Record<string, string>>({});\n const [problem, setProblem] = useState<string | null>(null);\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n\n const field = fields[step];\n const config = STEPS[field];\n const value = values[field] ?? '';\n const isLast = step === fields.length - 1;\n\n if (saved) {\n return (\n <div\n data-testid=\"support-chat-contact-saved\"\n className=\"mb-3 ml-1 flex max-w-[85%] flex-col gap-1 rounded-2xl border border-border-100 px-4 py-3\"\n >\n {fields.map((item) => (\n <Text key={item} size=\"xs\" color=\"text-text-600\">\n {STEPS[item].label}:{' '}\n <Text as=\"span\" size=\"xs\" weight=\"semibold\" color=\"text-text-900\">\n {values[item]}\n </Text>\n </Text>\n ))}\n </div>\n );\n }\n\n const advance = async (event: FormEvent) => {\n event.preventDefault();\n const typed = field === 'email' ? value.trim().toLowerCase() : value.trim();\n const error = validate(field, typed);\n setProblem(error);\n if (error) return;\n\n const next = { ...values, [field]: typed };\n setValues(next);\n if (!isLast) {\n setStep(step + 1);\n return;\n }\n\n setSaving(true);\n const ok = await onSubmit({\n ...(next.name ? { requesterName: next.name } : {}),\n ...(next.email ? { email: next.email } : {}),\n });\n setSaving(false);\n if (ok) setSaved(true);\n };\n\n const inputId = `support-chat-contact-${field}`;\n\n return (\n <form\n aria-label=\"Seus dados\"\n noValidate\n onSubmit={(event) => void advance(event)}\n className=\"mb-3 ml-1 flex max-w-[85%] flex-col gap-3 rounded-2xl border border-border-100 px-4 py-3\"\n >\n <Input\n id={inputId}\n key={field}\n label={config.label}\n variant=\"rounded\"\n size=\"small\"\n type={config.type}\n autoComplete={config.autoComplete}\n placeholder={config.placeholder}\n value={value}\n autoFocus\n disabled={saving}\n errorMessage={problem ?? undefined}\n onChange={(event) =>\n setValues((current) => ({ ...current, [field]: event.target.value }))\n }\n />\n <div className=\"flex items-center justify-between\">\n <Text size=\"xs\" color=\"text-text-500\">\n {fields.length > 1 ? `${step + 1} de ${fields.length}` : ''}\n </Text>\n <Button\n type=\"submit\"\n size=\"small\"\n disabled={saving}\n style={accentColor ? { backgroundColor: accentColor } : undefined}\n >\n {isLast ? 'Enviar' : 'Avançar'}\n </Button>\n </div>\n </form>\n );\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n ArrowLeftIcon,\n ArrowSquareOutIcon,\n ArrowsInSimpleIcon,\n ArrowsOutSimpleIcon,\n} from '@phosphor-icons/react';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport { ArticleContent } from '../ArticleContent/ArticleContent';\nimport { embedVideoLinks } from '../../utils/videoEmbed';\nimport type { SupportChatArticle } from '../../types/supportChat';\nimport { cn } from '../../utils/utils';\n\nexport interface SupportChatArticleViewProps {\n /** Article to show */\n articleId: string;\n /** Title known from the chat, shown while the article loads */\n initialTitle?: string;\n /** Loads the article (adapter.getArticle bound to the institution) */\n loadArticle: (articleId: string) => Promise<SupportChatArticle>;\n /** Whether the chat window is in the wide mode */\n expanded: boolean;\n onToggleExpanded: () => void;\n /** Back to the conversation (it is kept as it was) */\n onBack: () => void;\n /** Page of the article in the help center, for \"Abrir em nova aba\" */\n externalUrl?: string;\n /** Header background (theme) */\n accentStyle?: { backgroundColor: string };\n}\n\nconst formatUpdatedAt = (iso: string) =>\n new Date(iso).toLocaleDateString('pt-BR', {\n day: '2-digit',\n month: '2-digit',\n year: 'numeric',\n });\n\n/**\n * FAQ article read inside the support chat, like the Zendesk messenger: the\n * conversation is replaced by the article (no new tab), with back,\n * expand/reduce and open-in-new-tab controls. The big title moves to the\n * header once it scrolls out of view. YouTube/Vimeo links of the article\n * become players.\n */\nexport const SupportChatArticleView = ({\n articleId,\n initialTitle,\n loadArticle,\n expanded,\n onToggleExpanded,\n onBack,\n externalUrl,\n accentStyle,\n}: SupportChatArticleViewProps) => {\n const [article, setArticle] = useState<SupportChatArticle | null>(null);\n const [failed, setFailed] = useState(false);\n const [titleHidden, setTitleHidden] = useState(false);\n const titleRef = useRef<HTMLHeadingElement>(null);\n\n useEffect(() => {\n let active = true;\n setArticle(null);\n setFailed(false);\n loadArticle(articleId)\n .then((loaded) => {\n if (active) setArticle(loaded);\n })\n .catch(() => {\n if (active) setFailed(true);\n });\n return () => {\n active = false;\n };\n }, [articleId, loadArticle]);\n\n // The big title leaves the screen → show it in the header\n useEffect(() => {\n const title = titleRef.current;\n if (!title || typeof IntersectionObserver === 'undefined') {\n return undefined;\n }\n const observer = new IntersectionObserver(([entry]) =>\n setTitleHidden(!entry.isIntersecting)\n );\n observer.observe(title);\n return () => observer.disconnect();\n }, [article]);\n\n const html = useMemo(\n () => (article ? embedVideoLinks(article.body) : ''),\n [article]\n );\n const title = article?.title ?? initialTitle ?? 'Artigo';\n\n return (\n <div\n data-testid=\"support-chat-article\"\n className=\"flex min-h-0 flex-1 flex-col\"\n >\n <header\n className=\"flex items-center gap-1 px-2 py-2 bg-primary-500 text-white\"\n style={accentStyle}\n >\n <Button\n variant=\"raw\"\n aria-label=\"Voltar para a janela de mensagens\"\n onClick={onBack}\n className=\"p-1 rounded hover:bg-white/20\"\n >\n <ArrowLeftIcon size={18} />\n </Button>\n <Text\n as=\"span\"\n size=\"sm\"\n weight=\"semibold\"\n color=\"\"\n aria-hidden={!titleHidden || undefined}\n className={cn(\n 'min-w-0 flex-1 truncate transition-opacity',\n titleHidden ? 'opacity-100' : 'opacity-0'\n )}\n >\n {title}\n </Text>\n <Button\n variant=\"raw\"\n aria-label={expanded ? 'Reduzir artigo' : 'Expandir artigo'}\n onClick={onToggleExpanded}\n className=\"p-1 rounded hover:bg-white/20\"\n >\n {expanded ? (\n <ArrowsInSimpleIcon size={18} />\n ) : (\n <ArrowsOutSimpleIcon size={18} />\n )}\n </Button>\n {externalUrl && (\n <a\n href={externalUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label=\"Abrir em nova aba\"\n className=\"p-1 rounded hover:bg-white/20\"\n >\n <ArrowSquareOutIcon size={18} />\n </a>\n )}\n </header>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4\">\n <Text\n as=\"h2\"\n ref={titleRef}\n size=\"xl\"\n weight=\"bold\"\n color=\"text-text-950\"\n >\n {title}\n </Text>\n {article?.updatedAt && (\n <Text size=\"xs\" color=\"text-text-500\" className=\"mt-1\">\n Atualizado em {formatUpdatedAt(article.updatedAt)}\n </Text>\n )}\n\n <div className=\"mt-4\">\n {failed && (\n <Text size=\"sm\" role=\"alert\" color=\"text-error-700\">\n Não foi possível abrir o artigo.\n </Text>\n )}\n {!failed && !article && (\n <Text size=\"sm\" color=\"text-text-500\">\n Carregando…\n </Text>\n )}\n {article && <ArticleContent html={html} />}\n </div>\n </div>\n </div>\n );\n};\n","import { useEffect, useState, type ReactNode } from 'react';\nimport {\n FileIcon,\n FilePdfIcon,\n FileVideoIcon,\n XIcon,\n} from '@phosphor-icons/react';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport {\n SUPPORT_CHAT_ATTACHMENT_RULES,\n SUPPORT_CHAT_MAX_ATTACHMENTS,\n type SupportChatAttachment,\n} from '../../types/supportChat';\n\n/** Value of the `accept` attribute of the file picker */\nexport const SUPPORT_CHAT_ACCEPT = Object.keys(\n SUPPORT_CHAT_ATTACHMENT_RULES\n).join(',');\n\nconst isImage = (mimeType?: string) => Boolean(mimeType?.startsWith('image/'));\nconst isVideo = (mimeType?: string) => Boolean(mimeType?.startsWith('video/'));\n\nconst formatSize = (bytes: number) => `${Math.round(bytes / (1024 * 1024))} MB`;\n\n/**\n * Keep the files the backend accepts (type, size and count) and say why the\n * others were left out.\n * @param current - Files already picked\n * @param picked - Files just chosen\n * @returns The accepted files and the last problem found, if any\n */\nexport const pickAttachments = (current: File[], picked: File[]) => {\n const accepted = [...current];\n let problem: string | null = null;\n for (const file of picked) {\n const maxBytes = SUPPORT_CHAT_ATTACHMENT_RULES[file.type];\n if (!maxBytes) {\n problem =\n 'Envie imagens (JPG, PNG, GIF, WEBP), PDF ou vídeo (MP4, WEBM, MOV)';\n } else if (file.size > maxBytes) {\n problem = `${file.name} passa de ${formatSize(maxBytes)}`;\n } else if (accepted.length >= SUPPORT_CHAT_MAX_ATTACHMENTS) {\n problem = `Máximo de ${SUPPORT_CHAT_MAX_ATTACHMENTS} arquivos por mensagem`;\n } else {\n accepted.push(file);\n }\n }\n return { accepted, problem };\n};\n\nconst FileTypeIcon = ({ mimeType }: { mimeType?: string }) => {\n if (mimeType === 'application/pdf') return <FilePdfIcon size={18} />;\n if (isVideo(mimeType)) return <FileVideoIcon size={18} />;\n return <FileIcon size={18} />;\n};\n\n/** Files of a message: images and videos inline, other files as links */\nexport const AttachmentList = ({\n items,\n}: {\n items: SupportChatAttachment[];\n}) => (\n <div className=\"flex flex-wrap gap-2 first:mt-0 mt-1\">\n {items.map((item) => {\n if (isImage(item.mimeType)) {\n return (\n <a key={item.id} href={item.url} target=\"_blank\" rel=\"noreferrer\">\n <img\n src={item.url}\n alt={item.fileName}\n className=\"max-w-[200px] max-h-[200px] rounded-lg object-cover\"\n />\n </a>\n );\n }\n if (isVideo(item.mimeType)) {\n return (\n <video\n key={item.id}\n src={item.url}\n controls\n preload=\"metadata\"\n aria-label={item.fileName}\n className=\"max-w-[240px] max-h-[200px] rounded-lg bg-black\"\n />\n );\n }\n return (\n <a\n key={item.id}\n href={item.url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"flex items-center gap-1 underline\"\n >\n <FileTypeIcon mimeType={item.mimeType} />\n <Text as=\"span\" size=\"sm\" color=\"\">\n {item.fileName}\n </Text>\n </a>\n );\n })}\n </div>\n);\n\n/** A file picked but not sent yet: thumbnail for images, name for the rest */\nexport const PendingAttachment = ({\n file,\n onRemove,\n}: {\n file: File;\n onRemove: () => void;\n}) => {\n const image = isImage(file.type);\n const [url, setUrl] = useState('');\n useEffect(() => {\n if (!image) return undefined;\n const objectUrl = URL.createObjectURL(file);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [file, image]);\n\n return (\n <div className=\"relative\">\n {image ? (\n url && (\n <img\n src={url}\n alt={file.name}\n className=\"w-14 h-14 rounded-lg object-cover border border-border-100\"\n />\n )\n ) : (\n <div className=\"flex h-14 max-w-[160px] items-center gap-1 rounded-lg border border-border-100 px-2 text-text-700\">\n <FileTypeIcon mimeType={file.type} />\n <Text as=\"span\" size=\"xs\" className=\"truncate\">\n {file.name}\n </Text>\n </div>\n )}\n <Button\n variant=\"raw\"\n aria-label={`Remover ${file.name}`}\n onClick={onRemove}\n className=\"absolute -top-1 -right-1 w-5 h-5 rounded-full bg-text-700 text-white flex items-center justify-center\"\n >\n <XIcon size={12} />\n </Button>\n </div>\n );\n};\n\n/** http(s) addresses inside a message */\nconst URL_PATTERN = /https?:\\/\\/[^\\s<>\"]+/g;\n\n/** Punctuation that ends a sentence, not the address */\nconst TRAILING_PUNCTUATION = /[.,;:!?)\\]]+$/;\n\n/** A FAQ article page: `/artigo/<uuid>` */\nconst ARTICLE_PATH =\n /\\/artigo\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i;\n\n/**\n * Message text with its addresses as links. A link to a FAQ article opens in\n * the chat (when `onOpenArticle` is given); the others open a new tab.\n */\nexport const MessageText = ({\n text,\n onOpenArticle,\n}: {\n text: string;\n onOpenArticle?: (articleId: string) => void;\n}) => {\n const parts: ReactNode[] = [];\n let cursor = 0;\n for (const match of text.matchAll(URL_PATTERN)) {\n const raw = match[0];\n const url = raw.replace(TRAILING_PUNCTUATION, '');\n const start = match.index ?? 0;\n if (start > cursor) parts.push(text.slice(cursor, start));\n\n const articleId = onOpenArticle ? ARTICLE_PATH.exec(url)?.[1] : undefined;\n parts.push(\n <a\n key={`${start}-${url}`}\n href={url}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline break-all\"\n onClick={\n articleId\n ? (event) => {\n event.preventDefault();\n onOpenArticle?.(articleId);\n }\n : undefined\n }\n >\n {url}\n </a>\n );\n cursor = start + url.length;\n }\n if (cursor < text.length) parts.push(text.slice(cursor));\n\n return (\n <Text size=\"sm\" color=\"\" className=\"whitespace-pre-wrap\">\n {parts}\n </Text>\n );\n};\n","import { useMemo } from 'react';\nimport { SupportChatWidget } from './SupportChatWidget';\nimport { createGuestSupportChatAdapter } from './guestSupportChatAdapter';\nimport { useSupportFeatureFlag } from '../../hooks/useSupportFeatureFlag';\nimport { useAppStore } from '../../store/appStore';\nimport { useAuthStore } from '../../store/authStore';\nimport { SupportType, type SupportApiClient } from '../../types/support';\nimport type {\n SupportChatHttpClient,\n SupportChatTheme,\n} from '../../types/supportChat';\n\nexport interface NativeSupportChatProps {\n /** Client of the backend API (the app axios instance fits as it is) */\n apiClient: SupportApiClient & SupportChatHttpClient;\n /** App the chat runs in, sent with the ticket (e.g. \"aluno\", \"login\") */\n channel: string;\n /**\n * Extra condition of the app to show the chat, on top of the SUPPORT flag\n * (e.g. logged in and with the support module). Default: true.\n */\n enabled?: boolean;\n /**\n * Link of a FAQ article. Default: the FAQ address of the SUPPORT flag\n * (`<faqUrl>/artigo/<id>`).\n */\n faqArticleUrl?: (articleId: string) => string;\n /** Support WebSocket; without it the chat polls the REST API */\n wsUrl?: string;\n theme?: SupportChatTheme;\n}\n\n/**\n * Native support chat ready to drop in an app: reads the SUPPORT feature flag\n * of the institution (from the app store), the logged user (from the auth\n * store) and talks to the support API by itself.\n *\n * Shown only when the institution uses the native support with the internal\n * support and its chat switched on in the backoffice, once the flag is read,\n * and when `enabled`. With Zendesk it renders nothing (the app loads the\n * Zendesk widget). A logged user opens the ticket with their name and e-mail;\n * a visitor gives them to the AI on the first contact.\n *\n * @example\n * <NativeSupportChat apiClient={api} channel=\"aluno\" enabled={hasSupport} />\n */\nexport const NativeSupportChat = ({\n apiClient,\n channel,\n enabled = true,\n faqArticleUrl,\n wsUrl,\n theme,\n}: NativeSupportChatProps) => {\n const { institutionId } = useAppStore();\n const userName = useAuthStore(\n (state) => state.user?.name ?? state.sessionInfo?.userName\n );\n const userEmail = useAuthStore((state) => state.user?.email);\n const flag = useSupportFeatureFlag({ apiClient });\n const adapter = useMemo(\n () => createGuestSupportChatAdapter({ apiClient, wsUrl }),\n [apiClient, wsUrl]\n );\n\n const user =\n userName || userEmail ? { name: userName, email: userEmail } : undefined;\n\n return (\n <SupportChatWidget\n adapter={adapter}\n channel={channel}\n institutionId={institutionId || undefined}\n user={user}\n theme={theme}\n faqArticleUrl={faqArticleUrl ?? flag.faqArticleUrl}\n flags={{\n enabled: enabled && !flag.loading && flag.isNative && flag.chatEnabled,\n supportType: flag.isNative ? SupportType.NATIVE : SupportType.ZENDESK,\n }}\n />\n );\n};\n","import { isSupportTicketOrigin } from '../../types/support';\nimport {\n SUPPORT_CHAT_AUTHOR,\n SUPPORT_CHAT_GUEST_SENDER_ID,\n SUPPORT_CHAT_STATUS,\n type SupportChatAdapter,\n type SupportChatAnswerApi,\n type SupportChatArticle,\n type SupportChatEvent,\n type SupportChatHttpClient,\n type SupportChatMessage,\n type SupportChatTicket,\n} from '../../types/supportChat';\n\nexport interface GuestSupportChatAdapterOptions {\n /** Client of the backend API (e.g. the app axios instance) */\n apiClient: SupportChatHttpClient;\n /**\n * Support WebSocket, including ?channel=support (e.g.\n * wss://bff-hml-chat.analyticaensino.com.br?channel=support).\n * Without it the adapter only polls the REST API.\n */\n wsUrl?: string;\n /** Polling interval while the socket is not connected, in ms */\n pollIntervalMs?: number;\n /**\n * localStorage key of the open conversation, kept so a reload resumes it.\n * Default: `analytica:support-chat`.\n */\n storageKey?: string;\n}\n\n/** Open conversation kept across page loads */\ninterface StoredSupportChatSession {\n ticketId: string;\n token: string;\n name: string;\n /** E-mail of the logged user who opened it; null for a visitor */\n userEmail: string | null;\n /** Opening text the chat does not show (image-only start) */\n hiddenId?: string;\n}\n\nconst DEFAULT_STORAGE_KEY = 'analytica:support-chat';\n\n/** The browser may block storage (private mode, policies): never throw */\nconst readStoredSession = (key: string): StoredSupportChatSession | null => {\n try {\n const raw = globalThis.localStorage?.getItem(key);\n if (!raw) return null;\n const session = JSON.parse(raw) as Partial<StoredSupportChatSession>;\n return session.ticketId && session.token\n ? (session as StoredSupportChatSession)\n : null;\n } catch {\n return null;\n }\n};\n\nconst writeStoredSession = (key: string, session: StoredSupportChatSession) => {\n try {\n globalThis.localStorage?.setItem(key, JSON.stringify(session));\n } catch {\n // Not kept: a reload starts a new conversation, as before\n }\n};\n\nconst clearStoredSession = (key: string) => {\n try {\n globalThis.localStorage?.removeItem(key);\n } catch {\n // Nothing kept to clear\n }\n};\n\nconst statusOf = (error: unknown) =>\n (error as { response?: { status?: number } } | null)?.response?.status;\n\nconst GUEST_TOKEN_HEADER = 'x-support-guest-token';\n\nconst senderNameFor = (role: string, requesterName: string) => {\n if (role === SUPPORT_CHAT_AUTHOR.AGENT) return 'Suporte';\n if (role === SUPPORT_CHAT_AUTHOR.AI) return 'Assistente';\n return requesterName;\n};\n\n/** REST answer → widget message */\nexport const fromSupportAnswer = (\n answer: SupportChatAnswerApi,\n requesterName: string\n): SupportChatMessage => ({\n id: answer.id,\n senderId:\n answer.authorType === SUPPORT_CHAT_AUTHOR.GUEST\n ? SUPPORT_CHAT_GUEST_SENDER_ID\n : answer.authorType.toLowerCase(),\n senderName: senderNameFor(answer.authorType, requesterName),\n senderPhoto: null,\n senderRole: answer.authorType,\n content: answer.answer,\n messageType: 'text',\n createdAt: answer.createdAt,\n attachments: answer.attachments ?? [],\n faq:\n answer.faqArticleId && answer.faqArticleTitle\n ? { id: answer.faqArticleId, title: answer.faqArticleTitle }\n : null,\n contactRequest: answer.contactRequest ?? null,\n});\n\n/**\n * Support chat adapter for visitors (no login), on top of the support API:\n * - POST /support/external opens the ticket and returns the guest token;\n * - GET/POST /support/guest/:id/answer read and send, with the token header;\n * - the chat WebSocket (?channel=support&roomId=&token=) pushes the events,\n * and REST polling covers the time the socket is down.\n */\nexport const createGuestSupportChatAdapter = ({\n apiClient,\n wsUrl,\n pollIntervalMs = 3000,\n storageKey = DEFAULT_STORAGE_KEY,\n}: GuestSupportChatAdapterOptions): SupportChatAdapter => {\n const sessions = new Map<string, { token: string; name: string }>();\n /**\n * Ticket opening text written by the adapter (an image-only start still\n * needs a description). It is the ticket description for the agents, not\n * something the visitor typed, so the chat does not show it.\n */\n const hiddenIds = new Set<string>();\n const isVisible = (message: SupportChatMessage) => !hiddenIds.has(message.id);\n\n const headersFor = (ticketId: string) => ({\n [GUEST_TOKEN_HEADER]: sessions.get(ticketId)?.token ?? '',\n });\n const nameFor = (ticketId: string) =>\n sessions.get(ticketId)?.name ?? 'Visitante';\n\n const listMessages = async (ticketId: string) => {\n const { data } = await apiClient.get<{ data: SupportChatAnswerApi[] }>(\n `/support/guest/${ticketId}/answer`,\n { headers: headersFor(ticketId) }\n );\n return data.data\n .map((answer) => fromSupportAnswer(answer, nameFor(ticketId)))\n .filter(isVisible);\n };\n\n /**\n * Upload each file straight to the storage: ask the backend for a signed\n * URL, then PUT the file there. Returns what the message needs.\n */\n const uploadFiles = (ticketId: string, files: File[]) =>\n Promise.all(\n files.map(async (file) => {\n const { data } = await apiClient.post<{\n data: { uploadUrl: string; key: string; contentType: string };\n }>(\n `/support/guest/${ticketId}/upload-url`,\n { fileName: file.name, fileSize: file.size, mimeType: file.type },\n { headers: headersFor(ticketId) }\n );\n const { uploadUrl, key, contentType } = data.data;\n const response = await fetch(uploadUrl, {\n method: 'PUT',\n headers: { 'Content-Type': contentType },\n body: file,\n });\n if (!response.ok) {\n throw new Error(`Não foi possível enviar ${file.name}`);\n }\n return {\n key,\n fileName: file.name,\n mimeType: contentType,\n size: file.size,\n };\n })\n );\n\n const sendMessage = async (\n ticketId: string,\n content: string,\n files: File[] = []\n ) => {\n const attachments = await uploadFiles(ticketId, files);\n const { data } = await apiClient.post<{ data: SupportChatAnswerApi }>(\n `/support/guest/${ticketId}/answer`,\n { answer: content, attachments },\n { headers: headersFor(ticketId) }\n );\n return fromSupportAnswer(data.data, nameFor(ticketId));\n };\n\n return {\n async startConversation({\n message,\n channel,\n institutionId,\n requesterName,\n email,\n files = [],\n }) {\n // The ticket needs a description; an image-only start uses the names\n const description = message || files.map((file) => file.name).join(', ');\n const { data } = await apiClient.post<{\n data: { id: string; guestToken: string };\n }>('/support/external', {\n description,\n ...(institutionId ? { institutionId } : {}),\n ...(requesterName ? { requesterName } : {}),\n ...(email ? { email } : {}),\n // The app the chat runs in, when it is one the API knows\n ...(isSupportTicketOrigin(channel) ? { origin: channel } : {}),\n });\n const ticketId = data.data.id;\n const name = requesterName || 'Visitante';\n sessions.set(ticketId, { token: data.data.guestToken, name });\n\n // The first message is saved with the ticket; read it back for its id.\n // /support/external takes no files, so they go as the next message.\n let messages = await listMessages(ticketId);\n let hiddenId: string | undefined;\n if (!message && messages[0]) {\n hiddenId = messages[0].id;\n hiddenIds.add(hiddenId);\n messages = messages.slice(1);\n }\n writeStoredSession(storageKey, {\n ticketId,\n token: data.data.guestToken,\n name,\n userEmail: email ?? null,\n hiddenId,\n });\n if (files.length) messages.push(await sendMessage(ticketId, '', files));\n return {\n ticket: {\n id: ticketId,\n status: SUPPORT_CHAT_STATUS.ABERTO,\n handlerType: null,\n problemType: null,\n },\n messages,\n };\n },\n\n sendMessage,\n\n async getArticle(institutionId, articleId) {\n const { data } = await apiClient.get<{\n data: { article: SupportChatArticle };\n }>(`/help-center/${institutionId}/articles/${articleId}`);\n const { id, title, body, updatedAt } = data.data.article;\n return { id, title, body, updatedAt: updatedAt ?? null };\n },\n\n async updateContact(ticketId, contact) {\n if (!apiClient.put) {\n throw new Error('O cliente da API não envia PUT');\n }\n await apiClient.put(`/support/guest/${ticketId}`, contact, {\n headers: headersFor(ticketId),\n });\n const session = sessions.get(ticketId);\n if (session && contact.requesterName) {\n session.name = contact.requesterName;\n const stored = readStoredSession(storageKey);\n if (stored?.ticketId === ticketId) {\n writeStoredSession(storageKey, {\n ...stored,\n name: contact.requesterName,\n });\n }\n }\n },\n\n async restoreConversation({ email }) {\n const stored = readStoredSession(storageKey);\n if (!stored) return null;\n // Another account on this browser: that conversation is not theirs\n if (stored.userEmail !== (email ?? null)) {\n clearStoredSession(storageKey);\n return null;\n }\n\n const { ticketId } = stored;\n sessions.set(ticketId, { token: stored.token, name: stored.name });\n if (stored.hiddenId) hiddenIds.add(stored.hiddenId);\n try {\n const { data } = await apiClient.get<{ data: SupportChatTicket }>(\n `/support/guest/${ticketId}`,\n { headers: headersFor(ticketId) }\n );\n if (data.data.status === SUPPORT_CHAT_STATUS.FECHADO) {\n clearStoredSession(storageKey);\n return null;\n }\n return { ticket: data.data, messages: await listMessages(ticketId) };\n } catch (error) {\n // Ticket gone or token expired: it cannot be resumed. Any other\n // failure (offline) keeps it for the next load.\n if (statusOf(error) === 404) clearStoredSession(storageKey);\n sessions.delete(ticketId);\n return null;\n }\n },\n\n forgetConversation() {\n clearStoredSession(storageKey);\n },\n\n listMessages,\n\n subscribe(ticketId, listener) {\n // id → what the chat shows besides the text; a message seen again with\n // more of it (a stale WebSocket history may lack contactRequest/faq) is\n // delivered again so the chat replaces it\n const seen = new Map<string, string>();\n const extrasOf = (message: SupportChatMessage) =>\n JSON.stringify([message.contactRequest ?? null, message.faq ?? null]);\n const NO_EXTRAS = JSON.stringify([null, null]);\n let socket: WebSocket | null = null;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let active = true;\n\n const deliver = (message: SupportChatMessage) => {\n if (!isVisible(message)) return;\n const extras = extrasOf(message);\n const previous = seen.get(message.id);\n // Same as before, or a poorer copy: nothing new to show\n if (previous === extras || (previous && extras === NO_EXTRAS)) return;\n seen.set(message.id, extras);\n listener({ type: 'new_message', payload: { message } });\n };\n\n const poll = async () => {\n try {\n (await listMessages(ticketId)).forEach(deliver);\n } catch {\n // Next tick tries again\n }\n };\n const startPolling = () => {\n if (pollTimer || !active) return;\n void poll();\n pollTimer = setInterval(poll, pollIntervalMs);\n };\n const stopPolling = () => {\n if (pollTimer) clearInterval(pollTimer);\n pollTimer = null;\n };\n\n const handleFrame = (raw: string) => {\n let event: { type?: string; payload?: Record<string, unknown> };\n try {\n event = JSON.parse(raw);\n } catch {\n return;\n }\n const payload = event.payload ?? {};\n if (event.type === 'history') {\n (payload.messages as SupportChatMessage[]).forEach((message) =>\n deliver({ ...message, attachments: message.attachments ?? [] })\n );\n } else if (event.type === 'new_message') {\n const message = payload.message as SupportChatMessage;\n deliver({ ...message, attachments: message.attachments ?? [] });\n } else if (\n event.type === 'message_updated' ||\n event.type === 'ticket_updated'\n ) {\n listener(event as SupportChatEvent);\n } else if (event.type === 'error') {\n listener({\n type: 'error',\n payload: {\n message: String(payload.message_text ?? payload.message ?? ''),\n },\n });\n }\n };\n\n const token = sessions.get(ticketId)?.token;\n if (wsUrl && token) {\n const url = new URL(wsUrl);\n url.searchParams.set('channel', 'support');\n url.searchParams.set('roomId', ticketId);\n url.searchParams.set('token', token);\n socket = new WebSocket(url.toString());\n socket.onopen = () => {\n stopPolling();\n socket?.send(JSON.stringify({ type: 'getInitialData' }));\n // The REST API is the source of truth: a WebSocket deployed apart\n // from it may send a history without contactRequest/faq\n void poll();\n };\n socket.onmessage = (event) => handleFrame(String(event.data));\n socket.onclose = startPolling;\n socket.onerror = startPolling;\n } else {\n startPolling();\n }\n\n return () => {\n active = false;\n stopPolling();\n if (socket) {\n socket.onclose = null;\n socket.close();\n }\n };\n },\n };\n};\n","import {\n SUPPORT_CHAT_AUTHOR,\n SUPPORT_CHAT_GUEST_SENDER_ID,\n SUPPORT_CHAT_HANDLER,\n SUPPORT_CHAT_STATUS,\n type SupportChatAdapter,\n type SupportChatEvent,\n type SupportChatMessage,\n type SupportChatTicket,\n} from '../../types/supportChat';\n\nexport interface MockSupportChatAdapterOptions {\n /** Latency of every call, in ms (default 300) */\n delayMs?: number;\n /** Delay of the automatic agent reply, in ms (default 1500) */\n replyDelayMs?: number;\n /** Text of the agent reply; null disables it */\n replyText?: string | null;\n}\n\nconst DEFAULT_REPLY =\n 'Olá! Recebemos sua mensagem e já vamos te ajudar. Este é um atendimento de demonstração.';\n\n/**\n * In-memory adapter for the support chat widget. It mirrors the backend\n * contract (statuses, authors, events) so the widget can be built and tested\n * before the real API + WebSocket adapter exists.\n */\nexport const createMockSupportChatAdapter = ({\n delayMs = 300,\n replyDelayMs = 1500,\n replyText = DEFAULT_REPLY,\n}: MockSupportChatAdapterOptions = {}): SupportChatAdapter => {\n const tickets = new Map<string, SupportChatTicket>();\n const messages = new Map<string, SupportChatMessage[]>();\n const requesters = new Map<string, { name: string; logged: boolean }>();\n const listeners = new Map<string, Set<(event: SupportChatEvent) => void>>();\n let sequence = 0;\n\n const wait = () => new Promise((resolve) => setTimeout(resolve, delayMs));\n const nextId = (prefix: string) => `${prefix}-${++sequence}`;\n\n const emit = (ticketId: string, event: SupportChatEvent) => {\n listeners.get(ticketId)?.forEach((listener) => listener(event));\n };\n\n const append = (ticketId: string, message: SupportChatMessage) => {\n messages.set(ticketId, [...(messages.get(ticketId) ?? []), message]);\n };\n\n const toAttachments = (files: File[]) =>\n files.map((file) => ({\n id: nextId('file'),\n url: URL.createObjectURL(file),\n fileName: file.name,\n mimeType: file.type,\n size: file.size,\n }));\n\n const buildRequesterMessage = (\n ticketId: string,\n content: string,\n files: File[] = []\n ): SupportChatMessage => {\n const requester = requesters.get(ticketId);\n return {\n id: nextId('msg'),\n senderId: requester?.logged ? 'user' : SUPPORT_CHAT_GUEST_SENDER_ID,\n senderName: requester?.name ?? 'Visitante',\n senderPhoto: null,\n senderRole: requester?.logged\n ? SUPPORT_CHAT_AUTHOR.USER\n : SUPPORT_CHAT_AUTHOR.GUEST,\n content,\n messageType: 'text',\n createdAt: new Date().toISOString(),\n attachments: toAttachments(files),\n };\n };\n\n const scheduleReply = (ticketId: string) => {\n if (replyText === null) return;\n setTimeout(() => {\n const ticket = tickets.get(ticketId);\n if (!ticket) return;\n\n const reply: SupportChatMessage = {\n id: nextId('msg'),\n senderId: 'agent',\n senderName: 'Suporte',\n senderPhoto: null,\n senderRole: SUPPORT_CHAT_AUTHOR.AGENT,\n content: replyText,\n messageType: 'text',\n createdAt: new Date().toISOString(),\n attachments: [],\n };\n append(ticketId, reply);\n\n const updated: SupportChatTicket = {\n ...ticket,\n status: SUPPORT_CHAT_STATUS.EM_ANDAMENTO,\n handlerType: SUPPORT_CHAT_HANDLER.HUMANO,\n };\n tickets.set(ticketId, updated);\n\n emit(ticketId, { type: 'new_message', payload: { message: reply } });\n emit(ticketId, {\n type: 'ticket_updated',\n payload: {\n ticketId,\n status: updated.status,\n handlerType: updated.handlerType,\n problemType: updated.problemType,\n },\n });\n }, replyDelayMs);\n };\n\n return {\n async getArticle(_institutionId, articleId) {\n await wait();\n return {\n id: articleId,\n title: 'Como gerar e localizar simulados',\n body:\n '<p>Monte um simulado com as matérias que quiser e acompanhe o resultado. 📝</p>' +\n '<h2>Passo a passo</h2>' +\n '<ol><li><p>No menu, abra <strong>Simulados</strong>.</p></li>' +\n '<li><p>Clique em <strong>Gerar simulado</strong> e escolha as áreas.</p></li>' +\n '<li><p>Responda e veja o resultado em <strong>Histórico</strong>.</p></li></ol>' +\n '<p><a href=\"https://www.youtube.com/watch?v=dQw4w9WgXcQ\">Assista ao vídeo do passo a passo</a></p>' +\n '<blockquote><p>💡 Dica: refaça as questões que errou.</p></blockquote>',\n updatedAt: '2026-10-21T12:00:00.000Z',\n };\n },\n\n async startConversation({ message, requesterName, email, files }) {\n await wait();\n const ticket: SupportChatTicket = {\n id: nextId('ticket'),\n status: SUPPORT_CHAT_STATUS.ABERTO,\n handlerType: null,\n problemType: null,\n };\n tickets.set(ticket.id, ticket);\n requesters.set(ticket.id, {\n name: requesterName || 'Visitante',\n logged: Boolean(email),\n });\n\n const first = buildRequesterMessage(ticket.id, message, files);\n append(ticket.id, first);\n scheduleReply(ticket.id);\n return { ticket, messages: [first] };\n },\n\n async sendMessage(ticketId, content, files) {\n await wait();\n const ticket = tickets.get(ticketId);\n if (!ticket) throw new Error('Atendimento não encontrado');\n if (ticket.status === SUPPORT_CHAT_STATUS.FECHADO) {\n throw new Error('Este atendimento já foi encerrado');\n }\n\n const message = buildRequesterMessage(ticketId, content, files);\n append(ticketId, message);\n scheduleReply(ticketId);\n return message;\n },\n\n async listMessages(ticketId) {\n await wait();\n return [...(messages.get(ticketId) ?? [])];\n },\n\n subscribe(ticketId, listener) {\n const set = listeners.get(ticketId) ?? new Set();\n set.add(listener);\n listeners.set(ticketId, set);\n return () => {\n set.delete(listener);\n };\n },\n };\n};\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","XIcon","useState","useState","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","title","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","useState","useRef","useCallback","useEffect","XIcon","useMemo","jsx","useMemo"]}
@@ -15,13 +15,13 @@ var _chunkLUULWIKTjs = require('./chunk-LUULWIKT.js');
15
15
  var _chunkBSMYGZ5Qjs = require('./chunk-BSMYGZ5Q.js');
16
16
 
17
17
 
18
- var _chunkMNU45FM3js = require('./chunk-MNU45FM3.js');
18
+ var _chunkCOT4KW3Hjs = require('./chunk-COT4KW3H.js');
19
19
 
20
20
 
21
21
  var _chunkXVBSGC7Vjs = require('./chunk-XVBSGC7V.js');
22
22
 
23
23
 
24
- var _chunk23PAYKWBjs = require('./chunk-23PAYKWB.js');
24
+ var _chunkKM27ZDHZjs = require('./chunk-KM27ZDHZ.js');
25
25
 
26
26
 
27
27
  var _chunkXN2HPVVHjs = require('./chunk-XN2HPVVH.js');
@@ -180,7 +180,7 @@ function SupportConcludeModal({
180
180
  }
181
181
  };
182
182
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
183
- _chunk23PAYKWBjs.Modal_default,
183
+ _chunkKM27ZDHZjs.Modal_default,
184
184
  {
185
185
  isOpen,
186
186
  onClose,
@@ -294,7 +294,7 @@ function SupportConcludeModal({
294
294
  )
295
295
  ] }),
296
296
  _optionalChain([reason, 'optionalAccess', _9 => _9.suggestsTechTicket]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
297
- _chunkMNU45FM3js.CheckBox_default,
297
+ _chunkCOT4KW3Hjs.CheckBox_default,
298
298
  {
299
299
  size: "small",
300
300
  label: "Abrir ticket t\xE9cnico",
@@ -303,7 +303,7 @@ function SupportConcludeModal({
303
303
  }
304
304
  ),
305
305
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
306
- _chunkMNU45FM3js.CheckBox_default,
306
+ _chunkCOT4KW3Hjs.CheckBox_default,
307
307
  {
308
308
  size: "small",
309
309
  label: "Esta d\xFAvida deveria virar FAQ",
@@ -321,4 +321,4 @@ function SupportConcludeModal({
321
321
 
322
322
 
323
323
  exports.SUPPORT_CONCLUSION_REASONS = SUPPORT_CONCLUSION_REASONS; exports.SupportConcludeModal = SupportConcludeModal;
324
- //# sourceMappingURL=chunk-4OVIHZ3I.js.map
324
+ //# sourceMappingURL=chunk-CGXWWPEA.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-4OVIHZ3I.js","../src/components/SupportConcludeModal/SupportConcludeModal.tsx","../src/components/SupportConcludeModal/supportConclusionReasons.ts","../src/components/SupportConcludeModal/supportConclusionUtils.ts"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-4OVIHZ3I.js","sourcesContent":[null,"import { useEffect, useState } from 'react';\nimport Modal from '../Modal/Modal';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport Chips from '../Chips/Chips';\nimport TextArea from '../TextArea/TextArea';\nimport CheckBox from '../CheckBox/CheckBox';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport type { SupportApiClient } from '../../types/support';\nimport {\n SUPPORT_CONCLUSION_OUTCOME,\n type ConcludeSupportTicketRequest,\n type SupportConclusionFormData,\n type SupportConclusionOutcome,\n type SupportConclusionReason,\n} from '../../types/supportConclusion';\nimport { SUPPORT_CONCLUSION_REASONS } from './supportConclusionReasons';\nimport {\n buildConcludeTicketRequest,\n findConclusionReason,\n getConcludeTicketErrorMessage,\n isConclusionFormValid,\n} from './supportConclusionUtils';\n\n/**\n * Props for the \"Concluir atendimento\" modal\n */\nexport interface SupportConcludeModalProps {\n isOpen: boolean;\n onClose: () => void;\n /** Ticket id (uuid) used in `PATCH /support/admin/:id` */\n ticketId: string;\n /** Ticket number shown in the title, e.g. \"4808\" */\n ticketLabel?: string;\n /** API client of the consumer app (only `patch` is used) */\n apiClient: Pick<SupportApiClient, 'patch'>;\n /** Reasons catalog; defaults to the mocked reasons */\n reasons?: SupportConclusionReason[];\n /**\n * Called after the backend concludes the ticket, with every collected value\n * (including the ones the backend does not store yet) and the updated ticket\n */\n onConcluded?: (form: SupportConclusionFormData, ticket: unknown) => void;\n}\n\n/** Options of \"Resolvido?\" */\nconst OUTCOME_OPTIONS: { value: SupportConclusionOutcome; label: string }[] = [\n { value: SUPPORT_CONCLUSION_OUTCOME.RESOLVED, label: 'Sim, resolvido' },\n {\n value: SUPPORT_CONCLUSION_OUTCOME.NOT_RESOLVED_FORWARDED,\n label: 'Não resolvido (encaminhado)',\n },\n {\n value: SUPPORT_CONCLUSION_OUTCOME.NO_USER_RESPONSE,\n label: 'Sem resposta do usuário',\n },\n];\n\nconst INITIAL_FORM: SupportConclusionFormData = {\n reason: '',\n subReason: '',\n description: '',\n outcome: SUPPORT_CONCLUSION_OUTCOME.RESOLVED,\n internalNote: '',\n suggestFaq: false,\n openTechTicket: false,\n};\n\n/**\n * Bold section label of the form\n */\nfunction SectionLabel({ children }: Readonly<{ children: string }>) {\n return (\n <Text size=\"sm\" weight=\"bold\" color=\"text-text-950\">\n {children}\n </Text>\n );\n}\n\n/**\n * Modal that concludes a support ticket: classifies the reason, records the\n * outcome and an optional internal note, then closes the ticket in the\n * backend (`status: FECHADO` + `problemType` + `notes`).\n */\nexport default function SupportConcludeModal({\n isOpen,\n onClose,\n ticketId,\n ticketLabel,\n apiClient,\n reasons = SUPPORT_CONCLUSION_REASONS,\n onConcluded,\n}: Readonly<SupportConcludeModalProps>) {\n const [form, setForm] = useState<SupportConclusionFormData>(INITIAL_FORM);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (isOpen) {\n setForm(INITIAL_FORM);\n setError(null);\n }\n }, [isOpen]);\n\n const reason = findConclusionReason(reasons, form.reason);\n const hasSubReasons = !!reason && reason.subReasons.length > 0;\n const request =\n reason && isConclusionFormValid(form, reasons) && !isSubmitting\n ? buildConcludeTicketRequest(form, reason)\n : null;\n\n const updateForm = (changes: Partial<SupportConclusionFormData>) =>\n setForm((current) => ({ ...current, ...changes }));\n\n const handleReasonChange = (value: string) =>\n updateForm({\n reason: value,\n subReason: '',\n description: '',\n openTechTicket: false,\n });\n\n const submit = async (body: ConcludeSupportTicketRequest) => {\n setIsSubmitting(true);\n setError(null);\n try {\n const response = await apiClient.patch<unknown>(\n `/support/admin/${ticketId}`,\n body\n );\n onConcluded?.(form, response.data);\n onClose();\n } catch (requestError) {\n setError(getConcludeTicketErrorMessage(requestError));\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n size=\"md\"\n title={\n ticketLabel\n ? `Concluir atendimento #${ticketLabel}`\n : 'Concluir atendimento'\n }\n footer={\n <>\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onClose}\n disabled={isSubmitting}\n >\n Cancelar\n </Button>\n <Button\n variant=\"solid\"\n size=\"small\"\n onClick={request ? () => submit(request) : undefined}\n disabled={!request}\n >\n Concluir atendimento\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-4\">\n <Text size=\"sm\" color=\"text-text-600\">\n Esses dados são obrigatórios e alimentam o dashboard.\n </Text>\n\n <div className=\"flex flex-col gap-1.5\">\n <SectionLabel>Motivo da abertura *</SectionLabel>\n <div className=\"flex items-center gap-2\">\n <div className=\"min-w-0 flex-1\">\n <Select\n size=\"medium\"\n value={form.reason}\n onValueChange={handleReasonChange}\n >\n <SelectTrigger aria-label=\"Categoria\">\n <SelectValue placeholder=\"Selecione a categoria\" />\n </SelectTrigger>\n <SelectContent>\n {reasons.map((item) => (\n <SelectItem key={item.value} value={item.value}>\n {item.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"min-w-0 flex-1\">\n <Select\n key={form.reason}\n size=\"medium\"\n value={form.subReason}\n onValueChange={(value) => updateForm({ subReason: value })}\n >\n <SelectTrigger aria-label=\"Submotivo\" disabled={!hasSubReasons}>\n <SelectValue\n placeholder={\n hasSubReasons ? 'Selecione o submotivo' : 'Sem submotivos'\n }\n />\n </SelectTrigger>\n <SelectContent>\n {reason?.subReasons.map((item) => (\n <SelectItem key={item.value} value={item.value}>\n {item.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n {reason?.requiresDescription && (\n <TextArea\n label=\"Descreva o motivo *\"\n rows={3}\n maxLength={2000}\n placeholder=\"Explique o motivo do atendimento\"\n value={form.description}\n onChange={(event) =>\n updateForm({ description: event.target.value })\n }\n />\n )}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <SectionLabel>Resolvido?</SectionLabel>\n <div\n role=\"radiogroup\"\n aria-label=\"Resolvido?\"\n className=\"flex flex-wrap items-center gap-2\"\n >\n {OUTCOME_OPTIONS.map((option) => (\n <Chips\n key={option.value}\n role=\"radio\"\n aria-checked={form.outcome === option.value}\n selected={form.outcome === option.value}\n onClick={() => updateForm({ outcome: option.value })}\n >\n {option.label}\n </Chips>\n ))}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <SectionLabel>Observação interna</SectionLabel>\n <Text size=\"2xs\" color=\"text-text-600\">\n Opcional\n </Text>\n <TextArea\n aria-label=\"Observação interna\"\n rows={4}\n maxLength={2000}\n placeholder=\"Ex.: usuário orientado a limpar o cache; problema persistiu no Android 14\"\n value={form.internalNote}\n onChange={(event) =>\n updateForm({ internalNote: event.target.value })\n }\n />\n </div>\n\n {reason?.suggestsTechTicket && (\n <CheckBox\n size=\"small\"\n label=\"Abrir ticket técnico\"\n checked={form.openTechTicket}\n onChange={(event) =>\n updateForm({ openTechTicket: event.target.checked })\n }\n />\n )}\n\n <CheckBox\n size=\"small\"\n label=\"Esta dúvida deveria virar FAQ\"\n checked={form.suggestFaq}\n onChange={(event) => updateForm({ suggestFaq: event.target.checked })}\n />\n\n {error && (\n <Text size=\"sm\" color=\"text-error-600\" role=\"alert\">\n {error}\n </Text>\n )}\n </div>\n </Modal>\n );\n}\n","import {\n SUPPORT_PROBLEM_TYPE,\n type SupportConclusionReason,\n} from '../../types/supportConclusion';\n\n/**\n * Mocked conclusion reasons until the backend exposes a reasons catalog.\n * Each reason maps to one backend problem type.\n */\nexport const SUPPORT_CONCLUSION_REASONS: SupportConclusionReason[] = [\n {\n value: 'access',\n label: 'Acesso e login',\n problemType: SUPPORT_PROBLEM_TYPE.LOGIN,\n subReasons: [\n { value: 'forgot-password', label: 'Esqueci a senha' },\n { value: 'blocked-account', label: 'Conta bloqueada' },\n { value: 'email-not-received', label: 'Não recebo e-mail' },\n ],\n },\n {\n value: 'content',\n label: 'Conteúdo',\n problemType: SUPPORT_PROBLEM_TYPE.CONTENT,\n subReasons: [\n { value: 'video-not-loading', label: 'Vídeo não carrega' },\n { value: 'missing-material', label: 'Material ausente' },\n { value: 'activity-not-opening', label: 'Atividade não abre' },\n ],\n },\n {\n value: 'question-error',\n label: 'Erro em questão',\n problemType: SUPPORT_PROBLEM_TYPE.QUESTION_ERROR,\n subReasons: [\n { value: 'wrong-answer-key', label: 'Gabarito incorreto' },\n { value: 'statement-error', label: 'Enunciado com erro' },\n { value: 'wrong-grade', label: 'Nota incorreta' },\n ],\n },\n {\n value: 'platform-error',\n label: 'Erro da plataforma',\n problemType: SUPPORT_PROBLEM_TYPE.PLATFORM_ERROR,\n suggestsTechTicket: true,\n subReasons: [\n { value: 'bug', label: 'Bug' },\n { value: 'slowness', label: 'Lentidão' },\n { value: 'unavailable', label: 'Indisponibilidade' },\n ],\n },\n {\n value: 'other',\n label: 'Outros',\n problemType: SUPPORT_PROBLEM_TYPE.OTHER,\n requiresDescription: true,\n subReasons: [],\n },\n];\n","import {\n SUPPORT_CONCLUDED_STATUS,\n type ConcludeSupportTicketRequest,\n type SupportConclusionFormData,\n type SupportConclusionReason,\n} from '../../types/supportConclusion';\n\n/** Fallback shown when the API error has no message */\nexport const CONCLUDE_TICKET_ERROR_MESSAGE =\n 'Não foi possível concluir o atendimento.';\n\n/**\n * Extracts the API error message (`response.data.message`) of a failed request.\n *\n * @param error - Error thrown by the API client\n * @returns API message, or a generic fallback\n */\nexport function getConcludeTicketErrorMessage(error: unknown): string {\n const message = (error as { response?: { data?: { message?: unknown } } })\n ?.response?.data?.message;\n return typeof message === 'string' && message\n ? message\n : CONCLUDE_TICKET_ERROR_MESSAGE;\n}\n\n/**\n * Finds the selected reason in the catalog.\n *\n * @param reasons - Reasons catalog\n * @param value - Selected reason value\n * @returns The reason, or undefined when nothing (or an unknown value) is selected\n */\nexport function findConclusionReason(\n reasons: SupportConclusionReason[],\n value: string\n): SupportConclusionReason | undefined {\n return reasons.find((reason) => reason.value === value);\n}\n\n/**\n * Checks whether every required field of the conclusion form is filled:\n * a reason, its sub-reason (when it has any) and the description\n * (when the reason requires one).\n *\n * @param form - Current form values\n * @param reasons - Reasons catalog\n * @returns True when the ticket can be concluded\n */\nexport function isConclusionFormValid(\n form: SupportConclusionFormData,\n reasons: SupportConclusionReason[]\n): boolean {\n const reason = findConclusionReason(reasons, form.reason);\n if (!reason) return false;\n if (reason.subReasons.length > 0 && !form.subReason) return false;\n if (reason.requiresDescription && !form.description.trim()) return false;\n return true;\n}\n\n/**\n * Builds the `PATCH /support/admin/:id` body that concludes the ticket.\n * The reason description and the internal note go to `notes`, the only\n * free-text field the backend stores.\n *\n * @param form - Valid form values\n * @param reason - Selected reason\n * @returns Request body\n */\nexport function buildConcludeTicketRequest(\n form: SupportConclusionFormData,\n reason: SupportConclusionReason\n): ConcludeSupportTicketRequest {\n const description = reason.requiresDescription ? form.description.trim() : '';\n const notes = [description, form.internalNote.trim()]\n .filter((part) => part.length > 0)\n .join('\\n\\n');\n\n return {\n status: SUPPORT_CONCLUDED_STATUS,\n problemType: reason.problemType,\n notes: notes || null,\n };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-CGXWWPEA.js","../src/components/SupportConcludeModal/SupportConcludeModal.tsx","../src/components/SupportConcludeModal/supportConclusionReasons.ts","../src/components/SupportConcludeModal/supportConclusionUtils.ts"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-CGXWWPEA.js","sourcesContent":[null,"import { useEffect, useState } from 'react';\nimport Modal from '../Modal/Modal';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport Chips from '../Chips/Chips';\nimport TextArea from '../TextArea/TextArea';\nimport CheckBox from '../CheckBox/CheckBox';\nimport Select, {\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../Select/Select';\nimport type { SupportApiClient } from '../../types/support';\nimport {\n SUPPORT_CONCLUSION_OUTCOME,\n type ConcludeSupportTicketRequest,\n type SupportConclusionFormData,\n type SupportConclusionOutcome,\n type SupportConclusionReason,\n} from '../../types/supportConclusion';\nimport { SUPPORT_CONCLUSION_REASONS } from './supportConclusionReasons';\nimport {\n buildConcludeTicketRequest,\n findConclusionReason,\n getConcludeTicketErrorMessage,\n isConclusionFormValid,\n} from './supportConclusionUtils';\n\n/**\n * Props for the \"Concluir atendimento\" modal\n */\nexport interface SupportConcludeModalProps {\n isOpen: boolean;\n onClose: () => void;\n /** Ticket id (uuid) used in `PATCH /support/admin/:id` */\n ticketId: string;\n /** Ticket number shown in the title, e.g. \"4808\" */\n ticketLabel?: string;\n /** API client of the consumer app (only `patch` is used) */\n apiClient: Pick<SupportApiClient, 'patch'>;\n /** Reasons catalog; defaults to the mocked reasons */\n reasons?: SupportConclusionReason[];\n /**\n * Called after the backend concludes the ticket, with every collected value\n * (including the ones the backend does not store yet) and the updated ticket\n */\n onConcluded?: (form: SupportConclusionFormData, ticket: unknown) => void;\n}\n\n/** Options of \"Resolvido?\" */\nconst OUTCOME_OPTIONS: { value: SupportConclusionOutcome; label: string }[] = [\n { value: SUPPORT_CONCLUSION_OUTCOME.RESOLVED, label: 'Sim, resolvido' },\n {\n value: SUPPORT_CONCLUSION_OUTCOME.NOT_RESOLVED_FORWARDED,\n label: 'Não resolvido (encaminhado)',\n },\n {\n value: SUPPORT_CONCLUSION_OUTCOME.NO_USER_RESPONSE,\n label: 'Sem resposta do usuário',\n },\n];\n\nconst INITIAL_FORM: SupportConclusionFormData = {\n reason: '',\n subReason: '',\n description: '',\n outcome: SUPPORT_CONCLUSION_OUTCOME.RESOLVED,\n internalNote: '',\n suggestFaq: false,\n openTechTicket: false,\n};\n\n/**\n * Bold section label of the form\n */\nfunction SectionLabel({ children }: Readonly<{ children: string }>) {\n return (\n <Text size=\"sm\" weight=\"bold\" color=\"text-text-950\">\n {children}\n </Text>\n );\n}\n\n/**\n * Modal that concludes a support ticket: classifies the reason, records the\n * outcome and an optional internal note, then closes the ticket in the\n * backend (`status: FECHADO` + `problemType` + `notes`).\n */\nexport default function SupportConcludeModal({\n isOpen,\n onClose,\n ticketId,\n ticketLabel,\n apiClient,\n reasons = SUPPORT_CONCLUSION_REASONS,\n onConcluded,\n}: Readonly<SupportConcludeModalProps>) {\n const [form, setForm] = useState<SupportConclusionFormData>(INITIAL_FORM);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (isOpen) {\n setForm(INITIAL_FORM);\n setError(null);\n }\n }, [isOpen]);\n\n const reason = findConclusionReason(reasons, form.reason);\n const hasSubReasons = !!reason && reason.subReasons.length > 0;\n const request =\n reason && isConclusionFormValid(form, reasons) && !isSubmitting\n ? buildConcludeTicketRequest(form, reason)\n : null;\n\n const updateForm = (changes: Partial<SupportConclusionFormData>) =>\n setForm((current) => ({ ...current, ...changes }));\n\n const handleReasonChange = (value: string) =>\n updateForm({\n reason: value,\n subReason: '',\n description: '',\n openTechTicket: false,\n });\n\n const submit = async (body: ConcludeSupportTicketRequest) => {\n setIsSubmitting(true);\n setError(null);\n try {\n const response = await apiClient.patch<unknown>(\n `/support/admin/${ticketId}`,\n body\n );\n onConcluded?.(form, response.data);\n onClose();\n } catch (requestError) {\n setError(getConcludeTicketErrorMessage(requestError));\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Modal\n isOpen={isOpen}\n onClose={onClose}\n size=\"md\"\n title={\n ticketLabel\n ? `Concluir atendimento #${ticketLabel}`\n : 'Concluir atendimento'\n }\n footer={\n <>\n <Button\n variant=\"outline\"\n size=\"small\"\n onClick={onClose}\n disabled={isSubmitting}\n >\n Cancelar\n </Button>\n <Button\n variant=\"solid\"\n size=\"small\"\n onClick={request ? () => submit(request) : undefined}\n disabled={!request}\n >\n Concluir atendimento\n </Button>\n </>\n }\n >\n <div className=\"flex flex-col gap-4\">\n <Text size=\"sm\" color=\"text-text-600\">\n Esses dados são obrigatórios e alimentam o dashboard.\n </Text>\n\n <div className=\"flex flex-col gap-1.5\">\n <SectionLabel>Motivo da abertura *</SectionLabel>\n <div className=\"flex items-center gap-2\">\n <div className=\"min-w-0 flex-1\">\n <Select\n size=\"medium\"\n value={form.reason}\n onValueChange={handleReasonChange}\n >\n <SelectTrigger aria-label=\"Categoria\">\n <SelectValue placeholder=\"Selecione a categoria\" />\n </SelectTrigger>\n <SelectContent>\n {reasons.map((item) => (\n <SelectItem key={item.value} value={item.value}>\n {item.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"min-w-0 flex-1\">\n <Select\n key={form.reason}\n size=\"medium\"\n value={form.subReason}\n onValueChange={(value) => updateForm({ subReason: value })}\n >\n <SelectTrigger aria-label=\"Submotivo\" disabled={!hasSubReasons}>\n <SelectValue\n placeholder={\n hasSubReasons ? 'Selecione o submotivo' : 'Sem submotivos'\n }\n />\n </SelectTrigger>\n <SelectContent>\n {reason?.subReasons.map((item) => (\n <SelectItem key={item.value} value={item.value}>\n {item.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n {reason?.requiresDescription && (\n <TextArea\n label=\"Descreva o motivo *\"\n rows={3}\n maxLength={2000}\n placeholder=\"Explique o motivo do atendimento\"\n value={form.description}\n onChange={(event) =>\n updateForm({ description: event.target.value })\n }\n />\n )}\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <SectionLabel>Resolvido?</SectionLabel>\n <div\n role=\"radiogroup\"\n aria-label=\"Resolvido?\"\n className=\"flex flex-wrap items-center gap-2\"\n >\n {OUTCOME_OPTIONS.map((option) => (\n <Chips\n key={option.value}\n role=\"radio\"\n aria-checked={form.outcome === option.value}\n selected={form.outcome === option.value}\n onClick={() => updateForm({ outcome: option.value })}\n >\n {option.label}\n </Chips>\n ))}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <SectionLabel>Observação interna</SectionLabel>\n <Text size=\"2xs\" color=\"text-text-600\">\n Opcional\n </Text>\n <TextArea\n aria-label=\"Observação interna\"\n rows={4}\n maxLength={2000}\n placeholder=\"Ex.: usuário orientado a limpar o cache; problema persistiu no Android 14\"\n value={form.internalNote}\n onChange={(event) =>\n updateForm({ internalNote: event.target.value })\n }\n />\n </div>\n\n {reason?.suggestsTechTicket && (\n <CheckBox\n size=\"small\"\n label=\"Abrir ticket técnico\"\n checked={form.openTechTicket}\n onChange={(event) =>\n updateForm({ openTechTicket: event.target.checked })\n }\n />\n )}\n\n <CheckBox\n size=\"small\"\n label=\"Esta dúvida deveria virar FAQ\"\n checked={form.suggestFaq}\n onChange={(event) => updateForm({ suggestFaq: event.target.checked })}\n />\n\n {error && (\n <Text size=\"sm\" color=\"text-error-600\" role=\"alert\">\n {error}\n </Text>\n )}\n </div>\n </Modal>\n );\n}\n","import {\n SUPPORT_PROBLEM_TYPE,\n type SupportConclusionReason,\n} from '../../types/supportConclusion';\n\n/**\n * Mocked conclusion reasons until the backend exposes a reasons catalog.\n * Each reason maps to one backend problem type.\n */\nexport const SUPPORT_CONCLUSION_REASONS: SupportConclusionReason[] = [\n {\n value: 'access',\n label: 'Acesso e login',\n problemType: SUPPORT_PROBLEM_TYPE.LOGIN,\n subReasons: [\n { value: 'forgot-password', label: 'Esqueci a senha' },\n { value: 'blocked-account', label: 'Conta bloqueada' },\n { value: 'email-not-received', label: 'Não recebo e-mail' },\n ],\n },\n {\n value: 'content',\n label: 'Conteúdo',\n problemType: SUPPORT_PROBLEM_TYPE.CONTENT,\n subReasons: [\n { value: 'video-not-loading', label: 'Vídeo não carrega' },\n { value: 'missing-material', label: 'Material ausente' },\n { value: 'activity-not-opening', label: 'Atividade não abre' },\n ],\n },\n {\n value: 'question-error',\n label: 'Erro em questão',\n problemType: SUPPORT_PROBLEM_TYPE.QUESTION_ERROR,\n subReasons: [\n { value: 'wrong-answer-key', label: 'Gabarito incorreto' },\n { value: 'statement-error', label: 'Enunciado com erro' },\n { value: 'wrong-grade', label: 'Nota incorreta' },\n ],\n },\n {\n value: 'platform-error',\n label: 'Erro da plataforma',\n problemType: SUPPORT_PROBLEM_TYPE.PLATFORM_ERROR,\n suggestsTechTicket: true,\n subReasons: [\n { value: 'bug', label: 'Bug' },\n { value: 'slowness', label: 'Lentidão' },\n { value: 'unavailable', label: 'Indisponibilidade' },\n ],\n },\n {\n value: 'other',\n label: 'Outros',\n problemType: SUPPORT_PROBLEM_TYPE.OTHER,\n requiresDescription: true,\n subReasons: [],\n },\n];\n","import {\n SUPPORT_CONCLUDED_STATUS,\n type ConcludeSupportTicketRequest,\n type SupportConclusionFormData,\n type SupportConclusionReason,\n} from '../../types/supportConclusion';\n\n/** Fallback shown when the API error has no message */\nexport const CONCLUDE_TICKET_ERROR_MESSAGE =\n 'Não foi possível concluir o atendimento.';\n\n/**\n * Extracts the API error message (`response.data.message`) of a failed request.\n *\n * @param error - Error thrown by the API client\n * @returns API message, or a generic fallback\n */\nexport function getConcludeTicketErrorMessage(error: unknown): string {\n const message = (error as { response?: { data?: { message?: unknown } } })\n ?.response?.data?.message;\n return typeof message === 'string' && message\n ? message\n : CONCLUDE_TICKET_ERROR_MESSAGE;\n}\n\n/**\n * Finds the selected reason in the catalog.\n *\n * @param reasons - Reasons catalog\n * @param value - Selected reason value\n * @returns The reason, or undefined when nothing (or an unknown value) is selected\n */\nexport function findConclusionReason(\n reasons: SupportConclusionReason[],\n value: string\n): SupportConclusionReason | undefined {\n return reasons.find((reason) => reason.value === value);\n}\n\n/**\n * Checks whether every required field of the conclusion form is filled:\n * a reason, its sub-reason (when it has any) and the description\n * (when the reason requires one).\n *\n * @param form - Current form values\n * @param reasons - Reasons catalog\n * @returns True when the ticket can be concluded\n */\nexport function isConclusionFormValid(\n form: SupportConclusionFormData,\n reasons: SupportConclusionReason[]\n): boolean {\n const reason = findConclusionReason(reasons, form.reason);\n if (!reason) return false;\n if (reason.subReasons.length > 0 && !form.subReason) return false;\n if (reason.requiresDescription && !form.description.trim()) return false;\n return true;\n}\n\n/**\n * Builds the `PATCH /support/admin/:id` body that concludes the ticket.\n * The reason description and the internal note go to `notes`, the only\n * free-text field the backend stores.\n *\n * @param form - Valid form values\n * @param reason - Selected reason\n * @returns Request body\n */\nexport function buildConcludeTicketRequest(\n form: SupportConclusionFormData,\n reason: SupportConclusionReason\n): ConcludeSupportTicketRequest {\n const description = reason.requiresDescription ? form.description.trim() : '';\n const notes = [description, form.internalNote.trim()]\n .filter((part) => part.length > 0)\n .join('\\n\\n');\n\n return {\n status: SUPPORT_CONCLUDED_STATUS,\n problemType: reason.problemType,\n notes: notes || null,\n };\n}\n"]}
@@ -140,7 +140,7 @@ var CheckBox = _react.forwardRef.call(void 0,
140
140
  "div",
141
141
  {
142
142
  className: _chunkTN3AYOMVjs.cn.call(void 0,
143
- "flex flex-row items-center",
143
+ "relative flex flex-row items-center",
144
144
  sizeClasses.spacing,
145
145
  disabled ? "opacity-40" : ""
146
146
  ),
@@ -214,4 +214,4 @@ var CheckBox_default = CheckBox;
214
214
 
215
215
 
216
216
  exports.CheckBox_default = CheckBox_default;
217
- //# sourceMappingURL=chunk-MNU45FM3.js.map
217
+ //# sourceMappingURL=chunk-COT4KW3H.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-MNU45FM3.js","../src/components/CheckBox/CheckBox.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-MNU45FM3.js","sourcesContent":[null,"import {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n} from 'react';\nimport Text from '../Text/Text';\nimport { CheckIcon } from '@phosphor-icons/react/dist/csr/Check';\nimport { MinusIcon } from '@phosphor-icons/react/dist/csr/Minus';\nimport { cn } from '../../utils/utils';\n\n/**\n * CheckBox size variants\n */\ntype CheckBoxSize = 'small' | 'medium' | 'large';\n\n/**\n * CheckBox visual state\n */\ntype CheckBoxState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n checkbox: 'w-4 h-4', // 16px x 16px\n textSize: 'sm' as const,\n spacing: 'gap-1.5', // 6px\n borderWidth: 'border-2',\n iconSize: 14, // pixels for Phosphor icons\n labelHeight: 'h-[21px]',\n },\n medium: {\n checkbox: 'w-5 h-5', // 20px x 20px\n textSize: 'md' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2',\n iconSize: 16, // pixels for Phosphor icons\n labelHeight: 'h-6',\n },\n large: {\n checkbox: 'w-6 h-6', // 24px x 24px\n textSize: 'lg' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-[3px]', // 3px border\n iconSize: 20, // pixels for Phosphor icons\n labelHeight: 'h-[27px]',\n },\n} as const;\n\n/**\n * Base checkbox styling classes using design system colors\n */\nconst BASE_CHECKBOX_CLASSES =\n 'rounded border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked:\n 'border-primary-950 bg-primary-950 text-text hover:border-primary-800 hover:bg-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background',\n checked: 'border-primary-800 bg-primary-800 text-text',\n },\n focused: {\n unchecked:\n 'border-indicator-info bg-background ring-2 ring-indicator-info/20',\n checked:\n 'border-indicator-info bg-primary-950 text-text ring-2 ring-indicator-info/20',\n },\n invalid: {\n unchecked: 'border-error-700 bg-background hover:border-error-600',\n checked: 'border-error-700 bg-primary-950 text-text',\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed opacity-40',\n checked:\n 'border-primary-600 bg-primary-600 text-text cursor-not-allowed opacity-40',\n },\n} as const;\n\n/**\n * CheckBox component props interface\n */\nexport type CheckBoxProps = {\n /** Label text to display next to the checkbox */\n label?: ReactNode;\n /** Size variant of the checkbox */\n size?: CheckBoxSize;\n /** Visual state of the checkbox */\n state?: CheckBoxState;\n /** Indeterminate state for partial selections */\n indeterminate?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'>;\n\n/**\n * CheckBox component for Analytica Ensino platforms\n *\n * A checkbox component with essential states, sizes and themes.\n * Uses the Analytica Ensino Design System colors from styles.css with automatic\n * light/dark mode support. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic checkbox\n * <CheckBox label=\"Option\" />\n *\n * // Small size\n * <CheckBox size=\"small\" label=\"Small option\" />\n *\n * // Invalid state\n * <CheckBox state=\"invalid\" label=\"Required field\" />\n *\n * // Disabled state\n * <CheckBox disabled label=\"Disabled option\" />\n * ```\n */\nconst CheckBox = forwardRef<HTMLInputElement, CheckBoxProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n indeterminate = false,\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n disabled,\n id,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `checkbox-${generatedId}`;\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalChecked(event.target.checked);\n }\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Determine checkbox visual variant\n const checkVariant = checked || indeterminate ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][checkVariant];\n\n // Special border width handling for focused/hovered states and large size\n const borderWidthClass =\n state === 'focused' || (state === 'hovered' && size === 'large')\n ? 'border-[3px]'\n : sizeClasses.borderWidth;\n\n // Get final checkbox classes\n const checkboxClasses = cn(\n BASE_CHECKBOX_CLASSES,\n sizeClasses.checkbox,\n borderWidthClass,\n stylingClasses,\n className\n );\n\n // Render appropriate icon based on state\n const renderIcon = () => {\n if (indeterminate) {\n return (\n <MinusIcon\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n if (checked) {\n return (\n <CheckIcon\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n return null;\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.spacing,\n disabled ? 'opacity-40' : ''\n )}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={ref}\n type=\"checkbox\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n onChange={handleChange}\n className=\"sr-only\"\n {...props}\n />\n\n {/* Custom styled checkbox */}\n <label htmlFor={inputId} className={checkboxClasses}>\n {/* Show appropriate icon based on state */}\n {renderIcon()}\n </label>\n\n {/* Label text */}\n {label && (\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.labelHeight\n )}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={cn(\n 'cursor-pointer select-none leading-[150%] flex items-center font-roboto',\n labelClassName\n )}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nCheckBox.displayName = 'CheckBox';\n\nexport default CheckBox;\n"]}
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-COT4KW3H.js","../src/components/CheckBox/CheckBox.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-COT4KW3H.js","sourcesContent":[null,"import {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n} from 'react';\nimport Text from '../Text/Text';\nimport { CheckIcon } from '@phosphor-icons/react/dist/csr/Check';\nimport { MinusIcon } from '@phosphor-icons/react/dist/csr/Minus';\nimport { cn } from '../../utils/utils';\n\n/**\n * CheckBox size variants\n */\ntype CheckBoxSize = 'small' | 'medium' | 'large';\n\n/**\n * CheckBox visual state\n */\ntype CheckBoxState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n checkbox: 'w-4 h-4', // 16px x 16px\n textSize: 'sm' as const,\n spacing: 'gap-1.5', // 6px\n borderWidth: 'border-2',\n iconSize: 14, // pixels for Phosphor icons\n labelHeight: 'h-[21px]',\n },\n medium: {\n checkbox: 'w-5 h-5', // 20px x 20px\n textSize: 'md' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2',\n iconSize: 16, // pixels for Phosphor icons\n labelHeight: 'h-6',\n },\n large: {\n checkbox: 'w-6 h-6', // 24px x 24px\n textSize: 'lg' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-[3px]', // 3px border\n iconSize: 20, // pixels for Phosphor icons\n labelHeight: 'h-[27px]',\n },\n} as const;\n\n/**\n * Base checkbox styling classes using design system colors\n */\nconst BASE_CHECKBOX_CLASSES =\n 'rounded border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked:\n 'border-primary-950 bg-primary-950 text-text hover:border-primary-800 hover:bg-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background',\n checked: 'border-primary-800 bg-primary-800 text-text',\n },\n focused: {\n unchecked:\n 'border-indicator-info bg-background ring-2 ring-indicator-info/20',\n checked:\n 'border-indicator-info bg-primary-950 text-text ring-2 ring-indicator-info/20',\n },\n invalid: {\n unchecked: 'border-error-700 bg-background hover:border-error-600',\n checked: 'border-error-700 bg-primary-950 text-text',\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed opacity-40',\n checked:\n 'border-primary-600 bg-primary-600 text-text cursor-not-allowed opacity-40',\n },\n} as const;\n\n/**\n * CheckBox component props interface\n */\nexport type CheckBoxProps = {\n /** Label text to display next to the checkbox */\n label?: ReactNode;\n /** Size variant of the checkbox */\n size?: CheckBoxSize;\n /** Visual state of the checkbox */\n state?: CheckBoxState;\n /** Indeterminate state for partial selections */\n indeterminate?: boolean;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'>;\n\n/**\n * CheckBox component for Analytica Ensino platforms\n *\n * A checkbox component with essential states, sizes and themes.\n * Uses the Analytica Ensino Design System colors from styles.css with automatic\n * light/dark mode support. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic checkbox\n * <CheckBox label=\"Option\" />\n *\n * // Small size\n * <CheckBox size=\"small\" label=\"Small option\" />\n *\n * // Invalid state\n * <CheckBox state=\"invalid\" label=\"Required field\" />\n *\n * // Disabled state\n * <CheckBox disabled label=\"Disabled option\" />\n * ```\n */\nconst CheckBox = forwardRef<HTMLInputElement, CheckBoxProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n indeterminate = false,\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n disabled,\n id,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `checkbox-${generatedId}`;\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalChecked(event.target.checked);\n }\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Determine checkbox visual variant\n const checkVariant = checked || indeterminate ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][checkVariant];\n\n // Special border width handling for focused/hovered states and large size\n const borderWidthClass =\n state === 'focused' || (state === 'hovered' && size === 'large')\n ? 'border-[3px]'\n : sizeClasses.borderWidth;\n\n // Get final checkbox classes\n const checkboxClasses = cn(\n BASE_CHECKBOX_CLASSES,\n sizeClasses.checkbox,\n borderWidthClass,\n stylingClasses,\n className\n );\n\n // Render appropriate icon based on state\n const renderIcon = () => {\n if (indeterminate) {\n return (\n <MinusIcon\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n if (checked) {\n return (\n <CheckIcon\n size={sizeClasses.iconSize}\n weight=\"bold\"\n color=\"currentColor\"\n />\n );\n }\n\n return null;\n };\n\n return (\n <div className=\"flex flex-col\">\n {/*\n * `relative` anchors the `sr-only` input (absolutely positioned) to\n * this row. Without it the input is positioned against the nearest\n * positioned ancestor — inside a Modal, the <dialog> itself — and\n * ignores how far a scrolled list moved. Focusing it on click then\n * scrolled the dialog to \"reveal\" it and pushed the whole modal out of\n * view, leaving a blank box (AE-3237).\n */}\n <div\n className={cn(\n 'relative flex flex-row items-center',\n sizeClasses.spacing,\n disabled ? 'opacity-40' : ''\n )}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={ref}\n type=\"checkbox\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n onChange={handleChange}\n className=\"sr-only\"\n {...props}\n />\n\n {/* Custom styled checkbox */}\n <label htmlFor={inputId} className={checkboxClasses}>\n {/* Show appropriate icon based on state */}\n {renderIcon()}\n </label>\n\n {/* Label text */}\n {label && (\n <div\n className={cn(\n 'flex flex-row items-center',\n sizeClasses.labelHeight\n )}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={cn(\n 'cursor-pointer select-none leading-[150%] flex items-center font-roboto',\n labelClassName\n )}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nCheckBox.displayName = 'CheckBox';\n\nexport default CheckBox;\n"]}
@@ -13,7 +13,7 @@ var _chunkUJWCE4XPjs = require('./chunk-UJWCE4XP.js');
13
13
  var _chunkJVDEOFXDjs = require('./chunk-JVDEOFXD.js');
14
14
 
15
15
 
16
- var _chunk23PAYKWBjs = require('./chunk-23PAYKWB.js');
16
+ var _chunkKM27ZDHZjs = require('./chunk-KM27ZDHZ.js');
17
17
 
18
18
 
19
19
  var _chunkXN2HPVVHjs = require('./chunk-XN2HPVVH.js');
@@ -785,7 +785,7 @@ function ComparatorView({
785
785
  )) }),
786
786
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "main", { className: "flex-1 overflow-auto p-6", children: renderMainContent() }),
787
787
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
788
- _chunk23PAYKWBjs.Modal_default,
788
+ _chunkKM27ZDHZjs.Modal_default,
789
789
  {
790
790
  isOpen: isModalOpen,
791
791
  onClose: handleCloseModal,
@@ -850,4 +850,4 @@ function ComparatorView({
850
850
 
851
851
 
852
852
  exports.Legend = Legend; exports.PercentageScale = PercentageScale; exports.ChartArea = ChartArea; exports.BarChartRow = BarChartRow; exports.KnowledgeAreasContent = KnowledgeAreasContent; exports.CurricularComponentsContent = CurricularComponentsContent; exports.CompetenciesContent = CompetenciesContent; exports.NationalAverageCard = NationalAverageCard; exports.NationalAveragesContent = NationalAveragesContent; exports.ComparatorEmptyState = ComparatorEmptyState; exports.ComparatorLoadingState = ComparatorLoadingState; exports.ComparatorSelectTypeStep = ComparatorSelectTypeStep; exports.ComparatorSelectItemsStep = ComparatorSelectItemsStep; exports.ComparatorTabContent = ComparatorTabContent; exports.ComparatorView = ComparatorView;
853
- //# sourceMappingURL=chunk-JDQUXG75.js.map
853
+ //# sourceMappingURL=chunk-CVDNCU6L.js.map