@feugene/granularity 0.48.0 → 0.50.0

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 (418) hide show
  1. package/README.md +3 -3
  2. package/dist/chunks/chevron-up-BhW6hi8L.js +23 -0
  3. package/dist/chunks/chevron-up-BhW6hi8L.js.map +1 -0
  4. package/dist/chunks/{config-E1cTyRVV.js → config-8n1VR0ju.js} +1 -1
  5. package/dist/chunks/{config-E1cTyRVV.js.map → config-8n1VR0ju.js.map} +1 -1
  6. package/dist/chunks/{config-2vrOFn2f.js → config-AKpLyIGD.js} +2 -2
  7. package/dist/chunks/{config-2vrOFn2f.js.map → config-AKpLyIGD.js.map} +1 -1
  8. package/dist/chunks/{config-DIDz_E5m.js → config-B34mkd53.js} +66 -1
  9. package/dist/chunks/config-B34mkd53.js.map +1 -0
  10. package/dist/chunks/{config-B5SBUa6u.js → config-B7qZqiUB.js} +28 -1
  11. package/dist/chunks/config-B7qZqiUB.js.map +1 -0
  12. package/dist/chunks/config-BBrPUEye.js +8 -0
  13. package/dist/chunks/config-BBrPUEye.js.map +1 -0
  14. package/dist/chunks/config-BBtBQE3s.js +108 -0
  15. package/dist/chunks/config-BBtBQE3s.js.map +1 -0
  16. package/dist/chunks/{config-CT4lP6S4.js → config-BOCzHqWh.js} +2 -2
  17. package/dist/chunks/{config-CT4lP6S4.js.map → config-BOCzHqWh.js.map} +1 -1
  18. package/dist/chunks/{config-iemgzS4x.js → config-BP1ktzwh.js} +2 -24
  19. package/dist/chunks/config-BP1ktzwh.js.map +1 -0
  20. package/dist/chunks/config-BTxmdRzT.js +28 -0
  21. package/dist/chunks/config-BTxmdRzT.js.map +1 -0
  22. package/dist/chunks/{config-CjWOTgLL.js → config-Bk52xd5l.js} +12 -5
  23. package/dist/chunks/config-Bk52xd5l.js.map +1 -0
  24. package/dist/chunks/{config-D3HOuHDe.js → config-C3SqBqSQ.js} +3 -1
  25. package/dist/chunks/config-C3SqBqSQ.js.map +1 -0
  26. package/dist/chunks/{config-2ZHRsdOc.js → config-C3uqd-sW.js} +1 -1
  27. package/dist/chunks/config-C3uqd-sW.js.map +1 -0
  28. package/dist/chunks/{config-BXRmsn3t.js → config-CPhcZzHi.js} +72 -10
  29. package/dist/chunks/config-CPhcZzHi.js.map +1 -0
  30. package/dist/chunks/config-CWtfxkM9.js.map +1 -1
  31. package/dist/chunks/{config--t2dxj0t.js → config-CmLTCmY9.js} +2 -2
  32. package/dist/chunks/{config--t2dxj0t.js.map → config-CmLTCmY9.js.map} +1 -1
  33. package/dist/chunks/{config-BAse0laT.js → config-CvtqB4ki.js} +8 -3
  34. package/dist/chunks/config-CvtqB4ki.js.map +1 -0
  35. package/dist/chunks/{config-BcXX7S7B.js → config-D-JgqV0J.js} +5 -1
  36. package/dist/chunks/{config-BcXX7S7B.js.map → config-D-JgqV0J.js.map} +1 -1
  37. package/dist/chunks/{config-BHLMTJaR.js → config-D1oVht-E.js} +8 -3
  38. package/dist/chunks/config-D1oVht-E.js.map +1 -0
  39. package/dist/chunks/{config-BscVxZR3.js → config-DF1ezU6y.js} +1 -1
  40. package/dist/chunks/{config-BscVxZR3.js.map → config-DF1ezU6y.js.map} +1 -1
  41. package/dist/chunks/{config-B42iJ48O.js → config-DG41PD9i.js} +13 -1
  42. package/dist/chunks/config-DG41PD9i.js.map +1 -0
  43. package/dist/chunks/{config-Bs1HwUcx.js → config-DPJ3jtiB.js} +12 -2
  44. package/dist/chunks/config-DPJ3jtiB.js.map +1 -0
  45. package/dist/chunks/{config-tNqtapcT.js → config-DpqjlCfB.js} +2 -2
  46. package/dist/chunks/{config-tNqtapcT.js.map → config-DpqjlCfB.js.map} +1 -1
  47. package/dist/chunks/{config-DNDgp9bB.js → config-DpzFoSIh.js} +64 -2
  48. package/dist/chunks/config-DpzFoSIh.js.map +1 -0
  49. package/dist/chunks/config-MUkhktTP.js +267 -0
  50. package/dist/chunks/config-MUkhktTP.js.map +1 -0
  51. package/dist/chunks/config-SPugeaHT.js +37 -0
  52. package/dist/chunks/config-SPugeaHT.js.map +1 -0
  53. package/dist/chunks/{en-Bxyn5lW7.js → en-mIFywnV2.js} +27 -7
  54. package/dist/chunks/en-mIFywnV2.js.map +1 -0
  55. package/dist/chunks/{es-Dtl-a7ui.js → es-CvthYwtB.js} +27 -7
  56. package/dist/chunks/es-CvthYwtB.js.map +1 -0
  57. package/dist/chunks/{es-Bj_vc18Z.js → es-DlGd6Mrj.js} +3 -3
  58. package/dist/chunks/{es-Bj_vc18Z.js.map → es-DlGd6Mrj.js.map} +1 -1
  59. package/dist/chunks/{generated-hELWB0gZ.js → generated-Cx4C7GRN.js} +126 -0
  60. package/dist/chunks/{generated-hELWB0gZ.js.map → generated-Cx4C7GRN.js.map} +1 -1
  61. package/dist/chunks/{grBadgeStyles-DV0DrAew.js → grBadgeStyles-D51AXbj5.js} +57 -1
  62. package/dist/chunks/grBadgeStyles-D51AXbj5.js.map +1 -0
  63. package/dist/chunks/{grChipStyles-DcDyxAL0.js → grChipStyles-CA9Wj1_E.js} +1 -1
  64. package/dist/chunks/{grChipStyles-DcDyxAL0.js.map → grChipStyles-CA9Wj1_E.js.map} +1 -1
  65. package/dist/chunks/{grPopoverStyles-CYAeO3Ov.js → grPopoverStyles-CncEkiPu.js} +1 -1
  66. package/dist/chunks/{grPopoverStyles-CYAeO3Ov.js.map → grPopoverStyles-CncEkiPu.js.map} +1 -1
  67. package/dist/chunks/{grSelectStyles-D9EQ-pgK.js → grSelectStyles-Cam-IG9s.js} +3 -2
  68. package/dist/chunks/grSelectStyles-Cam-IG9s.js.map +1 -0
  69. package/dist/chunks/{grSliderStyles-kaz6VXZ3.js → grSliderStyles-CqzV0hll.js} +1 -1
  70. package/dist/chunks/grSliderStyles-CqzV0hll.js.map +1 -0
  71. package/dist/chunks/{config-CbEbLyDE.js → grSortableListStyles-CxieDmpe.js} +1 -27
  72. package/dist/chunks/grSortableListStyles-CxieDmpe.js.map +1 -0
  73. package/dist/chunks/grTableStyles-CPSxDTOW.js +66 -0
  74. package/dist/chunks/grTableStyles-CPSxDTOW.js.map +1 -0
  75. package/dist/chunks/{config-CMNfZO7S.js → grTabsStyles-DIz2VdIm.js} +1 -36
  76. package/dist/chunks/grTabsStyles-DIz2VdIm.js.map +1 -0
  77. package/dist/chunks/grTooltipStyles-CtbGEEGV.js +24 -0
  78. package/dist/chunks/grTooltipStyles-CtbGEEGV.js.map +1 -0
  79. package/dist/chunks/{granular-provider-BOQp7N5o.js → granular-provider-cv5vaM1a.js} +26 -22
  80. package/dist/chunks/granular-provider-cv5vaM1a.js.map +1 -0
  81. package/dist/chunks/hotkeySequence-BTHIM_5A.js +46 -0
  82. package/dist/chunks/hotkeySequence-BTHIM_5A.js.map +1 -0
  83. package/dist/chunks/{keyboard-DE2yhz_b.js → keyboard-BiFSgWLt.js} +70 -1
  84. package/dist/chunks/keyboard-BiFSgWLt.js.map +1 -0
  85. package/dist/chunks/optionPanel-DvY7Tv_4.js +182 -0
  86. package/dist/chunks/optionPanel-DvY7Tv_4.js.map +1 -0
  87. package/dist/chunks/overlayListPanel-D91jBCHU.js +21 -0
  88. package/dist/chunks/overlayListPanel-D91jBCHU.js.map +1 -0
  89. package/dist/chunks/{overlayStack-DH4Z7am1.js → overlayStack-DCkCgXZP.js} +1 -1
  90. package/dist/chunks/{overlayStack-DH4Z7am1.js.map → overlayStack-DCkCgXZP.js.map} +1 -1
  91. package/dist/chunks/{overlayPanelSurface-BKeMhRx4.js → overlayTransition-C0FDMx7Q.js} +24 -24
  92. package/dist/chunks/overlayTransition-C0FDMx7Q.js.map +1 -0
  93. package/dist/chunks/{ru-hrB4I1u_.js → ru-CQKDR-kD.js} +27 -7
  94. package/dist/chunks/ru-CQKDR-kD.js.map +1 -0
  95. package/dist/chunks/{safelist-x8USecK8.js → safelist-CSfynUC1.js} +5 -1
  96. package/dist/chunks/safelist-CSfynUC1.js.map +1 -0
  97. package/dist/chunks/{useMenuItemsFocus-B7Bl_aFA.js → useMenuItemsFocus-C031blYS.js} +1 -1
  98. package/dist/chunks/{useMenuItemsFocus-B7Bl_aFA.js.map → useMenuItemsFocus-C031blYS.js.map} +1 -1
  99. package/dist/chunks/{useModalOverlay-ACRkflzx.js → useModalOverlay-CKCQkGdB.js} +1 -1
  100. package/dist/chunks/{useModalOverlay-ACRkflzx.js.map → useModalOverlay-CKCQkGdB.js.map} +1 -1
  101. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-C-uovdv8.js → GrAutocomplete-Cyr1-ENw.js} +183 -125
  102. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-Cyr1-ENw.js.map +1 -0
  103. package/dist/components/GrAutocomplete/index.js +2 -2
  104. package/dist/components/GrAutocomplete/styles.css +1 -1
  105. package/dist/components/GrBadge/chunks/GrBadge-C42KLyUD.js +71 -0
  106. package/dist/components/GrBadge/chunks/GrBadge-C42KLyUD.js.map +1 -0
  107. package/dist/components/GrBadge/index.js +3 -3
  108. package/dist/components/GrBadge/styles.css +1 -1
  109. package/dist/components/GrCarousel/chunks/{GrCarousel-ByuughtI.js → GrCarousel-CBj-PEPB.js} +186 -37
  110. package/dist/components/GrCarousel/chunks/GrCarousel-CBj-PEPB.js.map +1 -0
  111. package/dist/components/GrCarousel/index.js +2 -2
  112. package/dist/components/GrCarousel/styles.css +1 -1
  113. package/dist/components/GrCheckbox/chunks/{GrCheckbox-Dp201frb.js → GrCheckbox-B4NJc7Ur.js} +2 -1
  114. package/dist/components/GrCheckbox/chunks/GrCheckbox-B4NJc7Ur.js.map +1 -0
  115. package/dist/components/GrCheckbox/index.js +1 -1
  116. package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-IpqG5qwm.js → GrCheckboxGroup-qZHpNFCX.js} +1 -1
  117. package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-IpqG5qwm.js.map → GrCheckboxGroup-qZHpNFCX.js.map} +1 -1
  118. package/dist/components/GrCheckboxGroup/index.js +1 -1
  119. package/dist/components/GrChip/chunks/{GrChip-CKqyzYcv.js → GrChip-DoyS1Dr4.js} +1 -1
  120. package/dist/components/GrChip/chunks/{GrChip-CKqyzYcv.js.map → GrChip-DoyS1Dr4.js.map} +1 -1
  121. package/dist/components/GrChip/index.js +2 -2
  122. package/dist/components/GrColorPicker/chunks/{GrColorPicker-BRM_4lyI.js → GrColorPicker-vGSgpUV9.js} +353 -38
  123. package/dist/components/GrColorPicker/chunks/GrColorPicker-vGSgpUV9.js.map +1 -0
  124. package/dist/components/GrColorPicker/index.js +2 -2
  125. package/dist/components/GrColorPicker/styles.css +1 -1
  126. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BJHmkDQv.js → GrCommandPalette-CAHgj0Aa.js} +23 -7
  127. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-CAHgj0Aa.js.map +1 -0
  128. package/dist/components/GrCommandPalette/index.js +1 -1
  129. package/dist/components/GrCommandPalette/styles.css +1 -1
  130. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BzUQwbec.js → GrConfirmDialog-dg021BMd.js} +1 -1
  131. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-BzUQwbec.js.map → GrConfirmDialog-dg021BMd.js.map} +1 -1
  132. package/dist/components/GrConfirmDialog/index.js +1 -1
  133. package/dist/components/GrContextMenu/chunks/{GrContextMenu-RpxMHQXH.js → GrContextMenu-bQ1Vvy2c.js} +3 -3
  134. package/dist/components/GrContextMenu/chunks/{GrContextMenu-RpxMHQXH.js.map → GrContextMenu-bQ1Vvy2c.js.map} +1 -1
  135. package/dist/components/GrContextMenu/index.js +1 -1
  136. package/dist/components/GrDataTable/chunks/{GrDataTable-DQxYYgQk.js → GrDataTable-Bb2jWnRG.js} +576 -136
  137. package/dist/components/GrDataTable/chunks/GrDataTable-Bb2jWnRG.js.map +1 -0
  138. package/dist/components/GrDataTable/index.js +2 -2
  139. package/dist/components/GrDelta/chunks/{GrDelta-CgTvfoIN.js → GrDelta-BSv1KdMy.js} +0 -0
  140. package/dist/components/GrDelta/chunks/{GrDelta-CgTvfoIN.js.map → GrDelta-BSv1KdMy.js.map} +1 -1
  141. package/dist/components/GrDelta/index.js +2 -2
  142. package/dist/components/GrDialog/chunks/{GrDialog-DDz_OEhk.js → GrDialog-C9Zu72jB.js} +1 -1
  143. package/dist/components/GrDialog/chunks/{GrDialog-DDz_OEhk.js.map → GrDialog-C9Zu72jB.js.map} +1 -1
  144. package/dist/components/GrDialog/index.js +1 -1
  145. package/dist/components/GrDialogService/chunks/{GrDialogService-Dtq0ZCN5.js → GrDialogService-DLBifO61.js} +2 -2
  146. package/dist/components/GrDialogService/chunks/{GrDialogService-Dtq0ZCN5.js.map → GrDialogService-DLBifO61.js.map} +1 -1
  147. package/dist/components/GrDialogService/index.js +1 -1
  148. package/dist/components/GrDrawer/chunks/{GrDrawer-CNpSMuN-.js → GrDrawer-DOcRTE8G.js} +1 -1
  149. package/dist/components/GrDrawer/chunks/{GrDrawer-CNpSMuN-.js.map → GrDrawer-DOcRTE8G.js.map} +1 -1
  150. package/dist/components/GrDrawer/index.js +1 -1
  151. package/dist/components/GrDropdown/chunks/{GrDropdown-cLZuZMEY.js → GrDropdown-kxwmgfSe.js} +2 -2
  152. package/dist/components/GrDropdown/chunks/{GrDropdown-cLZuZMEY.js.map → GrDropdown-kxwmgfSe.js.map} +1 -1
  153. package/dist/components/GrDropdown/index.js +2 -2
  154. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-Dxkz_ry4.js → GrDropdownMenu--VoK3VY0.js} +3 -34
  155. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu--VoK3VY0.js.map +1 -0
  156. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-CkM3BFPL.js +34 -0
  157. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-CkM3BFPL.js.map +1 -0
  158. package/dist/components/GrDropdownMenu/index.js +2 -1
  159. package/dist/components/GrEmptyState/chunks/{GrEmptyState-BbvwE-E0.js → GrEmptyState-Bz6-_ED4.js} +42 -6
  160. package/dist/components/GrEmptyState/chunks/GrEmptyState-Bz6-_ED4.js.map +1 -0
  161. package/dist/components/GrEmptyState/index.js +1 -1
  162. package/dist/components/GrFileUpload/chunks/{GrFileUpload-BwMR71zN.js → GrFileUpload-Bgdfnkd8.js} +5 -2
  163. package/dist/components/GrFileUpload/chunks/GrFileUpload-Bgdfnkd8.js.map +1 -0
  164. package/dist/components/GrFileUpload/index.js +1 -1
  165. package/dist/components/GrFormFile/chunks/{GrFormFile-Dlxx-9zi.js → GrFormFile-Ctq1isz-.js} +78 -11
  166. package/dist/components/GrFormFile/chunks/GrFormFile-Ctq1isz-.js.map +1 -0
  167. package/dist/components/GrFormFile/index.js +2 -2
  168. package/dist/components/GrFormFile/styles.css +1 -1
  169. package/dist/components/GrImageViewer/chunks/{GrImageViewer-DK-iVHHC.js → GrImageViewer-Bnql_dNP.js} +1 -1
  170. package/dist/components/GrImageViewer/chunks/{GrImageViewer-DK-iVHHC.js.map → GrImageViewer-Bnql_dNP.js.map} +1 -1
  171. package/dist/components/GrImageViewer/index.js +1 -1
  172. package/dist/components/GrInput/chunks/{GrInput-DV4gMWPR.js → GrInput-CoaFLpaU.js} +43 -22
  173. package/dist/components/GrInput/chunks/GrInput-CoaFLpaU.js.map +1 -0
  174. package/dist/components/GrInput/index.js +1 -1
  175. package/dist/components/GrInputTag/chunks/{GrInputTag-CO0YU-ok.js → GrInputTag-BzzNRBe3.js} +247 -20
  176. package/dist/components/GrInputTag/chunks/GrInputTag-BzzNRBe3.js.map +1 -0
  177. package/dist/components/GrInputTag/index.js +2 -2
  178. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-D7CyWzhT.js → GrJsonViewer-B6ZJ3GFH.js} +2 -2
  179. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-D7CyWzhT.js.map → GrJsonViewer-B6ZJ3GFH.js.map} +1 -1
  180. package/dist/components/GrJsonViewer/index.js +1 -1
  181. package/dist/components/GrKbd/chunks/{GrKbd-BNMeoaLV.js → GrKbd-D2rHDkQv.js} +42 -37
  182. package/dist/components/GrKbd/chunks/GrKbd-D2rHDkQv.js.map +1 -0
  183. package/dist/components/GrKbd/index.js +1 -1
  184. package/dist/components/GrModal/chunks/{GrModal-Cm0mtSXk.js → GrModal-SHb1U2qx.js} +1 -1
  185. package/dist/components/GrModal/chunks/{GrModal-Cm0mtSXk.js.map → GrModal-SHb1U2qx.js.map} +1 -1
  186. package/dist/components/GrModal/index.js +1 -1
  187. package/dist/components/GrNavbar/chunks/{GrNavbar-BRGuksiy.js → GrNavbar-IEIHC5Vt.js} +10 -4
  188. package/dist/components/GrNavbar/chunks/GrNavbar-IEIHC5Vt.js.map +1 -0
  189. package/dist/components/GrNavbar/index.js +2 -2
  190. package/dist/components/GrNumberInput/chunks/{GrNumberInput-BI6-vkcs.js → GrNumberInput-CmnUDaKi.js} +2 -22
  191. package/dist/components/GrNumberInput/chunks/{GrNumberInput-BI6-vkcs.js.map → GrNumberInput-CmnUDaKi.js.map} +1 -1
  192. package/dist/components/GrNumberInput/index.js +1 -1
  193. package/dist/components/GrOtpInput/chunks/GrOtpInput-B_Q-RDLw.js +419 -0
  194. package/dist/components/GrOtpInput/chunks/GrOtpInput-B_Q-RDLw.js.map +1 -0
  195. package/dist/components/GrOtpInput/index.js +3 -0
  196. package/dist/components/GrOtpInput/styles.css +1 -0
  197. package/dist/components/GrPagination/chunks/{GrPagination-BbaF5eXk.js → GrPagination-AMbn5D8I.js} +1 -1
  198. package/dist/components/GrPagination/chunks/{GrPagination-BbaF5eXk.js.map → GrPagination-AMbn5D8I.js.map} +1 -1
  199. package/dist/components/GrPagination/index.js +1 -1
  200. package/dist/components/GrPopover/chunks/{GrPopover-CcWvr1ZA.js → GrPopover-DjVxt8bf.js} +3 -3
  201. package/dist/components/GrPopover/chunks/{GrPopover-CcWvr1ZA.js.map → GrPopover-DjVxt8bf.js.map} +1 -1
  202. package/dist/components/GrPopover/index.js +2 -2
  203. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-BEL-QgwE.js → GrPromptDialog-BhbIZP1f.js} +3 -3
  204. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-BEL-QgwE.js.map → GrPromptDialog-BhbIZP1f.js.map} +1 -1
  205. package/dist/components/GrPromptDialog/index.js +1 -1
  206. package/dist/components/GrSelect/chunks/{GrSelect-0iI4wdR_.js → GrSelect-B-ykrHpL.js} +26 -182
  207. package/dist/components/GrSelect/chunks/GrSelect-B-ykrHpL.js.map +1 -0
  208. package/dist/components/GrSelect/index.js +2 -2
  209. package/dist/components/GrSelect/styles.css +1 -1
  210. package/dist/components/GrSidebar/chunks/GrSidebar-jVvoLGDO.js +543 -0
  211. package/dist/components/GrSidebar/chunks/GrSidebar-jVvoLGDO.js.map +1 -0
  212. package/dist/components/GrSidebar/index.js +2 -2
  213. package/dist/components/GrSlider/chunks/{GrSlider-CO8N9SF6.js → GrSlider-DF2Cq0rV.js} +29 -4
  214. package/dist/components/GrSlider/chunks/GrSlider-DF2Cq0rV.js.map +1 -0
  215. package/dist/components/GrSlider/index.js +2 -2
  216. package/dist/components/GrSortableList/chunks/{GrSortableList-NKriuGm_.js → GrSortableList-ChH9nQBv.js} +1 -1
  217. package/dist/components/GrSortableList/chunks/{GrSortableList-NKriuGm_.js.map → GrSortableList-ChH9nQBv.js.map} +1 -1
  218. package/dist/components/GrSortableList/index.js +2 -2
  219. package/dist/components/GrSwitch/chunks/{GrSwitch-CriHWT2A.js → GrSwitch-D7X42uIA.js} +61 -7
  220. package/dist/components/GrSwitch/chunks/GrSwitch-D7X42uIA.js.map +1 -0
  221. package/dist/components/GrSwitch/index.js +2 -2
  222. package/dist/components/GrTabPanels/chunks/GrTabPanels-BDt5oVdd.js +30 -0
  223. package/dist/components/GrTabPanels/chunks/GrTabPanels-BDt5oVdd.js.map +1 -0
  224. package/dist/components/GrTabPanels/chunks/GrTabPanels-BJvAflnA.js +83 -0
  225. package/dist/components/GrTabPanels/chunks/GrTabPanels-BJvAflnA.js.map +1 -0
  226. package/dist/components/GrTabPanels/index.js +2 -1
  227. package/dist/components/GrTable/chunks/{GrTable-CKJ-HrsN.js → GrTable-BQitSDep.js} +52 -16
  228. package/dist/components/GrTable/chunks/GrTable-BQitSDep.js.map +1 -0
  229. package/dist/components/GrTable/index.js +2 -2
  230. package/dist/components/GrTabs/chunks/{GrTabs-s9RzC1WX.js → GrTabs-DVC6nfWB.js} +1 -1
  231. package/dist/components/GrTabs/chunks/{GrTabs-s9RzC1WX.js.map → GrTabs-DVC6nfWB.js.map} +1 -1
  232. package/dist/components/GrTabs/index.js +2 -2
  233. package/dist/components/GrTabsWithPanels/chunks/GrTabsWithPanels-BYtuzouj.js +98 -0
  234. package/dist/components/GrTabsWithPanels/chunks/GrTabsWithPanels-BYtuzouj.js.map +1 -0
  235. package/dist/components/GrTabsWithPanels/index.js +3 -0
  236. package/dist/components/GrTextarea/chunks/{GrTextarea-Bfgc0DD2.js → GrTextarea-BFwyqcHB.js} +22 -5
  237. package/dist/components/GrTextarea/chunks/GrTextarea-BFwyqcHB.js.map +1 -0
  238. package/dist/components/GrTextarea/index.js +1 -1
  239. package/dist/components/GrToaster/chunks/{GrToaster-CZixNk0l.js → GrToaster-OzT1VKcp.js} +163 -32
  240. package/dist/components/GrToaster/chunks/GrToaster-OzT1VKcp.js.map +1 -0
  241. package/dist/components/GrToaster/index.js +2 -2
  242. package/dist/components/GrToaster/styles.css +1 -1
  243. package/dist/components/GrTooltip/chunks/{GrTooltip-DkMMM0uq.js → GrTooltip-BDcFycvW.js} +26 -13
  244. package/dist/components/GrTooltip/chunks/GrTooltip-BDcFycvW.js.map +1 -0
  245. package/dist/components/GrTooltip/index.js +2 -2
  246. package/dist/components/GrTransfer/chunks/{GrTransfer-DdfBUf35.js → GrTransfer-CV7BL5UK.js} +114 -12
  247. package/dist/components/GrTransfer/chunks/GrTransfer-CV7BL5UK.js.map +1 -0
  248. package/dist/components/GrTransfer/index.js +1 -1
  249. package/dist/components/GrTransfer/styles.css +1 -1
  250. package/dist/components/GrTree/chunks/{GrTree-6yZrncJE.js → GrTree-DpgaP8hk.js} +39 -1
  251. package/dist/components/GrTree/chunks/GrTree-DpgaP8hk.js.map +1 -0
  252. package/dist/components/GrTree/index.js +1 -1
  253. package/dist/components/GrTree/styles.css +1 -1
  254. package/dist/components/GrTreeSections/chunks/{GrTreeSections-DcmDcLwj.js → GrTreeSections-BeOj__44.js} +1 -1
  255. package/dist/components/GrTreeSections/chunks/{GrTreeSections-DcmDcLwj.js.map → GrTreeSections-BeOj__44.js.map} +1 -1
  256. package/dist/components/GrTreeSections/index.js +1 -1
  257. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-B6KoDYiZ.js → GrTreeSelect-BHq-T8wH.js} +113 -14
  258. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-BHq-T8wH.js.map +1 -0
  259. package/dist/components/GrTreeSelect/index.js +2 -2
  260. package/dist/composables/useFloating.js +1 -1
  261. package/dist/composables/useHotkeys.js +89 -0
  262. package/dist/composables/useHotkeys.js.map +1 -0
  263. package/dist/composables/useOverlayLayer.js +1 -1
  264. package/dist/directives/hotkey.js +19 -46
  265. package/dist/directives/hotkey.js.map +1 -1
  266. package/dist/granular-provider-node.js +1 -1
  267. package/dist/granular-provider.js +1 -1
  268. package/dist/i18n/all.js +1 -1
  269. package/dist/i18n/index.js +1 -1
  270. package/dist/index.js +80 -71
  271. package/dist/theme.js +1 -1
  272. package/dist/tokens.js +1 -1
  273. package/dist/types/components/GrAutocomplete/GrAutocomplete.vue.d.ts +4 -4
  274. package/dist/types/components/GrAutocomplete/composables/useAutocompleteNavigation.d.ts +12 -3
  275. package/dist/types/components/GrAutocomplete/composables/useAutocompletePanel.d.ts +12 -2
  276. package/dist/types/components/GrAutocomplete/composables/useAutocompleteValues.d.ts +7 -4
  277. package/dist/types/components/GrAutocomplete/composables/useRemoteOptions.d.ts +4 -4
  278. package/dist/types/components/GrAutocomplete/grAutocompleteStyles.d.ts +15 -1
  279. package/dist/types/components/GrAutocomplete/index.d.ts +1 -1
  280. package/dist/types/components/GrBadge/GrBadge.vue.d.ts +15 -1
  281. package/dist/types/components/GrBadge/grBadgeStyles.d.ts +57 -0
  282. package/dist/types/components/GrBadge/index.d.ts +1 -1
  283. package/dist/types/components/GrCarousel/GrCarousel.vue.d.ts +29 -1
  284. package/dist/types/components/GrCarousel/composables/useCarouselSwipe.d.ts +5 -0
  285. package/dist/types/components/GrCarousel/grCarouselContext.d.ts +21 -0
  286. package/dist/types/components/GrCarousel/grCarouselStyles.d.ts +39 -9
  287. package/dist/types/components/GrCheckbox/GrCheckbox.vue.d.ts +13 -0
  288. package/dist/types/components/GrColorPicker/GrColorPicker.vue.d.ts +18 -2
  289. package/dist/types/components/GrColorPicker/color.d.ts +13 -1
  290. package/dist/types/components/GrColorPicker/colorArea.d.ts +59 -0
  291. package/dist/types/components/GrColorPicker/defaults.d.ts +3 -1
  292. package/dist/types/components/GrColorPicker/eyeDropper.d.ts +21 -0
  293. package/dist/types/components/GrColorPicker/grColorPickerStyles.d.ts +42 -0
  294. package/dist/types/components/GrCommandPalette/GrCommandPalette.vue.d.ts +10 -1
  295. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +41 -1
  296. package/dist/types/components/GrDataTable/composables/useDataTableGridNavigation.d.ts +53 -0
  297. package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +8 -0
  298. package/dist/types/components/GrDataTable/index.d.ts +1 -1
  299. package/dist/types/components/GrDelta/grDeltaStyles.d.ts +10 -3
  300. package/dist/types/components/GrEmptyState/GrEmptyState.vue.d.ts +11 -2
  301. package/dist/types/components/GrEmptyState/grEmptyStateStyles.d.ts +10 -0
  302. package/dist/types/components/GrEmptyState/index.d.ts +1 -1
  303. package/dist/types/components/GrFileUpload/GrFileUpload.vue.d.ts +2 -1
  304. package/dist/types/components/GrFormFile/GrFormFile.vue.d.ts +10 -0
  305. package/dist/types/components/GrInput/GrInput.vue.d.ts +15 -0
  306. package/dist/types/components/GrInputTag/GrInputTag.vue.d.ts +16 -0
  307. package/dist/types/components/GrInputTag/grInputTagStyles.d.ts +11 -0
  308. package/dist/types/components/GrKbd/GrKbd.vue.d.ts +14 -0
  309. package/dist/types/components/GrNavbar/GrNavbar.vue.d.ts +18 -0
  310. package/dist/types/components/GrNavbar/grNavbarStyles.d.ts +10 -1
  311. package/dist/types/components/GrNavbar/index.d.ts +1 -0
  312. package/dist/types/components/GrOtpInput/GrOtpInput.vue.d.ts +164 -0
  313. package/dist/types/components/GrOtpInput/config.d.ts +1 -0
  314. package/dist/types/components/GrOtpInput/defaults.d.ts +15 -0
  315. package/dist/types/components/GrOtpInput/grOtpInputStyles.d.ts +62 -0
  316. package/dist/types/components/GrOtpInput/index.d.ts +9 -0
  317. package/dist/types/components/GrOtpInput/otpValue.d.ts +71 -0
  318. package/dist/types/components/GrOtpInput/safelist.d.ts +7 -0
  319. package/dist/types/components/GrSelect/composables/useSelectPanelItems.d.ts +8 -34
  320. package/dist/types/components/GrSelect/composables/useSelectVirtualization.d.ts +7 -0
  321. package/dist/types/components/GrSelect/grSelectStyles.d.ts +1 -1
  322. package/dist/types/components/GrSidebar/GrSidebar.vue.d.ts +20 -0
  323. package/dist/types/components/GrSidebar/GrSidebarItem.vue.d.ts +39 -5
  324. package/dist/types/components/GrSidebar/grSidebarStyles.d.ts +32 -0
  325. package/dist/types/components/GrSidebar/index.d.ts +1 -1
  326. package/dist/types/components/GrSidebar/sidebarContext.d.ts +23 -1
  327. package/dist/types/components/GrSlider/GrSlider.vue.d.ts +39 -1
  328. package/dist/types/components/GrSlider/grSliderStyles.d.ts +1 -1
  329. package/dist/types/components/GrSwitch/GrSwitch.vue.d.ts +42 -4
  330. package/dist/types/components/GrSwitch/defaults.d.ts +2 -0
  331. package/dist/types/components/GrSwitch/grSwitchStyles.d.ts +129 -25
  332. package/dist/types/components/GrSwitch/index.d.ts +1 -1
  333. package/dist/types/components/GrSwitch/safelist.d.ts +4 -3
  334. package/dist/types/components/GrTabPanels/context.d.ts +6 -0
  335. package/dist/types/components/GrTable/GrTable.vue.d.ts +37 -0
  336. package/dist/types/components/GrTable/grTableStyles.d.ts +16 -7
  337. package/dist/types/components/GrTabsWithPanels/GrTabsWithPanels.vue.d.ts +77 -0
  338. package/dist/types/components/GrTabsWithPanels/config.d.ts +1 -0
  339. package/dist/types/components/GrTabsWithPanels/index.d.ts +4 -0
  340. package/dist/types/components/GrTextarea/GrTextarea.vue.d.ts +19 -1
  341. package/dist/types/components/GrToaster/GrToaster.vue.d.ts +12 -0
  342. package/dist/types/components/GrToaster/grToasterStyles.d.ts +26 -0
  343. package/dist/types/components/GrTooltip/GrTooltip.vue.d.ts +22 -0
  344. package/dist/types/components/GrTransfer/GrTransfer.vue.d.ts +23 -0
  345. package/dist/types/components/GrTreeSelect/grTreeSelectStyles.d.ts +1 -1
  346. package/dist/types/components/GrTreeSelect/grTreeSelectTypes.d.ts +20 -0
  347. package/dist/types/components/shared/hotkey.d.ts +8 -9
  348. package/dist/types/components/shared/optionPanel.d.ts +100 -0
  349. package/dist/types/components/shared/overlayListPanel.d.ts +18 -0
  350. package/dist/types/composables/useHotkeys.d.ts +43 -0
  351. package/dist/types/granular-provider/shared.d.ts +2 -0
  352. package/dist/types/i18n/messages/en.d.ts +32 -0
  353. package/dist/types/i18n/messages/es.d.ts +32 -0
  354. package/dist/types/i18n/messages/ru.d.ts +32 -0
  355. package/dist/types/index.d.ts +4 -0
  356. package/dist/types/internal/hotkeySequence.d.ts +22 -0
  357. package/dist/types/internal/keyboard.d.ts +45 -0
  358. package/dist/web-types.json +784 -101
  359. package/package.json +13 -1
  360. package/dist/chunks/config-2ZHRsdOc.js.map +0 -1
  361. package/dist/chunks/config-B42iJ48O.js.map +0 -1
  362. package/dist/chunks/config-B5SBUa6u.js.map +0 -1
  363. package/dist/chunks/config-BAse0laT.js.map +0 -1
  364. package/dist/chunks/config-BHLMTJaR.js.map +0 -1
  365. package/dist/chunks/config-BXRmsn3t.js.map +0 -1
  366. package/dist/chunks/config-Bs1HwUcx.js.map +0 -1
  367. package/dist/chunks/config-CMNfZO7S.js.map +0 -1
  368. package/dist/chunks/config-CbEbLyDE.js.map +0 -1
  369. package/dist/chunks/config-CjWOTgLL.js.map +0 -1
  370. package/dist/chunks/config-D3HOuHDe.js.map +0 -1
  371. package/dist/chunks/config-DIDz_E5m.js.map +0 -1
  372. package/dist/chunks/config-DNDgp9bB.js.map +0 -1
  373. package/dist/chunks/config-Yy67uWHY.js +0 -140
  374. package/dist/chunks/config-Yy67uWHY.js.map +0 -1
  375. package/dist/chunks/config-iemgzS4x.js.map +0 -1
  376. package/dist/chunks/en-Bxyn5lW7.js.map +0 -1
  377. package/dist/chunks/es-Dtl-a7ui.js.map +0 -1
  378. package/dist/chunks/grBadgeStyles-DV0DrAew.js.map +0 -1
  379. package/dist/chunks/grSelectStyles-D9EQ-pgK.js.map +0 -1
  380. package/dist/chunks/grSliderStyles-kaz6VXZ3.js.map +0 -1
  381. package/dist/chunks/grTableStyles-DkQPMfx9.js +0 -39
  382. package/dist/chunks/grTableStyles-DkQPMfx9.js.map +0 -1
  383. package/dist/chunks/granular-provider-BOQp7N5o.js.map +0 -1
  384. package/dist/chunks/keyboard-DE2yhz_b.js.map +0 -1
  385. package/dist/chunks/overlayPanelSurface-BKeMhRx4.js.map +0 -1
  386. package/dist/chunks/ru-hrB4I1u_.js.map +0 -1
  387. package/dist/chunks/safelist-x8USecK8.js.map +0 -1
  388. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-C-uovdv8.js.map +0 -1
  389. package/dist/components/GrBadge/chunks/GrBadge-DBeQXEir.js +0 -47
  390. package/dist/components/GrBadge/chunks/GrBadge-DBeQXEir.js.map +0 -1
  391. package/dist/components/GrCarousel/chunks/GrCarousel-ByuughtI.js.map +0 -1
  392. package/dist/components/GrCheckbox/chunks/GrCheckbox-Dp201frb.js.map +0 -1
  393. package/dist/components/GrColorPicker/chunks/GrColorPicker-BRM_4lyI.js.map +0 -1
  394. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BJHmkDQv.js.map +0 -1
  395. package/dist/components/GrDataTable/chunks/GrDataTable-DQxYYgQk.js.map +0 -1
  396. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-Dxkz_ry4.js.map +0 -1
  397. package/dist/components/GrEmptyState/chunks/GrEmptyState-BbvwE-E0.js.map +0 -1
  398. package/dist/components/GrFileUpload/chunks/GrFileUpload-BwMR71zN.js.map +0 -1
  399. package/dist/components/GrFormFile/chunks/GrFormFile-Dlxx-9zi.js.map +0 -1
  400. package/dist/components/GrInput/chunks/GrInput-DV4gMWPR.js.map +0 -1
  401. package/dist/components/GrInputTag/chunks/GrInputTag-CO0YU-ok.js.map +0 -1
  402. package/dist/components/GrKbd/chunks/GrKbd-BNMeoaLV.js.map +0 -1
  403. package/dist/components/GrNavbar/chunks/GrNavbar-BRGuksiy.js.map +0 -1
  404. package/dist/components/GrSelect/chunks/GrSelect-0iI4wdR_.js.map +0 -1
  405. package/dist/components/GrSidebar/chunks/GrSidebar-DoKLlHSw.js +0 -264
  406. package/dist/components/GrSidebar/chunks/GrSidebar-DoKLlHSw.js.map +0 -1
  407. package/dist/components/GrSlider/chunks/GrSlider-CO8N9SF6.js.map +0 -1
  408. package/dist/components/GrSwitch/chunks/GrSwitch-CriHWT2A.js.map +0 -1
  409. package/dist/components/GrTabPanels/chunks/GrTabPanels-5zsbqS1v.js +0 -92
  410. package/dist/components/GrTabPanels/chunks/GrTabPanels-5zsbqS1v.js.map +0 -1
  411. package/dist/components/GrTable/chunks/GrTable-CKJ-HrsN.js.map +0 -1
  412. package/dist/components/GrTextarea/chunks/GrTextarea-Bfgc0DD2.js.map +0 -1
  413. package/dist/components/GrToaster/chunks/GrToaster-CZixNk0l.js.map +0 -1
  414. package/dist/components/GrTooltip/chunks/GrTooltip-DkMMM0uq.js.map +0 -1
  415. package/dist/components/GrTransfer/chunks/GrTransfer-DdfBUf35.js.map +0 -1
  416. package/dist/components/GrTree/chunks/GrTree-6yZrncJE.js.map +0 -1
  417. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-B6KoDYiZ.js.map +0 -1
  418. package/dist/types/components/GrAutocomplete/composables/useAutocompleteVirtual.d.ts +0 -33
@@ -1 +1 @@
1
- {"version":3,"file":"GrDialogService-Dtq0ZCN5.js","names":[],"sources":["../../../../src/components/GrDialogService/store.ts","../../../../src/components/GrDialogService/useDialogService.ts","../../../../src/components/GrDialogService/GrDialogServiceItem.vue","../../../../src/components/GrDialogService/GrDialogServiceItem.vue","../../../../src/components/GrDialogService/GrDialogServiceHost.vue","../../../../src/components/GrDialogService/GrDialogServiceHost.vue"],"sourcesContent":["import { reactive } from 'vue'\nimport type { AppContext, Raw } from 'vue'\n\nimport type { GrConfigContext } from '../GrConfigProvider/context'\nimport type { GranularityI18nLike } from '../../internal/granularityI18n'\n\nimport type {\n DialogBaseOptions,\n DialogKind,\n DialogOnConfirm,\n DialogResult,\n} from './types'\n\n/**\n * Внутреннее описание одного запроса диалога в очереди. Создаётся методами\n * сервиса (`confirm`/`alert`/`prompt`/`open`) и потребляется хостом\n * (`GrDialogServiceHost`), который рендерит видимую часть очереди.\n */\nexport interface DialogRequest {\n id: string\n kind: DialogKind\n message: string\n options: DialogBaseOptions\n onConfirm?: DialogOnConfirm<any>\n /** Позиция среди ожидающих: больше — раньше. При равенстве порядок FIFO. */\n priority: number\n /**\n * Заявка создана из `onConfirm` уже открытого диалога и показывается **поверх**\n * него, а не за ним. Без этого вложенный вызов вставал бы в очередь за тем,\n * кто его ждёт: внешнее окно висело бы в загрузке, а промис не резолвился бы\n * никогда.\n */\n nested: boolean\n /**\n * Заявка уже завершена. Флаг живёт на самой заявке, а не на хосте: завершить\n * её могут трое (кнопка в окне, `close()` промиса, `closeAll()`), и общее\n * состояние на хосте означало бы, что второй и третий путь про первый не\n * знают.\n */\n settled: boolean\n /** Резолвит промис вызова детальным результатом `{ action, value }`. */\n resolve: (result: DialogResult<any>) => void\n /**\n * Конфиг и i18n, захваченные в месте вызова сервиса (в `setup`, где вызывающий\n * компонент ещё находится внутри дерева провайдера). Хост монтируется в\n * `document.body` вне дерева, поэтому сам их не увидит — см.\n * `SPEC-GrConfig-resolver.md`.\n *\n * Лежат в запросе, а не в состоянии сервиса: два поддерева с разными\n * провайдерами должны получать каждое свой конфиг.\n *\n * `Raw<…>` обязателен: очередь — `reactive`, а он разворачивает вложенные рефы.\n * Без `markRaw` контекст превратился бы в объект значений, `size.value` стало\n * бы `undefined`, и мост молча перестал бы работать.\n */\n config?: Raw<GrConfigContext> | null\n i18n?: Raw<GranularityI18nLike> | null\n}\n\n/** Контекст, захваченный вызовом `useDialogService()` внутри `setup`. */\nexport interface CapturedDialogContext {\n config: Raw<GrConfigContext> | null\n i18n: Raw<GranularityI18nLike> | null\n}\n\n/**\n * Состояние одного инстанса сервиса: очередь, смонтированный хост и захваченный\n * контекст приложения. Живёт либо в приложении (через\n * `granularityDialogServicePlugin`), либо в ленивом модульном фолбэке для\n * простых SPA — см. `useDialogService.ts`.\n */\nexport interface DialogServiceState {\n /** Очередь заявок. Видимую часть выбирает хост, остальные ждут. */\n queue: DialogRequest[]\n mounted: boolean\n container: HTMLElement | null\n appContext: AppContext | null\n lastCapturedContext: CapturedDialogContext | null\n contextlessWarned: boolean\n /**\n * Заявки, чей `onConfirm` сейчас в полёте, от внешней к самой глубокой.\n * По ним определяется вложенность нового вызова.\n */\n inFlight: DialogRequest[]\n}\n\nexport function createDialogServiceState(): DialogServiceState {\n return {\n queue: reactive<DialogRequest[]>([]),\n mounted: false,\n container: null,\n appContext: null,\n lastCapturedContext: null,\n contextlessWarned: false,\n inFlight: [],\n }\n}\n\nlet counter = 0\n\nexport function makeDialogId(): string {\n counter += 1\n return `gr-dialog-${Date.now()}-${counter}`\n}\n\n/**\n * Видимая часть очереди: голова и непрерывный хвост вложенных заявок за ней.\n * Всё остальное ждёт — обычные вызовы по-прежнему идут по одному, чтобы три\n * алерта из цикла не легли стопкой.\n */\nexport function visibleDialogRequests(state: DialogServiceState): DialogRequest[] {\n const visible: DialogRequest[] = []\n\n for (const request of state.queue) {\n if (visible.length === 0 || request.nested)\n visible.push(request)\n else\n break\n }\n\n return visible\n}\n\n/**\n * Ставит заявку в очередь. Единственное место, где решается её позиция:\n *\n * - вложенная (создана, пока `onConfirm` другой заявки в полёте) встаёт сразу\n * за своим родителем и показывается поверх него;\n * - обычная — перед всеми ожидающими с меньшим приоритетом; показанные окна не\n * трогаются, выдёргивать фокус-ловушку из-под пользователя нельзя.\n */\nexport function enqueueDialogRequest(state: DialogServiceState, request: DialogRequest): void {\n const parent = state.inFlight[state.inFlight.length - 1]\n\n if (parent) {\n request.nested = true\n const parentIndex = state.queue.findIndex(item => item.id === parent.id)\n state.queue.splice(parentIndex + 1, 0, request)\n return\n }\n\n const visibleCount = visibleDialogRequests(state).length\n const insertAt = state.queue.findIndex(\n (item, index) => index >= visibleCount && item.priority < request.priority,\n )\n\n if (insertAt < 0)\n state.queue.push(request)\n else\n state.queue.splice(insertAt, 0, request)\n}\n\n/**\n * Заявка входит в «полёт»: пока её `onConfirm` не вернулся, новые вызовы\n * считаются вложенными в неё.\n */\nexport function startDialogInFlight(state: DialogServiceState, request: DialogRequest): void {\n state.inFlight.push(request)\n}\n\n/** Заявка вышла из полёта (колбэк вернулся или окно размонтировано). */\nexport function finishDialogInFlight(state: DialogServiceState, request: DialogRequest): void {\n const index = state.inFlight.indexOf(request)\n if (index >= 0)\n state.inFlight.splice(index, 1)\n}\n\n/**\n * Единственный способ завершить заявку: идемпотентно резолвит промис и снимает\n * её из очереди.\n *\n * `removeFromQueue: false` нужен окну: оно гасит себя и даёт анимации закрытия\n * доиграть, прежде чем заявка исчезнет из очереди. Корректность от этой\n * отсрочки не зависит: повторное завершение отсекается флагом на заявке.\n */\nexport function settleDialogRequest(\n state: DialogServiceState,\n request: DialogRequest,\n result: DialogResult<any>,\n { removeFromQueue = true }: { removeFromQueue?: boolean } = {},\n): boolean {\n if (request.settled)\n return false\n\n request.settled = true\n request.resolve(result)\n\n if (removeFromQueue)\n removeDialogRequest(state, request)\n\n return true\n}\n\n/** Снимает заявку из очереди, если она ещё там. */\nexport function removeDialogRequest(state: DialogServiceState, request: DialogRequest): void {\n const index = state.queue.findIndex(item => item.id === request.id)\n if (index >= 0)\n state.queue.splice(index, 1)\n}\n","import { createVNode, getCurrentInstance, inject, markRaw, render } from 'vue'\nimport type { App, AppContext, InjectionKey } from 'vue'\n\nimport { ensurePortalRoot } from '../../composables/internal/portalRoot'\nimport GrDialogServiceHost from './GrDialogServiceHost.vue'\nimport { useGrConfig } from '../GrConfigProvider/context'\nimport { resolveGranularityI18n } from '../../internal/granularityI18n'\nimport {\n createDialogServiceState,\n enqueueDialogRequest,\n makeDialogId,\n settleDialogRequest,\n} from './store'\nimport type { CapturedDialogContext, DialogRequest, DialogServiceState } from './store'\nimport type {\n DialogAlertOptions,\n DialogBaseOptions,\n DialogConfirmOptions,\n DialogKind,\n DialogOnConfirm,\n DialogPromise,\n DialogPromptOptions,\n DialogResult,\n DialogService,\n DialogServiceDefaults,\n} from './types'\n\n/**\n * `useDialogService` — императивный сервис диалогов (в духе Element Plus\n * `ElMessageBox`). Позволяет вызывать `confirm`/`alert`/`prompt` из `<script>`\n * или `.ts` без вставки компонента в шаблон.\n *\n * Поверх существующих `GrConfirmDialog`/`GrPromptDialog`: лениво монтирует\n * единый хост (`GrDialogServiceHost`) в `document.body`, наследуя контекст\n * приложения (i18n / тема / `granular-provider`).\n */\n\n/** Ключ provide/inject для app-scoped состояния сервиса (устанавливает плагин ниже). */\nexport const GRANULARITY_DIALOG_SERVICE_STATE: InjectionKey<DialogServiceState>\n = Symbol.for('@feugene/granularity/dialog-service-state')\n\n/**\n * Инстансы, заведённые плагином. Реестр нужен готовому синглтону\n * `dialogService`: он создаётся на импорте модуля, где `inject` не работает\n * вовсе, и сам до app-scoped состояния не дотянется. Ровно один\n * зарегистрированный — ответ однозначен; несколько — выбирать за пользователя\n * нечего, и он получает предупреждение с модульным фолбэком.\n */\nconst registeredStates = new Set<DialogServiceState>()\n\n/**\n * Vue-плагин: даёт каждому приложению собственное состояние сервиса и снимает\n * его хост вместе с приложением. Обязателен для нескольких Vue-приложений на\n * одной странице (микрофронтенды — иначе они делят одну очередь и один хост) и\n * для HMR, где контейнер прошлого приложения иначе остаётся в `document.body`.\n *\n * ```ts\n * app.use(granularityDialogServicePlugin)\n * ```\n */\nexport const granularityDialogServicePlugin = {\n install(app: App) {\n const state = createDialogServiceState()\n\n app.provide(GRANULARITY_DIALOG_SERVICE_STATE, state)\n registeredStates.add(state)\n\n app.onUnmount(() => {\n teardownDialogServiceState(state)\n registeredStates.delete(state)\n })\n },\n}\n\n// Ленивый модульный фолбэк — канонический вариант для простого SPA без плагина.\nlet moduleState: DialogServiceState | null = null\n\nfunction getModuleState(): DialogServiceState {\n if (!moduleState)\n moduleState = createDialogServiceState()\n\n return moduleState\n}\n\nlet ambiguousStateWarned = false\n\nfunction warnAmbiguousState(): void {\n if (ambiguousStateWarned)\n return\n if (!__GR_DEV__)\n return\n\n ambiguousStateWarned = true\n console.warn(\n '[granularity] useDialogService: плагин установлен в нескольких приложениях, '\n + 'а сервис запрошен вне `setup` — какое из них имелось в виду, знать неоткуда. '\n + 'Используется модульное состояние. Вызовите `useDialogService()` внутри `setup` нужного приложения.',\n )\n}\n\n/**\n * Состояние текущего вызова: app-scoped (плагин) → единственный\n * зарегистрированный инстанс → модульный фолбэк.\n */\nfunction resolveDialogServiceState(): DialogServiceState {\n // `inject` работает только в `setup` — там ответ точный.\n if (getCurrentInstance()) {\n const provided = inject(GRANULARITY_DIALOG_SERVICE_STATE, null)\n if (provided)\n return provided\n }\n\n if (registeredStates.size === 1)\n return registeredStates.values().next().value!\n\n if (registeredStates.size > 1)\n warnAmbiguousState()\n\n return getModuleState()\n}\n\nfunction ensureMounted(state: DialogServiceState, appContext?: AppContext | null): void {\n if (typeof window === 'undefined' || typeof document === 'undefined')\n return\n\n if (appContext)\n state.appContext = appContext\n if (state.mounted)\n return\n\n const container = document.createElement('div')\n container.setAttribute('data-gr-dialog-service-host', '')\n container.setAttribute('data-gr-overlay-root', '')\n // Хост уезжает в общий портал оверлеев: он должен лежать в той же ветке, что\n // и остальные слои, иначе правило `inert` пометит его вместе со страницей.\n ;(ensurePortalRoot() ?? document.body).appendChild(container)\n state.container = container\n\n // Состояние отдаём пропом: хост монтируется вне дерева и своим `inject` до\n // app-scoped состояния не дотянулся бы. `markRaw` — чтобы Vue не пытался\n // сделать реактивной саму обёртку: реактивна очередь внутри неё.\n const vnode = createVNode(GrDialogServiceHost, { state: markRaw(state) })\n vnode.appContext = state.appContext ?? null\n render(vnode, container)\n state.mounted = true\n}\n\nfunction warnIfContextless(state: DialogServiceState, context: CapturedDialogContext | null): void {\n if (state.contextlessWarned || context?.config || context?.i18n)\n return\n if (!__GR_DEV__)\n return\n\n state.contextlessWarned = true\n console.warn(\n '[granularity] useDialogService: диалог открыт без контекста приложения — '\n + 'ни `GrConfigProvider`, ни адаптер i18n не найдены, будут использованы дефолты. '\n + 'Вызовите `useDialogService()` внутри `setup` хотя бы один раз или передайте `setAppContext`.',\n )\n}\n\n/** Снимает смонтированный хост и сбрасывает захваченный контекст одного инстанса. */\nfunction teardownDialogServiceState(state: DialogServiceState): void {\n if (state.container) {\n render(null, state.container)\n state.container.remove()\n state.container = null\n }\n state.mounted = false\n // Сбрасываем и кэш контекста приложения: без этого он переживает teardown и\n // протекает в следующее приложение (в тестах — в следующий тест), из-за чего\n // диалог может подхватить чужие provides и проверка соврёт.\n state.appContext = null\n state.lastCapturedContext = null\n state.contextlessWarned = false\n state.queue.splice(0, state.queue.length)\n state.inFlight.splice(0, state.inFlight.length)\n}\n\n/**\n * Тестовая/служебная очистка смонтированного хоста. Работает над тем же\n * состоянием, что и сам сервис: app-scoped при вызове из `setup` или при\n * единственном зарегистрированном приложении, иначе — модульным.\n */\nexport function teardownDialogService(): void {\n teardownDialogServiceState(resolveDialogServiceState())\n}\n\nfunction enqueue(\n state: DialogServiceState,\n kind: DialogKind,\n message: string,\n options: DialogBaseOptions,\n onConfirm: DialogOnConfirm<any> | undefined,\n captured: CapturedDialogContext,\n): { promise: Promise<DialogResult<any>>, close: () => void } {\n // Императивный сервис клиент-only: монтирует хост в `document.body`. В SSR\n // выполнять его нельзя — очередь мутировалась бы на сервере и текла между\n // запросами. Явно запрещаем вместо тихого no-op.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error(\n '[granularity] useDialogService is client-only and cannot be called during SSR '\n + '(it mounts a host into document.body). Guard imperative dialog calls behind a client-side check.',\n )\n }\n\n ensureMounted(state, options.appContext ?? state.appContext)\n\n const id = makeDialogId()\n let resolveFn!: (result: DialogResult<any>) => void\n const promise = new Promise<DialogResult<any>>((resolve) => {\n resolveFn = resolve\n })\n\n // Синглтон `dialogService` создаётся на импорте модуля, вне `setup`, и своего\n // контекста не имеет в принципе. Берём последний захваченный — иначе такие\n // вызовы навсегда остаются без i18n и без `GrConfigProvider`.\n const context = captured.config || captured.i18n ? captured : state.lastCapturedContext\n warnIfContextless(state, context)\n\n const request: DialogRequest = {\n id,\n kind,\n message,\n options: { ...options, message },\n onConfirm,\n priority: options.priority ?? 0,\n nested: false,\n settled: false,\n resolve: resolveFn,\n config: context?.config ?? null,\n i18n: context?.i18n ?? null,\n }\n\n enqueueDialogRequest(state, request)\n\n // Закрытие через промис идёт тем же путём, что и кнопка в окне: заявка сама\n // знает, завершена ли она, а окно по её исчезновению свернёт всё, что под неё\n // заведено (в т.ч. оборвёт in-flight `onConfirm` через `abort()`).\n const close = (): void => {\n settleDialogRequest(state, request, { action: 'close' })\n }\n\n return { promise, close }\n}\n\nfunction withClose<T>(promise: Promise<T>, close: () => void): DialogPromise<T> {\n const result = promise as DialogPromise<T>\n result.close = close\n return result\n}\n\nfunction mergeErrorDefaults(\n defaults: DialogServiceDefaults,\n options: DialogBaseOptions,\n): DialogBaseOptions & Pick<DialogConfirmOptions, 'cancelText'> {\n return {\n size: defaults.size,\n confirmText: defaults.confirmText,\n confirmVariant: defaults.confirmVariant,\n confirmTone: defaults.confirmTone,\n cancelText: defaults.cancelText,\n buttonSize: defaults.buttonSize,\n closeOnBackdrop: defaults.closeOnBackdrop,\n closeOnEsc: defaults.closeOnEsc,\n errorParsers: defaults.errorParsers,\n errorTexts: defaults.errorTexts,\n errorMessageKey: defaults.errorMessageKey,\n fieldLabels: defaults.fieldLabels,\n ...options,\n }\n}\n\n/**\n * Создаёт сервис диалогов. Опциональные `defaults` применяются ко всем\n * вызовам (можно переопределить в каждом конкретном вызове).\n *\n * Контекст приложения кэшируется автоматически при первом вызове внутри\n * `setup`. Для вызовов вне компонента используйте `setAppContext`.\n */\nexport function useDialogService(defaults: DialogServiceDefaults = {}): DialogService {\n const state = resolveDialogServiceState()\n\n // Авто-кэш appContext из текущего компонента (если вызвано в setup).\n const instance = getCurrentInstance()\n if (instance?.appContext && !state.appContext) {\n state.appContext = instance.appContext\n }\n\n // Конфиг и i18n захватываем здесь и только здесь: `inject` работает лишь в\n // `setup`, а хост монтируется вне дерева и сам до провайдера не дотянется.\n // Храним в замыкании сервиса, а не в состоянии, — иначе два поддерева с\n // разными провайдерами делили бы конфиг первого.\n // i18n захватываем не «на всякий случай»: дочерний `GrConfirmDialog` сам зовёт\n // `useGranularityTranslations()`, но его `inject` из хоста уходит в\n // `appContext.provides` — то есть видит только установку через `app.use()`.\n // Адаптер, переданный пропом `<GrConfigProvider i18n>`, живёт в дереве, и без\n // захвата диалог откатился бы на встроенные английские строки.\n //\n // `markRaw` — потому что дальше контекст ложится в `reactive`-очередь, а она\n // разворачивает вложенные рефы (см. комментарий в `store.ts`).\n const capturedI18n = instance ? resolveGranularityI18n() : null\n const captured: CapturedDialogContext = {\n config: instance ? markRaw(useGrConfig()) : null,\n i18n: capturedI18n ? markRaw(capturedI18n) : null,\n }\n\n if (captured.config || captured.i18n)\n state.lastCapturedContext = captured\n\n function confirm(message: string, options: DialogConfirmOptions = {}): DialogPromise<boolean> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(state, 'confirm', message, merged, options.onConfirm, captured)\n return withClose(promise.then(r => r.action === 'confirm'), close)\n }\n\n function alert(message: string, options: DialogAlertOptions = {}): DialogPromise<void> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(state, 'alert', message, merged, options.onConfirm, captured)\n return withClose(promise.then(() => undefined), close)\n }\n\n function prompt(message: string, options: DialogPromptOptions = {}): DialogPromise<string | null> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(state, 'prompt', message, merged, options.onConfirm, captured)\n return withClose(\n promise.then(r => (r.action === 'confirm' ? ((r.value as string) ?? '') : null)),\n close,\n )\n }\n\n function open<V = unknown>(\n kind: DialogKind,\n message: string,\n options: DialogBaseOptions = {},\n ): DialogPromise<DialogResult<V>> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(\n state,\n kind,\n message,\n merged,\n (options as DialogConfirmOptions).onConfirm,\n captured,\n )\n return withClose(promise as Promise<DialogResult<V>>, close)\n }\n\n // Порядок разбора — FIFO, как и порядок показа: `pop()` резолвил промисы\n // задом наперёд, и вызывающий получал результаты в обратном порядке.\n function closeAll(): void {\n for (const request of [...state.queue])\n settleDialogRequest(state, request, { action: 'close' })\n }\n\n function setAppContext(ctx: AppContext | null): void {\n state.appContext = ctx\n }\n\n return { confirm, alert, prompt, open, closeAll, setAppContext }\n}\n\n/** Готовый синглтон-сервис с дефолтными настройками. */\nexport const dialogService: DialogService = {\n confirm: (message, options) => useDialogService().confirm(message, options),\n alert: (message, options) => useDialogService().alert(message, options),\n prompt: (message, options) => useDialogService().prompt(message, options),\n open: (kind, message, options) => useDialogService().open(kind, message, options),\n closeAll: () => useDialogService().closeAll(),\n setAppContext: ctx => useDialogService().setAppContext(ctx),\n}\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceItem — одно окно императивного сервиса. Внутренний компонент,\n * в шаблонах напрямую не используется.\n *\n * Всё состояние живёт здесь, а не на хосте, ровно потому, что окон может быть\n * несколько: вложенный вызов из `onConfirm` показывается поверх родителя, и\n * общий `loading` с общей ошибкой означали бы, что верхнее окно пишет в нижнее.\n */\nimport { computed, inject, nextTick, onBeforeUnmount, onMounted, provide, ref, shallowRef } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrConfirmDialog from '../GrConfirmDialog/GrConfirmDialog.vue'\nimport GrPromptDialog from '../GrPromptDialog/GrPromptDialog.vue'\nimport {\n coreResponseErrorParsers,\n createResponseErrorClassifier,\n responseErrorParserPresets,\n} from '../GrResponseErrorBanner/parsers'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\nimport { GR_CONFIG_KEY, type GrComponentDefaults, type GrConfigContext } from '../GrConfigProvider/context'\nimport { GRANULARITY_I18N_KEY } from '../../i18n/adapter'\nimport { resolveGranularityI18n, useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { finishDialogInFlight, removeDialogRequest, settleDialogRequest, startDialogInFlight } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\nimport type { DialogCloseAction, DialogConfirmContext, DialogConfirmOptions, DialogPromptOptions } from './types'\n\nconst props = defineProps<{\n request: DialogRequest\n}>()\n\n// Состояние инстанса приходит через `provide` хоста, а не пропом: окно его\n// мутирует (очередь, список заявок в полёте), а мутировать проп — значит писать\n// в чужое владение.\nconst state = inject(GRANULARITY_DIALOG_SERVICE_STATE) as DialogServiceState\n\n// ————— Мост конфига и i18n.\n//\n// Окно рендерится через `render(vnode, container)` в `document.body`, то есть вне\n// дерева компонентов. Vue в этом случае берёт `provides` только из `appContext`,\n// куда попадает лишь `app.provide()` — значения от `<GrConfigProvider>` до сюда\n// не доходят. Поэтому вызов сервиса захватывает их в `setup` и кладёт в заявку,\n// а окно раздаёт вниз конфиг **своей** заявки.\nconst EMPTY_DEFAULTS: GrComponentDefaults = Object.freeze({})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, {\n size: computed(() => props.request.config?.size.value),\n componentDefaults: computed(() => props.request.config?.componentDefaults.value ?? EMPTY_DEFAULTS),\n})\n\n// i18n: тот же приём. Адаптер хоста (из `appContext`) — запасной вариант для\n// вызова без захваченного: без него установка через `app.use()` осталась бы\n// незамеченной.\nconst hostI18n = resolveGranularityI18n()\n\nprovide(GRANULARITY_I18N_KEY, {\n t: (key: string, params?: Record<string, unknown>) => {\n const adapter = props.request.i18n ?? hostI18n\n // Вернуть сам ключ — принятый в пакете сигнал «перевода нет»: потребитель\n // подставит свой fallback-текст (см. `useGranularityTranslations`).\n return adapter?.t(key, params) ?? key\n },\n get locale() {\n return (props.request.i18n ?? hostI18n)?.locale\n },\n})\n\n// Подвал alert-ветки рисуется здесь, поэтому и перевод кнопки достаётся здесь.\n// Адаптер берём тот же, что раздан вниз: собственный `provide` компонента его\n// же `inject` не видит, и `useGranularityTranslations()` без аргумента ушёл бы\n// мимо захваченного вызовом адаптера — в фолбэк из `appContext`.\nconst alertConfirmText = computed(() => {\n const { t } = useGranularityTranslations(props.request.i18n ?? hostI18n)\n return t('gr.dialog.ok', 'OK')\n})\n\nconst open = ref(false)\nconst loading = ref(false)\nconst currentError = shallowRef<ResponseErrorInfo | null>(null)\n/**\n * Ошибки по именам полей. Карта, а не одна строка: `setFieldError(field, …)`\n * обещает адресность, и обещание должно быть правдой ещё до того, как в\n * диалоге появится второе поле.\n */\nconst fieldErrors = ref<Record<string, string>>({})\nconst promptValue = ref(\n props.request.options && 'value' in props.request.options\n ? ((props.request.options as { value?: string }).value ?? '')\n : '',\n)\n\n/** Единственное поле `GrPromptDialog` называется `value`. */\nconst PROMPT_FIELD = 'value'\n\n// Одна запись — её и показываем: адрес не важен, когда адресат один.\nconst promptFieldError = computed<string | null>(() => {\n const own = fieldErrors.value[PROMPT_FIELD]\n if (own != null)\n return own\n\n const entries = Object.values(fieldErrors.value)\n return entries.length === 1 ? entries[0] : null\n})\n\nconst hasFieldError = computed(() => Object.keys(fieldErrors.value).length > 0)\n\nconst controller = new AbortController()\nlet externalAbortCleanup: (() => void) | null = null\n\nfunction buildClassifier() {\n const opts = props.request.options\n const parsers = typeof opts.errorParsers === 'function'\n ? opts.errorParsers(responseErrorParserPresets)\n : opts.errorParsers ?? coreResponseErrorParsers\n\n return createResponseErrorClassifier({\n parsers,\n texts: opts.errorTexts,\n messageKey: opts.errorMessageKey,\n })\n}\n\nonMounted(() => {\n // Внешний AbortSignal закрывает диалог как `close`.\n const sig = props.request.options.signal\n if (sig) {\n if (sig.aborted) {\n finish('close')\n return\n }\n const onAbort = () => finish('close')\n sig.addEventListener('abort', onAbort)\n externalAbortCleanup = () => sig.removeEventListener('abort', onAbort)\n }\n\n void nextTick(() => {\n open.value = true\n })\n})\n\nonBeforeUnmount(() => {\n // Снимаем всё, что заведено под заявку: подписку на внешний сигнал и свой\n // контроллер. Размонтирование — единственная точка, которую видят все три\n // пути завершения (кнопка, `close()` промиса, `closeAll()`), поэтому обрыв\n // in-flight `onConfirm` живёт именно здесь.\n externalAbortCleanup?.()\n externalAbortCleanup = null\n controller.abort()\n\n finishDialogInFlight(state, props.request)\n})\n\nfunction finish(action: DialogCloseAction, value?: unknown): void {\n // Снятие заявки из очереди откладываем на тик: окно должно успеть закрыться\n // до того, как исчезнет из разметки.\n if (!settleDialogRequest(state, props.request, { action, value }, { removeFromQueue: false }))\n return\n\n open.value = false\n void nextTick(() => removeDialogRequest(state, props.request))\n}\n\nfunction buildContext(value: unknown): DialogConfirmContext<any> & { _errorSet: () => boolean } {\n let errorSet = false\n\n const setError = (message: string | null): void => {\n if (message == null) {\n currentError.value = null\n return\n }\n errorSet = true\n currentError.value = { kind: 'unknown', message, raw: message }\n }\n\n const setFieldError = (field: string, message: string | null): void => {\n const next = { ...fieldErrors.value }\n if (message == null) {\n delete next[field]\n fieldErrors.value = next\n return\n }\n errorSet = true\n next[field] = message\n fieldErrors.value = next\n }\n\n const clearErrors = (): void => {\n currentError.value = null\n fieldErrors.value = {}\n }\n\n const setRawError = async (raw: unknown, meta?: Record<string, unknown>): Promise<ResponseErrorInfo | null> => {\n const info = await buildClassifier()(raw, meta)\n if (info.fieldErrors?.length) {\n const next = { ...fieldErrors.value }\n for (const entry of info.fieldErrors)\n next[entry.field] = entry.messages.join(' ')\n fieldErrors.value = next\n }\n currentError.value = info\n errorSet = true\n return info\n }\n\n return {\n value,\n signal: controller.signal,\n setError,\n setRawError,\n setFieldError,\n clearErrors,\n setLoading: (v: boolean) => { loading.value = v },\n close: (action: DialogCloseAction = 'close') => finish(action),\n _errorSet: () => errorSet,\n }\n}\n\nasync function handleConfirm(): Promise<void> {\n const req = props.request\n const value = req.kind === 'prompt' ? promptValue.value : undefined\n\n if (!req.onConfirm) {\n finish('confirm', value)\n return\n }\n\n currentError.value = null\n fieldErrors.value = {}\n loading.value = true\n\n const ctx = buildContext(value)\n\n // Пока колбэк в полёте, заявка считается родителем для новых вызовов: диалог,\n // открытый изнутри `onConfirm`, показывается поверх, а не встаёт в очередь за\n // тем, кто его ждёт.\n startDialogInFlight(state, req)\n\n try {\n const result = await req.onConfirm(ctx)\n // Сначала проверка «диалог ещё жив», потом запись состояния: за время\n // `await` заявку мог завершить `ctx.close()` или `closeAll()`.\n if (req.settled)\n return\n loading.value = false\n if (result === false)\n return // оставить открытым без ошибки\n if (currentError.value || hasFieldError.value || ctx._errorSet())\n return // есть ошибка — не закрывать\n finish('confirm', value)\n }\n catch (error) {\n if (req.settled)\n return\n loading.value = false\n if (!ctx._errorSet())\n await ctx.setRawError(error)\n // оставить диалог открытым с показанной ошибкой\n }\n finally {\n finishDialogInFlight(state, req)\n }\n}\n\nfunction handleCancel(): void {\n finish('cancel')\n}\n\nfunction handleModelUpdate(value: boolean): void {\n if (!value)\n finish('close')\n}\n\n// Опции веток читаются типизированно, без `as any` в шаблоне.\nconst promptOptions = computed<DialogPromptOptions>(() => props.request.options as DialogPromptOptions)\nconst confirmOptions = computed<DialogConfirmOptions>(() => props.request.options as DialogConfirmOptions)\n\n// Прокидываемые в дочерний диалог общие пропы.\nconst sharedProps = computed(() => {\n const o = props.request.options\n return {\n title: o.title,\n size: o.size,\n closeOnBackdrop: o.closeOnBackdrop,\n closeOnEsc: o.closeOnEsc,\n // Подавление «мягкого» закрытия на время `onConfirm` считает сам диалог по\n // `confirmLoading` — здесь только включаем режим, чтобы механизм жил в\n // одном месте, а не дублировался сервисом.\n persistent: true,\n showHeader: o.showHeader,\n showCloseButton: o.showCloseButton,\n headerConfig: o.headerConfig,\n footerConfig: o.footerConfig,\n bodyConfig: o.bodyConfig,\n closeLabel: o.closeLabel,\n buttonSize: o.buttonSize,\n confirmText: o.confirmText,\n confirmVariant: o.confirmVariant,\n confirmTone: o.confirmTone,\n }\n})\n\n/**\n * `alert` рисуется тем же `GrConfirmDialog`, что и `confirm`, но без кнопки\n * отмены: у сообщения нет второго исхода, и лишняя кнопка предлагала бы выбор,\n * которого нет.\n */\n</script>\n\n<template>\n <GrPromptDialog\n v-if=\"request.kind === 'prompt'\"\n v-bind=\"sharedProps\"\n v-model:value=\"promptValue\"\n :model-value=\"open\"\n :description=\"request.options.message ?? request.options.description\"\n :label=\"promptOptions.label\"\n :placeholder=\"promptOptions.placeholder\"\n :required=\"promptOptions.required ?? false\"\n :required-error-text=\"promptOptions.requiredErrorText\"\n :cancel-text=\"promptOptions.cancelText\"\n :input-type=\"promptOptions.inputType\"\n :inputmode=\"promptOptions.inputmode\"\n :maxlength=\"promptOptions.maxlength\"\n :show-count=\"promptOptions.showCount\"\n :multiline=\"promptOptions.multiline\"\n :rows=\"promptOptions.rows\"\n :autosize=\"promptOptions.autosize\"\n :rules=\"promptOptions.rules\"\n :error=\"currentError\"\n :field-error=\"promptFieldError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n\n <GrConfirmDialog\n v-else-if=\"request.kind === 'alert'\"\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n >\n <template #footer>\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton\n data-testid=\"gr-alert-confirm\"\n :variant=\"sharedProps.confirmVariant ?? 'primary'\"\n :tone=\"sharedProps.confirmTone ?? 'primary'\"\n :size=\"sharedProps.buttonSize\"\n :loading=\"loading\"\n @click=\"handleConfirm\"\n >\n {{ sharedProps.confirmText ?? alertConfirmText }}\n </GrButton>\n </div>\n </template>\n </GrConfirmDialog>\n\n <GrConfirmDialog\n v-else\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :cancel-text=\"confirmOptions.cancelText\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceItem — одно окно императивного сервиса. Внутренний компонент,\n * в шаблонах напрямую не используется.\n *\n * Всё состояние живёт здесь, а не на хосте, ровно потому, что окон может быть\n * несколько: вложенный вызов из `onConfirm` показывается поверх родителя, и\n * общий `loading` с общей ошибкой означали бы, что верхнее окно пишет в нижнее.\n */\nimport { computed, inject, nextTick, onBeforeUnmount, onMounted, provide, ref, shallowRef } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrConfirmDialog from '../GrConfirmDialog/GrConfirmDialog.vue'\nimport GrPromptDialog from '../GrPromptDialog/GrPromptDialog.vue'\nimport {\n coreResponseErrorParsers,\n createResponseErrorClassifier,\n responseErrorParserPresets,\n} from '../GrResponseErrorBanner/parsers'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\nimport { GR_CONFIG_KEY, type GrComponentDefaults, type GrConfigContext } from '../GrConfigProvider/context'\nimport { GRANULARITY_I18N_KEY } from '../../i18n/adapter'\nimport { resolveGranularityI18n, useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { finishDialogInFlight, removeDialogRequest, settleDialogRequest, startDialogInFlight } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\nimport type { DialogCloseAction, DialogConfirmContext, DialogConfirmOptions, DialogPromptOptions } from './types'\n\nconst props = defineProps<{\n request: DialogRequest\n}>()\n\n// Состояние инстанса приходит через `provide` хоста, а не пропом: окно его\n// мутирует (очередь, список заявок в полёте), а мутировать проп — значит писать\n// в чужое владение.\nconst state = inject(GRANULARITY_DIALOG_SERVICE_STATE) as DialogServiceState\n\n// ————— Мост конфига и i18n.\n//\n// Окно рендерится через `render(vnode, container)` в `document.body`, то есть вне\n// дерева компонентов. Vue в этом случае берёт `provides` только из `appContext`,\n// куда попадает лишь `app.provide()` — значения от `<GrConfigProvider>` до сюда\n// не доходят. Поэтому вызов сервиса захватывает их в `setup` и кладёт в заявку,\n// а окно раздаёт вниз конфиг **своей** заявки.\nconst EMPTY_DEFAULTS: GrComponentDefaults = Object.freeze({})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, {\n size: computed(() => props.request.config?.size.value),\n componentDefaults: computed(() => props.request.config?.componentDefaults.value ?? EMPTY_DEFAULTS),\n})\n\n// i18n: тот же приём. Адаптер хоста (из `appContext`) — запасной вариант для\n// вызова без захваченного: без него установка через `app.use()` осталась бы\n// незамеченной.\nconst hostI18n = resolveGranularityI18n()\n\nprovide(GRANULARITY_I18N_KEY, {\n t: (key: string, params?: Record<string, unknown>) => {\n const adapter = props.request.i18n ?? hostI18n\n // Вернуть сам ключ — принятый в пакете сигнал «перевода нет»: потребитель\n // подставит свой fallback-текст (см. `useGranularityTranslations`).\n return adapter?.t(key, params) ?? key\n },\n get locale() {\n return (props.request.i18n ?? hostI18n)?.locale\n },\n})\n\n// Подвал alert-ветки рисуется здесь, поэтому и перевод кнопки достаётся здесь.\n// Адаптер берём тот же, что раздан вниз: собственный `provide` компонента его\n// же `inject` не видит, и `useGranularityTranslations()` без аргумента ушёл бы\n// мимо захваченного вызовом адаптера — в фолбэк из `appContext`.\nconst alertConfirmText = computed(() => {\n const { t } = useGranularityTranslations(props.request.i18n ?? hostI18n)\n return t('gr.dialog.ok', 'OK')\n})\n\nconst open = ref(false)\nconst loading = ref(false)\nconst currentError = shallowRef<ResponseErrorInfo | null>(null)\n/**\n * Ошибки по именам полей. Карта, а не одна строка: `setFieldError(field, …)`\n * обещает адресность, и обещание должно быть правдой ещё до того, как в\n * диалоге появится второе поле.\n */\nconst fieldErrors = ref<Record<string, string>>({})\nconst promptValue = ref(\n props.request.options && 'value' in props.request.options\n ? ((props.request.options as { value?: string }).value ?? '')\n : '',\n)\n\n/** Единственное поле `GrPromptDialog` называется `value`. */\nconst PROMPT_FIELD = 'value'\n\n// Одна запись — её и показываем: адрес не важен, когда адресат один.\nconst promptFieldError = computed<string | null>(() => {\n const own = fieldErrors.value[PROMPT_FIELD]\n if (own != null)\n return own\n\n const entries = Object.values(fieldErrors.value)\n return entries.length === 1 ? entries[0] : null\n})\n\nconst hasFieldError = computed(() => Object.keys(fieldErrors.value).length > 0)\n\nconst controller = new AbortController()\nlet externalAbortCleanup: (() => void) | null = null\n\nfunction buildClassifier() {\n const opts = props.request.options\n const parsers = typeof opts.errorParsers === 'function'\n ? opts.errorParsers(responseErrorParserPresets)\n : opts.errorParsers ?? coreResponseErrorParsers\n\n return createResponseErrorClassifier({\n parsers,\n texts: opts.errorTexts,\n messageKey: opts.errorMessageKey,\n })\n}\n\nonMounted(() => {\n // Внешний AbortSignal закрывает диалог как `close`.\n const sig = props.request.options.signal\n if (sig) {\n if (sig.aborted) {\n finish('close')\n return\n }\n const onAbort = () => finish('close')\n sig.addEventListener('abort', onAbort)\n externalAbortCleanup = () => sig.removeEventListener('abort', onAbort)\n }\n\n void nextTick(() => {\n open.value = true\n })\n})\n\nonBeforeUnmount(() => {\n // Снимаем всё, что заведено под заявку: подписку на внешний сигнал и свой\n // контроллер. Размонтирование — единственная точка, которую видят все три\n // пути завершения (кнопка, `close()` промиса, `closeAll()`), поэтому обрыв\n // in-flight `onConfirm` живёт именно здесь.\n externalAbortCleanup?.()\n externalAbortCleanup = null\n controller.abort()\n\n finishDialogInFlight(state, props.request)\n})\n\nfunction finish(action: DialogCloseAction, value?: unknown): void {\n // Снятие заявки из очереди откладываем на тик: окно должно успеть закрыться\n // до того, как исчезнет из разметки.\n if (!settleDialogRequest(state, props.request, { action, value }, { removeFromQueue: false }))\n return\n\n open.value = false\n void nextTick(() => removeDialogRequest(state, props.request))\n}\n\nfunction buildContext(value: unknown): DialogConfirmContext<any> & { _errorSet: () => boolean } {\n let errorSet = false\n\n const setError = (message: string | null): void => {\n if (message == null) {\n currentError.value = null\n return\n }\n errorSet = true\n currentError.value = { kind: 'unknown', message, raw: message }\n }\n\n const setFieldError = (field: string, message: string | null): void => {\n const next = { ...fieldErrors.value }\n if (message == null) {\n delete next[field]\n fieldErrors.value = next\n return\n }\n errorSet = true\n next[field] = message\n fieldErrors.value = next\n }\n\n const clearErrors = (): void => {\n currentError.value = null\n fieldErrors.value = {}\n }\n\n const setRawError = async (raw: unknown, meta?: Record<string, unknown>): Promise<ResponseErrorInfo | null> => {\n const info = await buildClassifier()(raw, meta)\n if (info.fieldErrors?.length) {\n const next = { ...fieldErrors.value }\n for (const entry of info.fieldErrors)\n next[entry.field] = entry.messages.join(' ')\n fieldErrors.value = next\n }\n currentError.value = info\n errorSet = true\n return info\n }\n\n return {\n value,\n signal: controller.signal,\n setError,\n setRawError,\n setFieldError,\n clearErrors,\n setLoading: (v: boolean) => { loading.value = v },\n close: (action: DialogCloseAction = 'close') => finish(action),\n _errorSet: () => errorSet,\n }\n}\n\nasync function handleConfirm(): Promise<void> {\n const req = props.request\n const value = req.kind === 'prompt' ? promptValue.value : undefined\n\n if (!req.onConfirm) {\n finish('confirm', value)\n return\n }\n\n currentError.value = null\n fieldErrors.value = {}\n loading.value = true\n\n const ctx = buildContext(value)\n\n // Пока колбэк в полёте, заявка считается родителем для новых вызовов: диалог,\n // открытый изнутри `onConfirm`, показывается поверх, а не встаёт в очередь за\n // тем, кто его ждёт.\n startDialogInFlight(state, req)\n\n try {\n const result = await req.onConfirm(ctx)\n // Сначала проверка «диалог ещё жив», потом запись состояния: за время\n // `await` заявку мог завершить `ctx.close()` или `closeAll()`.\n if (req.settled)\n return\n loading.value = false\n if (result === false)\n return // оставить открытым без ошибки\n if (currentError.value || hasFieldError.value || ctx._errorSet())\n return // есть ошибка — не закрывать\n finish('confirm', value)\n }\n catch (error) {\n if (req.settled)\n return\n loading.value = false\n if (!ctx._errorSet())\n await ctx.setRawError(error)\n // оставить диалог открытым с показанной ошибкой\n }\n finally {\n finishDialogInFlight(state, req)\n }\n}\n\nfunction handleCancel(): void {\n finish('cancel')\n}\n\nfunction handleModelUpdate(value: boolean): void {\n if (!value)\n finish('close')\n}\n\n// Опции веток читаются типизированно, без `as any` в шаблоне.\nconst promptOptions = computed<DialogPromptOptions>(() => props.request.options as DialogPromptOptions)\nconst confirmOptions = computed<DialogConfirmOptions>(() => props.request.options as DialogConfirmOptions)\n\n// Прокидываемые в дочерний диалог общие пропы.\nconst sharedProps = computed(() => {\n const o = props.request.options\n return {\n title: o.title,\n size: o.size,\n closeOnBackdrop: o.closeOnBackdrop,\n closeOnEsc: o.closeOnEsc,\n // Подавление «мягкого» закрытия на время `onConfirm` считает сам диалог по\n // `confirmLoading` — здесь только включаем режим, чтобы механизм жил в\n // одном месте, а не дублировался сервисом.\n persistent: true,\n showHeader: o.showHeader,\n showCloseButton: o.showCloseButton,\n headerConfig: o.headerConfig,\n footerConfig: o.footerConfig,\n bodyConfig: o.bodyConfig,\n closeLabel: o.closeLabel,\n buttonSize: o.buttonSize,\n confirmText: o.confirmText,\n confirmVariant: o.confirmVariant,\n confirmTone: o.confirmTone,\n }\n})\n\n/**\n * `alert` рисуется тем же `GrConfirmDialog`, что и `confirm`, но без кнопки\n * отмены: у сообщения нет второго исхода, и лишняя кнопка предлагала бы выбор,\n * которого нет.\n */\n</script>\n\n<template>\n <GrPromptDialog\n v-if=\"request.kind === 'prompt'\"\n v-bind=\"sharedProps\"\n v-model:value=\"promptValue\"\n :model-value=\"open\"\n :description=\"request.options.message ?? request.options.description\"\n :label=\"promptOptions.label\"\n :placeholder=\"promptOptions.placeholder\"\n :required=\"promptOptions.required ?? false\"\n :required-error-text=\"promptOptions.requiredErrorText\"\n :cancel-text=\"promptOptions.cancelText\"\n :input-type=\"promptOptions.inputType\"\n :inputmode=\"promptOptions.inputmode\"\n :maxlength=\"promptOptions.maxlength\"\n :show-count=\"promptOptions.showCount\"\n :multiline=\"promptOptions.multiline\"\n :rows=\"promptOptions.rows\"\n :autosize=\"promptOptions.autosize\"\n :rules=\"promptOptions.rules\"\n :error=\"currentError\"\n :field-error=\"promptFieldError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n\n <GrConfirmDialog\n v-else-if=\"request.kind === 'alert'\"\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n >\n <template #footer>\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton\n data-testid=\"gr-alert-confirm\"\n :variant=\"sharedProps.confirmVariant ?? 'primary'\"\n :tone=\"sharedProps.confirmTone ?? 'primary'\"\n :size=\"sharedProps.buttonSize\"\n :loading=\"loading\"\n @click=\"handleConfirm\"\n >\n {{ sharedProps.confirmText ?? alertConfirmText }}\n </GrButton>\n </div>\n </template>\n </GrConfirmDialog>\n\n <GrConfirmDialog\n v-else\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :cancel-text=\"confirmOptions.cancelText\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceHost — внутренний компонент-оркестратор императивного\n * `useDialogService`. Не предназначен для прямого использования в шаблонах.\n *\n * Держит раскладку очереди и ничего больше: состояние каждой заявки — загрузка,\n * ошибки, введённое значение, мост конфига и i18n — живёт в\n * `GrDialogServiceItem`, потому что окон может быть несколько.\n *\n * Видимы голова очереди и её вложенные окна (`store.visibleDialogRequests`):\n * обычные вызовы по-прежнему показываются по одному, а диалог, открытый из\n * `onConfirm` другого диалога, ложится поверх родителя — иначе он ждал бы в\n * очереди того, кто ждёт его.\n */\nimport { computed, inject, provide } from 'vue'\n\nimport GrDialogServiceItem from './GrDialogServiceItem.vue'\nimport { visibleDialogRequests } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\n\nexport interface GrDialogServiceHostProps {\n /**\n * Состояние инстанса сервиса. Приходит пропом при программном монтировании:\n * хост живёт вне дерева и своим `inject` до app-scoped состояния не дотянулся\n * бы. `inject` остаётся для случая, когда хост поставили в шаблон руками.\n */\n state?: DialogServiceState | null\n}\n\nconst props = defineProps<GrDialogServiceHostProps>()\n\nconst injected = inject(GRANULARITY_DIALOG_SERVICE_STATE, null)\n\nconst activeState = computed<DialogServiceState | null>(() => props.state ?? injected)\n\nconst visible = computed<DialogRequest[]>(() =>\n activeState.value ? visibleDialogRequests(activeState.value) : [],\n)\n\n// Окна берут состояние отсюда, а не пропом: они его мутируют (очередь, список\n// заявок в полёте), а мутировать проп — значит писать в чужое владение.\nprovide(GRANULARITY_DIALOG_SERVICE_STATE, activeState.value!)\n</script>\n\n<template>\n <GrDialogServiceItem\n v-for=\"request in visible\"\n :key=\"request.id\"\n :request=\"request\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceHost — внутренний компонент-оркестратор императивного\n * `useDialogService`. Не предназначен для прямого использования в шаблонах.\n *\n * Держит раскладку очереди и ничего больше: состояние каждой заявки — загрузка,\n * ошибки, введённое значение, мост конфига и i18n — живёт в\n * `GrDialogServiceItem`, потому что окон может быть несколько.\n *\n * Видимы голова очереди и её вложенные окна (`store.visibleDialogRequests`):\n * обычные вызовы по-прежнему показываются по одному, а диалог, открытый из\n * `onConfirm` другого диалога, ложится поверх родителя — иначе он ждал бы в\n * очереди того, кто ждёт его.\n */\nimport { computed, inject, provide } from 'vue'\n\nimport GrDialogServiceItem from './GrDialogServiceItem.vue'\nimport { visibleDialogRequests } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\n\nexport interface GrDialogServiceHostProps {\n /**\n * Состояние инстанса сервиса. Приходит пропом при программном монтировании:\n * хост живёт вне дерева и своим `inject` до app-scoped состояния не дотянулся\n * бы. `inject` остаётся для случая, когда хост поставили в шаблон руками.\n */\n state?: DialogServiceState | null\n}\n\nconst props = defineProps<GrDialogServiceHostProps>()\n\nconst injected = inject(GRANULARITY_DIALOG_SERVICE_STATE, null)\n\nconst activeState = computed<DialogServiceState | null>(() => props.state ?? injected)\n\nconst visible = computed<DialogRequest[]>(() =>\n activeState.value ? visibleDialogRequests(activeState.value) : [],\n)\n\n// Окна берут состояние отсюда, а не пропом: они его мутируют (очередь, список\n// заявок в полёте), а мутировать проп — значит писать в чужое владение.\nprovide(GRANULARITY_DIALOG_SERVICE_STATE, activeState.value!)\n</script>\n\n<template>\n <GrDialogServiceItem\n v-for=\"request in visible\"\n :key=\"request.id\"\n :request=\"request\"\n />\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrDialogService-DLBifO61.js","names":[],"sources":["../../../../src/components/GrDialogService/store.ts","../../../../src/components/GrDialogService/useDialogService.ts","../../../../src/components/GrDialogService/GrDialogServiceItem.vue","../../../../src/components/GrDialogService/GrDialogServiceItem.vue","../../../../src/components/GrDialogService/GrDialogServiceHost.vue","../../../../src/components/GrDialogService/GrDialogServiceHost.vue"],"sourcesContent":["import { reactive } from 'vue'\nimport type { AppContext, Raw } from 'vue'\n\nimport type { GrConfigContext } from '../GrConfigProvider/context'\nimport type { GranularityI18nLike } from '../../internal/granularityI18n'\n\nimport type {\n DialogBaseOptions,\n DialogKind,\n DialogOnConfirm,\n DialogResult,\n} from './types'\n\n/**\n * Внутреннее описание одного запроса диалога в очереди. Создаётся методами\n * сервиса (`confirm`/`alert`/`prompt`/`open`) и потребляется хостом\n * (`GrDialogServiceHost`), который рендерит видимую часть очереди.\n */\nexport interface DialogRequest {\n id: string\n kind: DialogKind\n message: string\n options: DialogBaseOptions\n onConfirm?: DialogOnConfirm<any>\n /** Позиция среди ожидающих: больше — раньше. При равенстве порядок FIFO. */\n priority: number\n /**\n * Заявка создана из `onConfirm` уже открытого диалога и показывается **поверх**\n * него, а не за ним. Без этого вложенный вызов вставал бы в очередь за тем,\n * кто его ждёт: внешнее окно висело бы в загрузке, а промис не резолвился бы\n * никогда.\n */\n nested: boolean\n /**\n * Заявка уже завершена. Флаг живёт на самой заявке, а не на хосте: завершить\n * её могут трое (кнопка в окне, `close()` промиса, `closeAll()`), и общее\n * состояние на хосте означало бы, что второй и третий путь про первый не\n * знают.\n */\n settled: boolean\n /** Резолвит промис вызова детальным результатом `{ action, value }`. */\n resolve: (result: DialogResult<any>) => void\n /**\n * Конфиг и i18n, захваченные в месте вызова сервиса (в `setup`, где вызывающий\n * компонент ещё находится внутри дерева провайдера). Хост монтируется в\n * `document.body` вне дерева, поэтому сам их не увидит — см.\n * `SPEC-GrConfig-resolver.md`.\n *\n * Лежат в запросе, а не в состоянии сервиса: два поддерева с разными\n * провайдерами должны получать каждое свой конфиг.\n *\n * `Raw<…>` обязателен: очередь — `reactive`, а он разворачивает вложенные рефы.\n * Без `markRaw` контекст превратился бы в объект значений, `size.value` стало\n * бы `undefined`, и мост молча перестал бы работать.\n */\n config?: Raw<GrConfigContext> | null\n i18n?: Raw<GranularityI18nLike> | null\n}\n\n/** Контекст, захваченный вызовом `useDialogService()` внутри `setup`. */\nexport interface CapturedDialogContext {\n config: Raw<GrConfigContext> | null\n i18n: Raw<GranularityI18nLike> | null\n}\n\n/**\n * Состояние одного инстанса сервиса: очередь, смонтированный хост и захваченный\n * контекст приложения. Живёт либо в приложении (через\n * `granularityDialogServicePlugin`), либо в ленивом модульном фолбэке для\n * простых SPA — см. `useDialogService.ts`.\n */\nexport interface DialogServiceState {\n /** Очередь заявок. Видимую часть выбирает хост, остальные ждут. */\n queue: DialogRequest[]\n mounted: boolean\n container: HTMLElement | null\n appContext: AppContext | null\n lastCapturedContext: CapturedDialogContext | null\n contextlessWarned: boolean\n /**\n * Заявки, чей `onConfirm` сейчас в полёте, от внешней к самой глубокой.\n * По ним определяется вложенность нового вызова.\n */\n inFlight: DialogRequest[]\n}\n\nexport function createDialogServiceState(): DialogServiceState {\n return {\n queue: reactive<DialogRequest[]>([]),\n mounted: false,\n container: null,\n appContext: null,\n lastCapturedContext: null,\n contextlessWarned: false,\n inFlight: [],\n }\n}\n\nlet counter = 0\n\nexport function makeDialogId(): string {\n counter += 1\n return `gr-dialog-${Date.now()}-${counter}`\n}\n\n/**\n * Видимая часть очереди: голова и непрерывный хвост вложенных заявок за ней.\n * Всё остальное ждёт — обычные вызовы по-прежнему идут по одному, чтобы три\n * алерта из цикла не легли стопкой.\n */\nexport function visibleDialogRequests(state: DialogServiceState): DialogRequest[] {\n const visible: DialogRequest[] = []\n\n for (const request of state.queue) {\n if (visible.length === 0 || request.nested)\n visible.push(request)\n else\n break\n }\n\n return visible\n}\n\n/**\n * Ставит заявку в очередь. Единственное место, где решается её позиция:\n *\n * - вложенная (создана, пока `onConfirm` другой заявки в полёте) встаёт сразу\n * за своим родителем и показывается поверх него;\n * - обычная — перед всеми ожидающими с меньшим приоритетом; показанные окна не\n * трогаются, выдёргивать фокус-ловушку из-под пользователя нельзя.\n */\nexport function enqueueDialogRequest(state: DialogServiceState, request: DialogRequest): void {\n const parent = state.inFlight[state.inFlight.length - 1]\n\n if (parent) {\n request.nested = true\n const parentIndex = state.queue.findIndex(item => item.id === parent.id)\n state.queue.splice(parentIndex + 1, 0, request)\n return\n }\n\n const visibleCount = visibleDialogRequests(state).length\n const insertAt = state.queue.findIndex(\n (item, index) => index >= visibleCount && item.priority < request.priority,\n )\n\n if (insertAt < 0)\n state.queue.push(request)\n else\n state.queue.splice(insertAt, 0, request)\n}\n\n/**\n * Заявка входит в «полёт»: пока её `onConfirm` не вернулся, новые вызовы\n * считаются вложенными в неё.\n */\nexport function startDialogInFlight(state: DialogServiceState, request: DialogRequest): void {\n state.inFlight.push(request)\n}\n\n/** Заявка вышла из полёта (колбэк вернулся или окно размонтировано). */\nexport function finishDialogInFlight(state: DialogServiceState, request: DialogRequest): void {\n const index = state.inFlight.indexOf(request)\n if (index >= 0)\n state.inFlight.splice(index, 1)\n}\n\n/**\n * Единственный способ завершить заявку: идемпотентно резолвит промис и снимает\n * её из очереди.\n *\n * `removeFromQueue: false` нужен окну: оно гасит себя и даёт анимации закрытия\n * доиграть, прежде чем заявка исчезнет из очереди. Корректность от этой\n * отсрочки не зависит: повторное завершение отсекается флагом на заявке.\n */\nexport function settleDialogRequest(\n state: DialogServiceState,\n request: DialogRequest,\n result: DialogResult<any>,\n { removeFromQueue = true }: { removeFromQueue?: boolean } = {},\n): boolean {\n if (request.settled)\n return false\n\n request.settled = true\n request.resolve(result)\n\n if (removeFromQueue)\n removeDialogRequest(state, request)\n\n return true\n}\n\n/** Снимает заявку из очереди, если она ещё там. */\nexport function removeDialogRequest(state: DialogServiceState, request: DialogRequest): void {\n const index = state.queue.findIndex(item => item.id === request.id)\n if (index >= 0)\n state.queue.splice(index, 1)\n}\n","import { createVNode, getCurrentInstance, inject, markRaw, render } from 'vue'\nimport type { App, AppContext, InjectionKey } from 'vue'\n\nimport { ensurePortalRoot } from '../../composables/internal/portalRoot'\nimport GrDialogServiceHost from './GrDialogServiceHost.vue'\nimport { useGrConfig } from '../GrConfigProvider/context'\nimport { resolveGranularityI18n } from '../../internal/granularityI18n'\nimport {\n createDialogServiceState,\n enqueueDialogRequest,\n makeDialogId,\n settleDialogRequest,\n} from './store'\nimport type { CapturedDialogContext, DialogRequest, DialogServiceState } from './store'\nimport type {\n DialogAlertOptions,\n DialogBaseOptions,\n DialogConfirmOptions,\n DialogKind,\n DialogOnConfirm,\n DialogPromise,\n DialogPromptOptions,\n DialogResult,\n DialogService,\n DialogServiceDefaults,\n} from './types'\n\n/**\n * `useDialogService` — императивный сервис диалогов (в духе Element Plus\n * `ElMessageBox`). Позволяет вызывать `confirm`/`alert`/`prompt` из `<script>`\n * или `.ts` без вставки компонента в шаблон.\n *\n * Поверх существующих `GrConfirmDialog`/`GrPromptDialog`: лениво монтирует\n * единый хост (`GrDialogServiceHost`) в `document.body`, наследуя контекст\n * приложения (i18n / тема / `granular-provider`).\n */\n\n/** Ключ provide/inject для app-scoped состояния сервиса (устанавливает плагин ниже). */\nexport const GRANULARITY_DIALOG_SERVICE_STATE: InjectionKey<DialogServiceState>\n = Symbol.for('@feugene/granularity/dialog-service-state')\n\n/**\n * Инстансы, заведённые плагином. Реестр нужен готовому синглтону\n * `dialogService`: он создаётся на импорте модуля, где `inject` не работает\n * вовсе, и сам до app-scoped состояния не дотянется. Ровно один\n * зарегистрированный — ответ однозначен; несколько — выбирать за пользователя\n * нечего, и он получает предупреждение с модульным фолбэком.\n */\nconst registeredStates = new Set<DialogServiceState>()\n\n/**\n * Vue-плагин: даёт каждому приложению собственное состояние сервиса и снимает\n * его хост вместе с приложением. Обязателен для нескольких Vue-приложений на\n * одной странице (микрофронтенды — иначе они делят одну очередь и один хост) и\n * для HMR, где контейнер прошлого приложения иначе остаётся в `document.body`.\n *\n * ```ts\n * app.use(granularityDialogServicePlugin)\n * ```\n */\nexport const granularityDialogServicePlugin = {\n install(app: App) {\n const state = createDialogServiceState()\n\n app.provide(GRANULARITY_DIALOG_SERVICE_STATE, state)\n registeredStates.add(state)\n\n app.onUnmount(() => {\n teardownDialogServiceState(state)\n registeredStates.delete(state)\n })\n },\n}\n\n// Ленивый модульный фолбэк — канонический вариант для простого SPA без плагина.\nlet moduleState: DialogServiceState | null = null\n\nfunction getModuleState(): DialogServiceState {\n if (!moduleState)\n moduleState = createDialogServiceState()\n\n return moduleState\n}\n\nlet ambiguousStateWarned = false\n\nfunction warnAmbiguousState(): void {\n if (ambiguousStateWarned)\n return\n if (!__GR_DEV__)\n return\n\n ambiguousStateWarned = true\n console.warn(\n '[granularity] useDialogService: плагин установлен в нескольких приложениях, '\n + 'а сервис запрошен вне `setup` — какое из них имелось в виду, знать неоткуда. '\n + 'Используется модульное состояние. Вызовите `useDialogService()` внутри `setup` нужного приложения.',\n )\n}\n\n/**\n * Состояние текущего вызова: app-scoped (плагин) → единственный\n * зарегистрированный инстанс → модульный фолбэк.\n */\nfunction resolveDialogServiceState(): DialogServiceState {\n // `inject` работает только в `setup` — там ответ точный.\n if (getCurrentInstance()) {\n const provided = inject(GRANULARITY_DIALOG_SERVICE_STATE, null)\n if (provided)\n return provided\n }\n\n if (registeredStates.size === 1)\n return registeredStates.values().next().value!\n\n if (registeredStates.size > 1)\n warnAmbiguousState()\n\n return getModuleState()\n}\n\nfunction ensureMounted(state: DialogServiceState, appContext?: AppContext | null): void {\n if (typeof window === 'undefined' || typeof document === 'undefined')\n return\n\n if (appContext)\n state.appContext = appContext\n if (state.mounted)\n return\n\n const container = document.createElement('div')\n container.setAttribute('data-gr-dialog-service-host', '')\n container.setAttribute('data-gr-overlay-root', '')\n // Хост уезжает в общий портал оверлеев: он должен лежать в той же ветке, что\n // и остальные слои, иначе правило `inert` пометит его вместе со страницей.\n ;(ensurePortalRoot() ?? document.body).appendChild(container)\n state.container = container\n\n // Состояние отдаём пропом: хост монтируется вне дерева и своим `inject` до\n // app-scoped состояния не дотянулся бы. `markRaw` — чтобы Vue не пытался\n // сделать реактивной саму обёртку: реактивна очередь внутри неё.\n const vnode = createVNode(GrDialogServiceHost, { state: markRaw(state) })\n vnode.appContext = state.appContext ?? null\n render(vnode, container)\n state.mounted = true\n}\n\nfunction warnIfContextless(state: DialogServiceState, context: CapturedDialogContext | null): void {\n if (state.contextlessWarned || context?.config || context?.i18n)\n return\n if (!__GR_DEV__)\n return\n\n state.contextlessWarned = true\n console.warn(\n '[granularity] useDialogService: диалог открыт без контекста приложения — '\n + 'ни `GrConfigProvider`, ни адаптер i18n не найдены, будут использованы дефолты. '\n + 'Вызовите `useDialogService()` внутри `setup` хотя бы один раз или передайте `setAppContext`.',\n )\n}\n\n/** Снимает смонтированный хост и сбрасывает захваченный контекст одного инстанса. */\nfunction teardownDialogServiceState(state: DialogServiceState): void {\n if (state.container) {\n render(null, state.container)\n state.container.remove()\n state.container = null\n }\n state.mounted = false\n // Сбрасываем и кэш контекста приложения: без этого он переживает teardown и\n // протекает в следующее приложение (в тестах — в следующий тест), из-за чего\n // диалог может подхватить чужие provides и проверка соврёт.\n state.appContext = null\n state.lastCapturedContext = null\n state.contextlessWarned = false\n state.queue.splice(0, state.queue.length)\n state.inFlight.splice(0, state.inFlight.length)\n}\n\n/**\n * Тестовая/служебная очистка смонтированного хоста. Работает над тем же\n * состоянием, что и сам сервис: app-scoped при вызове из `setup` или при\n * единственном зарегистрированном приложении, иначе — модульным.\n */\nexport function teardownDialogService(): void {\n teardownDialogServiceState(resolveDialogServiceState())\n}\n\nfunction enqueue(\n state: DialogServiceState,\n kind: DialogKind,\n message: string,\n options: DialogBaseOptions,\n onConfirm: DialogOnConfirm<any> | undefined,\n captured: CapturedDialogContext,\n): { promise: Promise<DialogResult<any>>, close: () => void } {\n // Императивный сервис клиент-only: монтирует хост в `document.body`. В SSR\n // выполнять его нельзя — очередь мутировалась бы на сервере и текла между\n // запросами. Явно запрещаем вместо тихого no-op.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error(\n '[granularity] useDialogService is client-only and cannot be called during SSR '\n + '(it mounts a host into document.body). Guard imperative dialog calls behind a client-side check.',\n )\n }\n\n ensureMounted(state, options.appContext ?? state.appContext)\n\n const id = makeDialogId()\n let resolveFn!: (result: DialogResult<any>) => void\n const promise = new Promise<DialogResult<any>>((resolve) => {\n resolveFn = resolve\n })\n\n // Синглтон `dialogService` создаётся на импорте модуля, вне `setup`, и своего\n // контекста не имеет в принципе. Берём последний захваченный — иначе такие\n // вызовы навсегда остаются без i18n и без `GrConfigProvider`.\n const context = captured.config || captured.i18n ? captured : state.lastCapturedContext\n warnIfContextless(state, context)\n\n const request: DialogRequest = {\n id,\n kind,\n message,\n options: { ...options, message },\n onConfirm,\n priority: options.priority ?? 0,\n nested: false,\n settled: false,\n resolve: resolveFn,\n config: context?.config ?? null,\n i18n: context?.i18n ?? null,\n }\n\n enqueueDialogRequest(state, request)\n\n // Закрытие через промис идёт тем же путём, что и кнопка в окне: заявка сама\n // знает, завершена ли она, а окно по её исчезновению свернёт всё, что под неё\n // заведено (в т.ч. оборвёт in-flight `onConfirm` через `abort()`).\n const close = (): void => {\n settleDialogRequest(state, request, { action: 'close' })\n }\n\n return { promise, close }\n}\n\nfunction withClose<T>(promise: Promise<T>, close: () => void): DialogPromise<T> {\n const result = promise as DialogPromise<T>\n result.close = close\n return result\n}\n\nfunction mergeErrorDefaults(\n defaults: DialogServiceDefaults,\n options: DialogBaseOptions,\n): DialogBaseOptions & Pick<DialogConfirmOptions, 'cancelText'> {\n return {\n size: defaults.size,\n confirmText: defaults.confirmText,\n confirmVariant: defaults.confirmVariant,\n confirmTone: defaults.confirmTone,\n cancelText: defaults.cancelText,\n buttonSize: defaults.buttonSize,\n closeOnBackdrop: defaults.closeOnBackdrop,\n closeOnEsc: defaults.closeOnEsc,\n errorParsers: defaults.errorParsers,\n errorTexts: defaults.errorTexts,\n errorMessageKey: defaults.errorMessageKey,\n fieldLabels: defaults.fieldLabels,\n ...options,\n }\n}\n\n/**\n * Создаёт сервис диалогов. Опциональные `defaults` применяются ко всем\n * вызовам (можно переопределить в каждом конкретном вызове).\n *\n * Контекст приложения кэшируется автоматически при первом вызове внутри\n * `setup`. Для вызовов вне компонента используйте `setAppContext`.\n */\nexport function useDialogService(defaults: DialogServiceDefaults = {}): DialogService {\n const state = resolveDialogServiceState()\n\n // Авто-кэш appContext из текущего компонента (если вызвано в setup).\n const instance = getCurrentInstance()\n if (instance?.appContext && !state.appContext) {\n state.appContext = instance.appContext\n }\n\n // Конфиг и i18n захватываем здесь и только здесь: `inject` работает лишь в\n // `setup`, а хост монтируется вне дерева и сам до провайдера не дотянется.\n // Храним в замыкании сервиса, а не в состоянии, — иначе два поддерева с\n // разными провайдерами делили бы конфиг первого.\n // i18n захватываем не «на всякий случай»: дочерний `GrConfirmDialog` сам зовёт\n // `useGranularityTranslations()`, но его `inject` из хоста уходит в\n // `appContext.provides` — то есть видит только установку через `app.use()`.\n // Адаптер, переданный пропом `<GrConfigProvider i18n>`, живёт в дереве, и без\n // захвата диалог откатился бы на встроенные английские строки.\n //\n // `markRaw` — потому что дальше контекст ложится в `reactive`-очередь, а она\n // разворачивает вложенные рефы (см. комментарий в `store.ts`).\n const capturedI18n = instance ? resolveGranularityI18n() : null\n const captured: CapturedDialogContext = {\n config: instance ? markRaw(useGrConfig()) : null,\n i18n: capturedI18n ? markRaw(capturedI18n) : null,\n }\n\n if (captured.config || captured.i18n)\n state.lastCapturedContext = captured\n\n function confirm(message: string, options: DialogConfirmOptions = {}): DialogPromise<boolean> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(state, 'confirm', message, merged, options.onConfirm, captured)\n return withClose(promise.then(r => r.action === 'confirm'), close)\n }\n\n function alert(message: string, options: DialogAlertOptions = {}): DialogPromise<void> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(state, 'alert', message, merged, options.onConfirm, captured)\n return withClose(promise.then(() => undefined), close)\n }\n\n function prompt(message: string, options: DialogPromptOptions = {}): DialogPromise<string | null> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(state, 'prompt', message, merged, options.onConfirm, captured)\n return withClose(\n promise.then(r => (r.action === 'confirm' ? ((r.value as string) ?? '') : null)),\n close,\n )\n }\n\n function open<V = unknown>(\n kind: DialogKind,\n message: string,\n options: DialogBaseOptions = {},\n ): DialogPromise<DialogResult<V>> {\n const merged = mergeErrorDefaults(defaults, options)\n const { promise, close } = enqueue(\n state,\n kind,\n message,\n merged,\n (options as DialogConfirmOptions).onConfirm,\n captured,\n )\n return withClose(promise as Promise<DialogResult<V>>, close)\n }\n\n // Порядок разбора — FIFO, как и порядок показа: `pop()` резолвил промисы\n // задом наперёд, и вызывающий получал результаты в обратном порядке.\n function closeAll(): void {\n for (const request of [...state.queue])\n settleDialogRequest(state, request, { action: 'close' })\n }\n\n function setAppContext(ctx: AppContext | null): void {\n state.appContext = ctx\n }\n\n return { confirm, alert, prompt, open, closeAll, setAppContext }\n}\n\n/** Готовый синглтон-сервис с дефолтными настройками. */\nexport const dialogService: DialogService = {\n confirm: (message, options) => useDialogService().confirm(message, options),\n alert: (message, options) => useDialogService().alert(message, options),\n prompt: (message, options) => useDialogService().prompt(message, options),\n open: (kind, message, options) => useDialogService().open(kind, message, options),\n closeAll: () => useDialogService().closeAll(),\n setAppContext: ctx => useDialogService().setAppContext(ctx),\n}\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceItem — одно окно императивного сервиса. Внутренний компонент,\n * в шаблонах напрямую не используется.\n *\n * Всё состояние живёт здесь, а не на хосте, ровно потому, что окон может быть\n * несколько: вложенный вызов из `onConfirm` показывается поверх родителя, и\n * общий `loading` с общей ошибкой означали бы, что верхнее окно пишет в нижнее.\n */\nimport { computed, inject, nextTick, onBeforeUnmount, onMounted, provide, ref, shallowRef } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrConfirmDialog from '../GrConfirmDialog/GrConfirmDialog.vue'\nimport GrPromptDialog from '../GrPromptDialog/GrPromptDialog.vue'\nimport {\n coreResponseErrorParsers,\n createResponseErrorClassifier,\n responseErrorParserPresets,\n} from '../GrResponseErrorBanner/parsers'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\nimport { GR_CONFIG_KEY, type GrComponentDefaults, type GrConfigContext } from '../GrConfigProvider/context'\nimport { GRANULARITY_I18N_KEY } from '../../i18n/adapter'\nimport { resolveGranularityI18n, useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { finishDialogInFlight, removeDialogRequest, settleDialogRequest, startDialogInFlight } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\nimport type { DialogCloseAction, DialogConfirmContext, DialogConfirmOptions, DialogPromptOptions } from './types'\n\nconst props = defineProps<{\n request: DialogRequest\n}>()\n\n// Состояние инстанса приходит через `provide` хоста, а не пропом: окно его\n// мутирует (очередь, список заявок в полёте), а мутировать проп — значит писать\n// в чужое владение.\nconst state = inject(GRANULARITY_DIALOG_SERVICE_STATE) as DialogServiceState\n\n// ————— Мост конфига и i18n.\n//\n// Окно рендерится через `render(vnode, container)` в `document.body`, то есть вне\n// дерева компонентов. Vue в этом случае берёт `provides` только из `appContext`,\n// куда попадает лишь `app.provide()` — значения от `<GrConfigProvider>` до сюда\n// не доходят. Поэтому вызов сервиса захватывает их в `setup` и кладёт в заявку,\n// а окно раздаёт вниз конфиг **своей** заявки.\nconst EMPTY_DEFAULTS: GrComponentDefaults = Object.freeze({})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, {\n size: computed(() => props.request.config?.size.value),\n componentDefaults: computed(() => props.request.config?.componentDefaults.value ?? EMPTY_DEFAULTS),\n})\n\n// i18n: тот же приём. Адаптер хоста (из `appContext`) — запасной вариант для\n// вызова без захваченного: без него установка через `app.use()` осталась бы\n// незамеченной.\nconst hostI18n = resolveGranularityI18n()\n\nprovide(GRANULARITY_I18N_KEY, {\n t: (key: string, params?: Record<string, unknown>) => {\n const adapter = props.request.i18n ?? hostI18n\n // Вернуть сам ключ — принятый в пакете сигнал «перевода нет»: потребитель\n // подставит свой fallback-текст (см. `useGranularityTranslations`).\n return adapter?.t(key, params) ?? key\n },\n get locale() {\n return (props.request.i18n ?? hostI18n)?.locale\n },\n})\n\n// Подвал alert-ветки рисуется здесь, поэтому и перевод кнопки достаётся здесь.\n// Адаптер берём тот же, что раздан вниз: собственный `provide` компонента его\n// же `inject` не видит, и `useGranularityTranslations()` без аргумента ушёл бы\n// мимо захваченного вызовом адаптера — в фолбэк из `appContext`.\nconst alertConfirmText = computed(() => {\n const { t } = useGranularityTranslations(props.request.i18n ?? hostI18n)\n return t('gr.dialog.ok', 'OK')\n})\n\nconst open = ref(false)\nconst loading = ref(false)\nconst currentError = shallowRef<ResponseErrorInfo | null>(null)\n/**\n * Ошибки по именам полей. Карта, а не одна строка: `setFieldError(field, …)`\n * обещает адресность, и обещание должно быть правдой ещё до того, как в\n * диалоге появится второе поле.\n */\nconst fieldErrors = ref<Record<string, string>>({})\nconst promptValue = ref(\n props.request.options && 'value' in props.request.options\n ? ((props.request.options as { value?: string }).value ?? '')\n : '',\n)\n\n/** Единственное поле `GrPromptDialog` называется `value`. */\nconst PROMPT_FIELD = 'value'\n\n// Одна запись — её и показываем: адрес не важен, когда адресат один.\nconst promptFieldError = computed<string | null>(() => {\n const own = fieldErrors.value[PROMPT_FIELD]\n if (own != null)\n return own\n\n const entries = Object.values(fieldErrors.value)\n return entries.length === 1 ? entries[0] : null\n})\n\nconst hasFieldError = computed(() => Object.keys(fieldErrors.value).length > 0)\n\nconst controller = new AbortController()\nlet externalAbortCleanup: (() => void) | null = null\n\nfunction buildClassifier() {\n const opts = props.request.options\n const parsers = typeof opts.errorParsers === 'function'\n ? opts.errorParsers(responseErrorParserPresets)\n : opts.errorParsers ?? coreResponseErrorParsers\n\n return createResponseErrorClassifier({\n parsers,\n texts: opts.errorTexts,\n messageKey: opts.errorMessageKey,\n })\n}\n\nonMounted(() => {\n // Внешний AbortSignal закрывает диалог как `close`.\n const sig = props.request.options.signal\n if (sig) {\n if (sig.aborted) {\n finish('close')\n return\n }\n const onAbort = () => finish('close')\n sig.addEventListener('abort', onAbort)\n externalAbortCleanup = () => sig.removeEventListener('abort', onAbort)\n }\n\n void nextTick(() => {\n open.value = true\n })\n})\n\nonBeforeUnmount(() => {\n // Снимаем всё, что заведено под заявку: подписку на внешний сигнал и свой\n // контроллер. Размонтирование — единственная точка, которую видят все три\n // пути завершения (кнопка, `close()` промиса, `closeAll()`), поэтому обрыв\n // in-flight `onConfirm` живёт именно здесь.\n externalAbortCleanup?.()\n externalAbortCleanup = null\n controller.abort()\n\n finishDialogInFlight(state, props.request)\n})\n\nfunction finish(action: DialogCloseAction, value?: unknown): void {\n // Снятие заявки из очереди откладываем на тик: окно должно успеть закрыться\n // до того, как исчезнет из разметки.\n if (!settleDialogRequest(state, props.request, { action, value }, { removeFromQueue: false }))\n return\n\n open.value = false\n void nextTick(() => removeDialogRequest(state, props.request))\n}\n\nfunction buildContext(value: unknown): DialogConfirmContext<any> & { _errorSet: () => boolean } {\n let errorSet = false\n\n const setError = (message: string | null): void => {\n if (message == null) {\n currentError.value = null\n return\n }\n errorSet = true\n currentError.value = { kind: 'unknown', message, raw: message }\n }\n\n const setFieldError = (field: string, message: string | null): void => {\n const next = { ...fieldErrors.value }\n if (message == null) {\n delete next[field]\n fieldErrors.value = next\n return\n }\n errorSet = true\n next[field] = message\n fieldErrors.value = next\n }\n\n const clearErrors = (): void => {\n currentError.value = null\n fieldErrors.value = {}\n }\n\n const setRawError = async (raw: unknown, meta?: Record<string, unknown>): Promise<ResponseErrorInfo | null> => {\n const info = await buildClassifier()(raw, meta)\n if (info.fieldErrors?.length) {\n const next = { ...fieldErrors.value }\n for (const entry of info.fieldErrors)\n next[entry.field] = entry.messages.join(' ')\n fieldErrors.value = next\n }\n currentError.value = info\n errorSet = true\n return info\n }\n\n return {\n value,\n signal: controller.signal,\n setError,\n setRawError,\n setFieldError,\n clearErrors,\n setLoading: (v: boolean) => { loading.value = v },\n close: (action: DialogCloseAction = 'close') => finish(action),\n _errorSet: () => errorSet,\n }\n}\n\nasync function handleConfirm(): Promise<void> {\n const req = props.request\n const value = req.kind === 'prompt' ? promptValue.value : undefined\n\n if (!req.onConfirm) {\n finish('confirm', value)\n return\n }\n\n currentError.value = null\n fieldErrors.value = {}\n loading.value = true\n\n const ctx = buildContext(value)\n\n // Пока колбэк в полёте, заявка считается родителем для новых вызовов: диалог,\n // открытый изнутри `onConfirm`, показывается поверх, а не встаёт в очередь за\n // тем, кто его ждёт.\n startDialogInFlight(state, req)\n\n try {\n const result = await req.onConfirm(ctx)\n // Сначала проверка «диалог ещё жив», потом запись состояния: за время\n // `await` заявку мог завершить `ctx.close()` или `closeAll()`.\n if (req.settled)\n return\n loading.value = false\n if (result === false)\n return // оставить открытым без ошибки\n if (currentError.value || hasFieldError.value || ctx._errorSet())\n return // есть ошибка — не закрывать\n finish('confirm', value)\n }\n catch (error) {\n if (req.settled)\n return\n loading.value = false\n if (!ctx._errorSet())\n await ctx.setRawError(error)\n // оставить диалог открытым с показанной ошибкой\n }\n finally {\n finishDialogInFlight(state, req)\n }\n}\n\nfunction handleCancel(): void {\n finish('cancel')\n}\n\nfunction handleModelUpdate(value: boolean): void {\n if (!value)\n finish('close')\n}\n\n// Опции веток читаются типизированно, без `as any` в шаблоне.\nconst promptOptions = computed<DialogPromptOptions>(() => props.request.options as DialogPromptOptions)\nconst confirmOptions = computed<DialogConfirmOptions>(() => props.request.options as DialogConfirmOptions)\n\n// Прокидываемые в дочерний диалог общие пропы.\nconst sharedProps = computed(() => {\n const o = props.request.options\n return {\n title: o.title,\n size: o.size,\n closeOnBackdrop: o.closeOnBackdrop,\n closeOnEsc: o.closeOnEsc,\n // Подавление «мягкого» закрытия на время `onConfirm` считает сам диалог по\n // `confirmLoading` — здесь только включаем режим, чтобы механизм жил в\n // одном месте, а не дублировался сервисом.\n persistent: true,\n showHeader: o.showHeader,\n showCloseButton: o.showCloseButton,\n headerConfig: o.headerConfig,\n footerConfig: o.footerConfig,\n bodyConfig: o.bodyConfig,\n closeLabel: o.closeLabel,\n buttonSize: o.buttonSize,\n confirmText: o.confirmText,\n confirmVariant: o.confirmVariant,\n confirmTone: o.confirmTone,\n }\n})\n\n/**\n * `alert` рисуется тем же `GrConfirmDialog`, что и `confirm`, но без кнопки\n * отмены: у сообщения нет второго исхода, и лишняя кнопка предлагала бы выбор,\n * которого нет.\n */\n</script>\n\n<template>\n <GrPromptDialog\n v-if=\"request.kind === 'prompt'\"\n v-bind=\"sharedProps\"\n v-model:value=\"promptValue\"\n :model-value=\"open\"\n :description=\"request.options.message ?? request.options.description\"\n :label=\"promptOptions.label\"\n :placeholder=\"promptOptions.placeholder\"\n :required=\"promptOptions.required ?? false\"\n :required-error-text=\"promptOptions.requiredErrorText\"\n :cancel-text=\"promptOptions.cancelText\"\n :input-type=\"promptOptions.inputType\"\n :inputmode=\"promptOptions.inputmode\"\n :maxlength=\"promptOptions.maxlength\"\n :show-count=\"promptOptions.showCount\"\n :multiline=\"promptOptions.multiline\"\n :rows=\"promptOptions.rows\"\n :autosize=\"promptOptions.autosize\"\n :rules=\"promptOptions.rules\"\n :error=\"currentError\"\n :field-error=\"promptFieldError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n\n <GrConfirmDialog\n v-else-if=\"request.kind === 'alert'\"\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n >\n <template #footer>\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton\n data-testid=\"gr-alert-confirm\"\n :variant=\"sharedProps.confirmVariant ?? 'primary'\"\n :tone=\"sharedProps.confirmTone ?? 'primary'\"\n :size=\"sharedProps.buttonSize\"\n :loading=\"loading\"\n @click=\"handleConfirm\"\n >\n {{ sharedProps.confirmText ?? alertConfirmText }}\n </GrButton>\n </div>\n </template>\n </GrConfirmDialog>\n\n <GrConfirmDialog\n v-else\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :cancel-text=\"confirmOptions.cancelText\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceItem — одно окно императивного сервиса. Внутренний компонент,\n * в шаблонах напрямую не используется.\n *\n * Всё состояние живёт здесь, а не на хосте, ровно потому, что окон может быть\n * несколько: вложенный вызов из `onConfirm` показывается поверх родителя, и\n * общий `loading` с общей ошибкой означали бы, что верхнее окно пишет в нижнее.\n */\nimport { computed, inject, nextTick, onBeforeUnmount, onMounted, provide, ref, shallowRef } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrConfirmDialog from '../GrConfirmDialog/GrConfirmDialog.vue'\nimport GrPromptDialog from '../GrPromptDialog/GrPromptDialog.vue'\nimport {\n coreResponseErrorParsers,\n createResponseErrorClassifier,\n responseErrorParserPresets,\n} from '../GrResponseErrorBanner/parsers'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\nimport { GR_CONFIG_KEY, type GrComponentDefaults, type GrConfigContext } from '../GrConfigProvider/context'\nimport { GRANULARITY_I18N_KEY } from '../../i18n/adapter'\nimport { resolveGranularityI18n, useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport { finishDialogInFlight, removeDialogRequest, settleDialogRequest, startDialogInFlight } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\nimport type { DialogCloseAction, DialogConfirmContext, DialogConfirmOptions, DialogPromptOptions } from './types'\n\nconst props = defineProps<{\n request: DialogRequest\n}>()\n\n// Состояние инстанса приходит через `provide` хоста, а не пропом: окно его\n// мутирует (очередь, список заявок в полёте), а мутировать проп — значит писать\n// в чужое владение.\nconst state = inject(GRANULARITY_DIALOG_SERVICE_STATE) as DialogServiceState\n\n// ————— Мост конфига и i18n.\n//\n// Окно рендерится через `render(vnode, container)` в `document.body`, то есть вне\n// дерева компонентов. Vue в этом случае берёт `provides` только из `appContext`,\n// куда попадает лишь `app.provide()` — значения от `<GrConfigProvider>` до сюда\n// не доходят. Поэтому вызов сервиса захватывает их в `setup` и кладёт в заявку,\n// а окно раздаёт вниз конфиг **своей** заявки.\nconst EMPTY_DEFAULTS: GrComponentDefaults = Object.freeze({})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, {\n size: computed(() => props.request.config?.size.value),\n componentDefaults: computed(() => props.request.config?.componentDefaults.value ?? EMPTY_DEFAULTS),\n})\n\n// i18n: тот же приём. Адаптер хоста (из `appContext`) — запасной вариант для\n// вызова без захваченного: без него установка через `app.use()` осталась бы\n// незамеченной.\nconst hostI18n = resolveGranularityI18n()\n\nprovide(GRANULARITY_I18N_KEY, {\n t: (key: string, params?: Record<string, unknown>) => {\n const adapter = props.request.i18n ?? hostI18n\n // Вернуть сам ключ — принятый в пакете сигнал «перевода нет»: потребитель\n // подставит свой fallback-текст (см. `useGranularityTranslations`).\n return adapter?.t(key, params) ?? key\n },\n get locale() {\n return (props.request.i18n ?? hostI18n)?.locale\n },\n})\n\n// Подвал alert-ветки рисуется здесь, поэтому и перевод кнопки достаётся здесь.\n// Адаптер берём тот же, что раздан вниз: собственный `provide` компонента его\n// же `inject` не видит, и `useGranularityTranslations()` без аргумента ушёл бы\n// мимо захваченного вызовом адаптера — в фолбэк из `appContext`.\nconst alertConfirmText = computed(() => {\n const { t } = useGranularityTranslations(props.request.i18n ?? hostI18n)\n return t('gr.dialog.ok', 'OK')\n})\n\nconst open = ref(false)\nconst loading = ref(false)\nconst currentError = shallowRef<ResponseErrorInfo | null>(null)\n/**\n * Ошибки по именам полей. Карта, а не одна строка: `setFieldError(field, …)`\n * обещает адресность, и обещание должно быть правдой ещё до того, как в\n * диалоге появится второе поле.\n */\nconst fieldErrors = ref<Record<string, string>>({})\nconst promptValue = ref(\n props.request.options && 'value' in props.request.options\n ? ((props.request.options as { value?: string }).value ?? '')\n : '',\n)\n\n/** Единственное поле `GrPromptDialog` называется `value`. */\nconst PROMPT_FIELD = 'value'\n\n// Одна запись — её и показываем: адрес не важен, когда адресат один.\nconst promptFieldError = computed<string | null>(() => {\n const own = fieldErrors.value[PROMPT_FIELD]\n if (own != null)\n return own\n\n const entries = Object.values(fieldErrors.value)\n return entries.length === 1 ? entries[0] : null\n})\n\nconst hasFieldError = computed(() => Object.keys(fieldErrors.value).length > 0)\n\nconst controller = new AbortController()\nlet externalAbortCleanup: (() => void) | null = null\n\nfunction buildClassifier() {\n const opts = props.request.options\n const parsers = typeof opts.errorParsers === 'function'\n ? opts.errorParsers(responseErrorParserPresets)\n : opts.errorParsers ?? coreResponseErrorParsers\n\n return createResponseErrorClassifier({\n parsers,\n texts: opts.errorTexts,\n messageKey: opts.errorMessageKey,\n })\n}\n\nonMounted(() => {\n // Внешний AbortSignal закрывает диалог как `close`.\n const sig = props.request.options.signal\n if (sig) {\n if (sig.aborted) {\n finish('close')\n return\n }\n const onAbort = () => finish('close')\n sig.addEventListener('abort', onAbort)\n externalAbortCleanup = () => sig.removeEventListener('abort', onAbort)\n }\n\n void nextTick(() => {\n open.value = true\n })\n})\n\nonBeforeUnmount(() => {\n // Снимаем всё, что заведено под заявку: подписку на внешний сигнал и свой\n // контроллер. Размонтирование — единственная точка, которую видят все три\n // пути завершения (кнопка, `close()` промиса, `closeAll()`), поэтому обрыв\n // in-flight `onConfirm` живёт именно здесь.\n externalAbortCleanup?.()\n externalAbortCleanup = null\n controller.abort()\n\n finishDialogInFlight(state, props.request)\n})\n\nfunction finish(action: DialogCloseAction, value?: unknown): void {\n // Снятие заявки из очереди откладываем на тик: окно должно успеть закрыться\n // до того, как исчезнет из разметки.\n if (!settleDialogRequest(state, props.request, { action, value }, { removeFromQueue: false }))\n return\n\n open.value = false\n void nextTick(() => removeDialogRequest(state, props.request))\n}\n\nfunction buildContext(value: unknown): DialogConfirmContext<any> & { _errorSet: () => boolean } {\n let errorSet = false\n\n const setError = (message: string | null): void => {\n if (message == null) {\n currentError.value = null\n return\n }\n errorSet = true\n currentError.value = { kind: 'unknown', message, raw: message }\n }\n\n const setFieldError = (field: string, message: string | null): void => {\n const next = { ...fieldErrors.value }\n if (message == null) {\n delete next[field]\n fieldErrors.value = next\n return\n }\n errorSet = true\n next[field] = message\n fieldErrors.value = next\n }\n\n const clearErrors = (): void => {\n currentError.value = null\n fieldErrors.value = {}\n }\n\n const setRawError = async (raw: unknown, meta?: Record<string, unknown>): Promise<ResponseErrorInfo | null> => {\n const info = await buildClassifier()(raw, meta)\n if (info.fieldErrors?.length) {\n const next = { ...fieldErrors.value }\n for (const entry of info.fieldErrors)\n next[entry.field] = entry.messages.join(' ')\n fieldErrors.value = next\n }\n currentError.value = info\n errorSet = true\n return info\n }\n\n return {\n value,\n signal: controller.signal,\n setError,\n setRawError,\n setFieldError,\n clearErrors,\n setLoading: (v: boolean) => { loading.value = v },\n close: (action: DialogCloseAction = 'close') => finish(action),\n _errorSet: () => errorSet,\n }\n}\n\nasync function handleConfirm(): Promise<void> {\n const req = props.request\n const value = req.kind === 'prompt' ? promptValue.value : undefined\n\n if (!req.onConfirm) {\n finish('confirm', value)\n return\n }\n\n currentError.value = null\n fieldErrors.value = {}\n loading.value = true\n\n const ctx = buildContext(value)\n\n // Пока колбэк в полёте, заявка считается родителем для новых вызовов: диалог,\n // открытый изнутри `onConfirm`, показывается поверх, а не встаёт в очередь за\n // тем, кто его ждёт.\n startDialogInFlight(state, req)\n\n try {\n const result = await req.onConfirm(ctx)\n // Сначала проверка «диалог ещё жив», потом запись состояния: за время\n // `await` заявку мог завершить `ctx.close()` или `closeAll()`.\n if (req.settled)\n return\n loading.value = false\n if (result === false)\n return // оставить открытым без ошибки\n if (currentError.value || hasFieldError.value || ctx._errorSet())\n return // есть ошибка — не закрывать\n finish('confirm', value)\n }\n catch (error) {\n if (req.settled)\n return\n loading.value = false\n if (!ctx._errorSet())\n await ctx.setRawError(error)\n // оставить диалог открытым с показанной ошибкой\n }\n finally {\n finishDialogInFlight(state, req)\n }\n}\n\nfunction handleCancel(): void {\n finish('cancel')\n}\n\nfunction handleModelUpdate(value: boolean): void {\n if (!value)\n finish('close')\n}\n\n// Опции веток читаются типизированно, без `as any` в шаблоне.\nconst promptOptions = computed<DialogPromptOptions>(() => props.request.options as DialogPromptOptions)\nconst confirmOptions = computed<DialogConfirmOptions>(() => props.request.options as DialogConfirmOptions)\n\n// Прокидываемые в дочерний диалог общие пропы.\nconst sharedProps = computed(() => {\n const o = props.request.options\n return {\n title: o.title,\n size: o.size,\n closeOnBackdrop: o.closeOnBackdrop,\n closeOnEsc: o.closeOnEsc,\n // Подавление «мягкого» закрытия на время `onConfirm` считает сам диалог по\n // `confirmLoading` — здесь только включаем режим, чтобы механизм жил в\n // одном месте, а не дублировался сервисом.\n persistent: true,\n showHeader: o.showHeader,\n showCloseButton: o.showCloseButton,\n headerConfig: o.headerConfig,\n footerConfig: o.footerConfig,\n bodyConfig: o.bodyConfig,\n closeLabel: o.closeLabel,\n buttonSize: o.buttonSize,\n confirmText: o.confirmText,\n confirmVariant: o.confirmVariant,\n confirmTone: o.confirmTone,\n }\n})\n\n/**\n * `alert` рисуется тем же `GrConfirmDialog`, что и `confirm`, но без кнопки\n * отмены: у сообщения нет второго исхода, и лишняя кнопка предлагала бы выбор,\n * которого нет.\n */\n</script>\n\n<template>\n <GrPromptDialog\n v-if=\"request.kind === 'prompt'\"\n v-bind=\"sharedProps\"\n v-model:value=\"promptValue\"\n :model-value=\"open\"\n :description=\"request.options.message ?? request.options.description\"\n :label=\"promptOptions.label\"\n :placeholder=\"promptOptions.placeholder\"\n :required=\"promptOptions.required ?? false\"\n :required-error-text=\"promptOptions.requiredErrorText\"\n :cancel-text=\"promptOptions.cancelText\"\n :input-type=\"promptOptions.inputType\"\n :inputmode=\"promptOptions.inputmode\"\n :maxlength=\"promptOptions.maxlength\"\n :show-count=\"promptOptions.showCount\"\n :multiline=\"promptOptions.multiline\"\n :rows=\"promptOptions.rows\"\n :autosize=\"promptOptions.autosize\"\n :rules=\"promptOptions.rules\"\n :error=\"currentError\"\n :field-error=\"promptFieldError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n\n <GrConfirmDialog\n v-else-if=\"request.kind === 'alert'\"\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n >\n <template #footer>\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton\n data-testid=\"gr-alert-confirm\"\n :variant=\"sharedProps.confirmVariant ?? 'primary'\"\n :tone=\"sharedProps.confirmTone ?? 'primary'\"\n :size=\"sharedProps.buttonSize\"\n :loading=\"loading\"\n @click=\"handleConfirm\"\n >\n {{ sharedProps.confirmText ?? alertConfirmText }}\n </GrButton>\n </div>\n </template>\n </GrConfirmDialog>\n\n <GrConfirmDialog\n v-else\n :model-value=\"open\"\n v-bind=\"sharedProps\"\n :description=\"request.options.message ?? request.options.description\"\n :cancel-text=\"confirmOptions.cancelText\"\n :error=\"currentError\"\n :confirm-loading=\"loading\"\n :close-on-confirm=\"false\"\n @update:model-value=\"handleModelUpdate\"\n @confirm=\"handleConfirm\"\n @cancel=\"handleCancel\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceHost — внутренний компонент-оркестратор императивного\n * `useDialogService`. Не предназначен для прямого использования в шаблонах.\n *\n * Держит раскладку очереди и ничего больше: состояние каждой заявки — загрузка,\n * ошибки, введённое значение, мост конфига и i18n — живёт в\n * `GrDialogServiceItem`, потому что окон может быть несколько.\n *\n * Видимы голова очереди и её вложенные окна (`store.visibleDialogRequests`):\n * обычные вызовы по-прежнему показываются по одному, а диалог, открытый из\n * `onConfirm` другого диалога, ложится поверх родителя — иначе он ждал бы в\n * очереди того, кто ждёт его.\n */\nimport { computed, inject, provide } from 'vue'\n\nimport GrDialogServiceItem from './GrDialogServiceItem.vue'\nimport { visibleDialogRequests } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\n\nexport interface GrDialogServiceHostProps {\n /**\n * Состояние инстанса сервиса. Приходит пропом при программном монтировании:\n * хост живёт вне дерева и своим `inject` до app-scoped состояния не дотянулся\n * бы. `inject` остаётся для случая, когда хост поставили в шаблон руками.\n */\n state?: DialogServiceState | null\n}\n\nconst props = defineProps<GrDialogServiceHostProps>()\n\nconst injected = inject(GRANULARITY_DIALOG_SERVICE_STATE, null)\n\nconst activeState = computed<DialogServiceState | null>(() => props.state ?? injected)\n\nconst visible = computed<DialogRequest[]>(() =>\n activeState.value ? visibleDialogRequests(activeState.value) : [],\n)\n\n// Окна берут состояние отсюда, а не пропом: они его мутируют (очередь, список\n// заявок в полёте), а мутировать проп — значит писать в чужое владение.\nprovide(GRANULARITY_DIALOG_SERVICE_STATE, activeState.value!)\n</script>\n\n<template>\n <GrDialogServiceItem\n v-for=\"request in visible\"\n :key=\"request.id\"\n :request=\"request\"\n />\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrDialogServiceHost — внутренний компонент-оркестратор императивного\n * `useDialogService`. Не предназначен для прямого использования в шаблонах.\n *\n * Держит раскладку очереди и ничего больше: состояние каждой заявки — загрузка,\n * ошибки, введённое значение, мост конфига и i18n — живёт в\n * `GrDialogServiceItem`, потому что окон может быть несколько.\n *\n * Видимы голова очереди и её вложенные окна (`store.visibleDialogRequests`):\n * обычные вызовы по-прежнему показываются по одному, а диалог, открытый из\n * `onConfirm` другого диалога, ложится поверх родителя — иначе он ждал бы в\n * очереди того, кто ждёт его.\n */\nimport { computed, inject, provide } from 'vue'\n\nimport GrDialogServiceItem from './GrDialogServiceItem.vue'\nimport { visibleDialogRequests } from './store'\nimport type { DialogRequest, DialogServiceState } from './store'\nimport { GRANULARITY_DIALOG_SERVICE_STATE } from './useDialogService'\n\nexport interface GrDialogServiceHostProps {\n /**\n * Состояние инстанса сервиса. Приходит пропом при программном монтировании:\n * хост живёт вне дерева и своим `inject` до app-scoped состояния не дотянулся\n * бы. `inject` остаётся для случая, когда хост поставили в шаблон руками.\n */\n state?: DialogServiceState | null\n}\n\nconst props = defineProps<GrDialogServiceHostProps>()\n\nconst injected = inject(GRANULARITY_DIALOG_SERVICE_STATE, null)\n\nconst activeState = computed<DialogServiceState | null>(() => props.state ?? injected)\n\nconst visible = computed<DialogRequest[]>(() =>\n activeState.value ? visibleDialogRequests(activeState.value) : [],\n)\n\n// Окна берут состояние отсюда, а не пропом: они его мутируют (очередь, список\n// заявок в полёте), а мутировать проп — значит писать в чужое владение.\nprovide(GRANULARITY_DIALOG_SERVICE_STATE, activeState.value!)\n</script>\n\n<template>\n <GrDialogServiceItem\n v-for=\"request in visible\"\n :key=\"request.id\"\n :request=\"request\"\n />\n</template>\n"],"mappings":";;;;;;;;;;AAsFA,SAAgB,2BAA+C;CAC7D,OAAO;EACL,OAAO,SAA0B,CAAC,CAAC;EACnC,SAAS;EACT,WAAW;EACX,YAAY;EACZ,qBAAqB;EACrB,mBAAmB;EACnB,UAAU,CAAC;CACb;AACF;AAEA,IAAI,UAAU;AAEd,SAAgB,eAAuB;CACrC,WAAW;CACX,OAAO,aAAa,KAAK,IAAI,EAAE,GAAG;AACpC;;;;;;AAOA,SAAgB,sBAAsB,OAA4C;CAChF,MAAM,UAA2B,CAAC;CAElC,KAAK,MAAM,WAAW,MAAM,OAC1B,IAAI,QAAQ,WAAW,KAAK,QAAQ,QAClC,QAAQ,KAAK,OAAO;MAEpB;CAGJ,OAAO;AACT;;;;;;;;;AAUA,SAAgB,qBAAqB,OAA2B,SAA8B;CAC5F,MAAM,SAAS,MAAM,SAAS,MAAM,SAAS,SAAS;CAEtD,IAAI,QAAQ;EACV,QAAQ,SAAS;EACjB,MAAM,cAAc,MAAM,MAAM,WAAU,SAAQ,KAAK,OAAO,OAAO,EAAE;EACvE,MAAM,MAAM,OAAO,cAAc,GAAG,GAAG,OAAO;EAC9C;CACF;CAEA,MAAM,eAAe,sBAAsB,KAAK,CAAC,CAAC;CAClD,MAAM,WAAW,MAAM,MAAM,WAC1B,MAAM,UAAU,SAAS,gBAAgB,KAAK,WAAW,QAAQ,QACpE;CAEA,IAAI,WAAW,GACb,MAAM,MAAM,KAAK,OAAO;MAExB,MAAM,MAAM,OAAO,UAAU,GAAG,OAAO;AAC3C;;;;;AAMA,SAAgB,oBAAoB,OAA2B,SAA8B;CAC3F,MAAM,SAAS,KAAK,OAAO;AAC7B;;AAGA,SAAgB,qBAAqB,OAA2B,SAA8B;CAC5F,MAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO;CAC5C,IAAI,SAAS,GACX,MAAM,SAAS,OAAO,OAAO,CAAC;AAClC;;;;;;;;;AAUA,SAAgB,oBACd,OACA,SACA,QACA,EAAE,kBAAkB,SAAwC,CAAC,GACpD;CACT,IAAI,QAAQ,SACV,OAAO;CAET,QAAQ,UAAU;CAClB,QAAQ,QAAQ,MAAM;CAEtB,IAAI,iBACF,oBAAoB,OAAO,OAAO;CAEpC,OAAO;AACT;;AAGA,SAAgB,oBAAoB,OAA2B,SAA8B;CAC3F,MAAM,QAAQ,MAAM,MAAM,WAAU,SAAQ,KAAK,OAAO,QAAQ,EAAE;CAClE,IAAI,SAAS,GACX,MAAM,MAAM,OAAO,OAAO,CAAC;AAC/B;;;;;;;;;;;;;AChKA,IAAa,mCACT,OAAO,IAAI,2CAA2C;;;;;;;;AAS1D,IAAM,mCAAmB,IAAI,IAAwB;;;;;;;;;;;AAYrD,IAAa,iCAAiC,EAC5C,QAAQ,KAAU;CAChB,MAAM,QAAQ,yBAAyB;CAEvC,IAAI,QAAQ,kCAAkC,KAAK;CACnD,iBAAiB,IAAI,KAAK;CAE1B,IAAI,gBAAgB;EAClB,2BAA2B,KAAK;EAChC,iBAAiB,OAAO,KAAK;CAC/B,CAAC;AACH,EACF;AAGA,IAAI,cAAyC;AAE7C,SAAS,iBAAqC;CAC5C,IAAI,CAAC,aACH,cAAc,yBAAyB;CAEzC,OAAO;AACT;AAEA,IAAI,uBAAuB;AAE3B,SAAS,qBAA2B;CAClC,IAAI,sBACF;CACF,IAAI,EAAA,QAAA,IAAA,aAAA,eACF;CAEF,uBAAuB;CACvB,QAAQ,KACN,6PAGF;AACF;;;;;AAMA,SAAS,4BAAgD;CAEvD,IAAI,mBAAmB,GAAG;EACxB,MAAM,WAAW,OAAO,kCAAkC,IAAI;EAC9D,IAAI,UACF,OAAO;CACX;CAEA,IAAI,iBAAiB,SAAS,GAC5B,OAAO,iBAAiB,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC;CAE1C,IAAI,iBAAiB,OAAO,GAC1B,mBAAmB;CAErB,OAAO,eAAe;AACxB;AAEA,SAAS,cAAc,OAA2B,YAAsC;CACtF,IAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aACvD;CAEF,IAAI,YACF,MAAM,aAAa;CACrB,IAAI,MAAM,SACR;CAEF,MAAM,YAAY,SAAS,cAAc,KAAK;CAC9C,UAAU,aAAa,+BAA+B,EAAE;CACxD,UAAU,aAAa,wBAAwB,EAAE;CAGhD,CAAC,iBAAiB,KAAK,SAAS,KAAA,CAAM,YAAY,SAAS;CAC5D,MAAM,YAAY;CAKlB,MAAM,QAAQ,YAAY,6BAAqB,EAAE,OAAO,QAAQ,KAAK,EAAE,CAAC;CACxE,MAAM,aAAa,MAAM,cAAc;CACvC,OAAO,OAAO,SAAS;CACvB,MAAM,UAAU;AAClB;AAEA,SAAS,kBAAkB,OAA2B,SAA6C;CACjG,IAAI,MAAM,qBAAqB,SAAS,UAAU,SAAS,MACzD;CACF,IAAI,EAAA,QAAA,IAAA,aAAA,eACF;CAEF,MAAM,oBAAoB;CAC1B,QAAQ,KACN,sPAGF;AACF;;AAGA,SAAS,2BAA2B,OAAiC;CACnE,IAAI,MAAM,WAAW;EACnB,OAAO,MAAM,MAAM,SAAS;EAC5B,MAAM,UAAU,OAAO;EACvB,MAAM,YAAY;CACpB;CACA,MAAM,UAAU;CAIhB,MAAM,aAAa;CACnB,MAAM,sBAAsB;CAC5B,MAAM,oBAAoB;CAC1B,MAAM,MAAM,OAAO,GAAG,MAAM,MAAM,MAAM;CACxC,MAAM,SAAS,OAAO,GAAG,MAAM,SAAS,MAAM;AAChD;;;;;;AAOA,SAAgB,wBAA8B;CAC5C,2BAA2B,0BAA0B,CAAC;AACxD;AAEA,SAAS,QACP,OACA,MACA,SACA,SACA,WACA,UAC4D;CAI5D,IAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aACvD,MAAM,IAAI,MACR,gLAEF;CAGF,cAAc,OAAO,QAAQ,cAAc,MAAM,UAAU;CAE3D,MAAM,KAAK,aAAa;CACxB,IAAI;CACJ,MAAM,UAAU,IAAI,SAA4B,YAAY;EAC1D,YAAY;CACd,CAAC;CAKD,MAAM,UAAU,SAAS,UAAU,SAAS,OAAO,WAAW,MAAM;CACpE,kBAAkB,OAAO,OAAO;CAEhC,MAAM,UAAyB;EAC7B;EACA;EACA;EACA,SAAS;GAAE,GAAG;GAAS;EAAQ;EAC/B;EACA,UAAU,QAAQ,YAAY;EAC9B,QAAQ;EACR,SAAS;EACT,SAAS;EACT,QAAQ,SAAS,UAAU;EAC3B,MAAM,SAAS,QAAQ;CACzB;CAEA,qBAAqB,OAAO,OAAO;CAKnC,MAAM,cAAoB;EACxB,oBAAoB,OAAO,SAAS,EAAE,QAAQ,QAAQ,CAAC;CACzD;CAEA,OAAO;EAAE;EAAS;CAAM;AAC1B;AAEA,SAAS,UAAa,SAAqB,OAAqC;CAC9E,MAAM,SAAS;CACf,OAAO,QAAQ;CACf,OAAO;AACT;AAEA,SAAS,mBACP,UACA,SAC8D;CAC9D,OAAO;EACL,MAAM,SAAS;EACf,aAAa,SAAS;EACtB,gBAAgB,SAAS;EACzB,aAAa,SAAS;EACtB,YAAY,SAAS;EACrB,YAAY,SAAS;EACrB,iBAAiB,SAAS;EAC1B,YAAY,SAAS;EACrB,cAAc,SAAS;EACvB,YAAY,SAAS;EACrB,iBAAiB,SAAS;EAC1B,aAAa,SAAS;EACtB,GAAG;CACL;AACF;;;;;;;;AASA,SAAgB,iBAAiB,WAAkC,CAAC,GAAkB;CACpF,MAAM,QAAQ,0BAA0B;CAGxC,MAAM,WAAW,mBAAmB;CACpC,IAAI,UAAU,cAAc,CAAC,MAAM,YACjC,MAAM,aAAa,SAAS;CAe9B,MAAM,eAAe,WAAW,uBAAuB,IAAI;CAC3D,MAAM,WAAkC;EACtC,QAAQ,WAAW,QAAQ,YAAY,CAAC,IAAI;EAC5C,MAAM,eAAe,QAAQ,YAAY,IAAI;CAC/C;CAEA,IAAI,SAAS,UAAU,SAAS,MAC9B,MAAM,sBAAsB;CAE9B,SAAS,QAAQ,SAAiB,UAAgC,CAAC,GAA2B;EAC5F,MAAM,SAAS,mBAAmB,UAAU,OAAO;EACnD,MAAM,EAAE,SAAS,UAAU,QAAQ,OAAO,WAAW,SAAS,QAAQ,QAAQ,WAAW,QAAQ;EACjG,OAAO,UAAU,QAAQ,MAAK,MAAK,EAAE,WAAW,SAAS,GAAG,KAAK;CACnE;CAEA,SAAS,MAAM,SAAiB,UAA8B,CAAC,GAAwB;EACrF,MAAM,SAAS,mBAAmB,UAAU,OAAO;EACnD,MAAM,EAAE,SAAS,UAAU,QAAQ,OAAO,SAAS,SAAS,QAAQ,QAAQ,WAAW,QAAQ;EAC/F,OAAO,UAAU,QAAQ,WAAW,KAAA,CAAS,GAAG,KAAK;CACvD;CAEA,SAAS,OAAO,SAAiB,UAA+B,CAAC,GAAiC;EAChG,MAAM,SAAS,mBAAmB,UAAU,OAAO;EACnD,MAAM,EAAE,SAAS,UAAU,QAAQ,OAAO,UAAU,SAAS,QAAQ,QAAQ,WAAW,QAAQ;EAChG,OAAO,UACL,QAAQ,MAAK,MAAM,EAAE,WAAW,YAAc,EAAE,SAAoB,KAAM,IAAK,GAC/E,KACF;CACF;CAEA,SAAS,KACP,MACA,SACA,UAA6B,CAAC,GACE;EAChC,MAAM,SAAS,mBAAmB,UAAU,OAAO;EACnD,MAAM,EAAE,SAAS,UAAU,QACzB,OACA,MACA,SACA,QACC,QAAiC,WAClC,QACF;EACA,OAAO,UAAU,SAAqC,KAAK;CAC7D;CAIA,SAAS,WAAiB;EACxB,KAAK,MAAM,WAAW,CAAC,GAAG,MAAM,KAAK,GACnC,oBAAoB,OAAO,SAAS,EAAE,QAAQ,QAAQ,CAAC;CAC3D;CAEA,SAAS,cAAc,KAA8B;EACnD,MAAM,aAAa;CACrB;CAEA,OAAO;EAAE;EAAS;EAAO;EAAQ;EAAM;EAAU;CAAc;AACjE;;AAGA,IAAa,gBAA+B;CAC1C,UAAU,SAAS,YAAY,iBAAiB,CAAC,CAAC,QAAQ,SAAS,OAAO;CAC1E,QAAQ,SAAS,YAAY,iBAAiB,CAAC,CAAC,MAAM,SAAS,OAAO;CACtE,SAAS,SAAS,YAAY,iBAAiB,CAAC,CAAC,OAAO,SAAS,OAAO;CACxE,OAAO,MAAM,SAAS,YAAY,iBAAiB,CAAC,CAAC,KAAK,MAAM,SAAS,OAAO;CAChF,gBAAgB,iBAAiB,CAAC,CAAC,SAAS;CAC5C,gBAAe,QAAO,iBAAiB,CAAC,CAAC,cAAc,GAAG;AAC5D;;;;ACnRA,IAAM,eAAe;;;;;;;;;;;;;;;EAjErB,MAAM,QAAQ;EAOd,MAAM,QAAQ,OAAO,gCAAgC;EASrD,MAAM,iBAAsC,OAAO,OAAO,CAAC,CAAC;EAE5D,QAAyB,eAAe;GACtC,MAAM,eAAe,MAAM,QAAQ,QAAQ,KAAK,KAAK;GACrD,mBAAmB,eAAe,MAAM,QAAQ,QAAQ,kBAAkB,SAAS,cAAc;EACnG,CAAC;EAKD,MAAM,WAAW,uBAAuB;EAExC,QAAQ,sBAAsB;GAC5B,IAAI,KAAa,WAAqC;IAIpD,QAHgB,MAAM,QAAQ,QAAQ,SAAA,EAGtB,EAAE,KAAK,MAAM,KAAK;GACpC;GACA,IAAI,SAAS;IACX,QAAQ,MAAM,QAAQ,QAAQ,SAAA,EAAW;GAC3C;EACF,CAAC;EAMD,MAAM,mBAAmB,eAAe;GACtC,MAAM,EAAE,MAAM,2BAA2B,MAAM,QAAQ,QAAQ,QAAQ;GACvE,OAAO,EAAE,gBAAgB,IAAI;EAC/B,CAAC;EAED,MAAM,OAAO,IAAI,KAAK;EACtB,MAAM,UAAU,IAAI,KAAK;EACzB,MAAM,eAAe,WAAqC,IAAI;;;;;;EAM9D,MAAM,cAAc,IAA4B,CAAC,CAAC;EAClD,MAAM,cAAc,IAClB,MAAM,QAAQ,WAAW,WAAW,MAAM,QAAQ,UAC5C,MAAM,QAAQ,QAA+B,SAAS,KACxD,EACN;;EAMA,MAAM,mBAAmB,eAA8B;GACrD,MAAM,MAAM,YAAY,MAAM;GAC9B,IAAI,OAAO,MACT,OAAO;GAET,MAAM,UAAU,OAAO,OAAO,YAAY,KAAK;GAC/C,OAAO,QAAQ,WAAW,IAAI,QAAQ,KAAK;EAC7C,CAAC;EAED,MAAM,gBAAgB,eAAe,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,SAAS,CAAC;EAE9E,MAAM,aAAa,IAAI,gBAAgB;EACvC,IAAI,uBAA4C;EAEhD,SAAS,kBAAkB;GACzB,MAAM,OAAO,MAAM,QAAQ;GAC3B,MAAM,UAAU,OAAO,KAAK,iBAAiB,aACzC,KAAK,aAAa,0BAA0B,IAC5C,KAAK,gBAAgB;GAEzB,OAAO,8BAA8B;IACnC;IACA,OAAO,KAAK;IACZ,YAAY,KAAK;GACnB,CAAC;EACH;EAEA,gBAAgB;GAEd,MAAM,MAAM,MAAM,QAAQ,QAAQ;GAClC,IAAI,KAAK;IACP,IAAI,IAAI,SAAS;KACf,OAAO,OAAO;KACd;IACF;IACA,MAAM,gBAAgB,OAAO,OAAO;IACpC,IAAI,iBAAiB,SAAS,OAAO;IACrC,6BAA6B,IAAI,oBAAoB,SAAS,OAAO;GACvE;GAEA,eAAoB;IAClB,KAAK,QAAQ;GACf,CAAC;EACH,CAAC;EAED,sBAAsB;GAKpB,uBAAuB;GACvB,uBAAuB;GACvB,WAAW,MAAM;GAEjB,qBAAqB,OAAO,MAAM,OAAO;EAC3C,CAAC;EAED,SAAS,OAAO,QAA2B,OAAuB;GAGhE,IAAI,CAAC,oBAAoB,OAAO,MAAM,SAAS;IAAE;IAAQ;GAAM,GAAG,EAAE,iBAAiB,MAAM,CAAC,GAC1F;GAEF,KAAK,QAAQ;GACb,eAAoB,oBAAoB,OAAO,MAAM,OAAO,CAAC;EAC/D;EAEA,SAAS,aAAa,OAA0E;GAC9F,IAAI,WAAW;GAEf,MAAM,YAAY,YAAiC;IACjD,IAAI,WAAW,MAAM;KACnB,aAAa,QAAQ;KACrB;IACF;IACA,WAAW;IACX,aAAa,QAAQ;KAAE,MAAM;KAAW;KAAS,KAAK;IAAQ;GAChE;GAEA,MAAM,iBAAiB,OAAe,YAAiC;IACrE,MAAM,OAAO,EAAE,GAAG,YAAY,MAAM;IACpC,IAAI,WAAW,MAAM;KACnB,OAAO,KAAK;KACZ,YAAY,QAAQ;KACpB;IACF;IACA,WAAW;IACX,KAAK,SAAS;IACd,YAAY,QAAQ;GACtB;GAEA,MAAM,oBAA0B;IAC9B,aAAa,QAAQ;IACrB,YAAY,QAAQ,CAAC;GACvB;GAEA,MAAM,cAAc,OAAO,KAAc,SAAsE;IAC7G,MAAM,OAAO,MAAM,gBAAgB,CAAC,CAAC,KAAK,IAAI;IAC9C,IAAI,KAAK,aAAa,QAAQ;KAC5B,MAAM,OAAO,EAAE,GAAG,YAAY,MAAM;KACpC,KAAK,MAAM,SAAS,KAAK,aACvB,KAAK,MAAM,SAAS,MAAM,SAAS,KAAK,GAAG;KAC7C,YAAY,QAAQ;IACtB;IACA,aAAa,QAAQ;IACrB,WAAW;IACX,OAAO;GACT;GAEA,OAAO;IACL;IACA,QAAQ,WAAW;IACnB;IACA;IACA;IACA;IACA,aAAa,MAAe;KAAE,QAAQ,QAAQ;IAAE;IAChD,QAAQ,SAA4B,YAAY,OAAO,MAAM;IAC7D,iBAAiB;GACnB;EACF;EAEA,eAAe,gBAA+B;GAC5C,MAAM,MAAM,MAAM;GAClB,MAAM,QAAQ,IAAI,SAAS,WAAW,YAAY,QAAQ,KAAA;GAE1D,IAAI,CAAC,IAAI,WAAW;IAClB,OAAO,WAAW,KAAK;IACvB;GACF;GAEA,aAAa,QAAQ;GACrB,YAAY,QAAQ,CAAC;GACrB,QAAQ,QAAQ;GAEhB,MAAM,MAAM,aAAa,KAAK;GAK9B,oBAAoB,OAAO,GAAG;GAE9B,IAAI;IACF,MAAM,SAAS,MAAM,IAAI,UAAU,GAAG;IAGtC,IAAI,IAAI,SACN;IACF,QAAQ,QAAQ;IAChB,IAAI,WAAW,OACb;IACF,IAAI,aAAa,SAAS,cAAc,SAAS,IAAI,UAAU,GAC7D;IACF,OAAO,WAAW,KAAK;GACzB,SACO,OAAO;IACZ,IAAI,IAAI,SACN;IACF,QAAQ,QAAQ;IAChB,IAAI,CAAC,IAAI,UAAU,GACjB,MAAM,IAAI,YAAY,KAAK;GAE/B,UACQ;IACN,qBAAqB,OAAO,GAAG;GACjC;EACF;EAEA,SAAS,eAAqB;GAC5B,OAAO,QAAQ;EACjB;EAEA,SAAS,kBAAkB,OAAsB;GAC/C,IAAI,CAAC,OACH,OAAO,OAAO;EAClB;EAGA,MAAM,gBAAgB,eAAoC,MAAM,QAAQ,OAA8B;EACtG,MAAM,iBAAiB,eAAqC,MAAM,QAAQ,OAA+B;EAGzG,MAAM,cAAc,eAAe;GACjC,MAAM,IAAI,MAAM,QAAQ;GACxB,OAAO;IACL,OAAO,EAAE;IACT,MAAM,EAAE;IACR,iBAAiB,EAAE;IACnB,YAAY,EAAE;IAId,YAAY;IACZ,YAAY,EAAE;IACd,iBAAiB,EAAE;IACnB,cAAc,EAAE;IAChB,cAAc,EAAE;IAChB,YAAY,EAAE;IACd,YAAY,EAAE;IACd,YAAY,EAAE;IACd,aAAa,EAAE;IACf,gBAAgB,EAAE;IAClB,aAAa,EAAE;GACjB;EACF,CAAC;;;;;;;GAWS,OAAA,QAAA,QAAQ,SAAI,YADpB,UAAA,GAAA,YA0BE,wBA1BF,WA0BE,EAAA,KAAA,EAAA,GAxBQ,YAAA,OAAW;IACX,OAAO,YAAA;IAAA,kBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,YAAW,QAAA;IACzB,eAAa,KAAA;IACb,aAAa,QAAA,QAAQ,QAAQ,WAAW,QAAA,QAAQ,QAAQ;IACxD,OAAO,cAAA,MAAc;IACrB,aAAa,cAAA,MAAc;IAC3B,UAAU,cAAA,MAAc,YAAQ;IAChC,uBAAqB,cAAA,MAAc;IACnC,eAAa,cAAA,MAAc;IAC3B,cAAY,cAAA,MAAc;IAC1B,WAAW,cAAA,MAAc;IACzB,WAAW,cAAA,MAAc;IACzB,cAAY,cAAA,MAAc;IAC1B,WAAW,cAAA,MAAc;IACzB,MAAM,cAAA,MAAc;IACpB,UAAU,cAAA,MAAc;IACxB,OAAO,cAAA,MAAc;IACrB,OAAO,aAAA;IACP,eAAa,iBAAA;IACb,mBAAiB,QAAA;IACjB,oBAAkB;IAClB,uBAAoB;IACpB,WAAS;IACT,UAAQ;;;;;;;;;;;;;;;;;;;;;GAIE,CAAA,KAAA,QAAA,QAAQ,SAAI,WADzB,UAAA,GAAA,YAyBkB,yBAzBlB,WAyBkB;;IAvBf,eAAa,KAAA;GACN,GAAA,YAAA,OAAW;IAClB,aAAa,QAAA,QAAQ,QAAQ,WAAW,QAAA,QAAQ,QAAQ;IACxD,OAAO,aAAA;IACP,mBAAiB,QAAA;IACjB,oBAAkB;IAClB,uBAAoB;IACpB,WAAS;;IAEC,QAAM,cAYT,CAXN,mBAWM,OAXN,YAWM,CAVJ,YASW,kBAAA;KART,eAAY;KACX,SAAS,YAAA,MAAY,kBAAc;KACnC,MAAM,YAAA,MAAY,eAAW;KAC7B,MAAM,YAAA,MAAY;KAClB,SAAS,QAAA;KACT,SAAO;;KAER,SAAA,cAAiD,CAA9C,gBAAA,gBAAA,YAAA,MAAY,eAAe,iBAAA,KAAgB,GAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;GAMtD,CAAA,MAAA,UAAA,GAAA,YAYE,yBAZF,WAYE;;IAVC,eAAa,KAAA;GACN,GAAA,YAAA,OAAW;IAClB,aAAa,QAAA,QAAQ,QAAQ,WAAW,QAAA,QAAQ,QAAQ;IACxD,eAAa,eAAA,MAAe;IAC5B,OAAO,aAAA;IACP,mBAAiB,QAAA;IACjB,oBAAkB;IAClB,uBAAoB;IACpB,WAAS;IACT,UAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EE5Vb,MAAM,QAAQ;EAEd,MAAM,WAAW,OAAO,kCAAkC,IAAI;EAE9D,MAAM,cAAc,eAA0C,MAAM,SAAS,QAAQ;EAErF,MAAM,UAAU,eACd,YAAY,QAAQ,sBAAsB,YAAY,KAAK,IAAI,CAAC,CAClE;EAIA,QAAQ,kCAAkC,YAAY,KAAM;;GAI1D,OAAA,UAAA,IAAA,GAAA,mBAIE,UAAA,MAAA,WAHkB,QAAA,QAAX,YAAO;IADhB,OAAA,UAAA,GAAA,YAIE,6BAAA;KAFC,KAAK,QAAQ;KACJ"}
@@ -1,3 +1,3 @@
1
- import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./chunks/GrDialogService-Dtq0ZCN5.js";
1
+ import { a as useDialogService, i as teardownDialogService, n as dialogService, r as granularityDialogServicePlugin, t as GrDialogServiceHost_default } from "./chunks/GrDialogService-DLBifO61.js";
2
2
  import { t as grDialogServiceConfig } from "../../chunks/config-CjXjhphs.js";
3
3
  export { GrDialogServiceHost_default as GrDialogServiceHost, dialogService, grDialogServiceConfig, granularityDialogServicePlugin, teardownDialogService, useDialogService };
@@ -3,7 +3,7 @@ import { i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
3
3
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
4
4
  import { t as GrIcon_default } from "../../GrIcon/chunks/GrIcon-DTZIgmje.js";
5
5
  import { t as GrButton_default } from "../../GrButton/chunks/GrButton-CS4TqMtG.js";
6
- import { t as useModalOverlay } from "../../../chunks/useModalOverlay-ACRkflzx.js";
6
+ import { t as useModalOverlay } from "../../../chunks/useModalOverlay-CKCQkGdB.js";
7
7
  import { a as DEFAULT_GR_DRAWER_HEADER_CONFIG, c as grDrawerPanelClass, d as overlayClass, f as resolveGrDrawerSectionConfig, g as titleClass, h as srOnlyTitleClass, i as DEFAULT_GR_DRAWER_FOOTER_CONFIG, l as grDrawerPanelEnterFrom, m as rootPassThroughClass, o as footerBorderClass, p as rootClass, r as DEFAULT_GR_DRAWER_BODY_CONFIG, s as grDrawerAxis, u as headerBorderClass } from "../../../chunks/config-CviN-0d4.js";
8
8
  import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, normalizeClass, normalizeStyle, openBlock, ref, renderSlot, toDisplayString, toHandlers, unref, useId, useSlots, watch, withCtx } from "vue";
9
9
  //#region src/components/GrDrawer/GrDrawer.vue?vue&type=script&setup=true&lang.ts
@@ -1 +1 @@
1
- {"version":3,"file":"GrDrawer-CNpSMuN-.js","names":["$slots"],"sources":["../../../../src/components/GrDrawer/GrDrawer.vue","../../../../src/components/GrDrawer/GrDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n// Модальный слой целиком: стек (Esc верхнему, `inert` нижним модалкам), ловушка\n// фокуса, скролл-лок, портал. Немодальная панель регистрируется в стеке как\n// обычный dismissible-слой и страницу под собой не трогает.\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport {\n DEFAULT_GR_DRAWER_BODY_CONFIG,\n DEFAULT_GR_DRAWER_FOOTER_CONFIG,\n DEFAULT_GR_DRAWER_HEADER_CONFIG,\n footerBorderClass,\n grDrawerAxis,\n grDrawerPanelClass,\n grDrawerPanelEnterFrom,\n headerBorderClass,\n overlayClass,\n resolveGrDrawerSectionConfig,\n rootClass,\n rootPassThroughClass,\n srOnlyTitleClass,\n titleClass,\n type GrDrawerSectionConfig,\n type GrDrawerSide,\n type GrDrawerSize,\n} from './grDrawerStyles'\n\nimport IconClose from '~icons/lucide/x'\n\nimport './defaults'\n\nexport interface GrDrawerProps {\n /** Контроль открытия через v-model. */\n modelValue: boolean\n /** Заголовок; если передан — покажется в хедере. Можно переопределить слотом `#title`. */\n title?: string\n /**\n * Модальная панель: подложка, блокировка скролла, `inert` остальной странице\n * и ловушка фокуса. `false` — панель живёт рядом со страницей: с ней работают,\n * не закрывая, а Tab уходит наружу.\n */\n modal?: boolean\n /** Закрывать при клике по бэкдропу. В немодальном режиме подложки нет. */\n closeOnBackdrop?: boolean\n /** Закрывать по Esc. */\n closeOnEsc?: boolean\n /**\n * Запрет закрытия «мягкими» способами (бэкдроп, Esc) — на время операции,\n * которую нельзя бросить на полпути. Кнопка закрытия при этом остаётся:\n * панель без единого выхода — ловушка.\n */\n persistent?: boolean\n /** Сторона, с которой выезжает панель. */\n side?: GrDrawerSide\n /** Размер панели по её оси: ширина у боковых, высота у верхней и нижней. */\n size?: GrDrawerSize\n /** Произвольная ширина боковой панели. Число трактуется как пиксели; сильнее `size`. */\n width?: string | number\n /** Произвольная высота верхней или нижней панели. Число трактуется как пиксели. */\n height?: string | number\n /** Рендерить ли хедер (заголовок + кнопка закрытия). */\n showHeader?: boolean\n /** Рендерить ли кнопку закрытия в хедере. */\n showCloseButton?: boolean\n /** Паддинги и рамка секций — как у `GrDialog`. */\n headerConfig?: GrDrawerSectionConfig\n bodyConfig?: GrDrawerSectionConfig\n footerConfig?: GrDrawerSectionConfig\n /** Элемент, получающий фокус при открытии. По умолчанию — сама панель. */\n initialFocus?: HTMLElement | null\n /** i18n-friendly aria-label для кнопки закрытия. */\n closeLabel?: string\n}\n\nexport interface GrDrawerEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Панель выехала и анимация закончилась. */\n (e: 'opened'): void\n /** Панель уехала и анимация закончилась. */\n (e: 'closed'): void\n}\n\n// Дефолты оформления намеренно `undefined`: «настоящий» дефолт живёт в\n// `useGrComponentProp`, иначе `GrConfigProvider` не отличит заданный\n// пользователем проп от подставленного Vue.\nconst props = withDefaults(defineProps<GrDrawerProps>(), {\n title: undefined,\n modal: true,\n closeOnBackdrop: true,\n closeOnEsc: true,\n persistent: false,\n side: undefined,\n size: undefined,\n width: undefined,\n height: undefined,\n showHeader: true,\n showCloseButton: true,\n headerConfig: undefined,\n bodyConfig: undefined,\n footerConfig: undefined,\n initialFocus: null,\n closeLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\n\nconst emit = defineEmits<GrDrawerEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n title?: () => any\n /** Своя шапка целиком: заголовок, кнопка закрытия и всё, что нужно рядом. */\n header?: (props: { title?: string, close: () => void }) => any\n footer?: () => any\n}>()\n\nconst titleId = useId()\n\nconst size = useGrComponentProp('GrDrawer', 'size', () => props.size, 'md')\nconst side = useGrComponentProp('GrDrawer', 'side', () => props.side, 'right')\n\nconst axis = computed(() => grDrawerAxis(side.value))\n\n// Пустой/пробельный заголовок считается отсутствующим — иначе хедер занимал бы\n// место ради строки-заглушки.\nconst resolvedTitle = computed(() => props.title?.trim() || undefined)\nconst hasTitle = computed(() => Boolean(resolvedTitle.value) || Boolean(slots.title))\nconst hasCustomHeader = computed(() => Boolean(slots.header))\nconst hasHeader = computed(() =>\n props.showHeader && (hasCustomHeader.value || hasTitle.value || props.showCloseButton),\n)\n\n/**\n * Видимый заголовок рисуется только в стандартной шапке. Со своей шапкой и без\n * шапки вовсе заголовок всё равно нужен — но скрытым: имя слоя обязано остаться\n * осмысленным, а не свалиться на обобщённое «Drawer» из локали.\n */\nconst showVisibleTitle = computed(() =>\n props.showHeader && !hasCustomHeader.value && hasTitle.value,\n)\nconst showSrOnlyTitle = computed(() => hasTitle.value && !showVisibleTitle.value)\n\n// Имя модального слоя обязательно: без него axe роняет `aria-dialog-name`.\n// Есть заголовок — связываем `aria-labelledby`, иначе даём `aria-label` из i18n.\nconst labelledBy = computed(() => (hasTitle.value ? titleId : undefined))\nconst ariaLabel = computed(() => (labelledBy.value ? undefined : t('gr.drawer.title', 'Drawer')))\n\nconst panelEl = ref<HTMLElement | null>(null)\n\n/** Произвольный размер — только по оси панели: у боковой ширина, у нижней высота. */\nconst customLength = computed(() => (axis.value === 'horizontal' ? props.width : props.height))\n\nconst panelClass = computed(() => grDrawerPanelClass({\n side: side.value,\n size: size.value,\n hasCustomLength: customLength.value !== undefined,\n}))\n\nconst panelStyle = computed(() => {\n const length = customLength.value\n if (length === undefined)\n return undefined\n\n const value = typeof length === 'number' ? `${length}px` : length\n return axis.value === 'horizontal' ? { width: value } : { height: value }\n})\n\n// Проп не своей оси молча не работал бы — а выглядит это как баг компонента.\nif (__GR_DEV__) {\n watch(\n [axis, () => props.width, () => props.height],\n ([currentAxis, width, height]) => {\n const ignored = currentAxis === 'horizontal' ? 'height' : 'width'\n const value = currentAxis === 'horizontal' ? height : width\n if (value === undefined)\n return\n\n console.warn(\n `[GrDrawer] Проп \\`${ignored}\\` не применяется к стороне \"${side.value}\": `\n + `панель по этой оси растянута. Задайте \\`${ignored === 'height' ? 'width' : 'height'}\\`.`,\n )\n },\n { immediate: true },\n )\n}\n\nconst panelEnterFrom = computed(() => grDrawerPanelEnterFrom(side.value))\n\nconst headerSection = computed(() => resolveGrDrawerSectionConfig(props.headerConfig, DEFAULT_GR_DRAWER_HEADER_CONFIG))\nconst bodySection = computed(() => resolveGrDrawerSectionConfig(props.bodyConfig, DEFAULT_GR_DRAWER_BODY_CONFIG))\nconst footerSection = computed(() => resolveGrDrawerSectionConfig(props.footerConfig, DEFAULT_GR_DRAWER_FOOTER_CONFIG))\n\nfunction sectionClass(\n section: { paddingX: string, paddingY: string, bordered: boolean },\n borderClass: string,\n): string[] {\n return [section.paddingX, section.paddingY, section.bordered ? borderClass : '']\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\n/** Закрытие «мягким» способом: бэкдроп или Esc. `persistent` их и запрещает. */\nfunction closeSoftly(): void {\n if (props.persistent)\n return\n\n close()\n}\n\nconst rootClasses = computed(() => [rootClass, props.modal ? '' : rootPassThroughClass].filter(Boolean))\n\n// Немодальная панель остаётся в очереди Esc, но модалки под собой в `inert` не\n// отправляет и скролл не блокирует: она существует ровно ради работы со\n// страницей под ней, и Tab обязан уводить фокус туда.\nconst {\n rootEl,\n isMounted,\n isVisible,\n inertAttr,\n layerZIndex,\n portalTarget,\n teleportEnabled,\n themeAttrs,\n onPanelAfterLeave: releasePresence,\n backdrop,\n} = useModalOverlay(computed(() => props.modelValue), closeSoftly, {\n panel: panelEl,\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc && !props.persistent,\n closeOnBackdrop: () => props.closeOnBackdrop,\n initialFocus: () => props.initialFocus ?? panelEl.value,\n})\n\nfunction onPanelAfterLeave(): void {\n releasePresence()\n emit('closed')\n}\n\ndefineExpose({\n /** Закрыть панель (эквивалент `v-model = false`), минуя `persistent`. */\n close,\n /** Вернуть фокус на панель — например после операции, уведшей его наружу. */\n focus: () => panelEl.value?.focus(),\n})\n</script>\n\n<template>\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <div\n v-if=\"teleportEnabled && isMounted\"\n ref=\"rootEl\"\n data-gr-drawer\n data-gr-overlay-root\n role=\"dialog\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :class=\"rootClasses\"\n :style=\"{ zIndex: layerZIndex }\"\n :inert=\"inertAttr\"\n :aria-labelledby=\"labelledBy\"\n :aria-label=\"ariaLabel\"\n >\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n enter-from-class=\"opacity-0\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isVisible && modal\"\n data-gr-drawer-overlay\n :class=\"overlayClass\"\n aria-hidden=\"true\"\n v-on=\"backdrop\"\n />\n </Transition>\n\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n :enter-from-class=\"panelEnterFrom\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n :leave-to-class=\"panelEnterFrom\"\n @after-enter=\"emit('opened')\"\n @after-leave=\"onPanelAfterLeave\"\n >\n <div\n v-if=\"isVisible\"\n ref=\"panelEl\"\n v-bind=\"themeAttrs\"\n data-gr-drawer-panel\n tabindex=\"-1\"\n :class=\"panelClass\"\n :style=\"panelStyle\"\n >\n <!-- Заголовок без видимой шапки: имя слоя обязано остаться своим. -->\n <div\n v-if=\"showSrOnlyTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"srOnlyTitleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n\n <div\n v-if=\"hasHeader\"\n data-gr-drawer-header\n :class=\"[hasCustomHeader ? '' : 'flex items-center justify-between gap-4', sectionClass(headerSection, headerBorderClass)]\"\n >\n <slot name=\"header\" :title=\"resolvedTitle\" :close=\"close\">\n <div\n v-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n <div v-else class=\"min-w-0 flex-1\" />\n\n <GrButton\n v-if=\"showCloseButton\"\n variant=\"ghost\"\n size=\"sm\"\n square\n data-gr-drawer-close\n :aria-label=\"resolvedCloseLabel\"\n @click=\"close\"\n >\n <GrIcon size=\"sm\">\n <IconClose />\n </GrIcon>\n </GrButton>\n </slot>\n </div>\n\n <!-- Тело скроллится, поэтому обязано попадать в таб-порядок: длинный\n текст без единого фокусируемого элемента иначе не прокрутить с\n клавиатуры (axe: `scrollable-region-focusable`). -->\n <div\n data-gr-drawer-body\n tabindex=\"0\"\n class=\"min-h-0 flex-1 overflow-y-auto\"\n >\n <div :class=\"sectionClass(bodySection, '')\">\n <slot />\n </div>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n data-gr-drawer-footer\n :class=\"sectionClass(footerSection, footerBorderClass)\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </Transition>\n </div>\n </teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n// Модальный слой целиком: стек (Esc верхнему, `inert` нижним модалкам), ловушка\n// фокуса, скролл-лок, портал. Немодальная панель регистрируется в стеке как\n// обычный dismissible-слой и страницу под собой не трогает.\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport {\n DEFAULT_GR_DRAWER_BODY_CONFIG,\n DEFAULT_GR_DRAWER_FOOTER_CONFIG,\n DEFAULT_GR_DRAWER_HEADER_CONFIG,\n footerBorderClass,\n grDrawerAxis,\n grDrawerPanelClass,\n grDrawerPanelEnterFrom,\n headerBorderClass,\n overlayClass,\n resolveGrDrawerSectionConfig,\n rootClass,\n rootPassThroughClass,\n srOnlyTitleClass,\n titleClass,\n type GrDrawerSectionConfig,\n type GrDrawerSide,\n type GrDrawerSize,\n} from './grDrawerStyles'\n\nimport IconClose from '~icons/lucide/x'\n\nimport './defaults'\n\nexport interface GrDrawerProps {\n /** Контроль открытия через v-model. */\n modelValue: boolean\n /** Заголовок; если передан — покажется в хедере. Можно переопределить слотом `#title`. */\n title?: string\n /**\n * Модальная панель: подложка, блокировка скролла, `inert` остальной странице\n * и ловушка фокуса. `false` — панель живёт рядом со страницей: с ней работают,\n * не закрывая, а Tab уходит наружу.\n */\n modal?: boolean\n /** Закрывать при клике по бэкдропу. В немодальном режиме подложки нет. */\n closeOnBackdrop?: boolean\n /** Закрывать по Esc. */\n closeOnEsc?: boolean\n /**\n * Запрет закрытия «мягкими» способами (бэкдроп, Esc) — на время операции,\n * которую нельзя бросить на полпути. Кнопка закрытия при этом остаётся:\n * панель без единого выхода — ловушка.\n */\n persistent?: boolean\n /** Сторона, с которой выезжает панель. */\n side?: GrDrawerSide\n /** Размер панели по её оси: ширина у боковых, высота у верхней и нижней. */\n size?: GrDrawerSize\n /** Произвольная ширина боковой панели. Число трактуется как пиксели; сильнее `size`. */\n width?: string | number\n /** Произвольная высота верхней или нижней панели. Число трактуется как пиксели. */\n height?: string | number\n /** Рендерить ли хедер (заголовок + кнопка закрытия). */\n showHeader?: boolean\n /** Рендерить ли кнопку закрытия в хедере. */\n showCloseButton?: boolean\n /** Паддинги и рамка секций — как у `GrDialog`. */\n headerConfig?: GrDrawerSectionConfig\n bodyConfig?: GrDrawerSectionConfig\n footerConfig?: GrDrawerSectionConfig\n /** Элемент, получающий фокус при открытии. По умолчанию — сама панель. */\n initialFocus?: HTMLElement | null\n /** i18n-friendly aria-label для кнопки закрытия. */\n closeLabel?: string\n}\n\nexport interface GrDrawerEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Панель выехала и анимация закончилась. */\n (e: 'opened'): void\n /** Панель уехала и анимация закончилась. */\n (e: 'closed'): void\n}\n\n// Дефолты оформления намеренно `undefined`: «настоящий» дефолт живёт в\n// `useGrComponentProp`, иначе `GrConfigProvider` не отличит заданный\n// пользователем проп от подставленного Vue.\nconst props = withDefaults(defineProps<GrDrawerProps>(), {\n title: undefined,\n modal: true,\n closeOnBackdrop: true,\n closeOnEsc: true,\n persistent: false,\n side: undefined,\n size: undefined,\n width: undefined,\n height: undefined,\n showHeader: true,\n showCloseButton: true,\n headerConfig: undefined,\n bodyConfig: undefined,\n footerConfig: undefined,\n initialFocus: null,\n closeLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\n\nconst emit = defineEmits<GrDrawerEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n title?: () => any\n /** Своя шапка целиком: заголовок, кнопка закрытия и всё, что нужно рядом. */\n header?: (props: { title?: string, close: () => void }) => any\n footer?: () => any\n}>()\n\nconst titleId = useId()\n\nconst size = useGrComponentProp('GrDrawer', 'size', () => props.size, 'md')\nconst side = useGrComponentProp('GrDrawer', 'side', () => props.side, 'right')\n\nconst axis = computed(() => grDrawerAxis(side.value))\n\n// Пустой/пробельный заголовок считается отсутствующим — иначе хедер занимал бы\n// место ради строки-заглушки.\nconst resolvedTitle = computed(() => props.title?.trim() || undefined)\nconst hasTitle = computed(() => Boolean(resolvedTitle.value) || Boolean(slots.title))\nconst hasCustomHeader = computed(() => Boolean(slots.header))\nconst hasHeader = computed(() =>\n props.showHeader && (hasCustomHeader.value || hasTitle.value || props.showCloseButton),\n)\n\n/**\n * Видимый заголовок рисуется только в стандартной шапке. Со своей шапкой и без\n * шапки вовсе заголовок всё равно нужен — но скрытым: имя слоя обязано остаться\n * осмысленным, а не свалиться на обобщённое «Drawer» из локали.\n */\nconst showVisibleTitle = computed(() =>\n props.showHeader && !hasCustomHeader.value && hasTitle.value,\n)\nconst showSrOnlyTitle = computed(() => hasTitle.value && !showVisibleTitle.value)\n\n// Имя модального слоя обязательно: без него axe роняет `aria-dialog-name`.\n// Есть заголовок — связываем `aria-labelledby`, иначе даём `aria-label` из i18n.\nconst labelledBy = computed(() => (hasTitle.value ? titleId : undefined))\nconst ariaLabel = computed(() => (labelledBy.value ? undefined : t('gr.drawer.title', 'Drawer')))\n\nconst panelEl = ref<HTMLElement | null>(null)\n\n/** Произвольный размер — только по оси панели: у боковой ширина, у нижней высота. */\nconst customLength = computed(() => (axis.value === 'horizontal' ? props.width : props.height))\n\nconst panelClass = computed(() => grDrawerPanelClass({\n side: side.value,\n size: size.value,\n hasCustomLength: customLength.value !== undefined,\n}))\n\nconst panelStyle = computed(() => {\n const length = customLength.value\n if (length === undefined)\n return undefined\n\n const value = typeof length === 'number' ? `${length}px` : length\n return axis.value === 'horizontal' ? { width: value } : { height: value }\n})\n\n// Проп не своей оси молча не работал бы — а выглядит это как баг компонента.\nif (__GR_DEV__) {\n watch(\n [axis, () => props.width, () => props.height],\n ([currentAxis, width, height]) => {\n const ignored = currentAxis === 'horizontal' ? 'height' : 'width'\n const value = currentAxis === 'horizontal' ? height : width\n if (value === undefined)\n return\n\n console.warn(\n `[GrDrawer] Проп \\`${ignored}\\` не применяется к стороне \"${side.value}\": `\n + `панель по этой оси растянута. Задайте \\`${ignored === 'height' ? 'width' : 'height'}\\`.`,\n )\n },\n { immediate: true },\n )\n}\n\nconst panelEnterFrom = computed(() => grDrawerPanelEnterFrom(side.value))\n\nconst headerSection = computed(() => resolveGrDrawerSectionConfig(props.headerConfig, DEFAULT_GR_DRAWER_HEADER_CONFIG))\nconst bodySection = computed(() => resolveGrDrawerSectionConfig(props.bodyConfig, DEFAULT_GR_DRAWER_BODY_CONFIG))\nconst footerSection = computed(() => resolveGrDrawerSectionConfig(props.footerConfig, DEFAULT_GR_DRAWER_FOOTER_CONFIG))\n\nfunction sectionClass(\n section: { paddingX: string, paddingY: string, bordered: boolean },\n borderClass: string,\n): string[] {\n return [section.paddingX, section.paddingY, section.bordered ? borderClass : '']\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\n/** Закрытие «мягким» способом: бэкдроп или Esc. `persistent` их и запрещает. */\nfunction closeSoftly(): void {\n if (props.persistent)\n return\n\n close()\n}\n\nconst rootClasses = computed(() => [rootClass, props.modal ? '' : rootPassThroughClass].filter(Boolean))\n\n// Немодальная панель остаётся в очереди Esc, но модалки под собой в `inert` не\n// отправляет и скролл не блокирует: она существует ровно ради работы со\n// страницей под ней, и Tab обязан уводить фокус туда.\nconst {\n rootEl,\n isMounted,\n isVisible,\n inertAttr,\n layerZIndex,\n portalTarget,\n teleportEnabled,\n themeAttrs,\n onPanelAfterLeave: releasePresence,\n backdrop,\n} = useModalOverlay(computed(() => props.modelValue), closeSoftly, {\n panel: panelEl,\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc && !props.persistent,\n closeOnBackdrop: () => props.closeOnBackdrop,\n initialFocus: () => props.initialFocus ?? panelEl.value,\n})\n\nfunction onPanelAfterLeave(): void {\n releasePresence()\n emit('closed')\n}\n\ndefineExpose({\n /** Закрыть панель (эквивалент `v-model = false`), минуя `persistent`. */\n close,\n /** Вернуть фокус на панель — например после операции, уведшей его наружу. */\n focus: () => panelEl.value?.focus(),\n})\n</script>\n\n<template>\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <div\n v-if=\"teleportEnabled && isMounted\"\n ref=\"rootEl\"\n data-gr-drawer\n data-gr-overlay-root\n role=\"dialog\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :class=\"rootClasses\"\n :style=\"{ zIndex: layerZIndex }\"\n :inert=\"inertAttr\"\n :aria-labelledby=\"labelledBy\"\n :aria-label=\"ariaLabel\"\n >\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n enter-from-class=\"opacity-0\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isVisible && modal\"\n data-gr-drawer-overlay\n :class=\"overlayClass\"\n aria-hidden=\"true\"\n v-on=\"backdrop\"\n />\n </Transition>\n\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n :enter-from-class=\"panelEnterFrom\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n :leave-to-class=\"panelEnterFrom\"\n @after-enter=\"emit('opened')\"\n @after-leave=\"onPanelAfterLeave\"\n >\n <div\n v-if=\"isVisible\"\n ref=\"panelEl\"\n v-bind=\"themeAttrs\"\n data-gr-drawer-panel\n tabindex=\"-1\"\n :class=\"panelClass\"\n :style=\"panelStyle\"\n >\n <!-- Заголовок без видимой шапки: имя слоя обязано остаться своим. -->\n <div\n v-if=\"showSrOnlyTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"srOnlyTitleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n\n <div\n v-if=\"hasHeader\"\n data-gr-drawer-header\n :class=\"[hasCustomHeader ? '' : 'flex items-center justify-between gap-4', sectionClass(headerSection, headerBorderClass)]\"\n >\n <slot name=\"header\" :title=\"resolvedTitle\" :close=\"close\">\n <div\n v-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n <div v-else class=\"min-w-0 flex-1\" />\n\n <GrButton\n v-if=\"showCloseButton\"\n variant=\"ghost\"\n size=\"sm\"\n square\n data-gr-drawer-close\n :aria-label=\"resolvedCloseLabel\"\n @click=\"close\"\n >\n <GrIcon size=\"sm\">\n <IconClose />\n </GrIcon>\n </GrButton>\n </slot>\n </div>\n\n <!-- Тело скроллится, поэтому обязано попадать в таб-порядок: длинный\n текст без единого фокусируемого элемента иначе не прокрутить с\n клавиатуры (axe: `scrollable-region-focusable`). -->\n <div\n data-gr-drawer-body\n tabindex=\"0\"\n class=\"min-h-0 flex-1 overflow-y-auto\"\n >\n <div :class=\"sectionClass(bodySection, '')\">\n <slot />\n </div>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n data-gr-drawer-footer\n :class=\"sectionClass(footerSection, footerBorderClass)\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </Transition>\n </div>\n </teleport>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrDrawer-DOcRTE8G.js","names":["$slots"],"sources":["../../../../src/components/GrDrawer/GrDrawer.vue","../../../../src/components/GrDrawer/GrDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n// Модальный слой целиком: стек (Esc верхнему, `inert` нижним модалкам), ловушка\n// фокуса, скролл-лок, портал. Немодальная панель регистрируется в стеке как\n// обычный dismissible-слой и страницу под собой не трогает.\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport {\n DEFAULT_GR_DRAWER_BODY_CONFIG,\n DEFAULT_GR_DRAWER_FOOTER_CONFIG,\n DEFAULT_GR_DRAWER_HEADER_CONFIG,\n footerBorderClass,\n grDrawerAxis,\n grDrawerPanelClass,\n grDrawerPanelEnterFrom,\n headerBorderClass,\n overlayClass,\n resolveGrDrawerSectionConfig,\n rootClass,\n rootPassThroughClass,\n srOnlyTitleClass,\n titleClass,\n type GrDrawerSectionConfig,\n type GrDrawerSide,\n type GrDrawerSize,\n} from './grDrawerStyles'\n\nimport IconClose from '~icons/lucide/x'\n\nimport './defaults'\n\nexport interface GrDrawerProps {\n /** Контроль открытия через v-model. */\n modelValue: boolean\n /** Заголовок; если передан — покажется в хедере. Можно переопределить слотом `#title`. */\n title?: string\n /**\n * Модальная панель: подложка, блокировка скролла, `inert` остальной странице\n * и ловушка фокуса. `false` — панель живёт рядом со страницей: с ней работают,\n * не закрывая, а Tab уходит наружу.\n */\n modal?: boolean\n /** Закрывать при клике по бэкдропу. В немодальном режиме подложки нет. */\n closeOnBackdrop?: boolean\n /** Закрывать по Esc. */\n closeOnEsc?: boolean\n /**\n * Запрет закрытия «мягкими» способами (бэкдроп, Esc) — на время операции,\n * которую нельзя бросить на полпути. Кнопка закрытия при этом остаётся:\n * панель без единого выхода — ловушка.\n */\n persistent?: boolean\n /** Сторона, с которой выезжает панель. */\n side?: GrDrawerSide\n /** Размер панели по её оси: ширина у боковых, высота у верхней и нижней. */\n size?: GrDrawerSize\n /** Произвольная ширина боковой панели. Число трактуется как пиксели; сильнее `size`. */\n width?: string | number\n /** Произвольная высота верхней или нижней панели. Число трактуется как пиксели. */\n height?: string | number\n /** Рендерить ли хедер (заголовок + кнопка закрытия). */\n showHeader?: boolean\n /** Рендерить ли кнопку закрытия в хедере. */\n showCloseButton?: boolean\n /** Паддинги и рамка секций — как у `GrDialog`. */\n headerConfig?: GrDrawerSectionConfig\n bodyConfig?: GrDrawerSectionConfig\n footerConfig?: GrDrawerSectionConfig\n /** Элемент, получающий фокус при открытии. По умолчанию — сама панель. */\n initialFocus?: HTMLElement | null\n /** i18n-friendly aria-label для кнопки закрытия. */\n closeLabel?: string\n}\n\nexport interface GrDrawerEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Панель выехала и анимация закончилась. */\n (e: 'opened'): void\n /** Панель уехала и анимация закончилась. */\n (e: 'closed'): void\n}\n\n// Дефолты оформления намеренно `undefined`: «настоящий» дефолт живёт в\n// `useGrComponentProp`, иначе `GrConfigProvider` не отличит заданный\n// пользователем проп от подставленного Vue.\nconst props = withDefaults(defineProps<GrDrawerProps>(), {\n title: undefined,\n modal: true,\n closeOnBackdrop: true,\n closeOnEsc: true,\n persistent: false,\n side: undefined,\n size: undefined,\n width: undefined,\n height: undefined,\n showHeader: true,\n showCloseButton: true,\n headerConfig: undefined,\n bodyConfig: undefined,\n footerConfig: undefined,\n initialFocus: null,\n closeLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\n\nconst emit = defineEmits<GrDrawerEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n title?: () => any\n /** Своя шапка целиком: заголовок, кнопка закрытия и всё, что нужно рядом. */\n header?: (props: { title?: string, close: () => void }) => any\n footer?: () => any\n}>()\n\nconst titleId = useId()\n\nconst size = useGrComponentProp('GrDrawer', 'size', () => props.size, 'md')\nconst side = useGrComponentProp('GrDrawer', 'side', () => props.side, 'right')\n\nconst axis = computed(() => grDrawerAxis(side.value))\n\n// Пустой/пробельный заголовок считается отсутствующим — иначе хедер занимал бы\n// место ради строки-заглушки.\nconst resolvedTitle = computed(() => props.title?.trim() || undefined)\nconst hasTitle = computed(() => Boolean(resolvedTitle.value) || Boolean(slots.title))\nconst hasCustomHeader = computed(() => Boolean(slots.header))\nconst hasHeader = computed(() =>\n props.showHeader && (hasCustomHeader.value || hasTitle.value || props.showCloseButton),\n)\n\n/**\n * Видимый заголовок рисуется только в стандартной шапке. Со своей шапкой и без\n * шапки вовсе заголовок всё равно нужен — но скрытым: имя слоя обязано остаться\n * осмысленным, а не свалиться на обобщённое «Drawer» из локали.\n */\nconst showVisibleTitle = computed(() =>\n props.showHeader && !hasCustomHeader.value && hasTitle.value,\n)\nconst showSrOnlyTitle = computed(() => hasTitle.value && !showVisibleTitle.value)\n\n// Имя модального слоя обязательно: без него axe роняет `aria-dialog-name`.\n// Есть заголовок — связываем `aria-labelledby`, иначе даём `aria-label` из i18n.\nconst labelledBy = computed(() => (hasTitle.value ? titleId : undefined))\nconst ariaLabel = computed(() => (labelledBy.value ? undefined : t('gr.drawer.title', 'Drawer')))\n\nconst panelEl = ref<HTMLElement | null>(null)\n\n/** Произвольный размер — только по оси панели: у боковой ширина, у нижней высота. */\nconst customLength = computed(() => (axis.value === 'horizontal' ? props.width : props.height))\n\nconst panelClass = computed(() => grDrawerPanelClass({\n side: side.value,\n size: size.value,\n hasCustomLength: customLength.value !== undefined,\n}))\n\nconst panelStyle = computed(() => {\n const length = customLength.value\n if (length === undefined)\n return undefined\n\n const value = typeof length === 'number' ? `${length}px` : length\n return axis.value === 'horizontal' ? { width: value } : { height: value }\n})\n\n// Проп не своей оси молча не работал бы — а выглядит это как баг компонента.\nif (__GR_DEV__) {\n watch(\n [axis, () => props.width, () => props.height],\n ([currentAxis, width, height]) => {\n const ignored = currentAxis === 'horizontal' ? 'height' : 'width'\n const value = currentAxis === 'horizontal' ? height : width\n if (value === undefined)\n return\n\n console.warn(\n `[GrDrawer] Проп \\`${ignored}\\` не применяется к стороне \"${side.value}\": `\n + `панель по этой оси растянута. Задайте \\`${ignored === 'height' ? 'width' : 'height'}\\`.`,\n )\n },\n { immediate: true },\n )\n}\n\nconst panelEnterFrom = computed(() => grDrawerPanelEnterFrom(side.value))\n\nconst headerSection = computed(() => resolveGrDrawerSectionConfig(props.headerConfig, DEFAULT_GR_DRAWER_HEADER_CONFIG))\nconst bodySection = computed(() => resolveGrDrawerSectionConfig(props.bodyConfig, DEFAULT_GR_DRAWER_BODY_CONFIG))\nconst footerSection = computed(() => resolveGrDrawerSectionConfig(props.footerConfig, DEFAULT_GR_DRAWER_FOOTER_CONFIG))\n\nfunction sectionClass(\n section: { paddingX: string, paddingY: string, bordered: boolean },\n borderClass: string,\n): string[] {\n return [section.paddingX, section.paddingY, section.bordered ? borderClass : '']\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\n/** Закрытие «мягким» способом: бэкдроп или Esc. `persistent` их и запрещает. */\nfunction closeSoftly(): void {\n if (props.persistent)\n return\n\n close()\n}\n\nconst rootClasses = computed(() => [rootClass, props.modal ? '' : rootPassThroughClass].filter(Boolean))\n\n// Немодальная панель остаётся в очереди Esc, но модалки под собой в `inert` не\n// отправляет и скролл не блокирует: она существует ровно ради работы со\n// страницей под ней, и Tab обязан уводить фокус туда.\nconst {\n rootEl,\n isMounted,\n isVisible,\n inertAttr,\n layerZIndex,\n portalTarget,\n teleportEnabled,\n themeAttrs,\n onPanelAfterLeave: releasePresence,\n backdrop,\n} = useModalOverlay(computed(() => props.modelValue), closeSoftly, {\n panel: panelEl,\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc && !props.persistent,\n closeOnBackdrop: () => props.closeOnBackdrop,\n initialFocus: () => props.initialFocus ?? panelEl.value,\n})\n\nfunction onPanelAfterLeave(): void {\n releasePresence()\n emit('closed')\n}\n\ndefineExpose({\n /** Закрыть панель (эквивалент `v-model = false`), минуя `persistent`. */\n close,\n /** Вернуть фокус на панель — например после операции, уведшей его наружу. */\n focus: () => panelEl.value?.focus(),\n})\n</script>\n\n<template>\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <div\n v-if=\"teleportEnabled && isMounted\"\n ref=\"rootEl\"\n data-gr-drawer\n data-gr-overlay-root\n role=\"dialog\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :class=\"rootClasses\"\n :style=\"{ zIndex: layerZIndex }\"\n :inert=\"inertAttr\"\n :aria-labelledby=\"labelledBy\"\n :aria-label=\"ariaLabel\"\n >\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n enter-from-class=\"opacity-0\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isVisible && modal\"\n data-gr-drawer-overlay\n :class=\"overlayClass\"\n aria-hidden=\"true\"\n v-on=\"backdrop\"\n />\n </Transition>\n\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n :enter-from-class=\"panelEnterFrom\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n :leave-to-class=\"panelEnterFrom\"\n @after-enter=\"emit('opened')\"\n @after-leave=\"onPanelAfterLeave\"\n >\n <div\n v-if=\"isVisible\"\n ref=\"panelEl\"\n v-bind=\"themeAttrs\"\n data-gr-drawer-panel\n tabindex=\"-1\"\n :class=\"panelClass\"\n :style=\"panelStyle\"\n >\n <!-- Заголовок без видимой шапки: имя слоя обязано остаться своим. -->\n <div\n v-if=\"showSrOnlyTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"srOnlyTitleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n\n <div\n v-if=\"hasHeader\"\n data-gr-drawer-header\n :class=\"[hasCustomHeader ? '' : 'flex items-center justify-between gap-4', sectionClass(headerSection, headerBorderClass)]\"\n >\n <slot name=\"header\" :title=\"resolvedTitle\" :close=\"close\">\n <div\n v-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n <div v-else class=\"min-w-0 flex-1\" />\n\n <GrButton\n v-if=\"showCloseButton\"\n variant=\"ghost\"\n size=\"sm\"\n square\n data-gr-drawer-close\n :aria-label=\"resolvedCloseLabel\"\n @click=\"close\"\n >\n <GrIcon size=\"sm\">\n <IconClose />\n </GrIcon>\n </GrButton>\n </slot>\n </div>\n\n <!-- Тело скроллится, поэтому обязано попадать в таб-порядок: длинный\n текст без единого фокусируемого элемента иначе не прокрутить с\n клавиатуры (axe: `scrollable-region-focusable`). -->\n <div\n data-gr-drawer-body\n tabindex=\"0\"\n class=\"min-h-0 flex-1 overflow-y-auto\"\n >\n <div :class=\"sectionClass(bodySection, '')\">\n <slot />\n </div>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n data-gr-drawer-footer\n :class=\"sectionClass(footerSection, footerBorderClass)\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </Transition>\n </div>\n </teleport>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n// Модальный слой целиком: стек (Esc верхнему, `inert` нижним модалкам), ловушка\n// фокуса, скролл-лок, портал. Немодальная панель регистрируется в стеке как\n// обычный dismissible-слой и страницу под собой не трогает.\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport {\n DEFAULT_GR_DRAWER_BODY_CONFIG,\n DEFAULT_GR_DRAWER_FOOTER_CONFIG,\n DEFAULT_GR_DRAWER_HEADER_CONFIG,\n footerBorderClass,\n grDrawerAxis,\n grDrawerPanelClass,\n grDrawerPanelEnterFrom,\n headerBorderClass,\n overlayClass,\n resolveGrDrawerSectionConfig,\n rootClass,\n rootPassThroughClass,\n srOnlyTitleClass,\n titleClass,\n type GrDrawerSectionConfig,\n type GrDrawerSide,\n type GrDrawerSize,\n} from './grDrawerStyles'\n\nimport IconClose from '~icons/lucide/x'\n\nimport './defaults'\n\nexport interface GrDrawerProps {\n /** Контроль открытия через v-model. */\n modelValue: boolean\n /** Заголовок; если передан — покажется в хедере. Можно переопределить слотом `#title`. */\n title?: string\n /**\n * Модальная панель: подложка, блокировка скролла, `inert` остальной странице\n * и ловушка фокуса. `false` — панель живёт рядом со страницей: с ней работают,\n * не закрывая, а Tab уходит наружу.\n */\n modal?: boolean\n /** Закрывать при клике по бэкдропу. В немодальном режиме подложки нет. */\n closeOnBackdrop?: boolean\n /** Закрывать по Esc. */\n closeOnEsc?: boolean\n /**\n * Запрет закрытия «мягкими» способами (бэкдроп, Esc) — на время операции,\n * которую нельзя бросить на полпути. Кнопка закрытия при этом остаётся:\n * панель без единого выхода — ловушка.\n */\n persistent?: boolean\n /** Сторона, с которой выезжает панель. */\n side?: GrDrawerSide\n /** Размер панели по её оси: ширина у боковых, высота у верхней и нижней. */\n size?: GrDrawerSize\n /** Произвольная ширина боковой панели. Число трактуется как пиксели; сильнее `size`. */\n width?: string | number\n /** Произвольная высота верхней или нижней панели. Число трактуется как пиксели. */\n height?: string | number\n /** Рендерить ли хедер (заголовок + кнопка закрытия). */\n showHeader?: boolean\n /** Рендерить ли кнопку закрытия в хедере. */\n showCloseButton?: boolean\n /** Паддинги и рамка секций — как у `GrDialog`. */\n headerConfig?: GrDrawerSectionConfig\n bodyConfig?: GrDrawerSectionConfig\n footerConfig?: GrDrawerSectionConfig\n /** Элемент, получающий фокус при открытии. По умолчанию — сама панель. */\n initialFocus?: HTMLElement | null\n /** i18n-friendly aria-label для кнопки закрытия. */\n closeLabel?: string\n}\n\nexport interface GrDrawerEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Панель выехала и анимация закончилась. */\n (e: 'opened'): void\n /** Панель уехала и анимация закончилась. */\n (e: 'closed'): void\n}\n\n// Дефолты оформления намеренно `undefined`: «настоящий» дефолт живёт в\n// `useGrComponentProp`, иначе `GrConfigProvider` не отличит заданный\n// пользователем проп от подставленного Vue.\nconst props = withDefaults(defineProps<GrDrawerProps>(), {\n title: undefined,\n modal: true,\n closeOnBackdrop: true,\n closeOnEsc: true,\n persistent: false,\n side: undefined,\n size: undefined,\n width: undefined,\n height: undefined,\n showHeader: true,\n showCloseButton: true,\n headerConfig: undefined,\n bodyConfig: undefined,\n footerConfig: undefined,\n initialFocus: null,\n closeLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\n\nconst emit = defineEmits<GrDrawerEmits>()\n\nconst slots = defineSlots<{\n default?: () => any\n title?: () => any\n /** Своя шапка целиком: заголовок, кнопка закрытия и всё, что нужно рядом. */\n header?: (props: { title?: string, close: () => void }) => any\n footer?: () => any\n}>()\n\nconst titleId = useId()\n\nconst size = useGrComponentProp('GrDrawer', 'size', () => props.size, 'md')\nconst side = useGrComponentProp('GrDrawer', 'side', () => props.side, 'right')\n\nconst axis = computed(() => grDrawerAxis(side.value))\n\n// Пустой/пробельный заголовок считается отсутствующим — иначе хедер занимал бы\n// место ради строки-заглушки.\nconst resolvedTitle = computed(() => props.title?.trim() || undefined)\nconst hasTitle = computed(() => Boolean(resolvedTitle.value) || Boolean(slots.title))\nconst hasCustomHeader = computed(() => Boolean(slots.header))\nconst hasHeader = computed(() =>\n props.showHeader && (hasCustomHeader.value || hasTitle.value || props.showCloseButton),\n)\n\n/**\n * Видимый заголовок рисуется только в стандартной шапке. Со своей шапкой и без\n * шапки вовсе заголовок всё равно нужен — но скрытым: имя слоя обязано остаться\n * осмысленным, а не свалиться на обобщённое «Drawer» из локали.\n */\nconst showVisibleTitle = computed(() =>\n props.showHeader && !hasCustomHeader.value && hasTitle.value,\n)\nconst showSrOnlyTitle = computed(() => hasTitle.value && !showVisibleTitle.value)\n\n// Имя модального слоя обязательно: без него axe роняет `aria-dialog-name`.\n// Есть заголовок — связываем `aria-labelledby`, иначе даём `aria-label` из i18n.\nconst labelledBy = computed(() => (hasTitle.value ? titleId : undefined))\nconst ariaLabel = computed(() => (labelledBy.value ? undefined : t('gr.drawer.title', 'Drawer')))\n\nconst panelEl = ref<HTMLElement | null>(null)\n\n/** Произвольный размер — только по оси панели: у боковой ширина, у нижней высота. */\nconst customLength = computed(() => (axis.value === 'horizontal' ? props.width : props.height))\n\nconst panelClass = computed(() => grDrawerPanelClass({\n side: side.value,\n size: size.value,\n hasCustomLength: customLength.value !== undefined,\n}))\n\nconst panelStyle = computed(() => {\n const length = customLength.value\n if (length === undefined)\n return undefined\n\n const value = typeof length === 'number' ? `${length}px` : length\n return axis.value === 'horizontal' ? { width: value } : { height: value }\n})\n\n// Проп не своей оси молча не работал бы — а выглядит это как баг компонента.\nif (__GR_DEV__) {\n watch(\n [axis, () => props.width, () => props.height],\n ([currentAxis, width, height]) => {\n const ignored = currentAxis === 'horizontal' ? 'height' : 'width'\n const value = currentAxis === 'horizontal' ? height : width\n if (value === undefined)\n return\n\n console.warn(\n `[GrDrawer] Проп \\`${ignored}\\` не применяется к стороне \"${side.value}\": `\n + `панель по этой оси растянута. Задайте \\`${ignored === 'height' ? 'width' : 'height'}\\`.`,\n )\n },\n { immediate: true },\n )\n}\n\nconst panelEnterFrom = computed(() => grDrawerPanelEnterFrom(side.value))\n\nconst headerSection = computed(() => resolveGrDrawerSectionConfig(props.headerConfig, DEFAULT_GR_DRAWER_HEADER_CONFIG))\nconst bodySection = computed(() => resolveGrDrawerSectionConfig(props.bodyConfig, DEFAULT_GR_DRAWER_BODY_CONFIG))\nconst footerSection = computed(() => resolveGrDrawerSectionConfig(props.footerConfig, DEFAULT_GR_DRAWER_FOOTER_CONFIG))\n\nfunction sectionClass(\n section: { paddingX: string, paddingY: string, bordered: boolean },\n borderClass: string,\n): string[] {\n return [section.paddingX, section.paddingY, section.bordered ? borderClass : '']\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\n/** Закрытие «мягким» способом: бэкдроп или Esc. `persistent` их и запрещает. */\nfunction closeSoftly(): void {\n if (props.persistent)\n return\n\n close()\n}\n\nconst rootClasses = computed(() => [rootClass, props.modal ? '' : rootPassThroughClass].filter(Boolean))\n\n// Немодальная панель остаётся в очереди Esc, но модалки под собой в `inert` не\n// отправляет и скролл не блокирует: она существует ровно ради работы со\n// страницей под ней, и Tab обязан уводить фокус туда.\nconst {\n rootEl,\n isMounted,\n isVisible,\n inertAttr,\n layerZIndex,\n portalTarget,\n teleportEnabled,\n themeAttrs,\n onPanelAfterLeave: releasePresence,\n backdrop,\n} = useModalOverlay(computed(() => props.modelValue), closeSoftly, {\n panel: panelEl,\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc && !props.persistent,\n closeOnBackdrop: () => props.closeOnBackdrop,\n initialFocus: () => props.initialFocus ?? panelEl.value,\n})\n\nfunction onPanelAfterLeave(): void {\n releasePresence()\n emit('closed')\n}\n\ndefineExpose({\n /** Закрыть панель (эквивалент `v-model = false`), минуя `persistent`. */\n close,\n /** Вернуть фокус на панель — например после операции, уведшей его наружу. */\n focus: () => panelEl.value?.focus(),\n})\n</script>\n\n<template>\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <div\n v-if=\"teleportEnabled && isMounted\"\n ref=\"rootEl\"\n data-gr-drawer\n data-gr-overlay-root\n role=\"dialog\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :class=\"rootClasses\"\n :style=\"{ zIndex: layerZIndex }\"\n :inert=\"inertAttr\"\n :aria-labelledby=\"labelledBy\"\n :aria-label=\"ariaLabel\"\n >\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n enter-from-class=\"opacity-0\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"isVisible && modal\"\n data-gr-drawer-overlay\n :class=\"overlayClass\"\n aria-hidden=\"true\"\n v-on=\"backdrop\"\n />\n </Transition>\n\n <Transition\n appear\n enter-active-class=\"duration-[var(--gr-duration-base)] ease-[var(--gr-ease-out)]\"\n :enter-from-class=\"panelEnterFrom\"\n leave-active-class=\"duration-[var(--gr-duration-fast)] ease-[var(--gr-ease-in)]\"\n :leave-to-class=\"panelEnterFrom\"\n @after-enter=\"emit('opened')\"\n @after-leave=\"onPanelAfterLeave\"\n >\n <div\n v-if=\"isVisible\"\n ref=\"panelEl\"\n v-bind=\"themeAttrs\"\n data-gr-drawer-panel\n tabindex=\"-1\"\n :class=\"panelClass\"\n :style=\"panelStyle\"\n >\n <!-- Заголовок без видимой шапки: имя слоя обязано остаться своим. -->\n <div\n v-if=\"showSrOnlyTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"srOnlyTitleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n\n <div\n v-if=\"hasHeader\"\n data-gr-drawer-header\n :class=\"[hasCustomHeader ? '' : 'flex items-center justify-between gap-4', sectionClass(headerSection, headerBorderClass)]\"\n >\n <slot name=\"header\" :title=\"resolvedTitle\" :close=\"close\">\n <div\n v-if=\"showVisibleTitle\"\n :id=\"titleId\"\n data-gr-drawer-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ resolvedTitle }}\n </slot>\n </div>\n <div v-else class=\"min-w-0 flex-1\" />\n\n <GrButton\n v-if=\"showCloseButton\"\n variant=\"ghost\"\n size=\"sm\"\n square\n data-gr-drawer-close\n :aria-label=\"resolvedCloseLabel\"\n @click=\"close\"\n >\n <GrIcon size=\"sm\">\n <IconClose />\n </GrIcon>\n </GrButton>\n </slot>\n </div>\n\n <!-- Тело скроллится, поэтому обязано попадать в таб-порядок: длинный\n текст без единого фокусируемого элемента иначе не прокрутить с\n клавиатуры (axe: `scrollable-region-focusable`). -->\n <div\n data-gr-drawer-body\n tabindex=\"0\"\n class=\"min-h-0 flex-1 overflow-y-auto\"\n >\n <div :class=\"sectionClass(bodySection, '')\">\n <slot />\n </div>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n data-gr-drawer-footer\n :class=\"sectionClass(footerSection, footerBorderClass)\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </Transition>\n </div>\n </teleport>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  import { n as grDrawerSafelist, t as grDrawerConfig } from "../../chunks/config-CviN-0d4.js";
2
- import { t as GrDrawer_default } from "./chunks/GrDrawer-CNpSMuN-.js";
2
+ import { t as GrDrawer_default } from "./chunks/GrDrawer-DOcRTE8G.js";
3
3
  export { GrDrawer_default as GrDrawer, GrDrawer_default as default, grDrawerConfig, grDrawerSafelist };
@@ -1,6 +1,6 @@
1
1
  import { t as useControlledOpen } from "../../../chunks/useControlledOpen-DV3SqLTP.js";
2
- import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-CcWvr1ZA.js";
3
- import { t as useMenuItemsFocus } from "../../../chunks/useMenuItemsFocus-B7Bl_aFA.js";
2
+ import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-DjVxt8bf.js";
3
+ import { t as useMenuItemsFocus } from "../../../chunks/useMenuItemsFocus-C031blYS.js";
4
4
  import { t as grDropdownContentClass } from "../../../chunks/grDropdownStyles-DLToHWMX.js";
5
5
  import { computed, createElementBlock, createElementVNode, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, openBlock, ref, renderSlot, unref, watch, withCtx } from "vue";
6
6
  //#region src/components/GrDropdown/GrDropdown.vue?vue&type=script&setup=true&lang.ts