@12-apps/ui 6.94.0 → 6.95.1

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 (272) hide show
  1. package/NATIVE.md +1 -1
  2. package/components-catalog.md +7 -0
  3. package/dist/_internal/components/data-display/Avatar/Avatar.js +2 -2
  4. package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +1 -1
  5. package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +1 -1
  6. package/dist/_internal/components/data-display/Carousel/Carousel.js +3 -3
  7. package/dist/_internal/components/data-display/Chart/SpecChart.js +3 -3
  8. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +27 -27
  9. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +32 -32
  10. package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +1 -1
  11. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +2 -2
  12. package/dist/_internal/components/data-display/DataViews/base-list-card-layout.js +2 -2
  13. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +2 -2
  14. package/dist/_internal/components/data-display/DataViews/base-list-card.js +4 -4
  15. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +4 -4
  16. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +3 -3
  17. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +10 -10
  18. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +4 -4
  19. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +25 -25
  20. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +9 -9
  21. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +7 -7
  22. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +8 -8
  23. package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +2 -2
  24. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +7 -7
  25. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +2 -2
  26. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +6 -6
  27. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +2 -2
  28. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +2 -2
  29. package/dist/_internal/components/data-display/DayRuler/DayRuler.js +3 -3
  30. package/dist/_internal/components/data-display/HoverCard/HoverCard.js +1 -1
  31. package/dist/_internal/components/data-display/Lightbox/Lightbox.js +5 -5
  32. package/dist/_internal/components/data-display/Lightbox/LightboxControls.js +2 -2
  33. package/dist/_internal/components/data-display/Lightbox/LightboxOverlay.js +3 -3
  34. package/dist/_internal/components/data-display/Lightbox/LightboxThumbnails.js +2 -2
  35. package/dist/_internal/components/data-display/RegionMap/RegionMap.js +2 -2
  36. package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.js +1 -1
  37. package/dist/_internal/components/data-display/Sheet/Sheet.body.js +2 -2
  38. package/dist/_internal/components/data-display/Sheet/Sheet.hooks.js +2 -2
  39. package/dist/_internal/components/data-display/Sheet/Sheet.js +5 -5
  40. package/dist/_internal/components/data-display/Sheet/Sheet.parts.js +1 -1
  41. package/dist/_internal/components/data-display/Table/Table.js +3 -3
  42. package/dist/_internal/components/data-display/index.js +39 -39
  43. package/dist/_internal/components/feedback/StackedModal/StackedModal.hooks.js +2 -2
  44. package/dist/_internal/components/feedback/StackedModal/StackedModal.js +4 -4
  45. package/dist/_internal/components/feedback/StackedModal/modal-stack.js +3 -1
  46. package/dist/_internal/components/feedback/TutorialOverlay/TutorialOverlay.js +2 -2
  47. package/dist/_internal/components/feedback/UsableModal/UsableModal.js +11 -0
  48. package/dist/_internal/components/feedback/UsableModal/UsableModal.js.map +1 -0
  49. package/dist/_internal/components/feedback/UsableModal/UsableModal.modal.js +87 -0
  50. package/dist/_internal/components/feedback/UsableModal/UsableModal.modal.js.map +1 -0
  51. package/dist/_internal/components/feedback/UsableModal/UsableModal.sheet.js +91 -0
  52. package/dist/_internal/components/feedback/UsableModal/UsableModal.sheet.js.map +1 -0
  53. package/dist/_internal/components/feedback/UsableModal/UsableModal.types.js +1 -0
  54. package/dist/_internal/components/feedback/UsableModal/UsableModal.types.js.map +1 -0
  55. package/dist/_internal/components/feedback/UsableModal/has-footer.js +8 -0
  56. package/dist/_internal/components/feedback/UsableModal/has-footer.js.map +1 -0
  57. package/dist/_internal/components/feedback/UsableModal/recover-chunk.js +10 -0
  58. package/dist/_internal/components/feedback/UsableModal/recover-chunk.js.map +1 -0
  59. package/dist/_internal/components/feedback/index.js +9 -9
  60. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.hooks.js +3 -3
  61. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +5 -5
  62. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocompleteField.js +2 -2
  63. package/dist/_internal/components/form/CategorySelect/CategorySelect.js +2 -2
  64. package/dist/_internal/components/form/CodeEditor/CodeEditor.js +2 -2
  65. package/dist/_internal/components/form/Command/Command.js +2 -2
  66. package/dist/_internal/components/form/Menubar/Menubar.js +2 -2
  67. package/dist/_internal/components/form/UploadButton/UploadButton.js +2 -2
  68. package/dist/_internal/components/form/index.js +43 -43
  69. package/dist/_internal/components/form/total-form/Fields/CategoryField.js +3 -3
  70. package/dist/_internal/components/form/total-form/Fields/index.js +9 -9
  71. package/dist/_internal/components/index.js +125 -125
  72. package/dist/_internal/components/layout/SettingCard/SettingGroup.js +3 -3
  73. package/dist/_internal/components/layout/SettingCard/SettingToggle.js +3 -3
  74. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.js +3 -3
  75. package/dist/_internal/components/layout/SettingsLayout/SettingsPanel.js +2 -2
  76. package/dist/_internal/components/layout/index.js +17 -17
  77. package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +6 -6
  78. package/dist/_internal/components/navigation/NavigationMenu/NavigationMegaSection.js +2 -2
  79. package/dist/_internal/components/navigation/NavigationMenu/NavigationMenu.js +4 -4
  80. package/dist/_internal/components/navigation/NavigationMenu/NavigationStandardBody.js +2 -2
  81. package/dist/_internal/components/navigation/SectionNav/SectionNav.js +3 -3
  82. package/dist/_internal/components/navigation/index.js +19 -19
  83. package/dist/_internal/components/utility/index.js +4 -4
  84. package/dist/_internal/user-avatar/user-avatar.js +3 -3
  85. package/dist/charts.js +11 -11
  86. package/dist/{chunk-NQDOKJLI.js → chunk-2365CQJU.js} +2 -2
  87. package/dist/{chunk-4E2RQOSQ.js → chunk-24G3BWKD.js} +2 -2
  88. package/dist/{chunk-NASLJO2R.js → chunk-2KSFBZ2H.js} +5 -4
  89. package/dist/chunk-2KSFBZ2H.js.map +1 -0
  90. package/dist/{chunk-XE33EZVS.js → chunk-2SBQ47RI.js} +5 -5
  91. package/dist/{chunk-HWZETMO4.js → chunk-37SNQQ7P.js} +3 -3
  92. package/dist/{chunk-2L6TANRY.js → chunk-4RF4BALN.js} +3 -3
  93. package/dist/{chunk-X6D5JEUV.js → chunk-4RSFYS2V.js} +6 -6
  94. package/dist/{chunk-LYVTJLCF.js → chunk-56JF5PZK.js} +4 -4
  95. package/dist/{chunk-7WE432RQ.js → chunk-5HXVXW22.js} +5 -5
  96. package/dist/{chunk-N3GLX64O.js → chunk-5I75WRXT.js} +4 -4
  97. package/dist/{chunk-BP3ZKIPE.js → chunk-64UNVW6D.js} +4 -4
  98. package/dist/{chunk-NQ6P7O7C.js → chunk-6AKDAQSS.js} +2 -2
  99. package/dist/{chunk-PGJIWCQR.js → chunk-6EZQLNPK.js} +4 -4
  100. package/dist/{chunk-EE6DJPB7.js → chunk-6HXNFNOB.js} +4 -4
  101. package/dist/{chunk-4QTPERAY.js → chunk-6RW4WNGS.js} +4 -4
  102. package/dist/{chunk-GBB23QLL.js → chunk-6ZAKPYWX.js} +4 -4
  103. package/dist/{chunk-CWXX5JR3.js → chunk-75GAQL2Q.js} +5 -5
  104. package/dist/{chunk-JZRSHDNY.js → chunk-77FQFWA3.js} +6 -3
  105. package/dist/chunk-77FQFWA3.js.map +1 -0
  106. package/dist/{chunk-LY5I3ZSV.js → chunk-A2YLFKQU.js} +4 -4
  107. package/dist/{chunk-6DGNMASB.js → chunk-ALREWFRX.js} +4 -4
  108. package/dist/{chunk-F2UP5ZF4.js → chunk-BMC5KGH2.js} +4 -4
  109. package/dist/{chunk-3ODEBPGT.js → chunk-BRFL7OWI.js} +5 -5
  110. package/dist/chunk-BTMBQIED.js +7 -0
  111. package/dist/chunk-BTMBQIED.js.map +1 -0
  112. package/dist/{chunk-UIIHUWOV.js → chunk-C7IFBYIJ.js} +7 -7
  113. package/dist/{chunk-FKS2PNJF.js → chunk-CSD6SWBZ.js} +6 -6
  114. package/dist/{chunk-6LGKJVOA.js → chunk-E2UOEI7N.js} +2 -2
  115. package/dist/{chunk-K2VDRODL.js → chunk-E4NFH77Z.js} +4 -4
  116. package/dist/chunk-FRAFGRRD.js +53 -0
  117. package/dist/chunk-FRAFGRRD.js.map +1 -0
  118. package/dist/{chunk-VM4UYCD4.js → chunk-FTYOCFTV.js} +3 -3
  119. package/dist/{chunk-JVQ56E3U.js → chunk-FWTVIRZZ.js} +6 -6
  120. package/dist/{chunk-ALMGYCHY.js → chunk-I54YFYBS.js} +2 -2
  121. package/dist/chunk-IQDPMLDM.js +39 -0
  122. package/dist/chunk-IQDPMLDM.js.map +1 -0
  123. package/dist/{chunk-TSMF7K37.js → chunk-J4UA744J.js} +9 -2
  124. package/dist/chunk-J4UA744J.js.map +1 -0
  125. package/dist/{chunk-4J62V5OE.js → chunk-JIEVKHOH.js} +6 -6
  126. package/dist/{chunk-MKNW4FRR.js → chunk-JOQGKXR5.js} +5 -5
  127. package/dist/{chunk-Y3FYOKWF.js → chunk-KHDKG7XB.js} +2 -2
  128. package/dist/{chunk-TSID4257.js → chunk-KMMFN24G.js} +4 -4
  129. package/dist/{chunk-E5OBAS3U.js → chunk-LTJC7TGB.js} +4 -2
  130. package/dist/chunk-LTJC7TGB.js.map +1 -0
  131. package/dist/{chunk-LKWXU6NH.js → chunk-LV6AD6XC.js} +2 -2
  132. package/dist/{chunk-WQO5WONV.js → chunk-MWXZXCVX.js} +4 -4
  133. package/dist/{chunk-PNZH6CDD.js → chunk-NI3MC742.js} +4 -4
  134. package/dist/{chunk-BZYLTGOE.js → chunk-OKDKKBLI.js} +4 -4
  135. package/dist/{chunk-AJ6KFHEE.js → chunk-PJDAZG65.js} +2 -2
  136. package/dist/{chunk-FPNVOB52.js → chunk-RNIJL54W.js} +4 -4
  137. package/dist/{chunk-2M3W6ACW.js → chunk-S46LGAQ2.js} +4 -4
  138. package/dist/{chunk-6N2U67KF.js → chunk-T3KVZTO3.js} +4 -4
  139. package/dist/{chunk-GY53SDVL.js → chunk-U2SAW6DH.js} +4 -4
  140. package/dist/{chunk-P772HCHI.js → chunk-W676GY42.js} +4 -4
  141. package/dist/{chunk-T2G4LDU5.js → chunk-WLLUARTC.js} +2 -2
  142. package/dist/{chunk-SI5SKX52.js → chunk-WW3F7DCX.js} +2 -2
  143. package/dist/{chunk-UOKXYV3U.js → chunk-XALDXR3F.js} +2 -2
  144. package/dist/{chunk-ZM6FJCWS.js → chunk-XNAI7QGU.js} +4 -4
  145. package/dist/{chunk-LZ5PGB7U.js → chunk-XTYBJAZG.js} +21 -13
  146. package/dist/chunk-XTYBJAZG.js.map +1 -0
  147. package/dist/{chunk-JXK53XJW.js → chunk-YOLLISEY.js} +9 -9
  148. package/dist/{chunk-FKUVFPQZ.js → chunk-Z6QFIRD7.js} +4 -4
  149. package/dist/data-display/Avatar.js +2 -2
  150. package/dist/data-display/CardKit.js +1 -1
  151. package/dist/data-display/Carousel.js +3 -3
  152. package/dist/data-display/Chart.js +11 -11
  153. package/dist/data-display/DataViews.js +40 -40
  154. package/dist/data-display/DayRuler.js +3 -3
  155. package/dist/data-display/HoverCard.js +1 -1
  156. package/dist/data-display/Lightbox.js +5 -5
  157. package/dist/data-display/RegionMap.js +2 -2
  158. package/dist/data-display/ScheduleGrid.js +5 -5
  159. package/dist/data-display/Sheet.js +5 -5
  160. package/dist/data-display/Table.js +3 -3
  161. package/dist/feedback/ConfirmAction.js +3 -3
  162. package/dist/feedback/StackedModal.js +4 -4
  163. package/dist/feedback/TutorialOverlay.js +2 -2
  164. package/dist/feedback/UsableModal.js +9 -0
  165. package/dist/feedback/UsableModal.js.map +1 -0
  166. package/dist/form/AddressAutocomplete.js +5 -5
  167. package/dist/form/CategorySelect.js +2 -2
  168. package/dist/form/CodeEditor.js +2 -2
  169. package/dist/form/Command.js +2 -2
  170. package/dist/form/Menubar.js +2 -2
  171. package/dist/form/UploadButton.js +2 -2
  172. package/dist/form/total-form.js +7 -7
  173. package/dist/layout/ContentToolbar.js +3 -3
  174. package/dist/layout/SettingCard.js +7 -7
  175. package/dist/layout/SettingsLayout.js +3 -3
  176. package/dist/locales.js +4 -4
  177. package/dist/navigation/AppHeader.js +8 -8
  178. package/dist/navigation/NavigationMenu.js +4 -4
  179. package/dist/navigation/SectionNav.js +3 -3
  180. package/dist/pt-BR.js +5 -5
  181. package/dist/types/components/data-display/Sheet/Sheet.body.d.ts +2 -0
  182. package/dist/types/components/data-display/Sheet/Sheet.body.d.ts.map +1 -1
  183. package/dist/types/components/data-display/Sheet/Sheet.d.ts.map +1 -1
  184. package/dist/types/components/data-display/Sheet/Sheet.parts.d.ts.map +1 -1
  185. package/dist/types/components/data-display/Sheet/Sheet.types.d.ts +14 -0
  186. package/dist/types/components/data-display/Sheet/Sheet.types.d.ts.map +1 -1
  187. package/dist/types/components/feedback/StackedModal/StackedModal.hooks.d.ts.map +1 -1
  188. package/dist/types/components/feedback/StackedModal/modal-stack.d.ts +6 -0
  189. package/dist/types/components/feedback/StackedModal/modal-stack.d.ts.map +1 -1
  190. package/dist/types/components/feedback/UsableModal/UsableModal.d.ts +20 -0
  191. package/dist/types/components/feedback/UsableModal/UsableModal.d.ts.map +1 -0
  192. package/dist/types/components/feedback/UsableModal/UsableModal.modal.d.ts +11 -0
  193. package/dist/types/components/feedback/UsableModal/UsableModal.modal.d.ts.map +1 -0
  194. package/dist/types/components/feedback/UsableModal/UsableModal.sheet.d.ts +17 -0
  195. package/dist/types/components/feedback/UsableModal/UsableModal.sheet.d.ts.map +1 -0
  196. package/dist/types/components/feedback/UsableModal/UsableModal.types.d.ts +35 -0
  197. package/dist/types/components/feedback/UsableModal/UsableModal.types.d.ts.map +1 -0
  198. package/dist/types/components/feedback/UsableModal/has-footer.d.ts +4 -0
  199. package/dist/types/components/feedback/UsableModal/has-footer.d.ts.map +1 -0
  200. package/dist/types/components/feedback/UsableModal/index.d.ts +3 -0
  201. package/dist/types/components/feedback/UsableModal/index.d.ts.map +1 -0
  202. package/dist/types/components/feedback/UsableModal/recover-chunk.d.ts +24 -0
  203. package/dist/types/components/feedback/UsableModal/recover-chunk.d.ts.map +1 -0
  204. package/dist/user-avatar.js +3 -3
  205. package/package.json +5 -1
  206. package/src/components/data-display/Sheet/Sheet.body.tsx +4 -0
  207. package/src/components/data-display/Sheet/Sheet.md +5 -0
  208. package/src/components/data-display/Sheet/Sheet.parts.tsx +5 -3
  209. package/src/components/data-display/Sheet/Sheet.tsx +29 -9
  210. package/src/components/data-display/Sheet/Sheet.types.ts +14 -0
  211. package/src/components/feedback/StackedModal/StackedModal.hooks.ts +16 -0
  212. package/src/components/feedback/StackedModal/modal-stack.tsx +12 -2
  213. package/src/components/feedback/UsableModal/UsableModal.md +95 -0
  214. package/src/components/feedback/UsableModal/UsableModal.modal.tsx +76 -0
  215. package/src/components/feedback/UsableModal/UsableModal.sheet.tsx +65 -0
  216. package/src/components/feedback/UsableModal/UsableModal.tsx +92 -0
  217. package/src/components/feedback/UsableModal/UsableModal.types.ts +38 -0
  218. package/src/components/feedback/UsableModal/has-footer.ts +4 -0
  219. package/src/components/feedback/UsableModal/index.ts +2 -0
  220. package/src/components/feedback/UsableModal/recover-chunk.ts +61 -0
  221. package/dist/chunk-E5OBAS3U.js.map +0 -1
  222. package/dist/chunk-JZRSHDNY.js.map +0 -1
  223. package/dist/chunk-LZ5PGB7U.js.map +0 -1
  224. package/dist/chunk-NASLJO2R.js.map +0 -1
  225. package/dist/chunk-TSMF7K37.js.map +0 -1
  226. /package/dist/{chunk-NQDOKJLI.js.map → chunk-2365CQJU.js.map} +0 -0
  227. /package/dist/{chunk-4E2RQOSQ.js.map → chunk-24G3BWKD.js.map} +0 -0
  228. /package/dist/{chunk-XE33EZVS.js.map → chunk-2SBQ47RI.js.map} +0 -0
  229. /package/dist/{chunk-HWZETMO4.js.map → chunk-37SNQQ7P.js.map} +0 -0
  230. /package/dist/{chunk-2L6TANRY.js.map → chunk-4RF4BALN.js.map} +0 -0
  231. /package/dist/{chunk-X6D5JEUV.js.map → chunk-4RSFYS2V.js.map} +0 -0
  232. /package/dist/{chunk-LYVTJLCF.js.map → chunk-56JF5PZK.js.map} +0 -0
  233. /package/dist/{chunk-7WE432RQ.js.map → chunk-5HXVXW22.js.map} +0 -0
  234. /package/dist/{chunk-N3GLX64O.js.map → chunk-5I75WRXT.js.map} +0 -0
  235. /package/dist/{chunk-BP3ZKIPE.js.map → chunk-64UNVW6D.js.map} +0 -0
  236. /package/dist/{chunk-NQ6P7O7C.js.map → chunk-6AKDAQSS.js.map} +0 -0
  237. /package/dist/{chunk-PGJIWCQR.js.map → chunk-6EZQLNPK.js.map} +0 -0
  238. /package/dist/{chunk-EE6DJPB7.js.map → chunk-6HXNFNOB.js.map} +0 -0
  239. /package/dist/{chunk-4QTPERAY.js.map → chunk-6RW4WNGS.js.map} +0 -0
  240. /package/dist/{chunk-GBB23QLL.js.map → chunk-6ZAKPYWX.js.map} +0 -0
  241. /package/dist/{chunk-CWXX5JR3.js.map → chunk-75GAQL2Q.js.map} +0 -0
  242. /package/dist/{chunk-LY5I3ZSV.js.map → chunk-A2YLFKQU.js.map} +0 -0
  243. /package/dist/{chunk-6DGNMASB.js.map → chunk-ALREWFRX.js.map} +0 -0
  244. /package/dist/{chunk-F2UP5ZF4.js.map → chunk-BMC5KGH2.js.map} +0 -0
  245. /package/dist/{chunk-3ODEBPGT.js.map → chunk-BRFL7OWI.js.map} +0 -0
  246. /package/dist/{chunk-UIIHUWOV.js.map → chunk-C7IFBYIJ.js.map} +0 -0
  247. /package/dist/{chunk-FKS2PNJF.js.map → chunk-CSD6SWBZ.js.map} +0 -0
  248. /package/dist/{chunk-6LGKJVOA.js.map → chunk-E2UOEI7N.js.map} +0 -0
  249. /package/dist/{chunk-K2VDRODL.js.map → chunk-E4NFH77Z.js.map} +0 -0
  250. /package/dist/{chunk-VM4UYCD4.js.map → chunk-FTYOCFTV.js.map} +0 -0
  251. /package/dist/{chunk-JVQ56E3U.js.map → chunk-FWTVIRZZ.js.map} +0 -0
  252. /package/dist/{chunk-ALMGYCHY.js.map → chunk-I54YFYBS.js.map} +0 -0
  253. /package/dist/{chunk-4J62V5OE.js.map → chunk-JIEVKHOH.js.map} +0 -0
  254. /package/dist/{chunk-MKNW4FRR.js.map → chunk-JOQGKXR5.js.map} +0 -0
  255. /package/dist/{chunk-Y3FYOKWF.js.map → chunk-KHDKG7XB.js.map} +0 -0
  256. /package/dist/{chunk-TSID4257.js.map → chunk-KMMFN24G.js.map} +0 -0
  257. /package/dist/{chunk-LKWXU6NH.js.map → chunk-LV6AD6XC.js.map} +0 -0
  258. /package/dist/{chunk-WQO5WONV.js.map → chunk-MWXZXCVX.js.map} +0 -0
  259. /package/dist/{chunk-PNZH6CDD.js.map → chunk-NI3MC742.js.map} +0 -0
  260. /package/dist/{chunk-BZYLTGOE.js.map → chunk-OKDKKBLI.js.map} +0 -0
  261. /package/dist/{chunk-AJ6KFHEE.js.map → chunk-PJDAZG65.js.map} +0 -0
  262. /package/dist/{chunk-FPNVOB52.js.map → chunk-RNIJL54W.js.map} +0 -0
  263. /package/dist/{chunk-2M3W6ACW.js.map → chunk-S46LGAQ2.js.map} +0 -0
  264. /package/dist/{chunk-6N2U67KF.js.map → chunk-T3KVZTO3.js.map} +0 -0
  265. /package/dist/{chunk-GY53SDVL.js.map → chunk-U2SAW6DH.js.map} +0 -0
  266. /package/dist/{chunk-P772HCHI.js.map → chunk-W676GY42.js.map} +0 -0
  267. /package/dist/{chunk-T2G4LDU5.js.map → chunk-WLLUARTC.js.map} +0 -0
  268. /package/dist/{chunk-SI5SKX52.js.map → chunk-WW3F7DCX.js.map} +0 -0
  269. /package/dist/{chunk-UOKXYV3U.js.map → chunk-XALDXR3F.js.map} +0 -0
  270. /package/dist/{chunk-ZM6FJCWS.js.map → chunk-XNAI7QGU.js.map} +0 -0
  271. /package/dist/{chunk-JXK53XJW.js.map → chunk-YOLLISEY.js.map} +0 -0
  272. /package/dist/{chunk-FKUVFPQZ.js.map → chunk-Z6QFIRD7.js.map} +0 -0
@@ -17,7 +17,8 @@ const noop = (): void => {
17
17
  /** do nothing */
18
18
  };
19
19
 
20
- const ModalStackContext = createContext<ModalStackContextValue>({
20
+ /** What a `StackedModal` reads with no provider above it: an empty stack nothing can push onto. */
21
+ const NO_STACK: ModalStackContextValue = {
21
22
  stack: [],
22
23
  pushModal: noop,
23
24
  popModal: noop,
@@ -25,7 +26,16 @@ const ModalStackContext = createContext<ModalStackContextValue>({
25
26
  currentDepth: 0,
26
27
  isModalInStack: () => false,
27
28
  getModalRole: () => null,
28
- });
29
+ };
30
+
31
+ const ModalStackContext = createContext<ModalStackContextValue>(NO_STACK);
32
+
33
+ /**
34
+ * Whether a `ModalStackProvider` is above this point. A component that opens a
35
+ * `StackedModal` on its own (`UsableModal`) brings a provider only when the
36
+ * host has none, so its panel still joins a stack the host already keeps.
37
+ */
38
+ export const useInModalStack = (): boolean => useContext(ModalStackContext) !== NO_STACK;
29
39
 
30
40
  export const useModalStack = (): ModalStackContextValue => {
31
41
  const context = useContext(ModalStackContext);
@@ -0,0 +1,95 @@
1
+ # UsableModal
2
+
3
+ A modal that is a **`StackedModal` on a computer** and a **bottom `Sheet` on a
4
+ phone**, behind one API. A screen that opens "the same task" on both — a form, a
5
+ wizard, a pedido being written — uses this instead of switching between the two
6
+ by hand.
7
+
8
+ ```tsx
9
+ import { UsableModal } from '@12-apps/ui/feedback/UsableModal';
10
+
11
+ <UsableModal
12
+ open={open}
13
+ onClose={close}
14
+ title="Novo pedido"
15
+ closeLabel="Fechar"
16
+ backLabel="Voltar"
17
+ footer={<Actions />}
18
+ dataTestId="new-order"
19
+ >
20
+ <Form />
21
+ </UsableModal>
22
+ ```
23
+
24
+ ## The surface
25
+
26
+ | viewport | surface | from |
27
+ |---|---|---|
28
+ | below the theme's `sm` | bottom `Sheet`, as tall as its body up to the screen less a 3rem strip (a ceiling, not a height) | `UsableModal.sheet.tsx` |
29
+ | `sm` and up | `StackedModal` (`size`, `panelWidth` pass through) | `UsableModal.modal.tsx` |
30
+
31
+ `layout="modal"` or `layout="sheet"` fixes one surface for a host that already
32
+ knows (a test, a kiosk). With the default `auto` the surface is chosen when the
33
+ modal **opens** and kept until it closes: a phone turned to landscape or a
34
+ window narrowed past `sm` mid-task does not swap the surface and lose what was
35
+ typed. The next opening asks the viewport again.
36
+
37
+ ## Loaded on demand
38
+
39
+ Each surface is its own lazily imported chunk (the package builds with
40
+ `splitting: true`). A closed modal renders nothing and loads nothing; the first
41
+ open loads the one surface the viewport asks for. A phone never downloads
42
+ `StackedModal`, a computer never downloads `Sheet`. While the chunk loads the
43
+ screen shows nothing — no spinner before the content.
44
+
45
+ Closing hands the surface `open={false}`, so it runs its own way out (the
46
+ slide-out, the stacked modal leaving its stack), and `SURFACE_EXIT_MS` (400 ms)
47
+ later it unmounts. Every opening starts a fresh body on both surfaces, and a
48
+ closed sheet leaves nothing on the page, not even the drawer's swipe strip
49
+ along the bottom edge.
50
+
51
+ **A chunk a deploy replaced** (a tab opened before it asks for a file that is
52
+ gone) is retried once, then the page reloads once onto the current build; if
53
+ that already happened in this tab in the last five minutes the modal renders
54
+ nothing rather than throwing to the host's error boundary (`recover-chunk.ts`).
55
+ A later deploy earns its own reload.
56
+
57
+ ## Props
58
+
59
+ - **open**, **onClose** — `onClose` fires for every way out: the ✕, Esc, the
60
+ backdrop, a swipe down on the sheet.
61
+ - **title** — names the dialog (the stacked modal's bar, the sheet's header).
62
+ - **children** — the body. It scrolls.
63
+ - **footer** — the pinned action bar at the bottom of either surface. On the
64
+ stacked modal it is NOT `StackedModal`'s `actions`, which sit in the header
65
+ from `sm` up: a screen's acts belong under what they act on.
66
+ - **closeLabel** — the ✕'s accessible name, `common.close` by default.
67
+ - **backLabel** — the back arrow's (required, as on `StackedModal`; it shows when
68
+ the stacked modal opens over another panel).
69
+ - **layout**, **size**, **panelWidth**, **dataTestId**.
70
+
71
+ ## The stack
72
+
73
+ On a computer the panel joins a `ModalStackProvider` the host already keeps
74
+ (it is pushed over the host's panel and offers the way back) and leaves it when
75
+ it closes. A host with no provider gets a stack of one, so the component works
76
+ on its own.
77
+
78
+ On a phone the sheet takes the level a panel pushed onto the stack would take:
79
+ **above** any open `StackedModal` (a drawer's own level, 1200, is under the
80
+ stack's 1300 and up), and with no stack 1300, MUI's modal level, so the menus a
81
+ Select or a Popover in its body opens still land on top. It is a named modal dialog
82
+ (`role="dialog"`, `aria-modal`, `aria-labelledby` its title), like the stacked
83
+ surface.
84
+
85
+ ## Test ids
86
+
87
+ `dataTestId` marks the surface; `<id>-footer` marks the action bar on both.
88
+ The rest are each surface's own, so a host test that must not branch asks by
89
+ role instead (`getByRole('dialog', { name: title })`, the ✕ by `closeLabel`):
90
+
91
+ | | computer (`StackedModal`) | phone (`Sheet`) |
92
+ |---|---|---|
93
+ | title | `<id>-title` | `<id>-header-title` |
94
+ | ✕ | `<id>-close-button` | `<id>-header-close-button` |
95
+ | back | `<id>-back-button` | — |
@@ -0,0 +1,76 @@
1
+ import Box from '@mui/material/Box/index.js';
2
+ import type { ReactNode } from 'react';
3
+
4
+ import { safeAreaBottom } from '../../../utils/viewport';
5
+ import { StackedModal, StackedModalContent } from '../StackedModal/StackedModal';
6
+ import { ModalStackProvider, useInModalStack } from '../StackedModal/modal-stack';
7
+ import { hasFooter } from './has-footer';
8
+ import type { UsableModalSurfaceProps } from './UsableModal.types';
9
+
10
+ /**
11
+ * The computer's surface: a `StackedModal`, loaded only when this layout is the
12
+ * one drawn (`./UsableModal`).
13
+ *
14
+ * The footer is pinned at the bottom of the panel's scroll, not handed to
15
+ * `StackedModal`'s `actions`: those sit in the header from `sm` up, and a
16
+ * screen's acts belong under what they act on.
17
+ */
18
+ export function UsableModalStacked(props: UsableModalSurfaceProps): React.JSX.Element {
19
+ const inStack = useInModalStack();
20
+ const panel = <StackedPanel {...props} />;
21
+ // A host that keeps its own stack gets this panel pushed onto it; one that
22
+ // keeps none gets a stack of one, which is what `StackedModal` needs to draw.
23
+ return inStack ? panel : <ModalStackProvider>{panel}</ModalStackProvider>;
24
+ }
25
+
26
+ function StackedPanel({
27
+ open,
28
+ onClose,
29
+ title,
30
+ children,
31
+ footer,
32
+ closeLabel,
33
+ backLabel,
34
+ size,
35
+ panelWidth,
36
+ dataTestId,
37
+ }: UsableModalSurfaceProps): React.JSX.Element {
38
+ return (
39
+ <StackedModal
40
+ open={open}
41
+ onClose={onClose}
42
+ navigationTitle={title}
43
+ closeLabel={closeLabel}
44
+ backLabel={backLabel}
45
+ size={size}
46
+ panelWidth={panelWidth}
47
+ dataTestId={dataTestId}
48
+ >
49
+ <StackedModalContent sx={{ p: 0, display: 'flex', flexDirection: 'column', minHeight: '100%' }}>
50
+ <Box sx={{ flex: 1, p: 3 }}>{children}</Box>
51
+ {hasFooter(footer) && <PinnedFooter dataTestId={dataTestId}>{footer}</PinnedFooter>}
52
+ </StackedModalContent>
53
+ </StackedModal>
54
+ );
55
+ }
56
+
57
+ /** The action bar, held at the panel's bottom edge while the body scrolls under it. */
58
+ function PinnedFooter({ dataTestId, children }: { dataTestId?: string; children: ReactNode }): React.JSX.Element {
59
+ return (
60
+ <Box
61
+ sx={{
62
+ position: 'sticky',
63
+ bottom: 0,
64
+ px: 3,
65
+ py: 2,
66
+ bgcolor: 'background.paper',
67
+ borderTop: (theme) => `1px solid ${theme.palette.divider}`,
68
+ // Full screen under `sm` (`layout="modal"` on a phone): clear of the iOS home indicator.
69
+ ...safeAreaBottom(16),
70
+ }}
71
+ data-testid={dataTestId ? `${dataTestId}-footer` : undefined}
72
+ >
73
+ {children}
74
+ </Box>
75
+ );
76
+ }
@@ -0,0 +1,65 @@
1
+ import Box from '@mui/material/Box/index.js';
2
+ import { useTheme, type Theme } from '@mui/material/styles/index.js';
3
+
4
+ import { Sheet } from '../../data-display/Sheet/Sheet';
5
+ import { MODAL_STACK_BASE_Z_INDEX, MODAL_STACK_Z_INDEX_STEP } from '../../../tokens/layers';
6
+ import { rem } from '../../../tokens/relative';
7
+ import { safeAreaBottom } from '../../../utils/viewport';
8
+ import { useModalStack } from '../StackedModal/modal-stack';
9
+ import { hasFooter } from './has-footer';
10
+ import type { UsableModalSurfaceProps } from './UsableModal.types';
11
+
12
+ /**
13
+ * How tall the sheet may grow: the whole screen but a strip of the dimmed page
14
+ * above it, so it still reads as a sheet over the screen it came from. The
15
+ * Sheet's own `xl` ceiling is 600px — a phone of 844 lost a quarter of the
16
+ * screen to it, and a modal's body (a form, a cardápio) is what needs it.
17
+ */
18
+ const sheetCeiling = (theme: Theme) => ({ maxHeight: `calc(100% - ${rem(theme, 48)})` });
19
+
20
+ /**
21
+ * The phone's surface: a bottom `Sheet`, loaded only when this layout is the one
22
+ * drawn (`./UsableModal`). Its height is a ceiling, not a height: a short body
23
+ * gives a short sheet, and a long one grows to `sheetCeiling` and scrolls above
24
+ * the pinned footer.
25
+ *
26
+ * It is a named modal dialog (`asDialog`), like the stacked surface. And it
27
+ * takes the level a panel pushed onto the stack would take (`BASE + depth *
28
+ * STEP`): above any `StackedModal` already open — a drawer's default (1200) is
29
+ * under the stack's 1300 and up, and a sheet opened from a panel would slide in
30
+ * behind it, invisible, holding the focus — and never above the menus its own
31
+ * body opens. With no stack that is 1300, MUI's `zIndex.modal`, the level a
32
+ * Select's or a Popover's menu opens at; portalled later, the menu is on top.
33
+ */
34
+ export function UsableModalSheet({
35
+ open,
36
+ onClose,
37
+ title,
38
+ children,
39
+ footer,
40
+ closeLabel,
41
+ dataTestId,
42
+ }: UsableModalSurfaceProps): React.JSX.Element {
43
+ const { currentDepth } = useModalStack();
44
+ const theme = useTheme();
45
+ return (
46
+ <Sheet
47
+ open={open}
48
+ onOpenChange={(next) => {
49
+ if (!next) onClose();
50
+ }}
51
+ position="bottom"
52
+ size="xl"
53
+ style={sheetCeiling(theme)}
54
+ title={title}
55
+ closeLabel={closeLabel}
56
+ asDialog
57
+ zIndex={MODAL_STACK_BASE_Z_INDEX + currentDepth * MODAL_STACK_Z_INDEX_STEP}
58
+ // The sheet marks its own footer `${dataTestId}-footer`, as the stacked surface does.
59
+ footer={hasFooter(footer) ? <Box sx={safeAreaBottom(0)}>{footer}</Box> : undefined}
60
+ dataTestId={dataTestId}
61
+ >
62
+ {children}
63
+ </Sheet>
64
+ );
65
+ }
@@ -0,0 +1,92 @@
1
+ import { useTheme } from '@mui/material/styles/index.js';
2
+ import useMediaQuery from '@mui/material/useMediaQuery/index.js';
3
+ import { lazy, Suspense, useEffect, useState, type ComponentType } from 'react';
4
+
5
+ import { recoverChunk } from './recover-chunk';
6
+ import type { UsableModalLayout, UsableModalProps, UsableModalSurfaceProps } from './UsableModal.types';
7
+
8
+ type Surface = 'modal' | 'sheet';
9
+
10
+ /**
11
+ * Each surface is its own chunk (the package builds with `splitting: true`), so
12
+ * a phone never downloads `StackedModal` and a computer never downloads `Sheet`.
13
+ * A chunk a deploy replaced is retried, then the page reloads once onto the
14
+ * current build (`./recover-chunk`) — never the host's error boundary.
15
+ */
16
+ const StackedSurface = lazy(
17
+ recoverChunk(async (): Promise<{ default: ComponentType<UsableModalSurfaceProps> }> => ({
18
+ default: (await import('./UsableModal.modal')).UsableModalStacked,
19
+ })),
20
+ );
21
+ const SheetSurface = lazy(
22
+ recoverChunk(async (): Promise<{ default: ComponentType<UsableModalSurfaceProps> }> => ({
23
+ default: (await import('./UsableModal.sheet')).UsableModalSheet,
24
+ })),
25
+ );
26
+
27
+ /** The surface the viewport asks for now: a sheet below `sm`, a stacked modal from `sm` up. */
28
+ function useViewportSurface(layout: UsableModalLayout): Surface {
29
+ const theme = useTheme();
30
+ // `noSsr`: the first render already knows the width, so a phone never mounts
31
+ // (and never fetches) the stacked modal for one frame before the sheet.
32
+ const phone = useMediaQuery(theme.breakpoints.down('sm'), { noSsr: true });
33
+ if (layout !== 'auto') return layout;
34
+ return phone ? 'sheet' : 'modal';
35
+ }
36
+
37
+ /**
38
+ * How long a closed surface stays mounted: longer than its own way out — the
39
+ * drawer's slide-down (225 ms) and the stacked modal's leaving its stack
40
+ * (300 ms) — so neither is cut off.
41
+ */
42
+ export const SURFACE_EXIT_MS = 400;
43
+
44
+ /**
45
+ * The surface is chosen when the modal OPENS and kept until it closes: a phone
46
+ * turned to landscape, or a window narrowed past `sm`, mid-task, does not swap
47
+ * the surface and throw away what the person typed. The next opening asks the
48
+ * viewport again.
49
+ *
50
+ * Once closed, and its way out run, the surface is let go of: every opening
51
+ * starts with a fresh body on both surfaces (the sheet would otherwise keep its
52
+ * content mounted, and the last half-written form, while the stacked modal
53
+ * drops its own), and a closed sheet leaves nothing on the page — not even the
54
+ * drawer's edge strip that swallows taps and swipes the sheet open.
55
+ */
56
+ function useOpenedSurface(open: boolean, layout: UsableModalLayout): Surface | null {
57
+ const viewport = useViewportSurface(layout);
58
+ const [surface, setSurface] = useState<Surface | null>(open ? viewport : null);
59
+ const [wasOpen, setWasOpen] = useState(open);
60
+ if (open !== wasOpen) {
61
+ setWasOpen(open);
62
+ if (open) setSurface(viewport);
63
+ }
64
+ useEffect(() => {
65
+ if (open || surface === null) return;
66
+ const timer = window.setTimeout(() => setSurface(null), SURFACE_EXIT_MS);
67
+ return () => window.clearTimeout(timer);
68
+ }, [open, surface]);
69
+ return surface;
70
+ }
71
+
72
+ /**
73
+ * A modal that is a `StackedModal` on a computer and a bottom `Sheet` on a
74
+ * phone, behind one API: title, body, a pinned footer, and the ways out.
75
+ *
76
+ * Nothing is fetched until the first open: until then it renders nothing.
77
+ * Closing hands the surface `open={false}`, so it runs its own way out — the
78
+ * slide-out, and the stacked modal leaving its stack — and then it unmounts
79
+ * (`SURFACE_EXIT_MS`). While the
80
+ * chunk loads the screen shows no placeholder: a modal that blinks a spinner
81
+ * before its content is worse than one that appears a frame later.
82
+ */
83
+ export function UsableModal({ layout = 'auto', ...props }: UsableModalProps): React.JSX.Element | null {
84
+ const surface = useOpenedSurface(props.open, layout);
85
+ if (surface === null) return null;
86
+ const Shown = surface === 'sheet' ? SheetSurface : StackedSurface;
87
+ return (
88
+ <Suspense fallback={null}>
89
+ <Shown {...props} />
90
+ </Suspense>
91
+ );
92
+ }
@@ -0,0 +1,38 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ import type { PanelSize, PanelWidth } from '../StackedModal/StackedModal.types';
4
+
5
+ /** Which surface draws the modal: chosen by the viewport, or fixed by the host. */
6
+ export type UsableModalLayout = 'auto' | 'modal' | 'sheet';
7
+
8
+ export interface UsableModalProps {
9
+ /** Controls the visibility of the modal. */
10
+ open: boolean;
11
+ /** Fired by every way out: the ✕, Esc, the backdrop, a swipe down on the sheet. */
12
+ onClose: () => void;
13
+ /** Names the dialog: the stacked modal's bar, the sheet's header. */
14
+ title: string;
15
+ /** The body. It scrolls; the footer does not. */
16
+ children?: ReactNode;
17
+ /** The pinned action bar at the bottom of either surface — the screen's acts. */
18
+ footer?: ReactNode;
19
+ /** The ✕'s accessible name — it carries a glyph only. Defaults to `common.close` (`EN_US_UI_LABELS`). */
20
+ closeLabel?: string;
21
+ /** The stacked modal's back arrow, shown when it opens over another panel. REQUIRED. */
22
+ backLabel: string;
23
+ /**
24
+ * `auto` (default): a bottom `Sheet` below the theme's `sm` breakpoint, a
25
+ * `StackedModal` from `sm` up. `modal` and `sheet` fix one surface, for a host
26
+ * that already knows (a test, a kiosk).
27
+ */
28
+ layout?: UsableModalLayout;
29
+ /** The stacked modal's viewport share (`StackedModal`'s `size`). */
30
+ size?: PanelSize;
31
+ /** An exact width for the stacked modal (`StackedModal`'s `panelWidth`). */
32
+ panelWidth?: PanelWidth;
33
+ /** Base test id: the surface carries it, and `-footer` marks the action bar. */
34
+ dataTestId?: string;
35
+ }
36
+
37
+ /** What each lazily loaded surface receives: the host's props, layout already decided. */
38
+ export type UsableModalSurfaceProps = Omit<UsableModalProps, 'layout'>;
@@ -0,0 +1,4 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ /** A footer worth a bar: `null`, `false` and `undefined` draw none, on either surface. */
4
+ export const hasFooter = (footer: ReactNode): boolean => footer !== undefined && footer !== null && footer !== false;
@@ -0,0 +1,2 @@
1
+ export { UsableModal } from './UsableModal';
2
+ export type { UsableModalLayout, UsableModalProps } from './UsableModal.types';
@@ -0,0 +1,61 @@
1
+ import type { ComponentType } from 'react';
2
+
3
+ /** Remembers, for this tab, WHEN a reload was last spent on a missing chunk. */
4
+ const RELOADED_KEY = '12-apps-ui:usable-modal-chunk-reload';
5
+
6
+ /**
7
+ * How long a reload counts as spent. Inside it, a chunk still missing after the
8
+ * reload is not a deploy but a broken build: render nothing rather than loop.
9
+ * Past it, a missing chunk is the NEXT deploy — a tab open for days meets one a
10
+ * day — and earns its own reload; a flag kept for the tab's life would leave
11
+ * the modal silently dead after the second deploy.
12
+ */
13
+ export const RELOAD_SPENT_MS = 5 * 60 * 1000;
14
+
15
+ type Module<P> = { default: ComponentType<P> };
16
+
17
+ /** Renders nothing: what a surface becomes when its chunk cannot be had at all. */
18
+ const Nothing = (): null => null;
19
+
20
+ function readReloaded(): boolean {
21
+ try {
22
+ const at = Number(window.sessionStorage.getItem(RELOADED_KEY));
23
+ return at > 0 && Date.now() - at < RELOAD_SPENT_MS;
24
+ } catch {
25
+ return true;
26
+ }
27
+ }
28
+
29
+ function writeReloaded(value: boolean): void {
30
+ try {
31
+ if (value) window.sessionStorage.setItem(RELOADED_KEY, String(Date.now()));
32
+ else window.sessionStorage.removeItem(RELOADED_KEY);
33
+ } catch {
34
+ // Storage refused (private mode, quota): the reload guard is lost, not the modal.
35
+ }
36
+ }
37
+
38
+ /**
39
+ * A lazy loader that survives a deploy. Every deploy replaces a host's hashed
40
+ * chunks, so a tab opened before it asks for a file that is gone. The import is
41
+ * tried twice; then the page reloads ONCE onto the current build (the same
42
+ * answer as a host's own route loader); if that already happened in this tab
43
+ * in the last `RELOAD_SPENT_MS`,
44
+ * the modal renders nothing rather than handing the failure to the host's
45
+ * error boundary and losing the whole page for opening a modal.
46
+ */
47
+ export function recoverChunk<P>(load: () => Promise<Module<P>>): () => Promise<Module<P>> {
48
+ return async () => {
49
+ try {
50
+ const loaded = await load().catch(() => load());
51
+ writeReloaded(false);
52
+ return loaded;
53
+ } catch {
54
+ if (typeof window === 'undefined' || readReloaded()) return { default: Nothing };
55
+ writeReloaded(true);
56
+ window.location.reload();
57
+ // The page is going away; nothing should render in the meantime.
58
+ return new Promise<Module<P>>(() => undefined);
59
+ }
60
+ };
61
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Sheet/Sheet.body.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport CircularProgress from '@mui/material/CircularProgress/index.js';\nimport React from 'react';\n\nimport { SheetContent, SheetFooter, SheetHeader } from './Sheet.parts';\nimport type { SheetProps } from './Sheet.types';\nimport { sxRem } from '../../../tokens/relative';\nimport { muiColor } from '../../../tokens/scales';\n\nexport interface SheetBodyProps extends Pick<\n SheetProps,\n | 'title'\n | 'description'\n | 'showCloseButton'\n | 'closeLabel'\n | 'showHandle'\n | 'header'\n | 'footer'\n | 'loading'\n | 'color'\n | 'children'\n | 'onClick'\n | 'onFocus'\n | 'onBlur'\n> {\n testId: string;\n isDragging: boolean;\n isVerticalSheet: boolean;\n isDraggableVariant: boolean;\n onClose: () => void;\n onDragStart: (e: React.MouseEvent | React.TouchEvent) => void;\n}\n\n/**\n * The header earns its place if it would show anything at all — a grab handle,\n * either piece of text, the close button, or caller-supplied content.\n */\nconst needsHeader = (props: SheetBodyProps) =>\n Boolean(\n props.showHandle ||\n props.title ||\n props.description ||\n props.showCloseButton ||\n props.header,\n );\n\n/** The centred spinner shown in place of the children while `loading`. */\nconst SheetLoading: React.FC<Pick<SheetBodyProps, 'color'>> = ({ color }) => (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n minHeight: sxRem(200),\n }}\n >\n <CircularProgress color={color === undefined ? undefined : muiColor(color, 'inherit')} />\n </Box>\n);\n\n/**\n * What the sheet contains, independent of which drawer is carrying it. The\n * swipeable and plain branches render exactly this — they differ only in the\n * MUI component and its swipe props, so the contents are built once.\n */\nexport const SheetBody: React.FC<SheetBodyProps> = (props) => {\n const {\n title,\n description,\n showCloseButton,\n closeLabel,\n showHandle,\n header,\n footer,\n loading,\n color,\n children,\n onClick,\n onFocus,\n onBlur,\n testId,\n isDragging,\n isVerticalSheet,\n isDraggableVariant,\n onClose,\n onDragStart,\n } = props;\n\n return (\n <Box\n onClick={onClick}\n onFocus={onFocus}\n onBlur={onBlur}\n data-testid={testId}\n sx={{\n // A vertical sheet's panel is a column whose height is its CONTENT, up\n // to the `size` ceiling — so this fills what the panel has rather than\n // asking for a percentage of it, and `minHeight: 0` is what lets it\n // shrink past its content so `SheetContent` scrolls instead of the\n // panel overflowing. A side sheet's panel is full-height already.\n ...(isVerticalSheet ? { flex: '1 1 auto', minHeight: 0 } : { height: '100%' }),\n display: 'flex',\n flexDirection: 'column',\n position: 'relative',\n userSelect: isDragging ? 'none' : 'auto',\n }}\n >\n {needsHeader(props) && (\n <SheetHeader\n title={title}\n description={description}\n showCloseButton={showCloseButton}\n closeLabel={closeLabel}\n onClose={onClose}\n showHandle={showHandle && isVerticalSheet}\n isDraggable={isDraggableVariant && isVerticalSheet}\n onDragStart={onDragStart}\n dataTestId={`${testId}-header`}\n >\n {header}\n </SheetHeader>\n )}\n\n <SheetContent padded dataTestId={`${testId}-content`}>\n {loading ? <SheetLoading color={color} /> : children}\n </SheetContent>\n\n {footer && (\n <SheetFooter sticky divider dataTestId={`${testId}-footer`}>\n {footer}\n </SheetFooter>\n )}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAAA,OAAO,SAAS;AAChB,OAAO,sBAAsB;AAuDzB,cAiCA,YAjCA;AAnBJ,IAAM,cAAc,CAAC,UACnB;AAAA,EACE,MAAM,cACN,MAAM,SACN,MAAM,eACN,MAAM,mBACN,MAAM;AACR;AAGF,IAAM,eAAwD,CAAC,EAAE,MAAM,MACrE;AAAA,EAAC;AAAA;AAAA,IACC,IAAI;AAAA,MACF,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,WAAW,MAAM,GAAG;AAAA,IACtB;AAAA,IAEA,8BAAC,oBAAiB,OAAO,UAAU,SAAY,SAAY,SAAS,OAAO,SAAS,GAAG;AAAA;AACzF;AAQK,IAAM,YAAsC,CAAC,UAAU;AAC5D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAa;AAAA,MACb,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMF,GAAI,kBAAkB,EAAE,MAAM,YAAY,WAAW,EAAE,IAAI,EAAE,QAAQ,OAAO;AAAA,QAC5E,SAAS;AAAA,QACT,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAY,aAAa,SAAS;AAAA,MACpC;AAAA,MAEC;AAAA,oBAAY,KAAK,KAChB;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY,cAAc;AAAA,YAC1B,aAAa,sBAAsB;AAAA,YACnC;AAAA,YACA,YAAY,GAAG,MAAM;AAAA,YAEpB;AAAA;AAAA,QACH;AAAA,QAGF,oBAAC,gBAAa,QAAM,MAAC,YAAY,GAAG,MAAM,YACvC,oBAAU,oBAAC,gBAAa,OAAc,IAAK,UAC9C;AAAA,QAEC,UACC,oBAAC,eAAY,QAAM,MAAC,SAAO,MAAC,YAAY,GAAG,MAAM,WAC9C,kBACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/feedback/StackedModal/modal-stack.tsx"],"sourcesContent":["import type { FC, ReactNode } from 'react';\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { MODAL_STACK_BASE_Z_INDEX, MODAL_STACK_Z_INDEX_STEP } from '../../../tokens/layers';\nimport type { ModalInfo, ModalPanelRole, ModalStackContextValue } from './StackedModal.types';\n\n/**\n * MUI Dialog default z-index; each panel in the stack sits 10 above the last.\n *\n * Imported rather than declared here: anything that portals out of a panel has\n * to clear this ladder, so the numbers are shared with the token that tells it\n * how — see `tokens/layers`.\n */\nconst BASE_Z_INDEX = MODAL_STACK_BASE_Z_INDEX;\nconst Z_INDEX_STEP = MODAL_STACK_Z_INDEX_STEP;\n\nconst noop = (): void => {\n /** do nothing */\n};\n\nconst ModalStackContext = createContext<ModalStackContextValue>({\n stack: [],\n pushModal: noop,\n popModal: noop,\n clearStack: noop,\n currentDepth: 0,\n isModalInStack: () => false,\n getModalRole: () => null,\n});\n\nexport const useModalStack = (): ModalStackContextValue => {\n const context = useContext(ModalStackContext);\n if (!context) {\n throw new Error('useModalStack must be used within a ModalStackProvider');\n }\n return context;\n};\n\n/** Top of the stack drives the view; the one behind it recedes; the rest are hidden. */\nconst roleAt = (index: number, depth: number): ModalPanelRole => {\n if (index === depth - 1) return 'primary';\n if (index === depth - 2) return 'secondary';\n return 'background';\n};\n\n/** Re-derive every role from stack position — the one place roles are assigned. */\nconst withRoles = (stack: ModalInfo[]): ModalInfo[] =>\n stack.map((modal, index) => ({ ...modal, role: roleAt(index, stack.length) }));\n\n/**\n * Locks body scroll while any modal is open, restoring whatever the page had\n * before. Owned by the provider rather than each modal, so nested panels can't\n * fight over the same style.\n */\nconst useBodyScrollLock = (locked: boolean): void => {\n const originalOverflow = useRef<string>('');\n\n useEffect(() => {\n const restore = (): void => {\n if (!originalOverflow.current) return;\n document.body.style.overflow = originalOverflow.current;\n originalOverflow.current = '';\n };\n\n if (locked) {\n if (!originalOverflow.current) {\n originalOverflow.current = document.body.style.overflow || '';\n }\n document.body.style.overflow = 'hidden';\n } else {\n restore();\n }\n\n return restore;\n }, [locked]);\n};\n\nexport const ModalStackProvider: FC<{ children: ReactNode }> = ({ children }) => {\n const [stack, setStack] = useState<ModalInfo[]>([]);\n\n useBodyScrollLock(stack.length > 0);\n\n const pushModal = useCallback((modalId: string) => {\n setStack((prev) => {\n if (prev.some((m) => m.id === modalId)) return prev;\n const entry: ModalInfo = {\n id: modalId,\n zIndex: BASE_Z_INDEX + prev.length * Z_INDEX_STEP,\n role: 'primary',\n };\n return withRoles([...prev, entry]);\n });\n }, []);\n\n const popModal = useCallback((modalId?: string) => {\n setStack((prev) =>\n withRoles(modalId ? prev.filter((m) => m.id !== modalId) : prev.slice(0, -1)),\n );\n }, []);\n\n const clearStack = useCallback(() => setStack([]), []);\n\n const isModalInStack = useCallback(\n (modalId: string) => stack.some((m) => m.id === modalId),\n [stack],\n );\n\n const getModalRole = useCallback(\n (modalId: string) => stack.find((m) => m.id === modalId)?.role ?? null,\n [stack],\n );\n\n const value = useMemo(\n () => ({\n stack,\n pushModal,\n popModal,\n clearStack,\n currentDepth: stack.length,\n isModalInStack,\n getModalRole,\n }),\n [stack, pushModal, popModal, clearStack, isModalInStack, getModalRole],\n );\n\n return <ModalStackContext.Provider value={value}>{children}</ModalStackContext.Provider>;\n};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Sheet/Sheet.tsx"],"sourcesContent":["import Drawer from '@mui/material/Drawer/index.js';\nimport SwipeableDrawer from '@mui/material/SwipeableDrawer/index.js';\nimport { useTheme } from '@mui/material/styles/index.js';\nimport type { BackdropProps } from '@mui/material/Backdrop/index.js';\nimport React from 'react';\n\nimport { withDefaults } from '../../../utils/withDefaults';\n\nimport {\n DEFAULT_DRAG_RESISTANCE,\n DEFAULT_VELOCITY_THRESHOLD,\n SPRING_CONFIG,\n} from './Sheet.animations';\nimport { SheetBody } from './Sheet.body';\nimport { useSheetDrag, useSheetOpen } from './Sheet.hooks';\nimport { SheetOverlay } from './Sheet.parts';\nimport { panelSx } from './Sheet.styles';\nimport type { SheetProps } from './Sheet.types';\n\nexport { SheetContent, SheetFooter, SheetHeader, SheetOverlay } from './Sheet.parts';\n\nconst DEFAULTS = {\n open: false,\n position: 'bottom',\n variant: 'default',\n size: 'md',\n color: 'primary',\n glow: false,\n pulse: false,\n glass: false,\n gradient: false,\n loading: false,\n disabled: false,\n showOverlay: true,\n closeOnOverlayClick: true,\n closeOnEscape: true,\n showCloseButton: true,\n showHandle: true,\n swipeable: true,\n snapPoints: [0.25, 0.5, 0.75, 1],\n defaultSnapPoint: 0.5,\n minSnapPoint: 0,\n maxSnapPoint: 1,\n velocityThreshold: DEFAULT_VELOCITY_THRESHOLD,\n dragResistance: DEFAULT_DRAG_RESISTANCE,\n animationConfig: SPRING_CONFIG,\n persistent: false,\n fullHeight: false,\n rounded: true,\n elevation: 16,\n dataTestId: 'sheet',\n} satisfies Partial<SheetProps>;\n\n/**\n * The props with every defaulted key now guaranteed present. Without this the\n * component would need a `?? fallback` at each use site, and each of those is a\n * branch the complexity gate counts.\n */\ntype ResolvedSheetProps = SheetProps & Required<Pick<SheetProps, keyof typeof DEFAULTS>>;\n\n/**\n * The drawer's own backdrop, made invisible: it only CATCHES the tap.\n *\n * The visible veil is {@link SheetOverlay}, which knows about the `glass`\n * blur. But the drawer's modal root covers the whole viewport above that veil,\n * so with no backdrop at all a tap on the veil landed on the bare root, which\n * handles nothing — and no sheet ever closed on an outside tap. This one sits\n * under the panel, paints nothing, and hands the tap to the drawer's\n * `onClose('backdropClick')`, which the sheet routes through its own\n * `closeOnOverlayClick` / `persistent` rules.\n *\n * Defined at module scope: a component built inside a render is a new type on\n * every pass, which remounts the subtree it belongs to.\n */\nconst ClickCatcher = React.forwardRef<HTMLDivElement, BackdropProps & { 'data-testid'?: string }>(\n ({ onClick, 'data-testid': testId }, ref) => (\n <div\n ref={ref}\n aria-hidden\n onClick={onClick}\n data-testid={testId}\n style={{ position: 'fixed', inset: 0, backgroundColor: 'transparent' }}\n />\n ),\n) as React.ComponentType<BackdropProps>;\nClickCatcher.displayName = 'SheetClickCatcher';\n\n/**\n * Which way the sheet is anchored. Four flags rather than four repeated\n * comparisons, and the only thing the hooks and styles need to know about\n * `position` and `variant`.\n */\nconst orientationOf = ({ position, variant }: ResolvedSheetProps) => {\n const isBottomSheet = position === 'bottom';\n const isTopSheet = position === 'top';\n\n return {\n isBottomSheet,\n isTopSheet,\n isVerticalSheet: isBottomSheet || isTopSheet,\n isDraggableVariant: variant === 'draggable',\n };\n};\n\nexport const Sheet: React.FC<SheetProps> = (props) => {\n const resolved = withDefaults(props, DEFAULTS) as ResolvedSheetProps;\n const { position, variant, showOverlay, swipeable, className, dataTestId } = resolved;\n\n const theme = useTheme();\n const orientation = orientationOf(resolved);\n\n // Support both the dataTestId prop and a plain data-testid attribute.\n const testId = (resolved as { 'data-testid'?: string })['data-testid'] || dataTestId;\n\n const { sheetRef, currentHeight, isDragging, isAnimating, handleDragStart, resetToDefaultSnapPoint } =\n useSheetDrag({ ...resolved, ...orientation });\n\n const { isOpen, handleClose, handleOverlayClick, handleSwipeOpen } = useSheetOpen({\n ...resolved,\n ...orientation,\n resetToDefaultSnapPoint,\n });\n\n const drawerProps = {\n anchor: position,\n open: isOpen,\n className,\n ...(resolved.animated === false ? { transitionDuration: 0 } : {}),\n // A tap outside obeys `closeOnOverlayClick`. A swipe-to-dismiss (no\n // reason: SwipeableDrawer calls `onClose()` bare) closes. Escape is the\n // hook's own listener alone, which honours `closeOnEscape` — the modal's\n // is switched off below so the key never closes twice or past the flag.\n onClose: (_event?: object, reason?: 'backdropClick' | 'escapeKeyDown') =>\n reason === 'backdropClick' ? handleOverlayClick() : handleClose(),\n PaperProps: {\n ref: sheetRef,\n sx: panelSx({ ...resolved, ...orientation, theme, currentHeight, isDragging, isAnimating }),\n },\n ModalProps: {\n keepMounted: true,\n disableEscapeKeyDown: true,\n BackdropComponent: ClickCatcher,\n BackdropProps: { 'data-testid': testId ? `${testId}-click-catcher` : undefined } as Partial<BackdropProps>,\n },\n };\n\n const body = (\n <SheetBody\n {...resolved}\n {...orientation}\n testId={testId}\n isDragging={isDragging}\n onClose={handleClose}\n onDragStart={handleDragStart}\n />\n );\n\n // The draggable variant drives the panel's height itself; MUI's swipe handling\n // would be a second thing moving it.\n const isSwipeable = swipeable && !orientation.isDraggableVariant;\n\n return (\n <>\n {showOverlay && isOpen && (\n <SheetOverlay open={isOpen} onClick={handleOverlayClick} blur={variant === 'glass'} animated={resolved.animated} />\n )}\n\n {isSwipeable ? (\n <SwipeableDrawer\n {...drawerProps}\n onOpen={handleSwipeOpen}\n disableSwipeToOpen={false}\n swipeAreaWidth={20}\n >\n {body}\n </SwipeableDrawer>\n ) : (\n <Drawer {...drawerProps}>{body}</Drawer>\n )}\n </>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Sheet/Sheet.parts.tsx"],"sourcesContent":["import CloseIcon from '@mui/icons-material/Close';\nimport Backdrop from '@mui/material/Backdrop/index.js';\nimport Box from '@mui/material/Box/index.js';\nimport Divider from '@mui/material/Divider/index.js';\nimport Fade from '@mui/material/Fade/index.js';\nimport IconButton from '@mui/material/IconButton/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport { alpha, useTheme } from '@mui/material/styles/index.js';\nimport type { Theme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport { EN_US_UI_LABELS } from '../../../en-US.labels';\nimport { scrim, sheen } from '../../../tokens/ink';\nimport { rem, rems } from '../../../tokens/relative';\nimport { withDefaults } from '../../../utils/withDefaults';\n\nimport { shimmerAnimation } from './Sheet.animations';\nimport type {\n SheetContentProps,\n SheetFooterProps,\n SheetHeaderProps,\n SheetOverlayProps,\n} from './Sheet.types';\n\n/**\n * The grab handle's own styling. A draggable handle is deliberately larger and\n * tinted, so the affordance reads as draggable before the user tries it; a\n * decorative one stays a neutral bar.\n */\nconst handleSx = (theme: Theme, isDraggable: boolean) => ({\n width: rem(theme, isDraggable ? 48 : 32),\n height: rem(theme, isDraggable ? 6 : 4),\n backgroundColor: alpha(theme.palette.text.primary, 0.3),\n borderRadius: 3,\n transition: theme.transitions.create(['all'], {\n duration: theme.transitions.duration.short,\n easing: theme.transitions.easing.easeInOut,\n }),\n position: 'relative',\n overflow: 'hidden',\n '&::after': {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n left: '-100%',\n width: '100%',\n height: '100%',\n background: `linear-gradient(\n 90deg,\n transparent,\n ${sheen(theme, 0.3)},\n transparent\n )`,\n animation: isDraggable ? `${shimmerAnimation(theme)} 2s infinite` : 'none',\n },\n ...(isDraggable && {\n backgroundColor: alpha(theme.palette.primary.main, 0.4),\n boxShadow: `${rems(theme, 0, 2, 4)} ${alpha(theme.palette.primary.main, 0.2)}`,\n '&:hover': {\n backgroundColor: theme.palette.primary.main,\n transform: 'scaleX(1.15) scaleY(1.2)',\n boxShadow: `${rems(theme, 0, 3, 6)} ${alpha(theme.palette.primary.main, 0.3)}`,\n },\n }),\n});\n\nconst SheetHandle: React.FC<{ isDraggable: boolean }> = ({ isDraggable }) => {\n const theme = useTheme();\n\n return (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n mb: 1,\n // The handle is decoration on a draggable header: the drag listeners sit\n // on the header itself, so letting the bar swallow the press would open\n // a dead zone in the middle of the grab target.\n pointerEvents: isDraggable ? 'none' : 'auto',\n }}\n >\n <Box sx={handleSx(theme, isDraggable)} />\n </Box>\n );\n};\n\nconst HEADER_DEFAULTS: Partial<SheetHeaderProps> = {\n closeLabel: EN_US_UI_LABELS.common.close,\n isDraggable: false,\n dataTestId: 'sheet-header',\n};\n\nexport const SheetHeader: React.FC<SheetHeaderProps> = (props) => {\n const {\n title,\n description,\n showCloseButton,\n closeLabel,\n onClose,\n showHandle,\n isDraggable,\n onDragStart,\n className,\n style,\n children,\n dataTestId,\n } = withDefaults(props, HEADER_DEFAULTS);\n\n return (\n <Box\n className={className}\n data-testid={dataTestId}\n sx={{\n p: 2,\n pb: showHandle ? 1 : 2,\n cursor: isDraggable ? 'grab' : 'auto',\n '&:active': isDraggable ? { cursor: 'grabbing' } : {},\n ...style,\n }}\n onMouseDown={isDraggable ? onDragStart : undefined}\n onTouchStart={isDraggable ? onDragStart : undefined}\n >\n {showHandle && <SheetHandle isDraggable={Boolean(isDraggable)} />}\n\n <Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>\n <Box sx={{ flex: 1 }}>\n {title && (\n <Typography variant=\"h6\" sx={{ fontWeight: 600 }} data-testid={`${dataTestId}-title`}>\n {title}\n </Typography>\n )}\n {description && (\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ mt: 0.5 }}>\n {description}\n </Typography>\n )}\n {children}\n </Box>\n\n {showCloseButton && (\n <IconButton\n onClick={onClose}\n aria-label={closeLabel}\n size=\"small\"\n sx={{ ml: 1, mt: -0.5 }}\n data-testid={`${dataTestId}-close-button`}\n >\n <CloseIcon data-testid={`${dataTestId}-close-icon`} />\n </IconButton>\n )}\n </Box>\n </Box>\n );\n};\n\nconst CONTENT_DEFAULTS: Partial<SheetContentProps> = {\n padded: true,\n dataTestId: 'sheet-content',\n};\n\nexport const SheetContent: React.FC<SheetContentProps> = (props) => {\n const { children, className, style, padded, dataTestId } = withDefaults(props, CONTENT_DEFAULTS);\n\n return (\n <Box\n className={className}\n data-testid={dataTestId}\n // No `minHeight: 0` here, deliberately: a flex item's automatic minimum\n // size only applies while its main-axis `overflow` is `visible`, and this\n // one is `auto`, so it already shrinks. `SheetBody` above is the item that\n // needs it stated.\n sx={{ flex: 1, overflow: 'auto', p: padded ? 2 : 0, ...style }}\n >\n {children}\n </Box>\n );\n};\n\nconst FOOTER_DEFAULTS: Partial<SheetFooterProps> = {\n sticky: false,\n divider: false,\n dataTestId: 'sheet-footer',\n};\n\nexport const SheetFooter: React.FC<SheetFooterProps> = (props) => {\n const { children, className, style, sticky, divider, dataTestId } = withDefaults(\n props,\n FOOTER_DEFAULTS,\n );\n\n return (\n <>\n {divider && <Divider />}\n <Box\n className={className}\n data-testid={dataTestId}\n sx={{\n p: 2,\n position: sticky ? 'sticky' : 'relative',\n bottom: sticky ? 0 : 'auto',\n backgroundColor: 'background.paper',\n borderTop: sticky ? '1px solid' : 'none',\n borderColor: 'divider',\n ...style,\n }}\n >\n {children}\n </Box>\n </>\n );\n};\n\nconst OVERLAY_DEFAULTS: Partial<SheetOverlayProps> = {\n open: false,\n blur: false,\n};\n\nexport const SheetOverlay: React.FC<SheetOverlayProps> = (props) => {\n const { open, onClick, className, style, blur, animated } = withDefaults(props, OVERLAY_DEFAULTS);\n const theme = useTheme();\n const timeout = animated === false ? 0 : 300;\n\n return (\n <Fade in={open} timeout={timeout}>\n <Backdrop\n open={Boolean(open)}\n transitionDuration={timeout}\n onClick={onClick}\n className={className}\n sx={{\n // One below the drawer, under the panel. Inside a Sheet this veil is\n // VISUAL only: the drawer's invisible backdrop above it catches the\n // tap (`ClickCatcher` in Sheet.tsx). The onClick keeps it usable alone.\n zIndex: theme.zIndex.drawer - 1,\n backgroundColor: scrim(theme, blur ? 0.6 : 0.5),\n backdropFilter: blur ? `blur(${rem(theme, 8)}) saturate(180%)` : 'none',\n WebkitBackdropFilter: blur ? `blur(${rem(theme, 8)}) saturate(180%)` : 'none',\n ...style,\n }}\n />\n </Fade>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/feedback/StackedModal/StackedModal.hooks.ts"],"sourcesContent":["import { useTheme } from '@mui/material/styles/index.js';\nimport useMediaQuery from '@mui/material/useMediaQuery/index.js';\nimport type { RefObject } from 'react';\nimport { useEffect, useRef, useState } from 'react';\nimport { useModalStack } from './modal-stack';\nimport type { ModalPanelRole } from './StackedModal.types';\n\nconst FOCUSABLE = 'a[href], button, textarea, input, select, [tabindex]:not([tabindex=\"-1\"])';\n/** MUI Dialog's own default, used when the modal isn't registered in the stack yet. */\nconst FALLBACK_Z_INDEX = 1300;\n/** Matches the panel's slide duration, so role swaps animate rather than jump. */\nconst ROLE_TRANSITION_MS = 300;\n\n/** Keeps Tab cycling inside the open panel instead of escaping to the page behind. */\nconst useFocusTrap = (\n ref: RefObject<HTMLElement | null>,\n isActive: boolean,\n disabled?: boolean,\n): void => {\n useEffect(() => {\n if (!isActive || disabled || !ref.current) return;\n\n const element = ref.current;\n const focusable = element.querySelectorAll(FOCUSABLE);\n const first = focusable[0] as HTMLElement | undefined;\n const last = focusable[focusable.length - 1] as HTMLElement | undefined;\n\n window.setTimeout(() => first?.focus(), 100);\n\n const handleTabKey = (e: globalThis.KeyboardEvent): void => {\n if (e.key !== 'Tab') return;\n const atEdge = e.shiftKey ? first : last;\n if (document.activeElement !== atEdge) return;\n e.preventDefault();\n (e.shiftKey ? last : first)?.focus();\n };\n\n element.addEventListener('keydown', handleTabKey);\n return () => element.removeEventListener('keydown', handleTabKey);\n }, [ref, isActive, disabled]);\n};\n\n/** Closes the panel on Escape — only while it is the top one. */\nconst useEscapeToClose = (active: boolean, onClose: () => void): void => {\n useEffect(() => {\n if (!active) return;\n\n const handleEsc = (e: globalThis.KeyboardEvent): void => {\n if (e.key !== 'Escape') return;\n e.preventDefault();\n onClose();\n };\n\n window.addEventListener('keydown', handleEsc);\n return () => window.removeEventListener('keydown', handleEsc);\n }, [active, onClose]);\n};\n\n/** Holds the skeleton a beat past `loading` so the swap to content isn't a flash. */\nconst useSkeleton = (loading: boolean): boolean => {\n const [showSkeleton, setShowSkeleton] = useState(loading);\n\n useEffect(() => {\n if (loading) {\n setShowSkeleton(true);\n return;\n }\n const timer = window.setTimeout(() => setShowSkeleton(false), 200);\n return () => window.clearTimeout(timer);\n }, [loading]);\n\n return showSkeleton;\n};\n\n/** Registers the modal in the stack while open, and unregisters it after it slides out. */\nconst useStackRegistration = (open: boolean, modalId: string): void => {\n const { pushModal, popModal, isModalInStack } = useModalStack();\n const hasRegisteredRef = useRef(false);\n\n useEffect(() => {\n if (open && !hasRegisteredRef.current) {\n pushModal(modalId);\n hasRegisteredRef.current = true;\n } else if (!open) {\n hasRegisteredRef.current = false;\n }\n }, [open, modalId, pushModal]);\n\n useEffect(() => {\n if (open || !isModalInStack(modalId)) return;\n const timer = window.setTimeout(() => popModal(modalId), ROLE_TRANSITION_MS);\n return () => window.clearTimeout(timer);\n }, [open, modalId, popModal, isModalInStack]);\n};\n\ninterface PanelChromeOptions {\n open?: boolean;\n modalId: string;\n loading?: boolean;\n closeOnEsc?: boolean;\n closeOnClickOutside?: boolean;\n disableFocusTrap?: boolean;\n onClose: () => void;\n}\n\ninterface PanelChrome {\n dialogRef: RefObject<HTMLDivElement | null>;\n modalRole: ModalPanelRole;\n isAnimating: boolean;\n showSkeleton: boolean;\n zIndex: number;\n isMobile: boolean;\n canGoBack: boolean;\n /**\n * This panel is the bottom of the stack. Read from ITS position, not from the\n * depth: once a child opens, the depth says \"can go back\" for every panel,\n * the receding root included.\n */\n isRoot: boolean;\n handleBack: () => void;\n handleClose: (event: object, reason: 'backdropClick' | 'escapeKeyDown') => void;\n}\n\n/**\n * Everything the panel needs to render itself: its place in the stack, the\n * viewport it is on, and the handlers that dismiss it. Bundled into one hook so\n * the component stays a description of the markup.\n */\nexport const usePanelChrome = (options: PanelChromeOptions): PanelChrome => {\n const { open, modalId, loading, closeOnEsc, closeOnClickOutside, disableFocusTrap, onClose } =\n options;\n\n const dialogRef = useRef<HTMLDivElement>(null);\n const { currentDepth, stack } = useModalStack();\n const { modalRole, isAnimating } = useModalRole(Boolean(open), modalId);\n const showSkeleton = useSkeleton(Boolean(loading));\n const zIndex = usePanelZIndex(modalId, FALLBACK_Z_INDEX);\n\n const theme = useTheme();\n const isMobile = useMediaQuery(theme.breakpoints.down('sm'));\n const isPrimary = modalRole === 'primary';\n const canGoBack = currentDepth > 1;\n // Not yet pushed (its first render) and something already below it: NOT the\n // root — so a child never renders a frame without its back arrow.\n const isRoot = (stack[0]?.id ?? modalId) === modalId;\n\n useFocusTrap(dialogRef, Boolean(open) && isPrimary, disableFocusTrap);\n useEscapeToClose(Boolean(open && closeOnEsc) && isPrimary, onClose);\n\n const { handleBack, handleClose } = useCloseHandlers({\n isPrimary,\n closeOnClickOutside,\n closeOnEsc,\n canGoBack,\n onClose,\n });\n\n return {\n dialogRef,\n modalRole,\n isAnimating,\n showSkeleton,\n zIndex,\n isMobile,\n canGoBack,\n isRoot,\n handleBack,\n handleClose,\n };\n};\n\ninterface CloseHandlerOptions {\n /** Only the top panel responds to a backdrop click or Escape. */\n isPrimary: boolean;\n closeOnClickOutside?: boolean;\n closeOnEsc?: boolean;\n /** Deeper than one panel, so the leading control goes back rather than closing. */\n canGoBack: boolean;\n onClose: () => void;\n}\n\n/** The panel's dismissal handlers, honouring which gestures the caller allows. */\nconst useCloseHandlers = ({\n isPrimary,\n closeOnClickOutside,\n closeOnEsc,\n canGoBack,\n onClose,\n}: CloseHandlerOptions): {\n handleBack: () => void;\n handleClose: (event: object, reason: 'backdropClick' | 'escapeKeyDown') => void;\n} => ({\n handleBack: () => {\n if (canGoBack) onClose();\n },\n handleClose: (_event, reason) => {\n if (!isPrimary) return;\n if (reason === 'backdropClick' && !closeOnClickOutside) return;\n if (reason === 'escapeKeyDown' && !closeOnEsc) return;\n onClose();\n },\n});\n\n/** The z-index this panel was assigned when it joined the stack. */\nconst usePanelZIndex = (modalId: string, fallback: number): number => {\n const { stack } = useModalStack();\n return stack.find((m) => m.id === modalId)?.zIndex ?? fallback;\n};\n\n/**\n * This modal's role in the stack, plus whether it is mid-transition between two\n * roles (which drives the expand/contract animation).\n */\nconst useModalRole = (\n open: boolean,\n modalId: string,\n): { modalRole: ModalPanelRole; isAnimating: boolean } => {\n const { stack } = useModalStack();\n const [modalRole, setModalRole] = useState<ModalPanelRole>('primary');\n const [isAnimating, setIsAnimating] = useState(false);\n\n useStackRegistration(open, modalId);\n\n useEffect(() => {\n if (!open) return;\n\n const newRole = stack.find((m) => m.id === modalId)?.role;\n if (!newRole || newRole === modalRole) return;\n\n setIsAnimating(true);\n setModalRole(newRole);\n const timer = window.setTimeout(() => setIsAnimating(false), ROLE_TRANSITION_MS);\n return () => window.clearTimeout(timer);\n }, [stack, modalId, open, modalRole]);\n\n return { modalRole, isAnimating };\n};\n"],"mappings":"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","names":[]}