analytica-frontend-lib 1.5.39 → 1.5.41

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 (130) hide show
  1. package/dist/ActivitiesHistory/index.js +11 -11
  2. package/dist/ActivitiesHistory/index.mjs +10 -10
  3. package/dist/ActivityCardQuestionBanks/index.js +11 -11
  4. package/dist/ActivityCardQuestionBanks/index.mjs +10 -10
  5. package/dist/ActivityCardQuestionPreview/index.js +11 -11
  6. package/dist/ActivityCardQuestionPreview/index.mjs +10 -10
  7. package/dist/ActivityCreate/index.js +11 -11
  8. package/dist/ActivityCreate/index.mjs +10 -10
  9. package/dist/ActivityDetails/index.js +11 -11
  10. package/dist/ActivityDetails/index.mjs +10 -10
  11. package/dist/ActivityFilters/index.js +11 -11
  12. package/dist/ActivityFilters/index.mjs +10 -10
  13. package/dist/ActivityPageLayout/index.js +11 -11
  14. package/dist/ActivityPageLayout/index.mjs +10 -10
  15. package/dist/ActivityPreview/index.js +11 -11
  16. package/dist/ActivityPreview/index.mjs +10 -10
  17. package/dist/AlertManager/index.js +11 -11
  18. package/dist/AlertManager/index.mjs +10 -10
  19. package/dist/AppHeader/index.d.ts.map +1 -1
  20. package/dist/AppHeader/index.js +5 -5
  21. package/dist/AppHeader/index.mjs +4 -4
  22. package/dist/CalendarCard/index.d.ts.map +1 -1
  23. package/dist/CalendarCard/index.js +3 -3
  24. package/dist/CalendarCard/index.mjs +2 -2
  25. package/dist/CheckBoxGroup/index.js +11 -11
  26. package/dist/CheckBoxGroup/index.mjs +10 -10
  27. package/dist/DropdownMenu/index.d.ts +8 -0
  28. package/dist/DropdownMenu/index.d.ts.map +1 -1
  29. package/dist/DropdownMenu/index.js +2 -2
  30. package/dist/DropdownMenu/index.mjs +1 -1
  31. package/dist/ExamDetailsLayout/ExamDetailsPage/index.js +11 -11
  32. package/dist/ExamDetailsLayout/ExamDetailsPage/index.mjs +10 -10
  33. package/dist/ExamPageLayout/index.js +11 -11
  34. package/dist/ExamPageLayout/index.mjs +10 -10
  35. package/dist/Forum/index.js +3 -3
  36. package/dist/Forum/index.mjs +2 -2
  37. package/dist/NotificationCard/index.js +3 -3
  38. package/dist/NotificationCard/index.mjs +2 -2
  39. package/dist/PrintableUsersTable/index.js +11 -11
  40. package/dist/PrintableUsersTable/index.mjs +10 -10
  41. package/dist/RecommendedLessonCreate/index.js +11 -11
  42. package/dist/RecommendedLessonCreate/index.mjs +10 -10
  43. package/dist/RecommendedLessonsHistory/index.js +11 -11
  44. package/dist/RecommendedLessonsHistory/index.mjs +10 -10
  45. package/dist/Search/index.js +3 -3
  46. package/dist/Search/index.mjs +2 -2
  47. package/dist/SendActivityModal/SendActivityModal.js +11 -11
  48. package/dist/SendActivityModal/SendActivityModal.mjs +10 -10
  49. package/dist/SendActivityModal/index.js +11 -11
  50. package/dist/SendActivityModal/index.mjs +10 -10
  51. package/dist/SendLessonModal/index.js +11 -11
  52. package/dist/SendLessonModal/index.mjs +10 -10
  53. package/dist/SimulatedPerformance/SimulatedPerformanceView/index.js +11 -11
  54. package/dist/SimulatedPerformance/SimulatedPerformanceView/index.mjs +10 -10
  55. package/dist/SimulationsPage/index.js +11 -11
  56. package/dist/SimulationsPage/index.mjs +10 -10
  57. package/dist/TableProvider/index.js +11 -11
  58. package/dist/TableProvider/index.mjs +10 -10
  59. package/dist/UnifiedDraftModelPage/index.js +11 -11
  60. package/dist/UnifiedDraftModelPage/index.mjs +10 -10
  61. package/dist/UnifiedHistoryPage/index.js +11 -11
  62. package/dist/UnifiedHistoryPage/index.mjs +10 -10
  63. package/dist/{chunk-OCIBLTVL.js → chunk-2DPLSITC.js} +58 -31
  64. package/dist/chunk-2DPLSITC.js.map +1 -0
  65. package/dist/{chunk-Q5VRX5TR.js → chunk-4SBNOQ4H.js} +6 -5
  66. package/dist/chunk-4SBNOQ4H.js.map +1 -0
  67. package/dist/{chunk-AFBTGILL.mjs → chunk-4TBI57KA.mjs} +20 -13
  68. package/dist/{chunk-AFBTGILL.mjs.map → chunk-4TBI57KA.mjs.map} +1 -1
  69. package/dist/{chunk-MTZ6C74W.js → chunk-55TDQZMC.js} +10 -6
  70. package/dist/chunk-55TDQZMC.js.map +1 -0
  71. package/dist/{chunk-SIER6LRJ.mjs → chunk-66A37LW7.mjs} +6 -2
  72. package/dist/chunk-66A37LW7.mjs.map +1 -0
  73. package/dist/{chunk-EWG6Q2QF.mjs → chunk-6MZEJVNV.mjs} +3 -2
  74. package/dist/{chunk-EWG6Q2QF.mjs.map → chunk-6MZEJVNV.mjs.map} +1 -1
  75. package/dist/{chunk-FA6GCOJW.js → chunk-DH6WK44A.js} +7 -7
  76. package/dist/{chunk-FA6GCOJW.js.map → chunk-DH6WK44A.js.map} +1 -1
  77. package/dist/{chunk-MVEXCJVJ.js → chunk-DOIJGYYP.js} +10 -10
  78. package/dist/{chunk-MVEXCJVJ.js.map → chunk-DOIJGYYP.js.map} +1 -1
  79. package/dist/{chunk-LH4UP3H6.mjs → chunk-DTVNS6NN.mjs} +2 -2
  80. package/dist/{chunk-HFY4S3JV.mjs → chunk-GAKQ52B6.mjs} +2 -2
  81. package/dist/chunk-GAKQ52B6.mjs.map +1 -0
  82. package/dist/{chunk-2MDHKQ33.js → chunk-KHES64RG.js} +6 -6
  83. package/dist/{chunk-2MDHKQ33.js.map → chunk-KHES64RG.js.map} +1 -1
  84. package/dist/{chunk-MLOZE23Y.mjs → chunk-KX6BL4OV.mjs} +1 -1
  85. package/dist/{chunk-MLOZE23Y.mjs.map → chunk-KX6BL4OV.mjs.map} +1 -1
  86. package/dist/{chunk-VMWF6DND.js → chunk-LZSPF5CN.js} +2 -2
  87. package/dist/chunk-LZSPF5CN.js.map +1 -0
  88. package/dist/{chunk-5RBZCQGH.mjs → chunk-NI6GSD6A.mjs} +4 -4
  89. package/dist/chunk-NI6GSD6A.mjs.map +1 -0
  90. package/dist/{chunk-EBGFR7IQ.mjs → chunk-RS2OOTJS.mjs} +2 -2
  91. package/dist/{chunk-TYQP2J4H.js → chunk-TU3BJQBV.js} +30 -23
  92. package/dist/chunk-TU3BJQBV.js.map +1 -0
  93. package/dist/{chunk-CFLFCBRM.js → chunk-UVY6KLC7.js} +17 -17
  94. package/dist/{chunk-CFLFCBRM.js.map → chunk-UVY6KLC7.js.map} +1 -1
  95. package/dist/{chunk-7LRIQOCS.mjs → chunk-VAYB6LNV.mjs} +51 -24
  96. package/dist/chunk-VAYB6LNV.mjs.map +1 -0
  97. package/dist/{chunk-FZUPX44N.mjs → chunk-VG5EMAOF.mjs} +3 -3
  98. package/dist/{chunk-FZUPX44N.mjs.map → chunk-VG5EMAOF.mjs.map} +1 -1
  99. package/dist/{chunk-TXHL7XLU.js → chunk-VSQ7UFGJ.js} +1 -1
  100. package/dist/{chunk-TXHL7XLU.js.map → chunk-VSQ7UFGJ.js.map} +1 -1
  101. package/dist/hooks/useAppContent/index.js +11 -11
  102. package/dist/hooks/useAppContent/index.mjs +10 -10
  103. package/dist/hooks/useRecommendedLessonsPage/index.js +2 -2
  104. package/dist/hooks/useRecommendedLessonsPage/index.mjs +1 -1
  105. package/dist/index.js +11 -11
  106. package/dist/index.mjs +10 -10
  107. package/dist/types/lessonAvailability/index.d.ts +7 -0
  108. package/dist/types/lessonAvailability/index.d.ts.map +1 -1
  109. package/dist/types/lessonAvailability/index.js +2 -2
  110. package/dist/types/lessonAvailability/index.mjs +1 -1
  111. package/dist/types/lessonAvailability.d.ts +7 -0
  112. package/dist/types/lessonAvailability.d.ts.map +1 -1
  113. package/dist/utils/lessonAvailabilityUtils/index.d.ts +1 -0
  114. package/dist/utils/lessonAvailabilityUtils/index.d.ts.map +1 -1
  115. package/dist/utils/lessonAvailabilityUtils/index.js +3 -3
  116. package/dist/utils/lessonAvailabilityUtils/index.mjs +2 -2
  117. package/dist/utils/lessonAvailabilityUtils.d.ts +1 -0
  118. package/dist/utils/lessonAvailabilityUtils.d.ts.map +1 -1
  119. package/package.json +1 -1
  120. package/dist/chunk-5RBZCQGH.mjs.map +0 -1
  121. package/dist/chunk-7LRIQOCS.mjs.map +0 -1
  122. package/dist/chunk-HFY4S3JV.mjs.map +0 -1
  123. package/dist/chunk-MTZ6C74W.js.map +0 -1
  124. package/dist/chunk-OCIBLTVL.js.map +0 -1
  125. package/dist/chunk-Q5VRX5TR.js.map +0 -1
  126. package/dist/chunk-SIER6LRJ.mjs.map +0 -1
  127. package/dist/chunk-TYQP2J4H.js.map +0 -1
  128. package/dist/chunk-VMWF6DND.js.map +0 -1
  129. /package/dist/{chunk-LH4UP3H6.mjs.map → chunk-DTVNS6NN.mjs.map} +0 -0
  130. /package/dist/{chunk-EBGFR7IQ.mjs.map → chunk-RS2OOTJS.mjs.map} +0 -0
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  UnifiedHistoryPage
3
- } from "../chunk-5RBZCQGH.mjs";
4
- import "../chunk-SIER6LRJ.mjs";
3
+ } from "../chunk-NI6GSD6A.mjs";
4
+ import "../chunk-66A37LW7.mjs";
5
5
  import "../chunk-4CJLURKO.mjs";
6
6
  import "../chunk-GVGQ7EUU.mjs";
7
7
  import "../chunk-NVNYYFHH.mjs";
8
8
  import "../chunk-33ESUKAH.mjs";
9
9
  import "../chunk-5BF2Y5QF.mjs";
10
10
  import "../chunk-327WMPDH.mjs";
11
- import "../chunk-MLOZE23Y.mjs";
11
+ import "../chunk-KX6BL4OV.mjs";
12
12
  import "../chunk-Z3UV7NNE.mjs";
13
13
  import "../chunk-MEN33LGL.mjs";
14
14
  import "../chunk-S63KGDW4.mjs";
@@ -55,7 +55,7 @@ import "../chunk-RL26IDPE.mjs";
55
55
  import "../chunk-EDARVQYZ.mjs";
56
56
  import "../chunk-JZDM62IO.mjs";
57
57
  import "../chunk-45LJRS7N.mjs";
58
- import "../chunk-LH4UP3H6.mjs";
58
+ import "../chunk-DTVNS6NN.mjs";
59
59
  import "../chunk-IQEDRSDD.mjs";
60
60
  import "../chunk-OVRINYGJ.mjs";
61
61
  import "../chunk-JMMNZIDR.mjs";
@@ -100,7 +100,7 @@ import "../chunk-DJG7DLCI.mjs";
100
100
  import "../chunk-FZJYX3LL.mjs";
101
101
  import "../chunk-PBF56LM5.mjs";
102
102
  import "../chunk-KP6KKVAB.mjs";
103
- import "../chunk-HFY4S3JV.mjs";
103
+ import "../chunk-GAKQ52B6.mjs";
104
104
  import "../chunk-5WLR5TLU.mjs";
105
105
  import "../chunk-3DZ6JVFL.mjs";
106
106
  import "../chunk-UANZJ7NH.mjs";
@@ -124,7 +124,7 @@ import "../chunk-IFPB6M2V.mjs";
124
124
  import "../chunk-HDGN7BLD.mjs";
125
125
  import "../chunk-KTMAH3L5.mjs";
126
126
  import "../chunk-GNQHR4AT.mjs";
127
- import "../chunk-AFBTGILL.mjs";
127
+ import "../chunk-4TBI57KA.mjs";
128
128
  import "../chunk-FNP4RL3N.mjs";
129
129
  import "../chunk-DVVWILBK.mjs";
130
130
  import "../chunk-KE77J5B4.mjs";
@@ -141,10 +141,10 @@ import "../chunk-Z5ARCTJS.mjs";
141
141
  import "../chunk-G3RX4ZC5.mjs";
142
142
  import "../chunk-YPQFSNET.mjs";
143
143
  import "../chunk-4QZWLI7Q.mjs";
144
- import "../chunk-FZUPX44N.mjs";
144
+ import "../chunk-VG5EMAOF.mjs";
145
145
  import "../chunk-6Y3UKXTF.mjs";
146
146
  import "../chunk-MTSSK7ZZ.mjs";
147
- import "../chunk-EWG6Q2QF.mjs";
147
+ import "../chunk-6MZEJVNV.mjs";
148
148
  import "../chunk-GKY77WVA.mjs";
149
149
  import "../chunk-D5GBQJNA.mjs";
150
150
  import "../chunk-43CA6NQG.mjs";
@@ -202,13 +202,13 @@ import "../chunk-3ERLYM6Y.mjs";
202
202
  import "../chunk-VLYLNEAH.mjs";
203
203
  import "../chunk-FDFDHQDG.mjs";
204
204
  import "../chunk-QZHSY53O.mjs";
205
- import "../chunk-EBGFR7IQ.mjs";
205
+ import "../chunk-RS2OOTJS.mjs";
206
206
  import "../chunk-YQTOSHD5.mjs";
207
207
  import "../chunk-OEW3ST4F.mjs";
208
208
  import "../chunk-VDUO65VK.mjs";
209
209
  import "../chunk-TVFP3HZX.mjs";
210
210
  import "../chunk-VN4ORBHU.mjs";
211
- import "../chunk-7LRIQOCS.mjs";
211
+ import "../chunk-VAYB6LNV.mjs";
212
212
  import "../chunk-ED27XADA.mjs";
213
213
  import "../chunk-HYVBZ5EV.mjs";
214
214
  import "../chunk-GF2M5EE6.mjs";
@@ -100,6 +100,16 @@ var horizontalPortalStyle = (rect, { side, sideOffset, maxHeight }) => ({
100
100
  overflowY: "auto",
101
101
  ...side === "left" ? { right: window.innerWidth - rect.left + sideOffset } : { left: rect.right + sideOffset }
102
102
  });
103
+ var mergeRefs = (a, b) => {
104
+ if (!a) return b;
105
+ if (!b) return a;
106
+ return (node) => {
107
+ for (const r of [a, b]) {
108
+ if (typeof r === "function") r(node);
109
+ else r.current = node;
110
+ }
111
+ };
112
+ };
103
113
  var injectStore = (children, store) => {
104
114
  return _react.Children.map(children, (child) => {
105
115
  if (_react.isValidElement.call(void 0, child)) {
@@ -204,30 +214,47 @@ var DropdownMenu = ({
204
214
  }, [propOpen]);
205
215
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative", ref: menuRef, children: injectStore(children, store) });
206
216
  };
207
- var DropdownMenuTrigger = _react.forwardRef.call(void 0, ({ className, children, onClick, store: externalStore, ...props }, ref) => {
208
- const store = useDropdownStore(externalStore);
209
- const open = _zustand.useStore.call(void 0, store, (s) => s.open);
210
- const toggleOpen = () => store.setState({ open: !open });
211
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
212
- "button",
213
- {
214
- ref,
215
- type: "button",
216
- onClick: (e) => {
217
- e.stopPropagation();
218
- toggleOpen();
219
- _optionalChain([onClick, 'optionalCall', _11 => _11(e)]);
220
- },
221
- "aria-expanded": open,
222
- className: _chunkTN3AYOMVjs.cn.call(void 0,
223
- "appearance-none bg-transparent border-none p-0",
224
- className
225
- ),
226
- ...props,
227
- children
217
+ var DropdownMenuTrigger = _react.forwardRef.call(void 0,
218
+ ({ className, children, onClick, store: externalStore, asChild, ...props }, ref) => {
219
+ const store = useDropdownStore(externalStore);
220
+ const open = _zustand.useStore.call(void 0, store, (s) => s.open);
221
+ const toggleOpen = () => store.setState({ open: !open });
222
+ const handleTriggerClick = (e) => {
223
+ e.stopPropagation();
224
+ toggleOpen();
225
+ _optionalChain([onClick, 'optionalCall', _11 => _11(e)]);
226
+ };
227
+ const asChildElement = asChild ? _react.Children.toArray(children).find(_react.isValidElement) : void 0;
228
+ if (asChildElement) {
229
+ const child = asChildElement;
230
+ return _react.cloneElement.call(void 0, child, {
231
+ ...props,
232
+ ref: mergeRefs(ref, child.props.ref),
233
+ className: _chunkTN3AYOMVjs.cn.call(void 0, child.props.className, className),
234
+ "aria-expanded": open,
235
+ onClick: (e) => {
236
+ _optionalChain([child, 'access', _12 => _12.props, 'access', _13 => _13.onClick, 'optionalCall', _14 => _14(e)]);
237
+ handleTriggerClick(e);
238
+ }
239
+ });
228
240
  }
229
- );
230
- });
241
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
242
+ "button",
243
+ {
244
+ ref,
245
+ type: "button",
246
+ onClick: handleTriggerClick,
247
+ "aria-expanded": open,
248
+ className: _chunkTN3AYOMVjs.cn.call(void 0,
249
+ "appearance-none bg-transparent border-none p-0",
250
+ className
251
+ ),
252
+ ...props,
253
+ children
254
+ }
255
+ );
256
+ }
257
+ );
231
258
  DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
232
259
  var ITEM_SIZE_CLASSES = {
233
260
  small: "text-sm",
@@ -288,7 +315,7 @@ var DropdownMenuContent = _react.forwardRef.call(void 0,
288
315
  }
289
316
  }, [open]);
290
317
  const updatePortalPosition = _react.useCallback.call(void 0, () => {
291
- if (!portal || !_optionalChain([triggerRef, 'optionalAccess', _12 => _12.current])) return;
318
+ if (!portal || !_optionalChain([triggerRef, 'optionalAccess', _15 => _15.current])) return;
292
319
  const rect = triggerRef.current.getBoundingClientRect();
293
320
  const placement = { side, align, sideOffset, maxHeight };
294
321
  const style = side === "left" || side === "right" ? horizontalPortalStyle(rect, placement) : verticalPortalStyle(rect, placement);
@@ -374,13 +401,13 @@ var DropdownMenuItem = _react.forwardRef.call(void 0,
374
401
  return;
375
402
  }
376
403
  if (e.type === "click") {
377
- _optionalChain([onClick, 'optionalCall', _13 => _13(e)]);
404
+ _optionalChain([onClick, 'optionalCall', _16 => _16(e)]);
378
405
  } else if (e.type === "keydown") {
379
406
  const keyEvent = e;
380
407
  if (keyEvent.key === "Enter" || keyEvent.key === " ") {
381
408
  e.currentTarget.click();
382
409
  }
383
- _optionalChain([props, 'access', _14 => _14.onKeyDown, 'optionalCall', _15 => _15(keyEvent)]);
410
+ _optionalChain([props, 'access', _17 => _17.onKeyDown, 'optionalCall', _18 => _18(keyEvent)]);
384
411
  }
385
412
  if (!preventClose) {
386
413
  setOpen(false);
@@ -453,7 +480,7 @@ var ProfileMenuTrigger = _react.forwardRef.call(void 0, ({ className, onClick, s
453
480
  onClick: (e) => {
454
481
  e.stopPropagation();
455
482
  toggleOpen();
456
- _optionalChain([onClick, 'optionalCall', _16 => _16(e)]);
483
+ _optionalChain([onClick, 'optionalCall', _19 => _19(e)]);
457
484
  },
458
485
  "aria-expanded": open,
459
486
  ...props,
@@ -639,7 +666,7 @@ var ProfileMenuFooter = ({
639
666
  disabled,
640
667
  onClick: (e) => {
641
668
  setOpen(false);
642
- _optionalChain([onClick, 'optionalCall', _17 => _17(e)]);
669
+ _optionalChain([onClick, 'optionalCall', _20 => _20(e)]);
643
670
  },
644
671
  ...props,
645
672
  children: [
@@ -666,7 +693,7 @@ var ProfileMenuReadingFluencyTrigger = _react.forwardRef.call(void 0, ({ classNa
666
693
  onClick: (e) => {
667
694
  e.stopPropagation();
668
695
  toggleOpen();
669
- _optionalChain([onClick, 'optionalCall', _18 => _18(e)]);
696
+ _optionalChain([onClick, 'optionalCall', _21 => _21(e)]);
670
697
  },
671
698
  "aria-expanded": open,
672
699
  "aria-label": "Abrir menu de perfil",
@@ -745,7 +772,7 @@ var ProfileMenuReadingFluencyFooter = ({
745
772
  disabled,
746
773
  onClick: (e) => {
747
774
  setOpen(false);
748
- _optionalChain([onClick, 'optionalCall', _19 => _19(e)]);
775
+ _optionalChain([onClick, 'optionalCall', _22 => _22(e)]);
749
776
  },
750
777
  ...props,
751
778
  children: "Sair"
@@ -774,4 +801,4 @@ var DropdownMenu_default = DropdownMenu;
774
801
 
775
802
 
776
803
  exports.createDropdownStore = createDropdownStore; exports.useDropdownStore = useDropdownStore; exports.DropdownMenuTrigger = DropdownMenuTrigger; exports.MenuLabel = MenuLabel; exports.DropdownMenuContent = DropdownMenuContent; exports.DropdownMenuItem = DropdownMenuItem; exports.DropdownMenuSeparator = DropdownMenuSeparator; exports.ProfileMenuTrigger = ProfileMenuTrigger; exports.ProfileMenuHeader = ProfileMenuHeader; exports.ProfileMenuInfo = ProfileMenuInfo; exports.ProfileToggleTheme = ProfileToggleTheme; exports.ProfileMenuSection = ProfileMenuSection; exports.ProfileMenuFooter = ProfileMenuFooter; exports.ProfileMenuReadingFluencyTrigger = ProfileMenuReadingFluencyTrigger; exports.ProfileMenuReadingFluencyInfo = ProfileMenuReadingFluencyInfo; exports.ProfileMenuReadingFluencyFooter = ProfileMenuReadingFluencyFooter; exports.DropdownMenu_default = DropdownMenu_default;
777
- //# sourceMappingURL=chunk-OCIBLTVL.js.map
804
+ //# sourceMappingURL=chunk-2DPLSITC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-2DPLSITC.js","../src/components/DropdownMenu/DropdownMenu.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACvBA,uEAA+B;AAC/B,iEAA4B;AAC5B,2DAAyB;AACzB;AACE;AAGA;AACA;AACA;AACA;AAIA;AACA;AACA;AAEA;AAAA,8BAIK;AACP,qCAA6B;AAC7B,kCAA2C;AAkWvC,+CAAA;AAjVG,SAAS,mBAAA,CAAA,EAAwC;AACtD,EAAA,OAAO,6BAAA,CAAuB,GAAA,EAAA,GAAA,CAAS;AAAA,IACrC,IAAA,EAAM,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKN,OAAA,EAAS,CAAC,IAAA,EAAA,GAAS,GAAA,CAAI,CAAC,KAAA,EAAA,GAAW,KAAA,CAAM,KAAA,IAAS,KAAA,EAAO,MAAA,EAAQ,EAAE,KAAK,CAAE;AAAA,EAC5E,CAAA,CAAE,CAAA;AACJ;AAEO,IAAM,iBAAA,EAAmB,CAAC,aAAA,EAAA,GAAqC;AACpE,EAAA,GAAA,CAAI,CAAC,aAAA,EAAe;AAClB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,EACF;AAEA,EAAA,OAAO,aAAA;AACT,CAAA;AAMA,IAAM,kBAAA,EAAoB;AAAA,EACxB,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA;AAEA,IAAM,kBAAA,EAAoB,CAAC,CAAA,EAAkB,CAAA,EAAA,GAC3C,iBAAA,CAAkB,KAAA,CAAM,CAAC,GAAA,EAAA,GAAQ,CAAA,CAAE,GAAG,EAAA,IAAM,CAAA,CAAE,GAAG,CAAC,CAAA;AAGpD,IAAM,0BAAA,EAA4B,GAAA;AAGlC,IAAM,gBAAA,EAAkB,CAAA;AAMxB,IAAM,sBAAA,EAAwB,GAAA;AAwB9B,IAAM,gBAAA,EAAkB,CAAC,SAAA,EAAmB,SAAA,EAAA,GAC1C,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,qBAAqB,CAAC,CAAA;AAShE,IAAM,iBAAA,EAAmB,CAAC,IAAA,EAAe,KAAA,EAAA,GAAsC;AAC7E,EAAA,GAAA,CAAI,MAAA,IAAU,KAAA,EAAO,OAAO,EAAE,KAAA,EAAO,MAAA,CAAO,WAAA,EAAa,IAAA,CAAK,MAAM,CAAA;AACpE,EAAA,GAAA,CAAI,MAAA,IAAU,QAAA,EAAU;AACtB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,IAAA,CAAK,KAAA,EAAO,IAAA,CAAK,MAAA,EAAQ,CAAA;AAAA,MAC/B,SAAA,EAAW;AAAA,IACb,CAAA;AAAA,EACF;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,KAAK,CAAA;AAC3B,CAAA;AAmBA,IAAM,oBAAA,EAAsB,CAC1B,IAAA,EACA,EAAE,IAAA,EAAM,KAAA,EAAO,UAAA,EAAY,UAAU,CAAA,EAAA,GACnB;AAClB,EAAA,MAAM,WAAA,EACJ,MAAA,CAAO,YAAA,EAAc,IAAA,CAAK,OAAA,EAAS,WAAA,EAAa,eAAA;AAClD,EAAA,MAAM,WAAA,EAAa,IAAA,CAAK,IAAA,EAAM,WAAA,EAAa,eAAA;AAC3C,EAAA,MAAM,UAAA,EACJ,KAAA,IAAS,MAAA,GACR,WAAA,EAAa,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,qBAAqB,EAAA,GACrD,WAAA,EAAa,UAAA;AAEjB,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,eAAA,CAAgB,UAAA,EAAY,WAAA,EAAa,UAAA,EAAY,SAAS,CAAA;AAAA,IACzE,SAAA,EAAW,MAAA;AAAA,IACX,GAAI,UAAA,EACA,EAAE,MAAA,EAAQ,MAAA,CAAO,YAAA,EAAc,IAAA,CAAK,IAAA,EAAM,WAAW,EAAA,EACrD,EAAE,GAAA,EAAK,IAAA,CAAK,OAAA,EAAS,WAAW,CAAA;AAAA,IACpC,GAAG,gBAAA,CAAiB,IAAA,EAAM,KAAK;AAAA,EACjC,CAAA;AACF,CAAA;AAcA,IAAM,sBAAA,EAAwB,CAC5B,IAAA,EACA,EAAE,IAAA,EAAM,UAAA,EAAY,UAAU,CAAA,EAAA,GAAA,CACX;AAAA,EACnB,GAAA,EAAK,IAAA,CAAK,GAAA;AAAA,EACV,SAAA,EAAW,eAAA;AAAA,IACT,MAAA,CAAO,YAAA,EAAc,IAAA,CAAK,IAAA,EAAM,eAAA;AAAA,IAChC;AAAA,EACF,CAAA;AAAA,EACA,SAAA,EAAW,MAAA;AAAA,EACX,GAAI,KAAA,IAAS,OAAA,EACT,EAAE,KAAA,EAAO,MAAA,CAAO,WAAA,EAAa,IAAA,CAAK,KAAA,EAAO,WAAW,EAAA,EACpD,EAAE,IAAA,EAAM,IAAA,CAAK,MAAA,EAAQ,WAAW;AACtC,CAAA,CAAA;AAOA,IAAM,UAAA,EAAY,CAChB,CAAA,EACA,CAAA,EAAA,GACuB;AACvB,EAAA,GAAA,CAAI,CAAC,CAAA,EAAG,OAAO,CAAA;AACf,EAAA,GAAA,CAAI,CAAC,CAAA,EAAG,OAAO,CAAA;AACf,EAAA,OAAO,CAAC,IAAA,EAAA,GAAmB;AACzB,IAAA,IAAA,CAAA,MAAW,EAAA,GAAK,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG;AACtB,MAAA,GAAA,CAAI,OAAO,EAAA,IAAM,UAAA,EAAY,CAAA,CAAE,IAAI,CAAA;AAAA,MAAA,KAC7B,CAAA,CAA0B,QAAA,EAAU,IAAA;AAAA,IAC5C;AAAA,EACF,CAAA;AACF,CAAA;AAEA,IAAM,YAAA,EAAc,CAClB,QAAA,EACA,KAAA,EAAA,GACc;AACd,EAAA,OAAO,eAAA,CAAS,GAAA,CAAI,QAAA,EAAU,CAAC,KAAA,EAAA,GAAU;AACvC,IAAA,GAAA,CAAI,mCAAA,KAAoB,CAAA,EAAG;AACzB,MAAA,MAAM,WAAA,EAAa,KAAA;AAMnB,MAAA,MAAM,YAAA,EACJ,UAAA,CAAW,IAAA,CACX,WAAA;AAGF,MAAA,MAAM,QAAA,EAAU;AAAA,QACd,qBAAA;AAAA,QACA,iBAAA;AAAA,QACA,qBAAA;AAAA,QACA,uBAAA;AAAA,QACA,kBAAA;AAAA,QACA,WAAA;AAAA,QACA,oBAAA;AAAA,QACA,mBAAA;AAAA,QACA,mBAAA;AAAA,QACA,oBAAA;AAAA,QACA,kCAAA;AAAA,QACA;AAAA,MACF,CAAA;AAEA,MAAA,IAAI,SAAA,EAGC,CAAC,CAAA;AAEN,MAAA,GAAA,CAAI,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACjC,QAAA,QAAA,CAAS,MAAA,EAAQ,KAAA;AAAA,MACnB;AAEA,MAAA,GAAA,CAAI,UAAA,CAAW,KAAA,CAAM,QAAA,EAAU;AAC7B,QAAA,QAAA,CAAS,SAAA,EAAW,WAAA,CAAY,UAAA,CAAW,KAAA,CAAM,QAAA,EAAU,KAAK,CAAA;AAAA,MAClE;AAEA,MAAA,OAAO,iCAAA,UAAa,EAAY,QAAQ,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH,CAAA;AAQA,IAAM,aAAA,EAAe,CAAC;AAAA,EACpB,QAAA;AAAA,EACA,IAAA,EAAM,QAAA;AAAA,EACN;AACF,CAAA,EAAA,GAAyB;AACvB,EAAA,MAAM,SAAA,EAAW,2BAAA,IAAoC,CAAA;AACrD,EAAA,QAAA,CAAS,QAAA,IAAY,mBAAA,CAAoB,CAAA;AACzC,EAAA,MAAM,MAAA,EAAQ,QAAA,CAAS,OAAA;AACvB,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,aAAa,EAAA,EAAI,+BAAA,KAAS,EAAO,CAAC,CAAA,EAAA,GAAM,CAAC,CAAA;AAEhE,EAAA,MAAM,QAAA,EAAU,CAAC,OAAA,EAAA,GAAqB;AACpC,IAAA,YAAA,CAAa,OAAO,CAAA;AAAA,EACtB,CAAA;AAEA,EAAA,MAAM,QAAA,EAAU,2BAAA,IAAkC,CAAA;AAElD,EAAA,MAAM,yBAAA,EAA2B,CAAC,KAAA,EAAA,GAAoC;AAIpE,IAAA,MAAM,YAAA,mCACJ,OAAA,mBAAQ,OAAA,6BAAS,aAAA,mBAAc,eAAe,GAAA,UAC9C,QAAA,CAAS,aAAA;AAAA,MACP;AAAA,IACF,GAAA;AACF,IAAA,GAAA,CAAI,WAAA,EAAa;AACf,MAAA,KAAA,CAAM,cAAA,CAAe,CAAA;AAErB,MAAA,MAAM,MAAA,EAAQ,KAAA,CAAM,IAAA;AAAA,QAClB,WAAA,CAAY,gBAAA;AAAA,UACV;AAAA,QACF;AAAA,MACF,CAAA,CAAE,MAAA,CAAO,CAAC,EAAA,EAAA,GAA0B,GAAA,WAAc,WAAW,CAAA;AAE7D,MAAA,GAAA,CAAI,KAAA,CAAM,OAAA,IAAW,CAAA,EAAG,MAAA;AAExB,MAAA,MAAM,YAAA,EAAc,QAAA,CAAS,aAAA;AAC7B,MAAA,MAAM,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA;AAE9C,MAAA,IAAI,SAAA;AACJ,MAAA,GAAA,CAAI,KAAA,CAAM,IAAA,IAAQ,WAAA,EAAa;AAC7B,QAAA,UAAA,EAAY,aAAA,IAAiB,CAAA,EAAA,EAAK,EAAA,EAAA,CAAK,aAAA,EAAe,CAAA,EAAA,EAAK,KAAA,CAAM,MAAA;AAAA,MACnE,EAAA,KAAO;AAEL,QAAA,UAAA,EACE,aAAA,IAAiB,CAAA,EAAA,EACb,KAAA,CAAM,OAAA,EAAS,EAAA,EAAA,CACd,aAAA,EAAe,EAAA,EAAI,KAAA,CAAM,MAAA,EAAA,EAAU,KAAA,CAAM,MAAA;AAAA,MAClD;AAEA,sBAAA,KAAA,qBAAM,SAAS,CAAA,6BAAG,KAAA,mBAAM,GAAA;AAAA,IAC1B;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,cAAA,EAAgB,CAAC,KAAA,EAAA,GAAoC;AACzD,IAAA,GAAA,CAAI,KAAA,CAAM,IAAA,IAAQ,QAAA,EAAU;AAC1B,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,EAAA,KAAA,GAAA,CAAW,KAAA,CAAM,IAAA,IAAQ,YAAA,GAAe,KAAA,CAAM,IAAA,IAAQ,SAAA,EAAW;AAC/D,MAAA,wBAAA,CAAyB,KAAK,CAAA;AAAA,IAChC;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,mBAAA,EAAqB,CAAC,KAAA,EAAA,GAAiB;AAC3C,IAAA,MAAM,OAAA,EAAS,KAAA,CAAM,MAAA;AAErB,IAAA,GAAA,iBAAI,OAAA,qBAAQ,OAAA,6BAAS,QAAA,mBAAS,MAAM,GAAA,EAAG;AACrC,MAAA,MAAA;AAAA,IACF;AAEA,IAAA,GAAA,CACE,OAAA,WAAkB,QAAA,GAClB,MAAA,CAAO,OAAA,CAAQ,gCAAgC,CAAA,EAC/C;AACA,MAAA,MAAA;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,IAAA,EAAM;AACR,MAAA,QAAA,CAAS,gBAAA,CAAiB,aAAA,EAAe,kBAAkB,CAAA;AAC3D,MAAA,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,aAAa,CAAA;AAAA,IACpD;AAEA,IAAA,OAAO,CAAA,EAAA,GAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAA,EAAe,kBAAkB,CAAA;AAC9D,MAAA,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,aAAa,CAAA;AAAA,IACvD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,oBAAA,YAAA,4BAAA,CAAe,IAAI,GAAA;AAAA,EACrB,CAAA,EAAG,CAAC,IAAA,EAAM,YAAY,CAAC,CAAA;AAEvB,EAAA,8BAAA,CAAU,EAAA,GAAM;AACd,IAAA,GAAA,CAAI,SAAA,IAAa,KAAA,CAAA,EAAW;AAC1B,MAAA,OAAA,CAAQ,QAAQ,CAAA;AAAA,IAClB;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,uBACE,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,UAAA,EAAW,GAAA,EAAK,OAAA,EAC5B,QAAA,EAAA,WAAA,CAAY,QAAA,EAAU,KAAK,EAAA,CAC9B,CAAA;AAEJ,CAAA;AAGA,IAAM,oBAAA,EAAsB,+BAAA;AAAA,EAe1B,CACE,EAAE,SAAA,EAAW,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,aAAA,EAAe,OAAA,EAAS,GAAG,MAAM,CAAA,EACxE,GAAA,EAAA,GACG;AACH,IAAA,MAAM,MAAA,EAAQ,gBAAA,CAAiB,aAAa,CAAA;AAE5C,IAAA,MAAM,KAAA,EAAO,+BAAA,KAAS,EAAO,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,IAAI,CAAA;AAC1C,IAAA,MAAM,WAAA,EAAa,CAAA,EAAA,GAAM,KAAA,CAAM,QAAA,CAAS,EAAE,IAAA,EAAM,CAAC,KAAK,CAAC,CAAA;AAEvD,IAAA,MAAM,mBAAA,EAAqB,CAAC,CAAA,EAAA,GAA+B;AACzD,MAAA,CAAA,CAAE,eAAA,CAAgB,CAAA;AAClB,MAAA,UAAA,CAAW,CAAA;AACX,sBAAA,OAAA,4BAAA,CAAU,CAAkC,GAAA;AAAA,IAC9C,CAAA;AAIA,IAAA,MAAM,eAAA,EAAiB,QAAA,EAClB,eAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAA,CAAK,qBAAc,EAAA,EAO/C,KAAA,CAAA;AAEJ,IAAA,GAAA,CAAI,cAAA,EAAgB;AAClB,MAAA,MAAM,MAAA,EAAQ,cAAA;AACd,MAAA,OAAO,iCAAA,KAAa,EAAO;AAAA,QACzB,GAAG,KAAA;AAAA,QACH,GAAA,EAAK,SAAA,CAAU,GAAA,EAAK,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA;AAAA,QACnC,SAAA,EAAW,iCAAA,KAAG,CAAM,KAAA,CAAM,SAAA,EAAW,SAAS,CAAA;AAAA,QAC9C,eAAA,EAAiB,IAAA;AAAA,QACjB,OAAA,EAAS,CAAC,CAAA,EAAA,GAA+B;AAGvC,0BAAA,KAAA,uBAAM,KAAA,uBAAM,OAAA,4BAAA,CAAU,CAAC,GAAA;AACvB,UAAA,kBAAA,CAAmB,CAAC,CAAA;AAAA,QACtB;AAAA,MACF,CAAwE,CAAA;AAAA,IAC1E;AAEA,IAAA,uBACE,6BAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,kBAAA;AAAA,QACT,eAAA,EAAe,IAAA;AAAA,QACf,SAAA,EAAW,iCAAA;AAAA,UACT,gDAAA;AAAA,UACA;AAAA,QACF,CAAA;AAAA,QACC,GAAG,KAAA;AAAA,QAEH;AAAA,MAAA;AAAA,IACH,CAAA;AAAA,EAEJ;AACF,CAAA;AACA,mBAAA,CAAoB,YAAA,EAAc,qBAAA;AAElC,IAAM,kBAAA,EAAoB;AAAA,EACxB,KAAA,EAAO,SAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAEA,IAAM,aAAA,EAAe;AAAA,EACnB,GAAA,EAAK,aAAA;AAAA,EACL,KAAA,EAAO,UAAA;AAAA,EACP,MAAA,EAAQ,UAAA;AAAA,EACR,IAAA,EAAM;AACR,CAAA;AAEA,IAAM,cAAA,EAAgB;AAAA,EACpB,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,2BAAA;AAAA,EACR,GAAA,EAAK;AACP,CAAA;AAMA,IAAM,4BAAA,EAA8B;AAAA,EAClC,IAAA,EAAM,oGAAA;AAAA,EACN,OAAA,EACE,oGAAA;AAAA,EACF,MAAA,EACE;AACJ,CAAA;AAEA,IAAM,UAAA,EAAY,+BAAA,CAMf,EAAE,SAAA,EAAW,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,GAAG,MAAM,CAAA,EAAG,GAAA,EAAA,GAAQ;AACxD,EAAA,uBACE,6BAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAW,iCAAA,gBAAG,EAAkB,MAAA,EAAQ,OAAA,EAAS,EAAA,EAAI,SAAS,CAAA;AAAA,MAC7D,GAAG;AAAA,IAAA;AAAA,EACN,CAAA;AAEJ,CAAC,CAAA;AACD,SAAA,CAAU,YAAA,EAAc,WAAA;AAExB,IAAM,oBAAA,EAAsB,+BAAA;AAAA,EAiB1B,CACE;AAAA,IACE,SAAA;AAAA,IACA,MAAA,EAAQ,OAAA;AAAA,IACR,KAAA,EAAO,QAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,CAAA;AAAA,IACb,QAAA;AAAA,IACA,KAAA,EAAO,aAAA;AAAA,IACP,OAAA,EAAS,KAAA;AAAA,IACT,UAAA;AAAA,IACA,UAAA,EAAY,yBAAA;AAAA,IACZ,GAAG;AAAA,EACL,CAAA,EACA,GAAA,EAAA,GACG;AACH,IAAA,MAAM,MAAA,EAAQ,gBAAA,CAAiB,aAAa,CAAA;AAC5C,IAAA,MAAM,KAAA,EAAO,+BAAA,KAAS,EAAO,CAAC,CAAA,EAAA,GAAM,CAAA,CAAE,IAAI,CAAA;AAC1C,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,EAAA,EAAI,6BAAA,IAAa,CAAA;AAC/C,IAAA,MAAM,CAAC,WAAA,EAAa,cAAc,EAAA,EAAI,6BAAA,CAAyB,CAAC,CAAA;AAChE,IAAA,MAAM,WAAA,EAAa,2BAAA,IAA2B,CAAA;AAE9C,IAAA,8BAAA,CAAU,EAAA,GAAM;AACd,MAAA,GAAA,CAAI,IAAA,EAAM;AACR,QAAA,YAAA,CAAa,IAAI,CAAA;AAAA,MACnB,EAAA,KAAO;AACL,QAAA,MAAM,MAAA,EAAQ,UAAA,CAAW,CAAA,EAAA,GAAM,YAAA,CAAa,KAAK,CAAA,EAAG,GAAG,CAAA;AACvD,QAAA,OAAO,CAAA,EAAA,GAAM,YAAA,CAAa,KAAK,CAAA;AAAA,MACjC;AAAA,IACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,IAAA,MAAM,qBAAA,EAAuB,gCAAA,CAAY,EAAA,GAAM;AAC7C,MAAA,GAAA,CAAI,CAAC,OAAA,GAAU,iBAAC,UAAA,+BAAY,SAAA,EAAS,MAAA;AAErC,MAAA,MAAM,KAAA,EAAO,UAAA,CAAW,OAAA,CAAQ,qBAAA,CAAsB,CAAA;AACtD,MAAA,MAAM,UAAA,EAAY,EAAE,IAAA,EAAM,KAAA,EAAO,UAAA,EAAY,UAAU,CAAA;AACvD,MAAA,MAAM,MAAA,EACJ,KAAA,IAAS,OAAA,GAAU,KAAA,IAAS,QAAA,EACxB,qBAAA,CAAsB,IAAA,EAAM,SAAS,EAAA,EACrC,mBAAA,CAAoB,IAAA,EAAM,SAAS,CAAA;AAEzC,MAAA,cAAA,CAAe,CAAC,IAAA,EAAA,GAAU,iBAAA,CAAkB,IAAA,EAAM,KAAK,EAAA,EAAI,KAAA,EAAO,KAAM,CAAA;AAAA,IAC1E,CAAA,EAAG,CAAC,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,IAAA,EAAM,UAAA,EAAY,SAAS,CAAC,CAAA;AAE3D,IAAA,oCAAA,CAAgB,EAAA,GAAM;AACpB,MAAA,GAAA,CAAI,IAAA,EAAM,oBAAA,CAAqB,CAAA;AAAA,IACjC,CAAA,EAAG,CAAC,IAAA,EAAM,oBAAoB,CAAC,CAAA;AAO/B,IAAA,8BAAA,CAAU,EAAA,GAAM;AACd,MAAA,GAAA,CAAI,CAAC,OAAA,GAAU,CAAC,IAAA,EAAM,MAAA;AAEtB,MAAA,MAAM,WAAA,EAAa,CAAA,EAAA,GAAM,oBAAA,CAAqB,CAAA;AAC9C,MAAA,MAAA,CAAO,gBAAA,CAAiB,QAAA,EAAU,UAAA,EAAY,IAAI,CAAA;AAClD,MAAA,MAAA,CAAO,gBAAA,CAAiB,QAAA,EAAU,UAAU,CAAA;AAE5C,MAAA,OAAO,CAAA,EAAA,GAAM;AACX,QAAA,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,UAAA,EAAY,IAAI,CAAA;AACrD,QAAA,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,UAAU,CAAA;AAAA,MACjD,CAAA;AAAA,IACF,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAA,EAAM,oBAAoB,CAAC,CAAA;AAEvC,IAAA,GAAA,CAAI,CAAC,SAAA,EAAW,OAAO,IAAA;AAEvB,IAAA,MAAM,mBAAA,EAAqB,CAAA,EAAA,GAAM;AAC/B,MAAA,GAAA,CAAI,MAAA,EAAQ;AACV,QAAA,OAAO,OAAA;AAAA,MACT;AACA,MAAA,MAAM,SAAA,EAAW,YAAA,CAAa,IAAI,CAAA;AAClC,MAAA,MAAM,WAAA,EAAa,aAAA,CAAc,KAAK,CAAA;AAEtC,MAAA,OAAO,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAC3C,IAAA;AAEuB,IAAA;AAGrB,IAAA;AAAC,MAAA;AAAA,MAAA;AAC4B,QAAA;AACtB,QAAA;AACiB,QAAA;AACX,QAAA;AACA,QAAA;AAAA;AAEF,QAAA;AACa,QAAA;AACN,QAAA;AACL,QAAA;AAAA,MAAA;AAEJ,QAAA;AAGD,UAAA;AACiC,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACjC,UAAA;AACN,QAAA;AACI,QAAA;AAEH,QAAA;AAAA,MAAA;AACH,IAAA;AAGgC,IAAA;AACU,MAAA;AAC5C,IAAA;AAEO,IAAA;AACT,EAAA;AACF;AACkC;AAET;AAcrB,EAAA;AACE,IAAA;AACO,IAAA;AACP,IAAA;AACA,IAAA;AACA,IAAA;AACW,IAAA;AACX,IAAA;AACU,IAAA;AACH,IAAA;AACQ,IAAA;AACZ,IAAA;AAGF,EAAA;AACyC,IAAA;AACH,IAAA;AACC,IAAA;AAIrC,IAAA;AACW,MAAA;AACK,QAAA;AACC,QAAA;AAClB,QAAA;AACF,MAAA;AACwB,MAAA;AACmB,wBAAA;AACV,MAAA;AAEd,QAAA;AACe,QAAA;AACS,UAAA;AACzC,QAAA;AAE0B,wBAAA;AAC5B,MAAA;AACmB,MAAA;AACJ,QAAA;AACf,MAAA;AACF,IAAA;AAEgC,IAAA;AACH,MAAA;AAClB,QAAA;AACT,MAAA;AACO,MAAA;AACT,IAAA;AAE8B,IAAA;AACK,MAAA;AACnC,IAAA;AAGE,IAAA;AAAC,MAAA;AAAA,MAAA;AACC,QAAA;AACK,QAAA;AACe,QAAA;AACL,QAAA;AACJ,QAAA;AAAA;AAEa,WAAA;AACT,UAAA;AACF,UAAA;AAGL,UAAA;AAEN,QAAA;AAEO,QAAA;AACS,QAAA;AACmB,UAAA;AAChB,YAAA;AACC,YAAA;AACL,YAAA;AACf,UAAA;AACF,QAAA;AAC0B,QAAA;AACtB,QAAA;AAEH,QAAA;AAAA,UAAA;AACI,0BAAA;AACJ,UAAA;AAAA,QAAA;AAAA,MAAA;AACH,IAAA;AAEJ,EAAA;AACF;AAC+B;AAK1B;AACF,EAAA;AAAA,EAAA;AACC,IAAA;AACyC,IAAA;AACrC,IAAA;AAAA,EAAA;AAEP;AACmC;AAM/B;AACyC,EAAA;AACF,EAAA;AACA,EAAA;AAGxC,EAAA;AAAC,IAAA;AAAA,IAAA;AACC,MAAA;AACW,MAAA;AACT,QAAA;AACA,QAAA;AACF,MAAA;AACgB,MAAA;AACI,QAAA;AACP,QAAA;AACA,wBAAA;AACb,MAAA;AACe,MAAA;AACX,MAAA;AAEE,MAAA;AAEN,IAAA;AACF,EAAA;AAEH;AACgC;AAU5B;AAED,EAAA;AAAC,IAAA;AAAA,IAAA;AACC,MAAA;AACe,MAAA;AACJ,MAAA;AACT,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AAEJ,MAAA;AAAM,wBAAA;AAED,UAAA;AAAA,UAAA;AACM,YAAA;AACD,YAAA;AACM,YAAA;AAAA,UAAA;AAGF,QAAA;AAGT,wBAAA;AACH,0BAAA;AAAC,YAAA;AAAA,YAAA;AACM,cAAA;AACE,cAAA;AACD,cAAA;AACI,cAAA;AAET,cAAA;AAAA,YAAA;AACH,UAAA;AACM,0BAAA;AAGR,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEH;AAC+B;AAER;AAUpB,EAAA;AACE,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACO,IAAA;AACJ,IAAA;AAGF,EAAA;AACmC,IAAA;AAC7B,MAAA;AACT,IAAA;AAGE,IAAA;AAAC,MAAA;AAAA,MAAA;AACC,QAAA;AACe,QAAA;AACD,QAAA;AACV,QAAA;AAEJ,QAAA;AAAM,0BAAA;AACD,0BAAA;AAEA,YAAA;AAKgB,YAAA;AAGb,cAAA;AAIgB,cAAA;AAMhB,cAAA;AAIJ,YAAA;AAEJ,UAAA;AAAA,QAAA;AAAA,MAAA;AACF,IAAA;AAEJ,EAAA;AACF;AAC8B;AAEF;AACnB,EAAA;AACJ,EAAA;AACgE;AAC1B,EAAA;AACG,EAAA;AACF,EAAA;AAEmB,EAAA;AAChC,EAAA;AACE,EAAA;AACU,EAAA;AAEc,EAAA;AACpC,IAAA;AACC,IAAA;AACM,IAAA;AAC1B,EAAA;AAEyB,EAAA;AACD,IAAA;AACG,IAAA;AACZ,IAAA;AACf,EAAA;AAE2B,EAAA;AACC,IAAA;AACD,IAAA;AACZ,IAAA;AACf,EAAA;AAII,EAAA;AAAA,oBAAA;AAAC,MAAA;AAAA,MAAA;AACS,QAAA;AACM,QAAA;AACd,QAAA;AAEE,QAAA;AAAC,UAAA;AAAA,UAAA;AACO,YAAA;AACC,YAAA;AACC,YAAA;AACH,YAAA;AACC,YAAA;AAEN,YAAA;AAAC,cAAA;AAAA,cAAA;AACG,gBAAA;AACG,gBAAA;AAAA,cAAA;AACP,YAAA;AAAA,UAAA;AACF,QAAA;AAEU,QAAA;AACH,QAAA;AACS,QAAA;AACmB,UAAA;AAChB,YAAA;AACC,YAAA;AACM,YAAA;AAC1B,UAAA;AACF,QAAA;AACI,QAAA;AAEH,QAAA;AAED,MAAA;AACF,IAAA;AAEA,oBAAA;AAAC,MAAA;AAAA,MAAA;AACS,QAAA;AACC,QAAA;AACH,QAAA;AACD,QAAA;AAEE,QAAA;AACK,0BAAA;AAGA,0BAAA;AAGV,QAAA;AAGG,QAAA;AACU,0BAAA;AACA,0BAAA;AACf,QAAA;AAAA,MAAA;AACF,IAAA;AACF,EAAA;AAEJ;AACiC;AAK5B;AAEc,EAAA;AAIlB;AACgC;AAEN;AACzB,EAAA;AACW,EAAA;AACX,EAAA;AACO,EAAA;AACJ,EAAA;AAIC;AACwC,EAAA;AACH,EAAA;AAGvC,EAAA;AAAC,IAAA;AAAA,IAAA;AACS,MAAA;AACyB,MAAA;AACjC,MAAA;AACgB,MAAA;AACD,QAAA;AACF,wBAAA;AACb,MAAA;AACI,MAAA;AAEJ,MAAA;AAAM,wBAAA;AAGA,wBAAA;AAAoB,MAAA;AAAA,IAAA;AAC5B,EAAA;AAEJ;AACgC;AAQS;AAOK,EAAA;AACF,EAAA;AACA,EAAA;AAGxC,EAAA;AAAC,IAAA;AAAA,IAAA;AACC,MAAA;AACK,MAAA;AACM,MAAA;AACT,QAAA;AACA,QAAA;AACF,MAAA;AACgB,MAAA;AACI,QAAA;AACP,QAAA;AACA,wBAAA;AACb,MAAA;AACe,MAAA;AACJ,MAAA;AACP,MAAA;AAEJ,MAAA;AAAC,QAAA;AAAA,QAAA;AACkB,UAAA;AACb,UAAA;AACM,UAAA;AAAA,QAAA;AACZ,MAAA;AAAA,IAAA;AACF,EAAA;AAEH;AAEC;AAIoC;AAYlC,EAAA;AACE,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACO,IAAA;AACJ,IAAA;AAGF,EAAA;AACqC,IAAA;AAGtC,IAAA;AAAC,MAAA;AAAA,MAAA;AACC,QAAA;AACe,QAAA;AACJ,QAAA;AACT,UAAA;AACA,UAAA;AACF,QAAA;AACI,QAAA;AAEJ,QAAA;AAAK,0BAAA;AACG,4BAAA;AAGA,4BAAA;AAGR,UAAA;AAGE,UAAA;AAEK,YAAA;AAIgB,YAAA;AAChB,cAAA;AAAA,cAAA;AACM,gBAAA;AACK,gBAAA;AAEO,gBAAA;AAA0C,cAAA;AAC7D,YAAA;AAEJ,UAAA;AAAA,QAAA;AAAA,MAAA;AAEJ,IAAA;AAEJ,EAAA;AACF;AAC4C;AAIH;AACvC,EAAA;AACW,EAAA;AACX,EAAA;AACO,EAAA;AACJ,EAAA;AAIC;AACwC,EAAA;AACH,EAAA;AAGvC,EAAA;AAAC,IAAA;AAAA,IAAA;AACS,MAAA;AACH,MAAA;AAC4B,MAAA;AACjC,MAAA;AACgB,MAAA;AACD,QAAA;AACF,wBAAA;AACb,MAAA;AACI,MAAA;AACL,MAAA;AAAA,IAAA;AAED,EAAA;AAEJ;AAC8C;AAG/B;AD1ZiC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-2DPLSITC.js","sourcesContent":[null,"import { CaretRightIcon } from '@phosphor-icons/react/dist/csr/CaretRight';\nimport { SignOutIcon } from '@phosphor-icons/react/dist/csr/SignOut';\nimport { UserIcon } from '@phosphor-icons/react/dist/csr/User';\nimport {\n forwardRef,\n ReactNode,\n ButtonHTMLAttributes,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n HTMLAttributes,\n MouseEvent,\n KeyboardEvent,\n isValidElement,\n Children,\n cloneElement,\n ReactElement,\n useState,\n Ref,\n RefObject,\n CSSProperties,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { create, StoreApi, useStore } from 'zustand';\nimport Button, { ButtonReadingFluency } from '../Button/Button';\nimport Text from '../Text/Text';\nimport { cn } from '../../utils/utils';\nimport readingFluencyBird from '../../assets/img/readingFluencyBird.png';\nimport Modal from '../Modal/Modal';\nimport { ThemeToggle } from '../ThemeToggle/ThemeToggle';\nimport type { ThemeMode } from '@/hooks/useTheme';\nimport { useTheme } from '../../hooks/useTheme';\n\ninterface DropdownStore {\n open: boolean;\n setOpen: (open: boolean) => void;\n}\n\ntype DropdownStoreApi = StoreApi<DropdownStore>;\n\nexport function createDropdownStore(): DropdownStoreApi {\n return create<DropdownStore>((set) => ({\n open: false,\n // Bail out when the value didn't change. Skipping `set` here prevents\n // zustand from creating a new state object, which in turn keeps\n // `useStore(store, (s) => s)` subscribers from re-rendering on no-op\n // syncs (e.g. the `useEffect [propOpen]` controlled-mode bridge).\n setOpen: (open) => set((state) => (state.open === open ? state : { open })),\n }));\n}\n\nexport const useDropdownStore = (externalStore?: DropdownStoreApi) => {\n if (!externalStore) {\n throw new Error(\n 'Component must be used within a DropdownMenu (store is missing)'\n );\n }\n\n return externalStore;\n};\n\n/**\n * Keep the same style object when nothing moved — a fresh object on every\n * scroll event would re-render the menu at 60fps for no reason.\n */\nconst PORTAL_STYLE_KEYS = [\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'transform',\n 'maxHeight',\n] as const;\n\nconst isSamePortalStyle = (a: CSSProperties, b: CSSProperties): boolean =>\n PORTAL_STYLE_KEYS.every((key) => a[key] === b[key]);\n\n/** Tallest a portaled menu gets when there is room for it. */\nconst DEFAULT_PORTAL_MAX_HEIGHT = 320;\n\n/** Breathing room between the menu and the edge of the viewport. */\nconst VIEWPORT_MARGIN = 8;\n\n/**\n * Never shrink a menu below this, however cramped the trigger is: a 20px-tall\n * scroller is worse than one that overhangs a little.\n */\nconst MIN_PORTAL_MAX_HEIGHT = 120;\n\ntype PortalSide = 'top' | 'right' | 'bottom' | 'left';\ntype PortalAlign = 'start' | 'center' | 'end';\n\ninterface PortalPlacement {\n side: PortalSide;\n align: PortalAlign;\n sideOffset: number;\n maxHeight: number;\n}\n\n/**\n * Height cap for a portaled menu, given the room it has.\n *\n * The minimum is a floor on the *viewport-derived* room only — it keeps a menu\n * squeezed against an edge from collapsing into a sliver. A caller that asks\n * for a shorter menu than the minimum still gets what it asked for: its value\n * is the ceiling, never something to be raised.\n *\n * @param available - Room in px between the trigger and the viewport edge\n * @param maxHeight - Tallest the caller allows the menu to be\n * @returns The `max-height` to apply, in px\n */\nconst clampMenuHeight = (available: number, maxHeight: number): number =>\n Math.min(maxHeight, Math.max(available, MIN_PORTAL_MAX_HEIGHT));\n\n/**\n * Horizontal edge the menu lines up with, for the `top`/`bottom` sides.\n *\n * @param rect - Trigger bounding rect\n * @param align - Requested alignment\n * @returns The horizontal part of the portal style\n */\nconst alignPortalStyle = (rect: DOMRect, align: PortalAlign): CSSProperties => {\n if (align === 'end') return { right: window.innerWidth - rect.right };\n if (align === 'center') {\n return {\n left: rect.left + rect.width / 2,\n transform: 'translateX(-50%)',\n };\n }\n return { left: rect.left };\n};\n\n/**\n * Place a menu above or below its trigger, sized to the room that exists.\n *\n * A portaled menu is `position: fixed`, so whatever falls past the edge of the\n * viewport can never be scrolled to. The menu therefore takes the space it\n * actually has and scrolls inside it, and turns over to the other side when\n * clamping alone would still leave it overhanging.\n *\n * The flip threshold is the minimum height rather than the maximum: turning\n * over as soon as the menu could not open at full height would send it over the\n * content on any trigger past the middle of the screen, which reads as a\n * glitch. `side=\"top\"` always opens above — the caller asked for it.\n *\n * @param rect - Trigger bounding rect\n * @param placement - Requested side/alignment, offset and height ceiling\n * @returns Style for a fixed menu anchored to the trigger's top or bottom edge\n */\nconst verticalPortalStyle = (\n rect: DOMRect,\n { side, align, sideOffset, maxHeight }: PortalPlacement\n): CSSProperties => {\n const spaceBelow =\n window.innerHeight - rect.bottom - sideOffset - VIEWPORT_MARGIN;\n const spaceAbove = rect.top - sideOffset - VIEWPORT_MARGIN;\n const openAbove =\n side === 'top' ||\n (spaceBelow < Math.min(maxHeight, MIN_PORTAL_MAX_HEIGHT) &&\n spaceAbove > spaceBelow);\n\n return {\n maxHeight: clampMenuHeight(openAbove ? spaceAbove : spaceBelow, maxHeight),\n overflowY: 'auto',\n ...(openAbove\n ? { bottom: window.innerHeight - rect.top + sideOffset }\n : { top: rect.bottom + sideOffset }),\n ...alignPortalStyle(rect, align),\n };\n};\n\n/**\n * Place a menu beside its trigger, sized to the room below the trigger's top.\n *\n * Anchored by the edge that faces the trigger: a `left` for `side=\"left\"` would\n * grow the menu back over the trigger it was meant to sit outside of. It runs\n * downwards from the trigger's top, so it needs the same clamping as a menu\n * opening below — without it a long list disappears past the viewport bottom.\n *\n * @param rect - Trigger bounding rect\n * @param placement - Requested side, offset and height ceiling\n * @returns Style for a fixed menu anchored to the trigger's left or right edge\n */\nconst horizontalPortalStyle = (\n rect: DOMRect,\n { side, sideOffset, maxHeight }: PortalPlacement\n): CSSProperties => ({\n top: rect.top,\n maxHeight: clampMenuHeight(\n window.innerHeight - rect.top - VIEWPORT_MARGIN,\n maxHeight\n ),\n overflowY: 'auto',\n ...(side === 'left'\n ? { right: window.innerWidth - rect.left + sideOffset }\n : { left: rect.right + sideOffset }),\n});\n\n/**\n * Merge two refs into one. Returns the single ref when only one is set (no\n * callback churn), or `undefined` when neither is — so a cloned child without a\n * ref stays refless.\n */\nconst mergeRefs = <T,>(\n a: Ref<T> | undefined,\n b: Ref<T> | undefined\n): Ref<T> | undefined => {\n if (!a) return b;\n if (!b) return a;\n return (node: T | null) => {\n for (const r of [a, b]) {\n if (typeof r === 'function') r(node);\n else (r as RefObject<T | null>).current = node;\n }\n };\n};\n\nconst injectStore = (\n children: ReactNode,\n store: DropdownStoreApi\n): ReactNode => {\n return Children.map(children, (child) => {\n if (isValidElement(child)) {\n const typedChild = child as ReactElement<{\n store?: DropdownStoreApi;\n children?: ReactNode;\n }>;\n\n // Aqui tu checa o displayName do componente\n const displayName = (\n typedChild.type as unknown as { displayName: string }\n ).displayName;\n\n // Lista de componentes que devem receber o store\n const allowed = [\n 'DropdownMenuTrigger',\n 'DropdownContent',\n 'DropdownMenuContent',\n 'DropdownMenuSeparator',\n 'DropdownMenuItem',\n 'MenuLabel',\n 'ProfileMenuTrigger',\n 'ProfileMenuHeader',\n 'ProfileMenuFooter',\n 'ProfileToggleTheme',\n 'ProfileMenuReadingFluencyTrigger',\n 'ProfileMenuReadingFluencyFooter',\n ];\n\n let newProps: Partial<{\n store: DropdownStoreApi;\n children: ReactNode;\n }> = {};\n\n if (allowed.includes(displayName)) {\n newProps.store = store;\n }\n\n if (typedChild.props.children) {\n newProps.children = injectStore(typedChild.props.children, store);\n }\n\n return cloneElement(typedChild, newProps);\n }\n\n return child;\n });\n};\n\ninterface DropdownMenuProps {\n children: ReactNode;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DropdownMenu = ({\n children,\n open: propOpen,\n onOpenChange,\n}: DropdownMenuProps) => {\n const storeRef = useRef<DropdownStoreApi | null>(null);\n storeRef.current ??= createDropdownStore();\n const store = storeRef.current;\n const { open, setOpen: storeSetOpen } = useStore(store, (s) => s);\n\n const setOpen = (newOpen: boolean) => {\n storeSetOpen(newOpen);\n };\n\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n const handleArrowDownOrArrowUp = (event: globalThis.KeyboardEvent) => {\n // A portaled content lives in document.body, outside menuRef — look it up\n // globally in that case. Only the open menu carries data-open=\"true\"\n // (a closing one keeps rendering for the 200ms fade-out).\n const menuContent =\n menuRef.current?.querySelector('[role=\"menu\"]') ??\n document.querySelector(\n '[data-dropdown-content=\"true\"][data-open=\"true\"]'\n );\n if (menuContent) {\n event.preventDefault();\n\n const items = Array.from(\n menuContent.querySelectorAll(\n '[role=\"menuitem\"]:not([aria-disabled=\"true\"])'\n )\n ).filter((el): el is HTMLElement => el instanceof HTMLElement);\n\n if (items.length === 0) return;\n\n const focusedItem = document.activeElement as HTMLElement;\n const currentIndex = items.indexOf(focusedItem);\n\n let nextIndex;\n if (event.key === 'ArrowDown') {\n nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length;\n } else {\n // ArrowUp\n nextIndex =\n currentIndex === -1\n ? items.length - 1\n : (currentIndex - 1 + items.length) % items.length;\n }\n\n items[nextIndex]?.focus();\n }\n };\n\n const handleDownkey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n setOpen(false);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n handleArrowDownOrArrowUp(event);\n }\n };\n\n const handleClickOutside = (event: Event) => {\n const target = event.target as Node;\n\n if (menuRef.current?.contains(target)) {\n return;\n }\n\n if (\n target instanceof Element &&\n target.closest('[data-dropdown-content=\"true\"]')\n ) {\n return;\n }\n\n setOpen(false);\n };\n\n useEffect(() => {\n if (open) {\n document.addEventListener('pointerdown', handleClickOutside);\n document.addEventListener('keydown', handleDownkey);\n }\n\n return () => {\n document.removeEventListener('pointerdown', handleClickOutside);\n document.removeEventListener('keydown', handleDownkey);\n };\n }, [open]);\n\n useEffect(() => {\n onOpenChange?.(open);\n }, [open, onOpenChange]);\n\n useEffect(() => {\n if (propOpen !== undefined) {\n setOpen(propOpen);\n }\n }, [propOpen]);\n\n return (\n <div className=\"relative\" ref={menuRef}>\n {injectStore(children, store)}\n </div>\n );\n};\n\n// Componentes genéricos do DropdownMenu\nconst DropdownMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n /**\n * Render the single child as the trigger instead of wrapping it in a\n * `<button>`. Use when the child is itself a button/interactive element, so\n * the trigger doesn't nest one button inside another (invalid HTML). The\n * child keeps its own props; the toggle behaviour and `aria-expanded` are\n * merged in.\n */\n asChild?: boolean;\n }\n>(\n (\n { className, children, onClick, store: externalStore, asChild, ...props },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n const handleTriggerClick = (e: MouseEvent<HTMLElement>) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e as MouseEvent<HTMLButtonElement>);\n };\n\n // `injectStore` re-wraps children through Children.map, so `children` may be\n // a single-element array rather than a bare element — unwrap it here.\n const asChildElement = asChild\n ? (Children.toArray(children).find(isValidElement) as\n | ReactElement<{\n className?: string;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n ref?: Ref<HTMLElement>;\n }>\n | undefined)\n : undefined;\n\n if (asChildElement) {\n const child = asChildElement;\n return cloneElement(child, {\n ...props,\n ref: mergeRefs(ref, child.props.ref),\n className: cn(child.props.className, className),\n 'aria-expanded': open,\n onClick: (e: MouseEvent<HTMLElement>) => {\n // Keep the child's own handler, then run the trigger's toggle — same\n // order as the previous nested-button version.\n child.props.onClick?.(e);\n handleTriggerClick(e);\n },\n } as Partial<HTMLAttributes<HTMLElement>> & { store?: DropdownStoreApi });\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={handleTriggerClick}\n aria-expanded={open}\n className={cn(\n 'appearance-none bg-transparent border-none p-0',\n className\n )}\n {...props}\n >\n {children}\n </button>\n );\n }\n);\nDropdownMenuTrigger.displayName = 'DropdownMenuTrigger';\n\nconst ITEM_SIZE_CLASSES = {\n small: 'text-sm',\n medium: 'text-md',\n} as const;\n\nconst SIDE_CLASSES = {\n top: 'bottom-full',\n right: 'top-full',\n bottom: 'top-full',\n left: 'top-full',\n};\n\nconst ALIGN_CLASSES = {\n start: 'left-0',\n center: 'left-1/2 -translate-x-1/2',\n end: 'right-0',\n};\n\n// O \"chrome\" do card (bg/borda/rounded/shadow) fica por variante para que a\n// variante `papole` possa ter o seu próprio (fundo secondary-500, sem borda,\n// sombra das vars --sds-* do Figma traduzidas: 0 8px 8px -2px, preto 10% + 20%).\n// `menu`/`profile` mantêm exatamente o visual de antes.\nconst MENUCONTENT_VARIANT_CLASSES = {\n menu: 'bg-background rounded-md border bg-popover text-popover-foreground shadow-md border-border-100 p-1',\n profile:\n 'bg-background rounded-md border bg-popover text-popover-foreground shadow-md border-border-100 p-6',\n papole:\n 'flex flex-col gap-4 bg-secondary-500 rounded-[20px] pt-6 px-6 pb-8 [box-shadow:0px_8px_8px_-2px_#0000001a,0px_8px_8px_-2px_#00000033]',\n};\n\nconst MenuLabel = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n store?: DropdownStoreApi;\n }\n>(({ className, inset, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('text-sm w-full', inset ? 'pl-8' : '', className)}\n {...props}\n />\n );\n});\nMenuLabel.displayName = 'MenuLabel';\n\nconst DropdownMenuContent = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n align?: 'start' | 'center' | 'end';\n side?: 'top' | 'right' | 'bottom' | 'left';\n variant?: 'menu' | 'profile' | 'papole';\n sideOffset?: number;\n store?: DropdownStoreApi;\n portal?: boolean;\n triggerRef?: RefObject<HTMLElement | null>;\n /**\n * Tallest the menu gets, in px, when the viewport allows it. Portaled menus\n * only — it is capped by the space actually available around the trigger.\n */\n maxHeight?: number;\n }\n>(\n (\n {\n className,\n align = 'start',\n side = 'bottom',\n variant = 'menu',\n sideOffset = 4,\n children,\n store: externalStore,\n portal = false,\n triggerRef,\n maxHeight = DEFAULT_PORTAL_MAX_HEIGHT,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const [isVisible, setIsVisible] = useState(open);\n const [portalStyle, setPortalStyle] = useState<CSSProperties>({});\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (open) {\n setIsVisible(true);\n } else {\n const timer = setTimeout(() => setIsVisible(false), 200);\n return () => clearTimeout(timer);\n }\n }, [open]);\n\n const updatePortalPosition = useCallback(() => {\n if (!portal || !triggerRef?.current) return;\n\n const rect = triggerRef.current.getBoundingClientRect();\n const placement = { side, align, sideOffset, maxHeight };\n const style =\n side === 'left' || side === 'right'\n ? horizontalPortalStyle(rect, placement)\n : verticalPortalStyle(rect, placement);\n\n setPortalStyle((prev) => (isSamePortalStyle(prev, style) ? prev : style));\n }, [portal, triggerRef, align, side, sideOffset, maxHeight]);\n\n useLayoutEffect(() => {\n if (open) updatePortalPosition();\n }, [open, updatePortalPosition]);\n\n // A portaled menu is position:fixed, so it doesn't follow the trigger when\n // an ancestor scrolls. Tables wrap their body in `overflow-x-auto`, so a\n // menu anchored to a column header would drift away from its <th> on any\n // horizontal scroll. Capture-phase catches scrolls on any ancestor, not\n // just the window.\n useEffect(() => {\n if (!portal || !open) return;\n\n const reposition = () => updatePortalPosition();\n window.addEventListener('scroll', reposition, true);\n window.addEventListener('resize', reposition);\n\n return () => {\n window.removeEventListener('scroll', reposition, true);\n window.removeEventListener('resize', reposition);\n };\n }, [portal, open, updatePortalPosition]);\n\n if (!isVisible) return null;\n\n const getPositionClasses = () => {\n if (portal) {\n return 'fixed';\n }\n const vertical = SIDE_CLASSES[side];\n const horizontal = ALIGN_CLASSES[align];\n\n return `absolute ${vertical} ${horizontal}`;\n };\n\n const variantClasses = MENUCONTENT_VARIANT_CLASSES[variant];\n\n const content = (\n <div\n ref={portal ? contentRef : ref}\n role=\"menu\"\n data-dropdown-content=\"true\"\n data-open={open}\n className={`\n z-50 min-w-[210px] overflow-hidden\n ${open ? 'animate-in fade-in-0 zoom-in-95' : 'animate-out fade-out-0 zoom-out-95'}\n ${getPositionClasses()}\n ${variantClasses}\n ${className}\n `}\n style={{\n ...(portal\n ? portalStyle\n : {\n marginTop: side === 'bottom' ? sideOffset : undefined,\n marginBottom: side === 'top' ? sideOffset : undefined,\n marginLeft: side === 'right' ? sideOffset : undefined,\n marginRight: side === 'left' ? sideOffset : undefined,\n }),\n }}\n {...props}\n >\n {children}\n </div>\n );\n\n if (portal && typeof document !== 'undefined') {\n return createPortal(content, document.body);\n }\n\n return content;\n }\n);\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nconst DropdownMenuItem = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n inset?: boolean;\n size?: 'small' | 'medium';\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n disabled?: boolean;\n variant?: 'profile' | 'menu';\n store?: DropdownStoreApi;\n preventClose?: boolean;\n }\n>(\n (\n {\n className,\n size = 'small',\n children,\n iconRight,\n iconLeft,\n disabled = false,\n onClick,\n variant = 'menu',\n store: externalStore,\n preventClose = false,\n ...props\n },\n ref\n ) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n const sizeClasses = ITEM_SIZE_CLASSES[size];\n\n const handleClick = (\n e: MouseEvent<HTMLDivElement> | KeyboardEvent<HTMLDivElement>\n ) => {\n if (disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n if (e.type === 'click') {\n onClick?.(e as MouseEvent<HTMLDivElement>);\n } else if (e.type === 'keydown') {\n // For keyboard events, trigger click if Enter or Space was pressed\n const keyEvent = e as KeyboardEvent<HTMLDivElement>;\n if (keyEvent.key === 'Enter' || keyEvent.key === ' ') {\n (e.currentTarget as HTMLElement).click();\n }\n // honor any user-provided key handler\n props.onKeyDown?.(keyEvent);\n }\n if (!preventClose) {\n setOpen(false);\n }\n };\n\n const getVariantClasses = () => {\n if (variant === 'profile') {\n return 'relative flex flex-row justify-between select-none items-center gap-2 rounded-sm p-4 text-sm outline-none transition-colors [&>svg]:size-6 [&>svg]:shrink-0';\n }\n return 'relative flex select-none items-center gap-2 rounded-sm p-3 text-sm outline-none transition-colors [&>svg]:size-4 [&>svg]:shrink-0';\n };\n\n const getVariantProps = () => {\n return variant === 'profile' ? { 'data-variant': 'profile' } : {};\n };\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n {...getVariantProps()}\n aria-disabled={disabled}\n className={`\n focus-visible:bg-background-50\n ${getVariantClasses()}\n ${sizeClasses}\n ${className}\n ${\n disabled\n ? 'cursor-not-allowed text-text-400'\n : 'cursor-pointer hover:bg-background-50 text-text-700 focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground'\n }\n `}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n handleClick(e);\n }\n }}\n tabIndex={disabled ? -1 : 0}\n {...props}\n >\n {iconLeft}\n <div className=\"w-full\">{children}</div>\n {iconRight}\n </div>\n );\n }\n);\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSeparator = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, store: _store, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('my-1 h-px bg-border-200', className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\n// Componentes específicos do ProfileMenu\nconst ProfileMenuTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & { store?: DropdownStoreApi }\n>(({ className, onClick, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n className={cn(\n 'rounded-lg size-10 bg-primary-50 flex items-center justify-center cursor-pointer',\n className\n )}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n {...props}\n >\n <span className=\"size-6 rounded-full bg-primary-100 flex items-center justify-center\">\n <UserIcon className=\"text-primary-950\" size={18} />\n </span>\n </button>\n );\n});\nProfileMenuTrigger.displayName = 'ProfileMenuTrigger';\n\nconst ProfileMenuHeader = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n photoUrl?: string | null;\n store?: DropdownStoreApi;\n }\n>(({ className, name, email, photoUrl, store: _store, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuHeader\"\n className={cn(\n 'flex flex-row gap-4 items-center min-w-[280px]',\n className\n )}\n {...props}\n >\n <span className=\"w-16 h-16 bg-primary-100 rounded-full flex items-center justify-center overflow-hidden flex-shrink-0\">\n {photoUrl ? (\n <img\n src={photoUrl}\n alt=\"Foto de perfil\"\n className=\"w-full h-full object-cover\"\n />\n ) : (\n <UserIcon size={34} className=\"text-primary-800\" />\n )}\n </span>\n <div className=\"flex flex-col min-w-0\">\n <Text\n size=\"xl\"\n weight=\"bold\"\n color=\"text-text-950\"\n className=\"truncate\"\n >\n {name}\n </Text>\n <Text size=\"md\" color=\"text-text-600\" className=\"truncate\">\n {email}\n </Text>\n </div>\n </div>\n );\n});\nProfileMenuHeader.displayName = 'ProfileMenuHeader';\n\nconst ProfileMenuInfo = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n schoolName: string;\n classYearName: string;\n schoolYearName: string;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n schoolName,\n classYearName,\n schoolYearName,\n store: _store,\n ...props\n },\n ref\n ) => {\n if (!schoolName && !classYearName && !schoolYearName) {\n return null;\n }\n\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuInfo\"\n className={cn('flex flex-row gap-4 items-center', className)}\n {...props}\n >\n <span className=\"w-16 h-16\" />\n <div className=\"flex flex-col \">\n {schoolName && (\n <Text size=\"md\" color=\"text-text-600\">\n {schoolName}\n </Text>\n )}\n\n {(classYearName || schoolYearName) && (\n <span className=\"flex flex-row items-center gap-2\">\n {classYearName && (\n <Text size=\"md\" color=\"text-text-600\">\n {classYearName}\n </Text>\n )}\n {classYearName && schoolYearName && (\n <Text size=\"md\" color=\"text-text-600\">\n ●\n </Text>\n )}\n {schoolYearName && (\n <Text size=\"md\" color=\"text-text-600\">\n {schoolYearName}\n </Text>\n )}\n </span>\n )}\n </div>\n </div>\n );\n }\n);\nProfileMenuInfo.displayName = 'ProfileMenuInfo';\n\nconst ProfileToggleTheme = ({\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }) => {\n const { themeMode, setTheme } = useTheme();\n const [modalThemeToggle, setModalThemeToggle] = useState(false);\n const [selectedTheme, setSelectedTheme] = useState<ThemeMode>(themeMode);\n\n const internalStoreRef = useRef<DropdownStoreApi | null>(null);\n internalStoreRef.current ??= createDropdownStore();\n const store = externalStore ?? internalStoreRef.current;\n const setOpen = useStore(store, (s) => s.setOpen);\n\n const handleClick = (e: MouseEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setModalThemeToggle(true);\n };\n\n const handleSave = () => {\n setTheme(selectedTheme);\n setModalThemeToggle(false);\n setOpen(false); // Close dropdown after saving\n };\n\n const handleCancel = () => {\n setSelectedTheme(themeMode); // Reset to current theme\n setModalThemeToggle(false);\n setOpen(false); // Close dropdown after canceling\n };\n\n return (\n <>\n <DropdownMenuItem\n variant=\"profile\"\n preventClose={true}\n store={store}\n iconLeft={\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12.5 2.75C15.085 2.75276 17.5637 3.78054 19.3916 5.6084C21.2195 7.43628 22.2473 9.915 22.25 12.5C22.25 14.4284 21.6778 16.3136 20.6064 17.917C19.5352 19.5201 18.0128 20.7699 16.2314 21.5078C14.4499 22.2458 12.489 22.4387 10.5977 22.0625C8.70642 21.6863 6.96899 20.758 5.60547 19.3945C4.24197 18.031 3.31374 16.2936 2.9375 14.4023C2.56129 12.511 2.75423 10.5501 3.49219 8.76855C4.23012 6.98718 5.47982 5.46483 7.08301 4.39355C8.68639 3.32221 10.5716 2.75 12.5 2.75ZM11.75 4.28516C9.70145 4.47452 7.7973 5.42115 6.41016 6.94043C5.02299 8.4599 4.25247 10.4426 4.25 12.5C4.25247 14.5574 5.02299 16.5401 6.41016 18.0596C7.7973 19.5789 9.70145 20.5255 11.75 20.7148V4.28516Z\"\n fill=\"currentColor\"\n />\n </svg>\n }\n iconRight={<CaretRightIcon />}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n setModalThemeToggle(true);\n }\n }}\n {...props}\n >\n <Text size=\"md\" color=\"text-text-700\">\n Aparência\n </Text>\n </DropdownMenuItem>\n\n <Modal\n isOpen={modalThemeToggle}\n onClose={handleCancel}\n title=\"Aparência\"\n size=\"md\"\n footer={\n <div className=\"flex gap-3\">\n <Button variant=\"outline\" onClick={handleCancel}>\n Cancelar\n </Button>\n <Button variant=\"solid\" onClick={handleSave}>\n Salvar\n </Button>\n </div>\n }\n >\n <div className=\"flex flex-col\">\n <p className=\"text-sm text-text-500\">Escolha o tema:</p>\n <ThemeToggle variant=\"with-save\" onToggle={setSelectedTheme} />\n </div>\n </Modal>\n </>\n );\n};\nProfileToggleTheme.displayName = 'ProfileToggleTheme';\n\nconst ProfileMenuSection = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & { store?: DropdownStoreApi }\n>(({ className, children, store: _store, ...props }, ref) => {\n return (\n <div ref={ref} className={cn('flex flex-col p-2', className)} {...props}>\n {children}\n </div>\n );\n});\nProfileMenuSection.displayName = 'ProfileMenuSection';\n\nconst ProfileMenuFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: HTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <Button\n variant=\"outline\"\n className={cn('w-full', className)}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n <span className=\"mr-2 flex items-center\">\n <SignOutIcon className=\"text-inherit\" />\n </span>\n <Text color=\"inherit\">Sair</Text>\n </Button>\n );\n};\nProfileMenuFooter.displayName = 'ProfileMenuFooter';\n\n// ======================================================================\n// Componentes do ProfileMenu Reading Fluency (usados com variant=\"papole\")\n// ======================================================================\n\n// Trigger de perfil Reading Fluency: ícone circular de 42px. Mostra a foto do usuário\n// (`photoUrl`) e cai no passarinho quando não houver.\nconst ProfileMenuReadingFluencyTrigger = forwardRef<\n HTMLButtonElement,\n ButtonHTMLAttributes<HTMLButtonElement> & {\n photoUrl?: string | null;\n store?: DropdownStoreApi;\n }\n>(({ className, onClick, photoUrl, store: externalStore, ...props }, ref) => {\n const store = useDropdownStore(externalStore);\n const open = useStore(store, (s) => s.open);\n const toggleOpen = () => store.setState({ open: !open });\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(\n 'size-[42px] rounded-full overflow-hidden cursor-pointer bg-secondary-600 flex items-center justify-center',\n className\n )}\n onClick={(e) => {\n e.stopPropagation();\n toggleOpen();\n onClick?.(e);\n }}\n aria-expanded={open}\n aria-label=\"Abrir menu de perfil\"\n {...props}\n >\n <img\n src={photoUrl ?? readingFluencyBird}\n alt=\"Foto de perfil\"\n className=\"w-full h-full object-cover\"\n />\n </button>\n );\n});\nProfileMenuReadingFluencyTrigger.displayName =\n 'ProfileMenuReadingFluencyTrigger';\n\n// Card de informações do aluno (fundo secondary-600). Dois blocos texto1/texto2:\n// nome/email (sempre) e escola/turma (quando houver).\nconst ProfileMenuReadingFluencyInfo = forwardRef<\n HTMLDivElement,\n HTMLAttributes<HTMLDivElement> & {\n name: string;\n email: string;\n schoolName?: string;\n classYearName?: string;\n schoolYearName?: string;\n store?: DropdownStoreApi;\n }\n>(\n (\n {\n className,\n name,\n email,\n schoolName,\n classYearName,\n schoolYearName,\n store: _store,\n ...props\n },\n ref\n ) => {\n const hasSchoolBlock = !!(schoolName || classYearName || schoolYearName);\n\n return (\n <div\n ref={ref}\n data-component=\"ProfileMenuReadingFluencyInfo\"\n className={cn(\n 'font-quicksand flex flex-col gap-4 rounded-[20px] bg-secondary-600 p-4',\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col\">\n <Text size=\"md\" className=\"font-bold text-text-100 truncate\">\n {name}\n </Text>\n <Text size=\"sm\" className=\"font-medium text-secondary-300 truncate\">\n {email}\n </Text>\n </div>\n\n {hasSchoolBlock && (\n <div className=\"flex flex-col\">\n {schoolName && (\n <Text size=\"md\" className=\"font-bold text-text-100 truncate\">\n {schoolName}\n </Text>\n )}\n {(classYearName || schoolYearName) && (\n <Text\n size=\"sm\"\n className=\"font-medium text-secondary-300 truncate\"\n >\n {[classYearName, schoolYearName].filter(Boolean).join(' • ')}\n </Text>\n )}\n </div>\n )}\n </div>\n );\n }\n);\nProfileMenuReadingFluencyInfo.displayName = 'ProfileMenuReadingFluencyInfo';\n\n// Rodapé Reading Fluency: botão \"Sair\" (ButtonReadingFluency outline md). Fecha o menu e repassa\n// o onClick (logout).\nconst ProfileMenuReadingFluencyFooter = ({\n className,\n disabled = false,\n onClick,\n store: externalStore,\n ...props\n}: ButtonHTMLAttributes<HTMLButtonElement> & {\n disabled?: boolean;\n store?: DropdownStoreApi;\n}) => {\n const store = useDropdownStore(externalStore);\n const setOpen = useStore(store, (s) => s.setOpen);\n\n return (\n <ButtonReadingFluency\n variant=\"outline-inverse\"\n size=\"medium\"\n className={cn('w-full', className)}\n disabled={disabled}\n onClick={(e) => {\n setOpen(false);\n onClick?.(e);\n }}\n {...props}\n >\n Sair\n </ButtonReadingFluency>\n );\n};\nProfileMenuReadingFluencyFooter.displayName = 'ProfileMenuReadingFluencyFooter';\n\n// Exportações\nexport default DropdownMenu;\nexport {\n // Componentes genéricos\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n MenuLabel,\n DropdownMenuSeparator,\n\n // Componentes específicos do ProfileMenu\n ProfileMenuTrigger,\n ProfileMenuHeader,\n ProfileMenuSection,\n ProfileMenuFooter,\n ProfileToggleTheme,\n ProfileMenuInfo,\n\n // Componentes do ProfileMenu Reading Fluency\n ProfileMenuReadingFluencyTrigger,\n ProfileMenuReadingFluencyInfo,\n ProfileMenuReadingFluencyFooter,\n};\n"]}
@@ -8,7 +8,7 @@ var _chunkBVUPM6EYjs = require('./chunk-BVUPM6EY.js');
8
8
 
9
9
 
10
10
 
11
- var _chunkOCIBLTVLjs = require('./chunk-OCIBLTVL.js');
11
+ var _chunk2DPLSITCjs = require('./chunk-2DPLSITC.js');
12
12
 
13
13
 
14
14
  var _chunkLS4EGCEJjs = require('./chunk-LS4EGCEJ.js');
@@ -61,16 +61,17 @@ var CalendarCard = ({
61
61
  )
62
62
  ] });
63
63
  }
64
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkOCIBLTVLjs.DropdownMenu_default, { open: effectiveOpen, onOpenChange: handleOpenChange, children: [
64
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk2DPLSITCjs.DropdownMenu_default, { open: effectiveOpen, onOpenChange: handleOpenChange, children: [
65
65
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
66
- _chunkOCIBLTVLjs.DropdownMenuTrigger,
66
+ _chunk2DPLSITCjs.DropdownMenuTrigger,
67
67
  {
68
68
  className: `text-primary cursor-pointer ${_nullishCoalesce(className, () => ( ""))}`,
69
+ asChild: true,
69
70
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkBVUPM6EYjs.IconButton_default, { active: effectiveOpen, icon: triggerIcon })
70
71
  }
71
72
  ),
72
73
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
73
- _chunkOCIBLTVLjs.DropdownMenuContent,
74
+ _chunk2DPLSITCjs.DropdownMenuContent,
74
75
  {
75
76
  className: "w-[320px] max-w-[calc(100vw-16px)] max-h-[80vh] overflow-y-auto",
76
77
  align: "end",
@@ -86,4 +87,4 @@ var CalendarCard_default = CalendarCard;
86
87
 
87
88
 
88
89
  exports.CalendarCard = CalendarCard; exports.CalendarCard_default = CalendarCard_default;
89
- //# sourceMappingURL=chunk-Q5VRX5TR.js.map
90
+ //# sourceMappingURL=chunk-4SBNOQ4H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-4SBNOQ4H.js","../src/components/CalendarCard/CalendarCard.tsx"],"names":[],"mappings":"AAAA;AACE;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACE;AACA;AACA;AACF,sDAA4B;AAC5B;AACE;AACF,sDAA4B;AAC5B;AACA;ACfA,6EAAkC;AAElC,8BAAsC;AAiEhB,+CAAA;AA5Bf,IAAM,aAAA,EAAe,CAAC;AAAA,EAC3B,OAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA,EAAQ,eAAA;AAAA,EACR;AACF,CAAA,EAAA,GAAyB;AACvB,EAAA,MAAM,EAAE,SAAS,EAAA,EAAI,wCAAA,CAAU;AAC/B,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,EAAA,EAAI,6BAAA,KAAc,CAAA;AAEtD,EAAA,MAAM,aAAA,EAAe,OAAA,IAAW,KAAA,CAAA;AAChC,EAAA,MAAM,cAAA,EAAgB,aAAA,EAAe,OAAA,EAAS,YAAA;AAM9C,EAAA,MAAM,iBAAA,EAAmB,gCAAA;AAAA,IACvB,CAAC,IAAA,EAAA,GAAkB;AACjB,MAAA,GAAA,CAAI,CAAC,YAAA,EAAc;AACjB,QAAA,eAAA,CAAgB,IAAI,CAAA;AAAA,MACtB;AACA,sBAAA,YAAA,wBAAA,CAAe,IAAI,GAAA;AAAA,IACrB,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,YAAY;AAAA,EAC7B,CAAA;AAEA,EAAA,MAAM,UAAA,EAAY,cAAA,EAAgB,mBAAA,EAAqB,cAAA;AACvD,EAAA,MAAM,YAAA,kBAAc,6BAAA,gCAAC,EAAA,EAAkB,IAAA,EAAM,EAAA,EAAI,SAAA,EAAW,UAAA,CAAW,CAAA;AAEvE,EAAA,GAAA,CAAI,QAAA,EAAU;AACZ,IAAA,uBACE,8BAAA,oBAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,6BAAA;AAAA,QAAC,mCAAA;AAAA,QAAA;AAAA,UACC,MAAA,EAAQ,aAAA;AAAA,UACR,OAAA,EAAS,CAAA,EAAA,GAAM,gBAAA,CAAiB,CAAC,aAAa,CAAA;AAAA,UAC9C,IAAA,EAAM,WAAA;AAAA,UACN;AAAA,QAAA;AAAA,MACF,CAAA;AAAA,sBACA,6BAAA;AAAA,QAAC,8BAAA;AAAA,QAAA;AAAA,UACC,MAAA,EAAQ,aAAA;AAAA,UACR,OAAA,EAAS,CAAA,EAAA,GAAM,gBAAA,CAAiB,KAAK,CAAA;AAAA,UACrC,KAAA;AAAA,UAEA,QAAA,kBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,qBAAA,EAAuB,QAAA,EAAA,QAAA,CAAQ;AAAA,QAAA;AAAA,MAChD;AAAA,IAAA,EAAA,CACF,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACE,8BAAA,qCAAC,EAAA,EAAa,IAAA,EAAM,aAAA,EAAe,YAAA,EAAc,gBAAA,EAC/C,QAAA,EAAA;AAAA,oBAAA,6BAAA;AAAA,MAAC,oCAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,CAAA,4BAAA,mBAA+B,SAAA,UAAa,IAAE,CAAA,CAAA;AAClD,QAAA;AAEK,QAAA;AAA0C,MAAA;AACxD,IAAA;AACA,oBAAA;AAAC,MAAA;AAAA,MAAA;AACW,QAAA;AACJ,QAAA;AACD,QAAA;AAEJ,QAAA;AAAA,MAAA;AACH,IAAA;AACF,EAAA;AAEJ;AAEe;ADxBmD;AACA;AACA;AACA;AACA","file":"/home/runner/work/analytica-frontend-lib/analytica-frontend-lib/dist/chunk-4SBNOQ4H.js","sourcesContent":[null,"import { CalendarBlankIcon } from '@phosphor-icons/react/dist/csr/CalendarBlank';\nimport type { ReactNode } from 'react';\nimport { useCallback, useState } from 'react';\nimport DropdownMenu, {\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from '../DropdownMenu/DropdownMenu';\nimport IconButton from '../IconButton/IconButton';\nimport Modal from '../Modal/Modal';\nimport { useMobile } from '../../hooks/useMobile';\n\nexport interface CalendarCardProps {\n /** Content rendered inside the calendar (calendar grid + activities list). */\n content: ReactNode;\n /**\n * Whether the calendar surface is currently open.\n * When provided, the component is **controlled**: the consumer is the source of truth.\n * When omitted, the component manages internal state.\n */\n isOpen?: boolean;\n /**\n * Fired whenever the open state changes (user click, outside click,\n * programmatic close, ESC, etc.).\n */\n onOpenChange?: (open: boolean) => void;\n /** Title displayed in the mobile Modal. Default: \"Calendário\". */\n title?: string;\n /** Optional className applied to the trigger button. */\n className?: string;\n}\n\n/**\n * Calendar widget for the app header. Renders a calendar icon trigger that\n * opens a `DropdownMenu` on tablet/desktop and a `Modal` on mobile (<500px).\n *\n * Pairs naturally with `AppHeader`'s `calendarContent` prop. Use the\n * controlled `isOpen` + `onOpenChange` pair when the consumer needs to close\n * the surface programmatically (e.g. on route change).\n */\nexport const CalendarCard = ({\n content,\n isOpen,\n onOpenChange,\n title = 'Calendário',\n className,\n}: CalendarCardProps) => {\n const { isMobile } = useMobile();\n const [internalOpen, setInternalOpen] = useState(false);\n\n const isControlled = isOpen !== undefined;\n const effectiveOpen = isControlled ? isOpen : internalOpen;\n\n // `useCallback` keeps the reference stable across renders, so the\n // `DropdownMenu`'s `useEffect [open, onOpenChange]` doesn't re-fire on\n // every parent re-render (which is what triggers the infinite update loop\n // observed before).\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setInternalOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n const iconColor = effectiveOpen ? 'text-primary-950' : 'text-primary';\n const triggerIcon = <CalendarBlankIcon size={24} className={iconColor} />;\n\n if (isMobile) {\n return (\n <>\n <IconButton\n active={effectiveOpen}\n onClick={() => handleOpenChange(!effectiveOpen)}\n icon={triggerIcon}\n className={className}\n />\n <Modal\n isOpen={effectiveOpen}\n onClose={() => handleOpenChange(false)}\n title={title}\n >\n <div className=\"flex justify-center\">{content}</div>\n </Modal>\n </>\n );\n }\n\n return (\n <DropdownMenu open={effectiveOpen} onOpenChange={handleOpenChange}>\n <DropdownMenuTrigger\n className={`text-primary cursor-pointer ${className ?? ''}`}\n asChild\n >\n <IconButton active={effectiveOpen} icon={triggerIcon} />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-[320px] max-w-[calc(100vw-16px)] max-h-[80vh] overflow-y-auto\"\n align=\"end\"\n side=\"bottom\"\n >\n {content}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n\nexport default CalendarCard;\n"]}
@@ -6,10 +6,10 @@ import {
6
6
  } from "./chunk-GNLZTQRR.mjs";
7
7
  import {
8
8
  NotificationCard_default
9
- } from "./chunk-FZUPX44N.mjs";
9
+ } from "./chunk-VG5EMAOF.mjs";
10
10
  import {
11
11
  CalendarCard_default
12
- } from "./chunk-EWG6Q2QF.mjs";
12
+ } from "./chunk-6MZEJVNV.mjs";
13
13
  import {
14
14
  useMobile
15
15
  } from "./chunk-GKY77WVA.mjs";
@@ -29,7 +29,7 @@ import {
29
29
  ProfileMenuInfo,
30
30
  ProfileMenuSection,
31
31
  ProfileToggleTheme
32
- } from "./chunk-7LRIQOCS.mjs";
32
+ } from "./chunk-VAYB6LNV.mjs";
33
33
  import {
34
34
  Text_default
35
35
  } from "./chunk-IMCIR6TJ.mjs";
@@ -219,20 +219,27 @@ var AppHeader = ({
219
219
  );
220
220
  },
221
221
  children: [
222
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { className: "text-primary cursor-pointer", children: /* @__PURE__ */ jsx(
223
- IconButton_default,
222
+ /* @__PURE__ */ jsx(
223
+ DropdownMenuTrigger,
224
224
  {
225
- active: activeStates.profile,
226
- onClick: () => toggleActive("profile"),
227
- icon: /* @__PURE__ */ jsx(
228
- UserIcon,
225
+ className: "text-primary cursor-pointer",
226
+ asChild: true,
227
+ children: /* @__PURE__ */ jsx(
228
+ IconButton_default,
229
229
  {
230
- size: 24,
231
- className: activeStates.profile ? "opacity-80" : ""
230
+ active: activeStates.profile,
231
+ onClick: () => toggleActive("profile"),
232
+ icon: /* @__PURE__ */ jsx(
233
+ UserIcon,
234
+ {
235
+ size: 24,
236
+ className: activeStates.profile ? "opacity-80" : ""
237
+ }
238
+ )
232
239
  }
233
240
  )
234
241
  }
235
- ) }),
242
+ ),
236
243
  /* @__PURE__ */ jsxs(
237
244
  DropdownMenuContent,
238
245
  {
@@ -292,4 +299,4 @@ export {
292
299
  AppHeader,
293
300
  AppHeader_default
294
301
  };
295
- //# sourceMappingURL=chunk-AFBTGILL.mjs.map
302
+ //# sourceMappingURL=chunk-4TBI57KA.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/AppHeader/AppHeader.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { CaretRightIcon } from '@phosphor-icons/react/dist/csr/CaretRight';\nimport { UserIcon as UserPhosphorIcon } from '@phosphor-icons/react/dist/csr/User';\n\nimport { BrandingLogo } from '../BrandingLogo/BrandingLogo';\nimport CalendarCard from '../CalendarCard/CalendarCard';\nimport IconButton from '../IconButton/IconButton';\nimport DropdownMenu, {\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n ProfileMenuFooter,\n ProfileMenuHeader,\n ProfileMenuInfo,\n ProfileMenuSection,\n ProfileToggleTheme,\n} from '../DropdownMenu/DropdownMenu';\nimport NotificationCard, {\n type NotificationGroup,\n} from '../NotificationCard/NotificationCard';\nimport { PageContainer } from '../PageContainer/PageContainer';\nimport Text from '../Text/Text';\nimport { UserIcon } from '../UserIcon/UserIcon';\nimport { useMobile } from '../../hooks/useMobile';\nimport { syncDropdownState } from '../../utils/dropdown';\nimport { NotificationEntityType } from '../../types/notifications';\n\n/**\n * Subset of session info consumed by the application header.\n * Each property is optional so the consumer can pass whatever it has.\n */\nexport interface AppHeaderSessionInfo {\n userName?: string;\n email?: string;\n urlProfilePicture?: string;\n schoolName?: string;\n className?: string;\n schoolYearName?: string;\n}\n\n/**\n * Minimal user shape needed to fill the profile dropdown header.\n */\nexport interface AppHeaderUser {\n name?: string;\n email?: string;\n}\n\n/**\n * Tutorial action rendered as a pill button in the header (left of the\n * notifications bell). The consumer owns the click behavior (usually opening\n * the configured tutorial URL in a new tab).\n */\nexport interface AppHeaderTutorial {\n /** Show the tutorial button. */\n visible?: boolean;\n /** Button label. Defaults to \"Tutoriais\". */\n label?: string;\n /** Fired when the tutorial button is clicked. */\n onClick: () => void;\n}\n\n/**\n * Notifications data + callbacks the AppHeader forwards to NotificationCard.\n * Built by the consumer (usually via `createNotificationsHook(api)`).\n */\nexport interface AppHeaderNotifications {\n unreadCount: number;\n loading: boolean;\n error: string | null;\n groupedNotifications: NotificationGroup[];\n refreshNotifications: () => void;\n markAsRead: (id: string) => void;\n deleteNotification: (id: string) => void;\n fetchNotifications: () => void;\n fetchUnreadCount?: () => void;\n getActionLabel: (entityType?: NotificationEntityType) => string | undefined;\n}\n\nexport interface AppHeaderProps {\n /** Authenticated user (fallback when sessionInfo doesn't carry name/email). */\n user?: AppHeaderUser;\n /** Session metadata used to render profile name, email, photo and school info. */\n sessionInfo?: AppHeaderSessionInfo;\n /** Notifications wiring (state + callbacks). */\n notifications: AppHeaderNotifications;\n /** Tutorial pill button shown before the notifications bell. */\n tutorial?: AppHeaderTutorial;\n /** Show the calendar widget in the header. */\n showCalendar?: boolean;\n /** Content rendered inside the calendar (dropdown on tablet/desktop, modal on mobile). */\n calendarContent?: ReactNode;\n /**\n * Optional controlled open state for the calendar.\n * When provided, the consumer is the source of truth; useful for closing\n * the calendar programmatically (e.g. on route change).\n */\n calendarOpen?: boolean;\n /** Fired whenever the calendar open state changes. */\n onCalendarOpenChange?: (open: boolean) => void;\n /** Show school/class/year inside the profile dropdown. */\n showProfileInfo?: boolean;\n /** Optional fallback image for the notifications empty state. */\n emptyNotificationsImage?: string;\n /** Empty-state title for notifications dropdown. */\n emptyNotificationsTitle?: string;\n /** Empty-state description for notifications dropdown. */\n emptyNotificationsDescription?: string;\n /** Callback fired when the user activates logout. */\n onLogout: () => void;\n /** Callback fired when the user activates the \"My data\" menu item. */\n onNavigateToMyData: () => void;\n /** Callback fired when the user clicks on a notification with entity info. */\n onNavigateByNotification?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n /**\n * Tailwind class overriding the default `max-w-[1000px]` of the header\n * content (forwarded to the internal `PageContainer`'s `innerClassName`).\n * Pass e.g. `max-w-[1350px]` to align the header with a widened page\n * content. When omitted, the default `max-w-[1000px]` is kept, so other\n * consumers are unaffected.\n */\n contentMaxWidth?: string;\n}\n\nconst DEFAULT_EMPTY_TITLE = 'Nenhuma notificação no momento';\nconst DEFAULT_EMPTY_DESCRIPTION =\n 'Você está em dia com todas as novidades. Volte depois para conferir atualizações!';\n\n/**\n * Application header shared across the analytica frontends.\n *\n * Renders the institution logo, optional calendar dropdown (mobile/tablet),\n * notifications center and a profile menu. Width is constrained by\n * `<PageContainer>` so it always aligns with the rest of the page content.\n */\nexport const AppHeader = ({\n user,\n sessionInfo,\n notifications,\n tutorial,\n showCalendar = false,\n calendarContent,\n calendarOpen,\n onCalendarOpenChange,\n showProfileInfo = false,\n emptyNotificationsImage,\n emptyNotificationsTitle = DEFAULT_EMPTY_TITLE,\n emptyNotificationsDescription = DEFAULT_EMPTY_DESCRIPTION,\n onLogout,\n onNavigateToMyData,\n onNavigateByNotification,\n contentMaxWidth,\n}: AppHeaderProps) => {\n const { isMobile, isExtraSmallMobile } = useMobile();\n const [activeStates, setActiveStates] = useState<Record<string, boolean>>({});\n\n useEffect(() => {\n notifications.fetchUnreadCount?.();\n }, []);\n\n const toggleActive = (buttonId: string) => {\n setActiveStates((prev) => {\n if (prev[buttonId]) {\n return { ...prev, [buttonId]: false };\n }\n return {\n calendar: false,\n notifications: false,\n profile: false,\n [buttonId]: true,\n };\n });\n };\n\n // Stable callback so `DropdownMenu`'s `useEffect [open, onOpenChange]`\n // doesn't re-fire on every parent re-render, which would cascade into a\n // Maximum-update-depth loop (same root cause class as PR #435).\n const handleCalendarOpenChange = useCallback(\n (open: boolean) => {\n setActiveStates((prev) => {\n const current = prev.calendar ?? false;\n if (current === open) {\n return prev;\n }\n if (open) {\n return {\n calendar: true,\n notifications: false,\n profile: false,\n };\n }\n return { ...prev, calendar: false };\n });\n onCalendarOpenChange?.(open);\n },\n [onCalendarOpenChange]\n );\n\n useEffect(() => {\n const handleEscapeKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setActiveStates({});\n }\n };\n document.addEventListener('keydown', handleEscapeKey);\n return () => document.removeEventListener('keydown', handleEscapeKey);\n }, []);\n\n const handleMyDataClick = () => {\n setActiveStates({});\n onNavigateToMyData();\n };\n\n const displayName = sessionInfo?.userName ?? user?.name ?? 'Usuário';\n const displayEmail = sessionInfo?.email ?? user?.email ?? '';\n\n const pickResponsiveClass = (\n extraSmall: string,\n mobile: string,\n desktop: string\n ): string => {\n if (isExtraSmallMobile) return extraSmall;\n if (isMobile) return mobile;\n return desktop;\n };\n const profileDropdownWidth = pickResponsiveClass(\n 'min-w-[260px]',\n 'min-w-[280px]',\n 'min-w-[320px]'\n );\n const sectionGap = pickResponsiveClass('gap-1', 'gap-2', 'gap-3');\n const logoHeight = pickResponsiveClass('h-6', 'h-8', 'h-10');\n const tutorialPadding = pickResponsiveClass(\n 'px-3 py-1.5 text-xs',\n 'px-3.5 py-2 text-sm',\n 'px-4 py-2 text-sm'\n );\n\n return (\n <header\n data-component=\"AppHeader\"\n className=\"bg-primary-800 w-full h-[70px] flex justify-center items-center\"\n >\n <PageContainer\n className=\"pb-0 justify-center\"\n innerClassName={contentMaxWidth}\n >\n <div className=\"w-full flex flex-row justify-between items-center gap-3\">\n {/* `min-w-0 shrink` lets the logo compress instead of overflowing:\n an <img> resolves `min-width:auto` to its intrinsic width, which\n would otherwise block flex-shrink and push the actions off-screen\n on narrow viewports. `object-left` keeps it left-aligned as it\n scales down. The actions never shrink. */}\n <BrandingLogo\n variant=\"main\"\n alt=\"Logo\"\n className={`${logoHeight} object-contain object-left min-w-0 shrink`}\n />\n <section\n className={`flex flex-row items-center shrink-0 ${sectionGap}`}\n >\n {tutorial?.visible && (\n <button\n type=\"button\"\n data-testid=\"app-header-tutorial\"\n onClick={tutorial.onClick}\n /* `primary` (não `text`) é o foreground de `primary-800` em\n todos os temas — os dois formam um par contrastante mesmo\n onde o dark inverte o header (paraiba/analytica). Usar\n `text-*` aqui inverteria com o modo enquanto o fundo do\n header não inverte, apagando o botão no dark. */\n className={`rounded-full border border-primary text-primary font-medium whitespace-nowrap cursor-pointer transition-colors hover:bg-primary-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${tutorialPadding}`}\n >\n {tutorial.label ?? 'Tutoriais'}\n </button>\n )}\n\n {showCalendar && (\n <div className=\"lg:hidden\">\n <CalendarCard\n content={calendarContent}\n isOpen={calendarOpen ?? activeStates.calendar ?? false}\n onOpenChange={handleCalendarOpenChange}\n />\n </div>\n )}\n\n <NotificationCard\n mode=\"center\"\n isActive={activeStates.notifications}\n onToggleActive={() => toggleActive('notifications')}\n onOpenChange={(open: boolean) => {\n syncDropdownState(\n open,\n activeStates.notifications,\n setActiveStates,\n 'notifications'\n );\n }}\n unreadCount={notifications.unreadCount}\n groupedNotifications={notifications.groupedNotifications}\n loading={notifications.loading}\n error={notifications.error}\n onRetry={notifications.refreshNotifications}\n onMarkAsReadById={notifications.markAsRead}\n onDeleteById={notifications.deleteNotification}\n onNavigateById={(entityType, entityId) => {\n if (entityType && entityId) {\n onNavigateByNotification?.(entityType, entityId);\n }\n }}\n getActionLabel={notifications.getActionLabel}\n onFetchNotifications={notifications.fetchNotifications}\n emptyStateImage={emptyNotificationsImage}\n emptyStateTitle={emptyNotificationsTitle}\n emptyStateDescription={emptyNotificationsDescription}\n />\n\n <DropdownMenu\n onOpenChange={(open: boolean) => {\n syncDropdownState(\n open,\n activeStates.profile,\n setActiveStates,\n 'profile'\n );\n }}\n >\n <DropdownMenuTrigger className=\"text-primary cursor-pointer\">\n <IconButton\n active={activeStates.profile}\n onClick={() => toggleActive('profile')}\n icon={\n <UserIcon\n size={24}\n className={activeStates.profile ? 'opacity-80' : ''}\n />\n }\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className={profileDropdownWidth}\n side=\"bottom\"\n variant=\"profile\"\n align=\"end\"\n >\n <ProfileMenuHeader\n name={displayName}\n email={displayEmail}\n photoUrl={sessionInfo?.urlProfilePicture}\n />\n\n {showProfileInfo && (\n <ProfileMenuInfo\n schoolName={sessionInfo?.schoolName ?? ''}\n classYearName={sessionInfo?.className ?? ''}\n schoolYearName={sessionInfo?.schoolYearName ?? ''}\n />\n )}\n\n <ProfileMenuSection>\n <DropdownMenuItem\n variant=\"profile\"\n iconLeft={<UserPhosphorIcon />}\n iconRight={<CaretRightIcon />}\n onClick={handleMyDataClick}\n >\n <Text size=\"md\" color=\"text-text-700\">\n Meus dados\n </Text>\n </DropdownMenuItem>\n\n <ProfileToggleTheme />\n </ProfileMenuSection>\n\n <ProfileMenuFooter onClick={onLogout} />\n </DropdownMenuContent>\n </DropdownMenu>\n </section>\n </div>\n </PageContainer>\n </header>\n );\n};\n\nexport default AppHeader;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/components/AppHeader/AppHeader.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { CaretRightIcon } from '@phosphor-icons/react/dist/csr/CaretRight';\nimport { UserIcon as UserPhosphorIcon } from '@phosphor-icons/react/dist/csr/User';\n\nimport { BrandingLogo } from '../BrandingLogo/BrandingLogo';\nimport CalendarCard from '../CalendarCard/CalendarCard';\nimport IconButton from '../IconButton/IconButton';\nimport DropdownMenu, {\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n ProfileMenuFooter,\n ProfileMenuHeader,\n ProfileMenuInfo,\n ProfileMenuSection,\n ProfileToggleTheme,\n} from '../DropdownMenu/DropdownMenu';\nimport NotificationCard, {\n type NotificationGroup,\n} from '../NotificationCard/NotificationCard';\nimport { PageContainer } from '../PageContainer/PageContainer';\nimport Text from '../Text/Text';\nimport { UserIcon } from '../UserIcon/UserIcon';\nimport { useMobile } from '../../hooks/useMobile';\nimport { syncDropdownState } from '../../utils/dropdown';\nimport { NotificationEntityType } from '../../types/notifications';\n\n/**\n * Subset of session info consumed by the application header.\n * Each property is optional so the consumer can pass whatever it has.\n */\nexport interface AppHeaderSessionInfo {\n userName?: string;\n email?: string;\n urlProfilePicture?: string;\n schoolName?: string;\n className?: string;\n schoolYearName?: string;\n}\n\n/**\n * Minimal user shape needed to fill the profile dropdown header.\n */\nexport interface AppHeaderUser {\n name?: string;\n email?: string;\n}\n\n/**\n * Tutorial action rendered as a pill button in the header (left of the\n * notifications bell). The consumer owns the click behavior (usually opening\n * the configured tutorial URL in a new tab).\n */\nexport interface AppHeaderTutorial {\n /** Show the tutorial button. */\n visible?: boolean;\n /** Button label. Defaults to \"Tutoriais\". */\n label?: string;\n /** Fired when the tutorial button is clicked. */\n onClick: () => void;\n}\n\n/**\n * Notifications data + callbacks the AppHeader forwards to NotificationCard.\n * Built by the consumer (usually via `createNotificationsHook(api)`).\n */\nexport interface AppHeaderNotifications {\n unreadCount: number;\n loading: boolean;\n error: string | null;\n groupedNotifications: NotificationGroup[];\n refreshNotifications: () => void;\n markAsRead: (id: string) => void;\n deleteNotification: (id: string) => void;\n fetchNotifications: () => void;\n fetchUnreadCount?: () => void;\n getActionLabel: (entityType?: NotificationEntityType) => string | undefined;\n}\n\nexport interface AppHeaderProps {\n /** Authenticated user (fallback when sessionInfo doesn't carry name/email). */\n user?: AppHeaderUser;\n /** Session metadata used to render profile name, email, photo and school info. */\n sessionInfo?: AppHeaderSessionInfo;\n /** Notifications wiring (state + callbacks). */\n notifications: AppHeaderNotifications;\n /** Tutorial pill button shown before the notifications bell. */\n tutorial?: AppHeaderTutorial;\n /** Show the calendar widget in the header. */\n showCalendar?: boolean;\n /** Content rendered inside the calendar (dropdown on tablet/desktop, modal on mobile). */\n calendarContent?: ReactNode;\n /**\n * Optional controlled open state for the calendar.\n * When provided, the consumer is the source of truth; useful for closing\n * the calendar programmatically (e.g. on route change).\n */\n calendarOpen?: boolean;\n /** Fired whenever the calendar open state changes. */\n onCalendarOpenChange?: (open: boolean) => void;\n /** Show school/class/year inside the profile dropdown. */\n showProfileInfo?: boolean;\n /** Optional fallback image for the notifications empty state. */\n emptyNotificationsImage?: string;\n /** Empty-state title for notifications dropdown. */\n emptyNotificationsTitle?: string;\n /** Empty-state description for notifications dropdown. */\n emptyNotificationsDescription?: string;\n /** Callback fired when the user activates logout. */\n onLogout: () => void;\n /** Callback fired when the user activates the \"My data\" menu item. */\n onNavigateToMyData: () => void;\n /** Callback fired when the user clicks on a notification with entity info. */\n onNavigateByNotification?: (\n entityType?: NotificationEntityType,\n entityId?: string\n ) => void;\n /**\n * Tailwind class overriding the default `max-w-[1000px]` of the header\n * content (forwarded to the internal `PageContainer`'s `innerClassName`).\n * Pass e.g. `max-w-[1350px]` to align the header with a widened page\n * content. When omitted, the default `max-w-[1000px]` is kept, so other\n * consumers are unaffected.\n */\n contentMaxWidth?: string;\n}\n\nconst DEFAULT_EMPTY_TITLE = 'Nenhuma notificação no momento';\nconst DEFAULT_EMPTY_DESCRIPTION =\n 'Você está em dia com todas as novidades. Volte depois para conferir atualizações!';\n\n/**\n * Application header shared across the analytica frontends.\n *\n * Renders the institution logo, optional calendar dropdown (mobile/tablet),\n * notifications center and a profile menu. Width is constrained by\n * `<PageContainer>` so it always aligns with the rest of the page content.\n */\nexport const AppHeader = ({\n user,\n sessionInfo,\n notifications,\n tutorial,\n showCalendar = false,\n calendarContent,\n calendarOpen,\n onCalendarOpenChange,\n showProfileInfo = false,\n emptyNotificationsImage,\n emptyNotificationsTitle = DEFAULT_EMPTY_TITLE,\n emptyNotificationsDescription = DEFAULT_EMPTY_DESCRIPTION,\n onLogout,\n onNavigateToMyData,\n onNavigateByNotification,\n contentMaxWidth,\n}: AppHeaderProps) => {\n const { isMobile, isExtraSmallMobile } = useMobile();\n const [activeStates, setActiveStates] = useState<Record<string, boolean>>({});\n\n useEffect(() => {\n notifications.fetchUnreadCount?.();\n }, []);\n\n const toggleActive = (buttonId: string) => {\n setActiveStates((prev) => {\n if (prev[buttonId]) {\n return { ...prev, [buttonId]: false };\n }\n return {\n calendar: false,\n notifications: false,\n profile: false,\n [buttonId]: true,\n };\n });\n };\n\n // Stable callback so `DropdownMenu`'s `useEffect [open, onOpenChange]`\n // doesn't re-fire on every parent re-render, which would cascade into a\n // Maximum-update-depth loop (same root cause class as PR #435).\n const handleCalendarOpenChange = useCallback(\n (open: boolean) => {\n setActiveStates((prev) => {\n const current = prev.calendar ?? false;\n if (current === open) {\n return prev;\n }\n if (open) {\n return {\n calendar: true,\n notifications: false,\n profile: false,\n };\n }\n return { ...prev, calendar: false };\n });\n onCalendarOpenChange?.(open);\n },\n [onCalendarOpenChange]\n );\n\n useEffect(() => {\n const handleEscapeKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setActiveStates({});\n }\n };\n document.addEventListener('keydown', handleEscapeKey);\n return () => document.removeEventListener('keydown', handleEscapeKey);\n }, []);\n\n const handleMyDataClick = () => {\n setActiveStates({});\n onNavigateToMyData();\n };\n\n const displayName = sessionInfo?.userName ?? user?.name ?? 'Usuário';\n const displayEmail = sessionInfo?.email ?? user?.email ?? '';\n\n const pickResponsiveClass = (\n extraSmall: string,\n mobile: string,\n desktop: string\n ): string => {\n if (isExtraSmallMobile) return extraSmall;\n if (isMobile) return mobile;\n return desktop;\n };\n const profileDropdownWidth = pickResponsiveClass(\n 'min-w-[260px]',\n 'min-w-[280px]',\n 'min-w-[320px]'\n );\n const sectionGap = pickResponsiveClass('gap-1', 'gap-2', 'gap-3');\n const logoHeight = pickResponsiveClass('h-6', 'h-8', 'h-10');\n const tutorialPadding = pickResponsiveClass(\n 'px-3 py-1.5 text-xs',\n 'px-3.5 py-2 text-sm',\n 'px-4 py-2 text-sm'\n );\n\n return (\n <header\n data-component=\"AppHeader\"\n className=\"bg-primary-800 w-full h-[70px] flex justify-center items-center\"\n >\n <PageContainer\n className=\"pb-0 justify-center\"\n innerClassName={contentMaxWidth}\n >\n <div className=\"w-full flex flex-row justify-between items-center gap-3\">\n {/* `min-w-0 shrink` lets the logo compress instead of overflowing:\n an <img> resolves `min-width:auto` to its intrinsic width, which\n would otherwise block flex-shrink and push the actions off-screen\n on narrow viewports. `object-left` keeps it left-aligned as it\n scales down. The actions never shrink. */}\n <BrandingLogo\n variant=\"main\"\n alt=\"Logo\"\n className={`${logoHeight} object-contain object-left min-w-0 shrink`}\n />\n <section\n className={`flex flex-row items-center shrink-0 ${sectionGap}`}\n >\n {tutorial?.visible && (\n <button\n type=\"button\"\n data-testid=\"app-header-tutorial\"\n onClick={tutorial.onClick}\n /* `primary` (não `text`) é o foreground de `primary-800` em\n todos os temas — os dois formam um par contrastante mesmo\n onde o dark inverte o header (paraiba/analytica). Usar\n `text-*` aqui inverteria com o modo enquanto o fundo do\n header não inverte, apagando o botão no dark. */\n className={`rounded-full border border-primary text-primary font-medium whitespace-nowrap cursor-pointer transition-colors hover:bg-primary-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${tutorialPadding}`}\n >\n {tutorial.label ?? 'Tutoriais'}\n </button>\n )}\n\n {showCalendar && (\n <div className=\"lg:hidden\">\n <CalendarCard\n content={calendarContent}\n isOpen={calendarOpen ?? activeStates.calendar ?? false}\n onOpenChange={handleCalendarOpenChange}\n />\n </div>\n )}\n\n <NotificationCard\n mode=\"center\"\n isActive={activeStates.notifications}\n onToggleActive={() => toggleActive('notifications')}\n onOpenChange={(open: boolean) => {\n syncDropdownState(\n open,\n activeStates.notifications,\n setActiveStates,\n 'notifications'\n );\n }}\n unreadCount={notifications.unreadCount}\n groupedNotifications={notifications.groupedNotifications}\n loading={notifications.loading}\n error={notifications.error}\n onRetry={notifications.refreshNotifications}\n onMarkAsReadById={notifications.markAsRead}\n onDeleteById={notifications.deleteNotification}\n onNavigateById={(entityType, entityId) => {\n if (entityType && entityId) {\n onNavigateByNotification?.(entityType, entityId);\n }\n }}\n getActionLabel={notifications.getActionLabel}\n onFetchNotifications={notifications.fetchNotifications}\n emptyStateImage={emptyNotificationsImage}\n emptyStateTitle={emptyNotificationsTitle}\n emptyStateDescription={emptyNotificationsDescription}\n />\n\n <DropdownMenu\n onOpenChange={(open: boolean) => {\n syncDropdownState(\n open,\n activeStates.profile,\n setActiveStates,\n 'profile'\n );\n }}\n >\n <DropdownMenuTrigger\n className=\"text-primary cursor-pointer\"\n asChild\n >\n <IconButton\n active={activeStates.profile}\n onClick={() => toggleActive('profile')}\n icon={\n <UserIcon\n size={24}\n className={activeStates.profile ? 'opacity-80' : ''}\n />\n }\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className={profileDropdownWidth}\n side=\"bottom\"\n variant=\"profile\"\n align=\"end\"\n >\n <ProfileMenuHeader\n name={displayName}\n email={displayEmail}\n photoUrl={sessionInfo?.urlProfilePicture}\n />\n\n {showProfileInfo && (\n <ProfileMenuInfo\n schoolName={sessionInfo?.schoolName ?? ''}\n classYearName={sessionInfo?.className ?? ''}\n schoolYearName={sessionInfo?.schoolYearName ?? ''}\n />\n )}\n\n <ProfileMenuSection>\n <DropdownMenuItem\n variant=\"profile\"\n iconLeft={<UserPhosphorIcon />}\n iconRight={<CaretRightIcon />}\n onClick={handleMyDataClick}\n >\n <Text size=\"md\" color=\"text-text-700\">\n Meus dados\n </Text>\n </DropdownMenuItem>\n\n <ProfileToggleTheme />\n </ProfileMenuSection>\n\n <ProfileMenuFooter onClick={onLogout} />\n </DropdownMenuContent>\n </DropdownMenu>\n </section>\n </div>\n </PageContainer>\n </header>\n );\n};\n\nexport default AppHeader;\n"],"mappings":"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","names":[]}
@@ -1,11 +1,14 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2
2
 
3
- var _chunkTXHL7XLUjs = require('./chunk-TXHL7XLU.js');
3
+ var _chunkVSQ7UFGJjs = require('./chunk-VSQ7UFGJ.js');
4
4
 
5
5
 
6
6
  var _chunkDNGOIXIWjs = require('./chunk-DNGOIXIW.js');
7
7
 
8
8
  // src/utils/lessonAvailabilityUtils.ts
9
+ var _dayjs = require('dayjs'); var _dayjs2 = _interopRequireDefault(_dayjs);
10
+ require('dayjs/locale/pt-br');
11
+ var formatLessonDateTime = (dateString) => _dayjs2.default.call(void 0, dateString).locale("pt-br").format("D [de] MMMM [de] YYYY [\xE0s] HH:mm");
9
12
  var isDateInPast = (dateString) => {
10
13
  const date = new Date(dateString);
11
14
  const now = /* @__PURE__ */ new Date();
@@ -19,17 +22,18 @@ var isDateInFuture = (dateString) => {
19
22
  var checkLessonAvailability = (startDate, finalDate) => {
20
23
  const start = startDate ? new Date(startDate) : null;
21
24
  const end = finalDate ? new Date(finalDate) : null;
22
- let status = _chunkTXHL7XLUjs.LESSON_AVAILABILITY.DISPONIVEL;
25
+ let status = _chunkVSQ7UFGJjs.LESSON_AVAILABILITY.DISPONIVEL;
23
26
  if (startDate && isDateInFuture(startDate)) {
24
- status = _chunkTXHL7XLUjs.LESSON_AVAILABILITY.NAO_INICIADA;
27
+ status = _chunkVSQ7UFGJjs.LESSON_AVAILABILITY.NAO_INICIADA;
25
28
  } else if (finalDate && isDateInPast(finalDate)) {
26
- status = _chunkTXHL7XLUjs.LESSON_AVAILABILITY.EXPIRADA;
29
+ status = _chunkVSQ7UFGJjs.LESSON_AVAILABILITY.EXPIRADA;
27
30
  }
28
31
  return {
29
32
  status,
30
33
  startDate: start,
31
34
  endDate: end,
32
35
  formattedStartDate: startDate ? _chunkDNGOIXIWjs.formatDateToBrazilian.call(void 0, startDate) : null,
36
+ formattedStartDateTime: startDate ? formatLessonDateTime(startDate) : null,
33
37
  formattedEndDate: finalDate ? _chunkDNGOIXIWjs.formatDateToBrazilian.call(void 0, finalDate) : null
34
38
  };
35
39
  };
@@ -47,4 +51,4 @@ var isLessonExpired = (finalDate) => {
47
51
 
48
52
 
49
53
  exports.checkLessonAvailability = checkLessonAvailability; exports.isLessonNotYetAvailable = isLessonNotYetAvailable; exports.isLessonExpired = isLessonExpired;
50
- //# sourceMappingURL=chunk-MTZ6C74W.js.map
54
+ //# sourceMappingURL=chunk-55TDQZMC.js.map