@feugene/granularity 0.35.0 → 0.37.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 (377) hide show
  1. package/dist/chunks/config-2ZHRsdOc.js.map +1 -1
  2. package/dist/chunks/config-2vrOFn2f.js.map +1 -1
  3. package/dist/chunks/config-3bQeQvqd.js.map +1 -1
  4. package/dist/chunks/config-87fszqnD.js.map +1 -1
  5. package/dist/chunks/config-8Pcutu1j.js.map +1 -1
  6. package/dist/chunks/config-A-bBiotF.js.map +1 -1
  7. package/dist/chunks/config-B0uvcTPH.js.map +1 -1
  8. package/dist/chunks/config-B3J0alyY.js.map +1 -1
  9. package/dist/chunks/config-B5SBUa6u.js.map +1 -1
  10. package/dist/chunks/config-B7W9VlZ7.js.map +1 -1
  11. package/dist/chunks/config-BDSaD-5p.js.map +1 -1
  12. package/dist/chunks/config-BEO7brpO.js.map +1 -1
  13. package/dist/chunks/config-BNu8lFQB.js.map +1 -1
  14. package/dist/chunks/config-BRESvs9g.js.map +1 -1
  15. package/dist/chunks/config-BTmfQFwi.js.map +1 -1
  16. package/dist/chunks/{config-CuQmUkMw2.js → config-BUNxHnEz.js} +1 -1
  17. package/dist/chunks/config-BUNxHnEz.js.map +1 -0
  18. package/dist/chunks/config-BaWANzzB.js.map +1 -1
  19. package/dist/chunks/config-BcXX7S7B.js.map +1 -1
  20. package/dist/chunks/config-Bd7QfiGj.js.map +1 -1
  21. package/dist/chunks/config-BhfNgyWL.js.map +1 -1
  22. package/dist/chunks/config-Bjn30smH.js.map +1 -1
  23. package/dist/chunks/config-BlJa1Mj9.js.map +1 -1
  24. package/dist/chunks/config-BoUI0t-t.js.map +1 -1
  25. package/dist/chunks/config-BqT6PMzO.js.map +1 -1
  26. package/dist/chunks/config-BscVxZR3.js.map +1 -1
  27. package/dist/chunks/config-BuGlNPE9.js.map +1 -1
  28. package/dist/chunks/config-C0Ea9ePP.js.map +1 -1
  29. package/dist/chunks/config-C0Eu8jpG.js.map +1 -1
  30. package/dist/chunks/config-CDat1wXf.js.map +1 -1
  31. package/dist/chunks/config-CIkdsWUk.js.map +1 -1
  32. package/dist/chunks/config-CJzmDHfI.js.map +1 -1
  33. package/dist/chunks/config-CLjjjPZj.js.map +1 -1
  34. package/dist/chunks/config-CMNfZO7S.js.map +1 -1
  35. package/dist/chunks/config-CQLNjc9X.js.map +1 -0
  36. package/dist/chunks/config-CT4lP6S4.js.map +1 -1
  37. package/dist/chunks/config-CWtfxkM9.js.map +1 -1
  38. package/dist/chunks/config-CYthTVK2.js.map +1 -1
  39. package/dist/chunks/config-CZPDPJlg.js.map +1 -1
  40. package/dist/chunks/config-CbEbLyDE.js.map +1 -1
  41. package/dist/chunks/config-ChPg-BQv.js.map +1 -1
  42. package/dist/chunks/config-CjKpUcmy.js.map +1 -1
  43. package/dist/chunks/config-CjWOTgLL.js.map +1 -1
  44. package/dist/chunks/config-CjXjhphs.js.map +1 -1
  45. package/dist/chunks/config-CnYdE3HZ.js.map +1 -0
  46. package/dist/chunks/config-CsCUuukB.js.map +1 -1
  47. package/dist/chunks/config-CvbVM4ep.js.map +1 -1
  48. package/dist/chunks/config-D0NzGYaE.js.map +1 -1
  49. package/dist/chunks/config-D0W8mGFD.js.map +1 -1
  50. package/dist/chunks/config-D82r782v.js.map +1 -1
  51. package/dist/chunks/{config-mlheIMtV.js → config-DBi0GVce.js} +2 -2
  52. package/dist/chunks/config-DBi0GVce.js.map +1 -0
  53. package/dist/chunks/config-DBmdgoVf.js.map +1 -0
  54. package/dist/chunks/config-DCq4JySZ.js.map +1 -1
  55. package/dist/chunks/config-DGC00bTp.js.map +1 -1
  56. package/dist/chunks/config-DIDz_E5m.js.map +1 -1
  57. package/dist/chunks/config-DM0lsduD.js.map +1 -1
  58. package/dist/chunks/config-DNDgp9bB.js.map +1 -1
  59. package/dist/chunks/config-DOYz_SVK.js.map +1 -1
  60. package/dist/chunks/config-DRbojEzO.js.map +1 -1
  61. package/dist/chunks/config-DUNH02Fg.js.map +1 -1
  62. package/dist/chunks/config-DUbbGcfw.js.map +1 -1
  63. package/dist/chunks/config-DVCNvhIG.js.map +1 -0
  64. package/dist/chunks/config-DWL81-aM.js.map +1 -1
  65. package/dist/chunks/config-DZCUPHPU.js.map +1 -1
  66. package/dist/chunks/config-DeyT9dJl.js.map +1 -1
  67. package/dist/chunks/config-DolULhjJ.js.map +1 -1
  68. package/dist/chunks/config-DpAYidyY.js.map +1 -0
  69. package/dist/chunks/config-Droqn55j.js.map +1 -1
  70. package/dist/chunks/config-DwABJHEo.js.map +1 -1
  71. package/dist/chunks/config-E1cTyRVV.js.map +1 -1
  72. package/dist/chunks/config-MmPym-Z7.js.map +1 -0
  73. package/dist/chunks/config-QaIc_gRa.js.map +1 -1
  74. package/dist/chunks/config-Yy67uWHY.js.map +1 -1
  75. package/dist/chunks/config-Z5LeUXys.js.map +1 -1
  76. package/dist/chunks/config-_jbgsFpw.js.map +1 -1
  77. package/dist/chunks/config-eXB87DOi.js.map +1 -1
  78. package/dist/chunks/config-rLkc9Zn2.js.map +1 -1
  79. package/dist/chunks/{context-CTbuwcYs.js → context-CPMRfwVr.js} +1 -1
  80. package/dist/chunks/{context-CTbuwcYs.js.map → context-CPMRfwVr.js.map} +1 -1
  81. package/dist/chunks/{grModalStyles-EZfuEiw_.js → grModalStyles-BEkiFal_.js} +10 -1
  82. package/dist/chunks/grModalStyles-BEkiFal_.js.map +1 -0
  83. package/dist/chunks/{grRadioStyles-DGL2QLy6.js → grRadioStyles-BwRyCjQQ.js} +4 -2
  84. package/dist/chunks/{grRadioStyles-DGL2QLy6.js.map → grRadioStyles-BwRyCjQQ.js.map} +1 -1
  85. package/dist/chunks/{granular-provider-DCn6fgEs.js → granular-provider-DP2gk0oa.js} +10 -9
  86. package/dist/chunks/{granular-provider-DCn6fgEs.js.map → granular-provider-DP2gk0oa.js.map} +1 -1
  87. package/dist/chunks/{overlayStack-0CZS99Da.js → overlayStack-B_UFaFzk.js} +65 -24
  88. package/dist/chunks/overlayStack-B_UFaFzk.js.map +1 -0
  89. package/dist/chunks/{renamedProp-BwcN-SJg.js → renamedProp-Dy96tT-F.js} +1 -1
  90. package/dist/chunks/{renamedProp-BwcN-SJg.js.map → renamedProp-Dy96tT-F.js.map} +1 -1
  91. package/dist/chunks/{useModalOverlay-BnAGZpcI.js → useModalOverlay-BwX8WEcI.js} +3 -3
  92. package/dist/chunks/{useModalOverlay-BnAGZpcI.js.map → useModalOverlay-BwX8WEcI.js.map} +1 -1
  93. package/dist/chunks/{usePortalTarget-C0p-mhaM.js → usePortalTarget-BhrRgdqW.js} +1 -1
  94. package/dist/chunks/{usePortalTarget-C0p-mhaM.js.map → usePortalTarget-BhrRgdqW.js.map} +1 -1
  95. package/dist/chunks/{validation-5HhpanPP.js → validation-BDjqsuGB.js} +1 -1
  96. package/dist/chunks/{validation-5HhpanPP.js.map → validation-BDjqsuGB.js.map} +1 -1
  97. package/dist/components/GrAlert/chunks/{GrAlert-FAVf-ksH.js → GrAlert-D72y1IEh.js} +1 -1
  98. package/dist/components/GrAlert/chunks/{GrAlert-FAVf-ksH.js.map → GrAlert-D72y1IEh.js.map} +1 -1
  99. package/dist/components/GrAlert/index.js +1 -1
  100. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-BQsSE7sj.js → GrAutocomplete-BpmFmpKs.js} +4 -6
  101. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-BQsSE7sj.js.map → GrAutocomplete-BpmFmpKs.js.map} +1 -1
  102. package/dist/components/GrAutocomplete/index.js +1 -1
  103. package/dist/components/GrAvatar/chunks/{GrAvatar-CNmLmgcr.js → GrAvatar-dWEXiCJG.js} +1 -1
  104. package/dist/components/GrAvatar/chunks/{GrAvatar-CNmLmgcr.js.map → GrAvatar-dWEXiCJG.js.map} +1 -1
  105. package/dist/components/GrAvatar/index.js +1 -1
  106. package/dist/components/GrBadge/chunks/{GrBadge-DpUDXKbq.js → GrBadge-DBeQXEir.js} +2 -2
  107. package/dist/components/GrBadge/chunks/{GrBadge-DpUDXKbq.js.map → GrBadge-DBeQXEir.js.map} +1 -1
  108. package/dist/components/GrBadge/index.js +1 -1
  109. package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-B-A3PRkE.js → GrBadgeWrap-wdfxaXiu.js} +3 -1
  110. package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-B-A3PRkE.js.map → GrBadgeWrap-wdfxaXiu.js.map} +1 -1
  111. package/dist/components/GrBadgeWrap/index.js +1 -1
  112. package/dist/components/GrBottomNav/chunks/{GrBottomNav-wtFatLjB.js → GrBottomNav-nE08pVUJ.js} +1 -1
  113. package/dist/components/GrBottomNav/chunks/{GrBottomNav-wtFatLjB.js.map → GrBottomNav-nE08pVUJ.js.map} +1 -1
  114. package/dist/components/GrBottomNav/index.js +1 -1
  115. package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-DRDNan_n.js → GrBreadcrumbs-DOpwY2EF.js} +3 -3
  116. package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-DRDNan_n.js.map → GrBreadcrumbs-DOpwY2EF.js.map} +1 -1
  117. package/dist/components/GrBreadcrumbs/index.js +1 -1
  118. package/dist/components/GrButton/chunks/{GrButton-7GP0zObj.js → GrButton-CS4TqMtG.js} +1 -1
  119. package/dist/components/GrButton/chunks/{GrButton-7GP0zObj.js.map → GrButton-CS4TqMtG.js.map} +1 -1
  120. package/dist/components/GrButton/index.js +1 -1
  121. package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js.map +1 -1
  122. package/dist/components/GrButtonGroup/index.js +1 -1
  123. package/dist/components/GrCard/chunks/{GrCard-BttXz1pQ.js → GrCard-Ck5--lMF.js} +2 -2
  124. package/dist/components/GrCard/chunks/{GrCard-BttXz1pQ.js.map → GrCard-Ck5--lMF.js.map} +1 -1
  125. package/dist/components/GrCard/index.js +1 -1
  126. package/dist/components/GrCheckbox/chunks/{GrCheckbox-CEcHIsXM.js → GrCheckbox-Dp201frb.js} +1 -1
  127. package/dist/components/GrCheckbox/chunks/{GrCheckbox-CEcHIsXM.js.map → GrCheckbox-Dp201frb.js.map} +1 -1
  128. package/dist/components/GrCheckbox/index.js +1 -1
  129. package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-BOwrVcFr.js → GrCheckboxGroup-IpqG5qwm.js} +2 -2
  130. package/dist/components/GrCheckboxGroup/chunks/{GrCheckboxGroup-BOwrVcFr.js.map → GrCheckboxGroup-IpqG5qwm.js.map} +1 -1
  131. package/dist/components/GrCheckboxGroup/index.js +1 -1
  132. package/dist/components/GrChip/chunks/{GrChip-BTivtwff.js → GrChip-CKqyzYcv.js} +10 -7
  133. package/dist/components/GrChip/chunks/{GrChip-BTivtwff.js.map → GrChip-CKqyzYcv.js.map} +1 -1
  134. package/dist/components/GrChip/index.js +1 -1
  135. package/dist/components/GrChipGroup/chunks/{GrChipGroup-C78Vcwos.js → GrChipGroup-dDGwnC04.js} +1 -1
  136. package/dist/components/GrChipGroup/chunks/{GrChipGroup-C78Vcwos.js.map → GrChipGroup-dDGwnC04.js.map} +1 -1
  137. package/dist/components/GrChipGroup/index.js +1 -1
  138. package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-Dp0eEBTZ.js → GrCodeBlock-BUOwKwQE.js} +2 -2
  139. package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-Dp0eEBTZ.js.map → GrCodeBlock-BUOwKwQE.js.map} +1 -1
  140. package/dist/components/GrCodeBlock/index.js +1 -1
  141. package/dist/components/GrCollapse/chunks/{GrCollapse-BlW6ybdL.js → GrCollapse-DWH3QAnU.js} +6 -5
  142. package/dist/components/GrCollapse/chunks/{GrCollapse-BlW6ybdL.js.map → GrCollapse-DWH3QAnU.js.map} +1 -1
  143. package/dist/components/GrCollapse/index.js +1 -1
  144. package/dist/components/GrColorPicker/chunks/{GrColorPicker-CIgdPXHn.js → GrColorPicker-BNtpj_P6.js} +4 -4
  145. package/dist/components/GrColorPicker/chunks/{GrColorPicker-CIgdPXHn.js.map → GrColorPicker-BNtpj_P6.js.map} +1 -1
  146. package/dist/components/GrColorPicker/index.js +1 -1
  147. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BZHUKlux.js → GrCommandPalette-BVZEd4yy.js} +7 -7
  148. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BZHUKlux.js.map → GrCommandPalette-BVZEd4yy.js.map} +1 -1
  149. package/dist/components/GrCommandPalette/index.js +1 -1
  150. package/dist/components/GrConfigProvider/chunks/{GrConfigProvider-BF7R3hgg.js → GrConfigProvider-t9x2UToH.js} +13 -12
  151. package/dist/components/GrConfigProvider/chunks/{GrConfigProvider-BF7R3hgg.js.map → GrConfigProvider-t9x2UToH.js.map} +1 -1
  152. package/dist/components/GrConfigProvider/index.js +2 -2
  153. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-jRDs_E6C.js → GrConfirmDialog-K5ht2cYq.js} +4 -4
  154. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-jRDs_E6C.js.map → GrConfirmDialog-K5ht2cYq.js.map} +1 -1
  155. package/dist/components/GrConfirmDialog/index.js +1 -1
  156. package/dist/components/GrContextMenu/chunks/{GrContextMenu-DlFWm0eW.js → GrContextMenu-Dd2tgMoL.js} +1 -1
  157. package/dist/components/GrContextMenu/chunks/{GrContextMenu-DlFWm0eW.js.map → GrContextMenu-Dd2tgMoL.js.map} +1 -1
  158. package/dist/components/GrContextMenu/index.js +1 -1
  159. package/dist/components/GrDataTable/chunks/{GrDataTable-4JAgOQ-7.js → GrDataTable-BYYG_XZA.js} +5 -5
  160. package/dist/components/GrDataTable/chunks/{GrDataTable-4JAgOQ-7.js.map → GrDataTable-BYYG_XZA.js.map} +1 -1
  161. package/dist/components/GrDataTable/index.js +1 -1
  162. package/dist/components/GrDelta/chunks/{GrDelta-BZwkgQW-.js → GrDelta-BpfqebEV.js} +0 -0
  163. package/dist/components/GrDelta/chunks/{GrDelta-BZwkgQW-.js.map → GrDelta-BpfqebEV.js.map} +1 -1
  164. package/dist/components/GrDelta/index.js +1 -1
  165. package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-BMeCgFV3.js → GrDescriptionList-D8ANFpn_.js} +2 -2
  166. package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-BMeCgFV3.js.map → GrDescriptionList-D8ANFpn_.js.map} +1 -1
  167. package/dist/components/GrDescriptionList/index.js +2 -2
  168. package/dist/components/GrDialog/chunks/{GrDialog-C01Hhk6G.js → GrDialog-CeJubnKJ.js} +3 -3
  169. package/dist/components/GrDialog/chunks/{GrDialog-C01Hhk6G.js.map → GrDialog-CeJubnKJ.js.map} +1 -1
  170. package/dist/components/GrDialog/index.js +1 -1
  171. package/dist/components/GrDialogService/chunks/{GrDialogService-CmsJNUmM.js → GrDialogService-BArvw1DV.js} +9 -8
  172. package/dist/components/GrDialogService/chunks/{GrDialogService-CmsJNUmM.js.map → GrDialogService-BArvw1DV.js.map} +1 -1
  173. package/dist/components/GrDialogService/index.js +1 -1
  174. package/dist/components/GrDivider/chunks/{GrDivider-BXavGcMX.js → GrDivider-DxA-zV25.js} +1 -1
  175. package/dist/components/GrDivider/chunks/{GrDivider-BXavGcMX.js.map → GrDivider-DxA-zV25.js.map} +1 -1
  176. package/dist/components/GrDivider/index.js +1 -1
  177. package/dist/components/GrDrawer/chunks/{GrDrawer-xfoy-MCj.js → GrDrawer-BBHNgeH0.js} +5 -5
  178. package/dist/components/GrDrawer/chunks/{GrDrawer-xfoy-MCj.js.map → GrDrawer-BBHNgeH0.js.map} +1 -1
  179. package/dist/components/GrDrawer/index.js +1 -1
  180. package/dist/components/GrDropdown/chunks/{GrDropdown-7r772-Cq.js → GrDropdown-CUlviqMi.js} +6 -8
  181. package/dist/components/GrDropdown/chunks/{GrDropdown-7r772-Cq.js.map → GrDropdown-CUlviqMi.js.map} +1 -1
  182. package/dist/components/GrDropdown/index.js +1 -1
  183. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DNurbsWc.js → GrDropdownMenu-COOR1LCs.js} +1 -1
  184. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-DNurbsWc.js.map → GrDropdownMenu-COOR1LCs.js.map} +1 -1
  185. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js.map +1 -1
  186. package/dist/components/GrDropdownMenu/index.js +1 -1
  187. package/dist/components/GrEmptyState/chunks/{GrEmptyState-RqsWvgI9.js → GrEmptyState-BbvwE-E0.js} +2 -2
  188. package/dist/components/GrEmptyState/chunks/{GrEmptyState-RqsWvgI9.js.map → GrEmptyState-BbvwE-E0.js.map} +1 -1
  189. package/dist/components/GrEmptyState/index.js +1 -1
  190. package/dist/components/GrFilePreview/chunks/{GrFilePreview-C9Z7hMK8.js → GrFilePreview-PabkLgYX.js} +1 -1
  191. package/dist/components/GrFilePreview/chunks/{GrFilePreview-C9Z7hMK8.js.map → GrFilePreview-PabkLgYX.js.map} +1 -1
  192. package/dist/components/GrFilePreview/index.js +1 -1
  193. package/dist/components/GrFileUpload/chunks/{GrFileUpload-LL8RZvC0.js → GrFileUpload-BwMR71zN.js} +4 -4
  194. package/dist/components/GrFileUpload/chunks/{GrFileUpload-LL8RZvC0.js.map → GrFileUpload-BwMR71zN.js.map} +1 -1
  195. package/dist/components/GrFileUpload/index.js +1 -1
  196. package/dist/components/GrForm/chunks/{GrForm-CrnfCsgj.js → GrForm-xTtavR-K.js} +1 -1
  197. package/dist/components/GrForm/chunks/{GrForm-CrnfCsgj.js.map → GrForm-xTtavR-K.js.map} +1 -1
  198. package/dist/components/GrForm/index.js +2 -2
  199. package/dist/components/GrFormField/chunks/{GrFormField-DSylU7IU.js → GrFormField-DO61vxpS.js} +2 -2
  200. package/dist/components/GrFormField/chunks/{GrFormField-DSylU7IU.js.map → GrFormField-DO61vxpS.js.map} +1 -1
  201. package/dist/components/GrFormField/index.js +1 -1
  202. package/dist/components/GrFormFile/chunks/{GrFormFile-B1jGZyIj.js → GrFormFile-Dlxx-9zi.js} +3 -3
  203. package/dist/components/GrFormFile/chunks/{GrFormFile-B1jGZyIj.js.map → GrFormFile-Dlxx-9zi.js.map} +1 -1
  204. package/dist/components/GrFormFile/index.js +1 -1
  205. package/dist/components/GrFormSection/chunks/{GrFormSection-ejieOg9H.js → GrFormSection-DV1S6R_N.js} +1 -1
  206. package/dist/components/GrFormSection/chunks/{GrFormSection-ejieOg9H.js.map → GrFormSection-DV1S6R_N.js.map} +1 -1
  207. package/dist/components/GrFormSection/index.js +1 -1
  208. package/dist/components/GrIcon/chunks/{GrIcon-Dmf0c9ba.js → GrIcon-DTZIgmje.js} +1 -1
  209. package/dist/components/GrIcon/chunks/{GrIcon-Dmf0c9ba.js.map → GrIcon-DTZIgmje.js.map} +1 -1
  210. package/dist/components/GrIcon/index.js +1 -1
  211. package/dist/components/GrImageViewer/chunks/{GrImageViewer--BU8yrfx.js → GrImageViewer-BjYw-uTF.js} +2 -4
  212. package/dist/components/GrImageViewer/chunks/{GrImageViewer--BU8yrfx.js.map → GrImageViewer-BjYw-uTF.js.map} +1 -1
  213. package/dist/components/GrImageViewer/index.js +1 -1
  214. package/dist/components/GrInput/chunks/{GrInput-BLywRZUN.js → GrInput-TFeBm3gQ.js} +2 -1
  215. package/dist/components/GrInput/chunks/{GrInput-BLywRZUN.js.map → GrInput-TFeBm3gQ.js.map} +1 -1
  216. package/dist/components/GrInput/index.js +1 -1
  217. package/dist/components/GrInputTag/chunks/{GrInputTag-ByD9NugQ.js → GrInputTag-DhfUNOA5.js} +3 -3
  218. package/dist/components/GrInputTag/chunks/{GrInputTag-ByD9NugQ.js.map → GrInputTag-DhfUNOA5.js.map} +1 -1
  219. package/dist/components/GrInputTag/index.js +1 -1
  220. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-BCZ7lE2k.js → GrJsonViewer-CdtmUpZ3.js} +6 -6
  221. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-BCZ7lE2k.js.map → GrJsonViewer-CdtmUpZ3.js.map} +1 -1
  222. package/dist/components/GrJsonViewer/index.js +2 -2
  223. package/dist/components/GrKbd/chunks/{GrKbd-D2ga1H9i.js → GrKbd-D_a1mPLe.js} +1 -1
  224. package/dist/components/GrKbd/chunks/{GrKbd-D2ga1H9i.js.map → GrKbd-D_a1mPLe.js.map} +1 -1
  225. package/dist/components/GrKbd/index.js +1 -1
  226. package/dist/components/GrLink/chunks/{GrLink-DYXw3W9w.js → GrLink-DwWErumU.js} +2 -2
  227. package/dist/components/GrLink/chunks/{GrLink-DYXw3W9w.js.map → GrLink-DwWErumU.js.map} +1 -1
  228. package/dist/components/GrLink/index.js +2 -2
  229. package/dist/components/GrList/chunks/{GrList-B_CRJB4c.js → GrList-Unya-LXb.js} +3 -3
  230. package/dist/components/GrList/chunks/{GrList-B_CRJB4c.js.map → GrList-Unya-LXb.js.map} +1 -1
  231. package/dist/components/GrList/index.js +1 -1
  232. package/dist/components/GrLoading/chunks/{GrLoading-CMD3Ri9P.js → GrLoading-BDrlrup_.js} +1 -1
  233. package/dist/components/GrLoading/chunks/{GrLoading-CMD3Ri9P.js.map → GrLoading-BDrlrup_.js.map} +1 -1
  234. package/dist/components/GrLoading/index.js +1 -1
  235. package/dist/components/GrModal/chunks/{GrModal-_JrDhon-.js → GrModal-xIWaJozo.js} +7 -6
  236. package/dist/components/GrModal/chunks/GrModal-xIWaJozo.js.map +1 -0
  237. package/dist/components/GrModal/index.js +2 -2
  238. package/dist/components/GrNavbar/chunks/{GrNavbar-Dr8e5kW-.js → GrNavbar-BRGuksiy.js} +3 -3
  239. package/dist/components/GrNavbar/chunks/{GrNavbar-Dr8e5kW-.js.map → GrNavbar-BRGuksiy.js.map} +1 -1
  240. package/dist/components/GrNavbar/index.js +1 -1
  241. package/dist/components/GrNumberInput/chunks/{GrNumberInput-DQ59YICu.js → GrNumberInput-BqPydXpK.js} +7 -9
  242. package/dist/components/GrNumberInput/chunks/{GrNumberInput-DQ59YICu.js.map → GrNumberInput-BqPydXpK.js.map} +1 -1
  243. package/dist/components/GrNumberInput/index.js +2 -2
  244. package/dist/components/GrPagination/chunks/{GrPagination-gBoWVHk6.js → GrPagination-DhbNZHEF.js} +26 -11
  245. package/dist/components/GrPagination/chunks/GrPagination-DhbNZHEF.js.map +1 -0
  246. package/dist/components/GrPagination/index.js +1 -1
  247. package/dist/components/GrPopover/chunks/{GrPopover-DEFxDffj.js → GrPopover-BakLcWkX.js} +3 -3
  248. package/dist/components/GrPopover/chunks/{GrPopover-DEFxDffj.js.map → GrPopover-BakLcWkX.js.map} +1 -1
  249. package/dist/components/GrPopover/index.js +2 -2
  250. package/dist/components/GrProgressBar/chunks/{GrProgressBar-hszUOC8f.js → GrProgressBar-C3NRBqIP.js} +6 -3
  251. package/dist/components/GrProgressBar/chunks/GrProgressBar-C3NRBqIP.js.map +1 -0
  252. package/dist/components/GrProgressBar/index.js +1 -1
  253. package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-D3yWXYDa.js → GrProgressCircle-CdvbINQc.js} +2 -2
  254. package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-D3yWXYDa.js.map → GrProgressCircle-CdvbINQc.js.map} +1 -1
  255. package/dist/components/GrProgressCircle/index.js +1 -1
  256. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-CailXSqW.js → GrPromptDialog-C9Y1ifE_.js} +8 -8
  257. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-CailXSqW.js.map → GrPromptDialog-C9Y1ifE_.js.map} +1 -1
  258. package/dist/components/GrPromptDialog/index.js +1 -1
  259. package/dist/components/GrRadio/chunks/{GrRadio-Aq3v8XgG.js → GrRadio-B1776V9D.js} +2 -2
  260. package/dist/components/GrRadio/chunks/{GrRadio-Aq3v8XgG.js.map → GrRadio-B1776V9D.js.map} +1 -1
  261. package/dist/components/GrRadio/index.js +2 -2
  262. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-y9LVdTWh.js → GrRadioGroup-UgitrBFl.js} +2 -2
  263. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-y9LVdTWh.js.map → GrRadioGroup-UgitrBFl.js.map} +1 -1
  264. package/dist/components/GrRadioGroup/index.js +1 -1
  265. package/dist/components/GrRating/chunks/{GrRating-IEiTOdnF.js → GrRating-DTriyyqG.js} +1 -1
  266. package/dist/components/GrRating/chunks/{GrRating-IEiTOdnF.js.map → GrRating-DTriyyqG.js.map} +1 -1
  267. package/dist/components/GrRating/index.js +1 -1
  268. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DMeOWlzj.js → GrResponseErrorBanner-NEEJZ8zi.js} +2 -2
  269. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DMeOWlzj.js.map → GrResponseErrorBanner-NEEJZ8zi.js.map} +1 -1
  270. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-CBVRpgIG.js → GrResponseErrorBanner-ZvBvEQDZ.js} +1 -1
  271. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-CBVRpgIG.js.map → GrResponseErrorBanner-ZvBvEQDZ.js.map} +1 -1
  272. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  273. package/dist/components/GrSegmented/chunks/{GrSegmented-CB-VR-yL.js → GrSegmented-NKTi9bMG.js} +1 -1
  274. package/dist/components/GrSegmented/chunks/{GrSegmented-CB-VR-yL.js.map → GrSegmented-NKTi9bMG.js.map} +1 -1
  275. package/dist/components/GrSegmented/index.js +1 -1
  276. package/dist/components/GrSelect/chunks/{GrSelect-CZqV1Eg4.js → GrSelect-Do1iAyp1.js} +8 -12
  277. package/dist/components/GrSelect/chunks/GrSelect-Do1iAyp1.js.map +1 -0
  278. package/dist/components/GrSelect/index.js +1 -1
  279. package/dist/components/GrSelect/styles.css +1 -1
  280. package/dist/components/GrSidebar/chunks/{GrSidebar-alkwBUzL.js → GrSidebar-DoKLlHSw.js} +2 -2
  281. package/dist/components/GrSidebar/chunks/{GrSidebar-alkwBUzL.js.map → GrSidebar-DoKLlHSw.js.map} +1 -1
  282. package/dist/components/GrSidebar/index.js +1 -1
  283. package/dist/components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js.map +1 -1
  284. package/dist/components/GrSlider/chunks/{GrSlider-DTTrZTHK.js → GrSlider-Db-jACXz.js} +14 -6
  285. package/dist/components/GrSlider/chunks/GrSlider-Db-jACXz.js.map +1 -0
  286. package/dist/components/GrSlider/index.js +1 -1
  287. package/dist/components/GrSortableList/chunks/{GrSortableList-HyKX--rO.js → GrSortableList-CQCaWivn.js} +1 -1
  288. package/dist/components/GrSortableList/chunks/{GrSortableList-HyKX--rO.js.map → GrSortableList-CQCaWivn.js.map} +1 -1
  289. package/dist/components/GrSortableList/index.js +1 -1
  290. package/dist/components/GrSplitter/chunks/{GrSplitter-MltjaADn.js → GrSplitter-C-XQzq7q.js} +1 -1
  291. package/dist/components/GrSplitter/chunks/{GrSplitter-MltjaADn.js.map → GrSplitter-C-XQzq7q.js.map} +1 -1
  292. package/dist/components/GrSplitter/index.js +1 -1
  293. package/dist/components/GrStatistic/chunks/{GrStatistic-qHVasK37.js → GrStatistic-C1_nY4Gc.js} +8 -4
  294. package/dist/components/GrStatistic/chunks/GrStatistic-C1_nY4Gc.js.map +1 -0
  295. package/dist/components/GrStatistic/index.js +1 -1
  296. package/dist/components/GrSteps/chunks/{GrSteps-C2jxpZoN.js → GrSteps-DXj7m-WO.js} +2 -2
  297. package/dist/components/GrSteps/chunks/{GrSteps-C2jxpZoN.js.map → GrSteps-DXj7m-WO.js.map} +1 -1
  298. package/dist/components/GrSteps/index.js +1 -1
  299. package/dist/components/GrSwitch/chunks/{GrSwitch-7Oe5QfQZ.js → GrSwitch-CriHWT2A.js} +1 -1
  300. package/dist/components/GrSwitch/chunks/{GrSwitch-7Oe5QfQZ.js.map → GrSwitch-CriHWT2A.js.map} +1 -1
  301. package/dist/components/GrSwitch/index.js +1 -1
  302. package/dist/components/GrTabPanels/chunks/{GrTabPanels-BZQS8-JM.js → GrTabPanels-5zsbqS1v.js} +1 -1
  303. package/dist/components/GrTabPanels/chunks/{GrTabPanels-BZQS8-JM.js.map → GrTabPanels-5zsbqS1v.js.map} +1 -1
  304. package/dist/components/GrTabPanels/index.js +1 -1
  305. package/dist/components/GrTable/chunks/{GrTable-jhUTczjv.js → GrTable-iwzHvlMC.js} +1 -1
  306. package/dist/components/GrTable/chunks/{GrTable-jhUTczjv.js.map → GrTable-iwzHvlMC.js.map} +1 -1
  307. package/dist/components/GrTable/index.js +1 -1
  308. package/dist/components/GrTabs/chunks/{GrTabs-CT2nk_HV.js → GrTabs-DHfv67cp.js} +1 -1
  309. package/dist/components/GrTabs/chunks/{GrTabs-CT2nk_HV.js.map → GrTabs-DHfv67cp.js.map} +1 -1
  310. package/dist/components/GrTabs/index.js +1 -1
  311. package/dist/components/GrTextarea/chunks/{GrTextarea-DinXG12-.js → GrTextarea-BII3w61K.js} +1 -1
  312. package/dist/components/GrTextarea/chunks/{GrTextarea-DinXG12-.js.map → GrTextarea-BII3w61K.js.map} +1 -1
  313. package/dist/components/GrTextarea/index.js +1 -1
  314. package/dist/components/GrTimeline/chunks/{GrTimeline-BiHpArsg.js → GrTimeline-Bs60huw0.js} +2 -2
  315. package/dist/components/GrTimeline/chunks/{GrTimeline-BiHpArsg.js.map → GrTimeline-Bs60huw0.js.map} +1 -1
  316. package/dist/components/GrTimeline/index.js +1 -1
  317. package/dist/components/GrToaster/chunks/{GrToaster-COXIBKzq.js → GrToaster-D-sV-9of.js} +4 -4
  318. package/dist/components/GrToaster/chunks/{GrToaster-COXIBKzq.js.map → GrToaster-D-sV-9of.js.map} +1 -1
  319. package/dist/components/GrToaster/index.js +1 -1
  320. package/dist/components/GrTooltip/chunks/{GrTooltip-uYETdbCD.js → GrTooltip-BUiTbROv.js} +3 -3
  321. package/dist/components/GrTooltip/chunks/{GrTooltip-uYETdbCD.js.map → GrTooltip-BUiTbROv.js.map} +1 -1
  322. package/dist/components/GrTooltip/index.js +1 -1
  323. package/dist/components/GrTree/chunks/{GrTree-Ci6CZfKR.js → GrTree-CkELQwR8.js} +1 -2
  324. package/dist/components/GrTree/chunks/{GrTree-Ci6CZfKR.js.map → GrTree-CkELQwR8.js.map} +1 -1
  325. package/dist/components/GrTree/index.js +1 -1
  326. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DOXcpWq2.js → GrTreeSelect-DurwZ7Cz.js} +4 -4
  327. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DOXcpWq2.js.map → GrTreeSelect-DurwZ7Cz.js.map} +1 -1
  328. package/dist/components/GrTreeSelect/index.js +1 -1
  329. package/dist/components/GrValue/chunks/GrValue-ezkQM05Q.js.map +1 -1
  330. package/dist/composables/useFloating.js +1 -1
  331. package/dist/composables/useGrComponentConfig.js +1 -1
  332. package/dist/composables/useOverlayLayer.js +1 -1
  333. package/dist/composables/usePortalTarget.js +1 -1
  334. package/dist/composables/useTheme.js +1 -1
  335. package/dist/composables/useTheme.js.map +1 -1
  336. package/dist/composables/useToast.js +1 -1
  337. package/dist/composables/useToast.js.map +1 -1
  338. package/dist/composables/useVirtualList.js +3 -5
  339. package/dist/composables/useVirtualList.js.map +1 -1
  340. package/dist/directives/loading.js +1 -1
  341. package/dist/granular-provider-node.js +1 -1
  342. package/dist/granular-provider.js +1 -1
  343. package/dist/index.js +87 -87
  344. package/dist/testing.js +1 -1
  345. package/dist/testing.js.map +1 -1
  346. package/dist/types/components/GrDialog/GrDialog.vue.d.ts +1 -1
  347. package/dist/types/components/GrDrawer/GrDrawer.vue.d.ts +1 -1
  348. package/dist/types/components/GrModal/GrModal.vue.d.ts +1 -1
  349. package/dist/types/components/GrModal/grModalStyles.d.ts +9 -0
  350. package/dist/types/components/GrProgressBar/GrProgressBar.vue.d.ts +1 -1
  351. package/dist/types/internal/devHook.d.ts +53 -0
  352. package/dist/vue/index.js +2 -2
  353. package/dist/vue/index.js.map +1 -1
  354. package/dist/web-types.json +2 -2
  355. package/package.json +17 -17
  356. package/dist/chunks/config-CQLNjc9X2.js.map +0 -1
  357. package/dist/chunks/config-CnYdE3HZ2.js.map +0 -1
  358. package/dist/chunks/config-CuQmUkMw2.js.map +0 -1
  359. package/dist/chunks/config-DBmdgoVf2.js.map +0 -1
  360. package/dist/chunks/config-DVCNvhIG2.js.map +0 -1
  361. package/dist/chunks/config-DpAYidyY2.js.map +0 -1
  362. package/dist/chunks/config-MmPym-Z72.js.map +0 -1
  363. package/dist/chunks/config-mlheIMtV.js.map +0 -1
  364. package/dist/chunks/grModalStyles-EZfuEiw_.js.map +0 -1
  365. package/dist/chunks/overlayStack-0CZS99Da.js.map +0 -1
  366. package/dist/components/GrModal/chunks/GrModal-_JrDhon-.js.map +0 -1
  367. package/dist/components/GrPagination/chunks/GrPagination-gBoWVHk6.js.map +0 -1
  368. package/dist/components/GrProgressBar/chunks/GrProgressBar-hszUOC8f.js.map +0 -1
  369. package/dist/components/GrSelect/chunks/GrSelect-CZqV1Eg4.js.map +0 -1
  370. package/dist/components/GrSlider/chunks/GrSlider-DTTrZTHK.js.map +0 -1
  371. package/dist/components/GrStatistic/chunks/GrStatistic-qHVasK37.js.map +0 -1
  372. /package/dist/chunks/{config-CQLNjc9X2.js → config-CQLNjc9X.js} +0 -0
  373. /package/dist/chunks/{config-CnYdE3HZ2.js → config-CnYdE3HZ.js} +0 -0
  374. /package/dist/chunks/{config-DBmdgoVf2.js → config-DBmdgoVf.js} +0 -0
  375. /package/dist/chunks/{config-DVCNvhIG2.js → config-DVCNvhIG.js} +0 -0
  376. /package/dist/chunks/{config-DpAYidyY2.js → config-DpAYidyY.js} +0 -0
  377. /package/dist/chunks/{config-MmPym-Z72.js → config-MmPym-Z7.js} +0 -0
@@ -1,9 +1,9 @@
1
- import { a as useGrComponentSize } from "../../../chunks/context-CTbuwcYs.js";
1
+ import { a as useGrComponentSize } from "../../../chunks/context-CPMRfwVr.js";
2
2
  import { vClickOutside } from "../../../directives/clickOutside.js";
3
3
  import { createFloatingAnchor, useFloating } from "../../../composables/useFloating.js";
4
4
  import { t as useControlledOpen } from "../../../chunks/useControlledOpen-DV3SqLTP.js";
5
5
  import { n as panelPopTransition } from "../../../chunks/overlayPanelSurface-BKeMhRx4.js";
6
- import { t as useModalOverlay } from "../../../chunks/useModalOverlay-BnAGZpcI.js";
6
+ import { t as useModalOverlay } from "../../../chunks/useModalOverlay-BwX8WEcI.js";
7
7
  import { t as grPopoverPanelClass } from "../../../chunks/grPopoverStyles-CYAeO3Ov.js";
8
8
  import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, mergeProps, nextTick, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderSlot, unref, useId, useSlots, vShow, watch, withCtx, withDirectives } from "vue";
9
9
  //#region src/components/GrPopover/GrPopover.vue?vue&type=script&setup=true&lang.ts
@@ -233,7 +233,7 @@ var GrPopover_default = /* @__PURE__ */ defineComponent({
233
233
  scheduleHover(false, props.closeDelay);
234
234
  }
235
235
  onMounted(() => {
236
- if (!(typeof process !== "undefined" && process.env.NODE_ENV !== "production") || !hasTrigger.value || hasBoundTrigger()) return;
236
+ if (!(process.env.NODE_ENV !== "production") || !hasTrigger.value || hasBoundTrigger()) return;
237
237
  console.warn("[GrPopover] триггер не привязан: добавьте `v-bind=\"triggerProps\"` на элемент внутри слота #trigger — <template #trigger=\"{ triggerProps }\"><GrButton v-bind=\"triggerProps\">…</GrButton></template>. Клик по обёртке пока работает, но у триггера нет ни клавиатуры, ни aria-haspopup/aria-expanded, а клик по вложенным элементам открывает панель.");
238
238
  });
239
239
  onBeforeUnmount(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"GrPopover-DEFxDffj.js","names":[],"sources":["../../../../src/components/GrPopover/GrPopover.vue","../../../../src/components/GrPopover/GrPopover.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrPopover — якорный немодальный оверлей с произвольным содержимым.\n *\n * Роль «универсального поповера» до сих пор насильно исполнял `GrDropdown`, но\n * он про меню: жёстко объявляет `role=\"menu\"`, `aria-haspopup=\"menu\"` и водит\n * фокус по пунктам. Для формы, подтверждения или палитры это неверная семантика.\n *\n * Здесь наоборот: позиционирование, слой и закрытие берёт на себя примитив, а\n * клавиатурный паттерн внутри панели остаётся за потребителем — поэтому `role`\n * задаётся пропом. На этом собираются `GrMenu` / `GrContextMenu` /\n * `GrColorPicker` / Popconfirm.\n *\n * A11y:\n * - триггер получает `aria-haspopup`/`aria-expanded`/`aria-controls` через\n * `triggerProps` (биндится на реальный фокусируемый элемент в слоте);\n * - панель — `role=\"dialog\"` по умолчанию и обязательное доступное имя\n * (`ariaLabel` либо `aria-labelledby` через `labelledBy`);\n * - Esc закрывает верхний слой стека, клик вне — закрывает по точке попадания;\n * - **по умолчанию фокус-ловушки нет намеренно**: Tab обязан уводить фокус\n * наружу, иначе немодальный слой запирает пользователя на странице, которая\n * не заблокирована. Проп `modal` включает второй режим — см. ниже.\n */\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, useSlots, watch } from 'vue'\n\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport { createFloatingAnchor, type GrFloatingAnchorRect, useFloating, type UseFloatingPlacement } from '../../composables/useFloating'\nimport { vClickOutside } from '../../directives'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport {\n type GrPopoverPadding,\n type GrPopoverRole,\n type GrPopoverSize,\n grPopoverPanelClass,\n} from './grPopoverStyles'\n\nexport interface GrPopoverProps {\n /**\n * Открыт ли поповер. Без этого пропа компонент ведёт состояние сам\n * (uncontrolled), с ним — слушайте `update:open`.\n */\n open?: boolean\n placement?: UseFloatingPlacement\n /** Зазор между триггером и панелью, px. */\n offsetPx?: number\n size?: GrPopoverSize\n /** Роль панели. Меняется теми, кто строит поверх примитива своё меню/список. */\n role?: GrPopoverRole\n /**\n * Модальный режим: фон уходит в `inert`, Tab ходит по кругу внутри панели,\n * скролл страницы блокируется, а слой встаёт в стек модальным — как окно.\n * Нужен поповеру с формой или подтверждением внутри: без изоляции фона\n * пользователь уводит фокус на страницу, к которой поповер и относится.\n *\n * В этом режиме фокус переносится в панель независимо от `autoFocus`: фон\n * недоступен, и слой без фокуса внутри стал бы клавиатурной ловушкой.\n */\n modal?: boolean\n /** Доступное имя панели. Обязательно для `role=\"dialog\"` без видимого заголовка. */\n ariaLabel?: string\n /** `id` видимого заголовка внутри панели — альтернатива `ariaLabel`. */\n labelledBy?: string\n /**\n * Чем открывается панель.\n *\n * `manual` — только программно (через `v-model:open`): нужно контекстному меню\n * и подтверждениям, где момент открытия решает потребитель. `hover` — по\n * наведению, с задержками из `openDelay` и `closeDelay`; клик и клавиатура в\n * этом режиме продолжают работать.\n */\n trigger?: 'click' | 'manual' | 'hover'\n /**\n * Задержка открытия по наведению, мс.\n *\n * Обе задержки нужны, и каждая по своей причине: без `openDelay` панель\n * выпрыгивает на любое пересечение курсором, без `closeDelay` её не удержать\n * при переходе с триггера на панель — между ними зазор `offsetPx`.\n */\n openDelay?: number\n /** Задержка закрытия после ухода курсора, мс. */\n closeDelay?: number\n closeOnEsc?: boolean\n closeOnClickOutside?: boolean\n /** Закрывать по клику внутри панели — удобно для меню, вредно для формы. */\n closeOnContentClick?: boolean\n /**\n * Переносить фокус на панель при открытии. Именно на панель, а не на первый\n * контрол внутри: сфокусировать поле ввода за пользователя — решение\n * содержимого, а не оболочки.\n */\n autoFocus?: boolean\n /**\n * Точечное переопределение точки монтирования. По умолчанию — общий портал\n * оверлеев (`#gr-portal` либо `portalTarget` из `GrConfigProvider`).\n */\n teleportTo?: string | HTMLElement\n contentClass?: string\n disabled?: boolean\n /**\n * Якорь-прямоугольник в координатах вьюпорта вместо обёртки слота `#trigger`:\n * панель встаёт у точки курсора или у строки списка. Нужен контекстному меню,\n * у которого триггера-элемента нет вовсе.\n *\n * `triggerProps` в этом режиме некому потребить, и своих ARIA-атрибутов\n * поповер никуда не вешает: `aria-haspopup` невалиден вне интерактивного\n * элемента, а `aria-expanded` без хозяина — шум. Связь с содержимым страницы\n * объявляет тот, кто открывает.\n */\n anchor?: GrFloatingAnchorRect | null\n /** Поле панели. `none` — содержимое рисует своё (меню, список опций). */\n padding?: GrPopoverPadding\n /**\n * Брать ширину у триггера: `true` — точно его ширина, `'min'` — не уже его,\n * дальше по содержимому. Панель у поля или у широкой кнопки, оказавшаяся уже\n * своего триггера, читается как ошибка вёрстки.\n *\n * С потолком `--gr-popover-max-width` сочетается, а не спорит: ширину задаёт\n * триггер, потолок её ограничивает — «шириной с триггер, но не шире\n * читаемого». Поэтому это отдельный проп, а не значение одного перечисления\n * вместе с потолком: оси независимы, и сочетание осмысленно.\n */\n matchWidth?: boolean | 'min'\n /**\n * Обёртка триггера занимает всю ширину родителя вместо того, чтобы обжимать\n * содержимое.\n *\n * Нужно форм-контролам: обёртка `inline-block` схлопывается по содержимому, и\n * `w-full` у самого триггера начинает резолвиться относительно неё, а не\n * относительно поля. Контрол, объявивший себя во всю ширину, рисуется по\n * содержимому — рядом с полем ввода это читается как сбитая вёрстка.\n *\n * Имя то же, что у `GrButton` и `GrSegmented`: в ядре это устоявшееся слово\n * для «во всю ширину».\n */\n block?: boolean\n}\n\nexport interface GrPopoverEmits {\n (e: 'update:open', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrPopoverProps>(), {\n open: undefined,\n placement: 'bottom-start',\n offsetPx: 8,\n size: undefined,\n role: 'dialog',\n modal: false,\n ariaLabel: undefined,\n labelledBy: undefined,\n trigger: 'click',\n openDelay: 120,\n closeDelay: 160,\n closeOnEsc: true,\n closeOnClickOutside: true,\n closeOnContentClick: false,\n autoFocus: true,\n teleportTo: undefined,\n contentClass: undefined,\n disabled: false,\n anchor: undefined,\n padding: 'default',\n matchWidth: false,\n block: false,\n})\n\nconst emit = defineEmits<GrPopoverEmits>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrPopover' })\n\nconst { open: isOpen, setOpen } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\nconst panelId = useId()\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hoverTimer: ReturnType<typeof setTimeout> | undefined\n\nfunction open(): void {\n if (props.disabled)\n return\n\n // Явное действие отменяет отложенное наведение: иначе таймер, заведённый\n // курсором, догонит и закроет панель, открытую кликом.\n clearTimeout(hoverTimer)\n setOpen(true)\n}\n\nfunction close(): void {\n clearTimeout(hoverTimer)\n setOpen(false)\n}\n\nfunction toggle(): void {\n isOpen.value ? close() : open()\n}\n\n/**\n * Якорь создаётся один раз и читает координаты геттером: `useFloating`\n * пересоздаёт подписку при смене самой ссылки, а точка меняется на каждый\n * вызов — новый объект рвал бы `autoUpdate` без нужды.\n */\nconst anchorEl = createFloatingAnchor(() => props.anchor)\n\n/** Обёртка триггера существует только вместе со слотом — см. проп `anchor`. */\nconst hasTrigger = computed(() => Boolean(slots.trigger))\n\nconst { floatingStyle, resolvedPlacement, update: updateFloatingPosition } = useFloating(\n () => (props.anchor ? anchorEl : rootEl.value),\n panelEl,\n isOpen,\n {\n placement: () => props.placement,\n offsetPx: props.offsetPx,\n // Своего слоя у поповера нет намеренно: он и дропдаун — один класс якорных\n // немодальных оверлеев и обязаны лежать на одной высоте, иначе начнут\n // перекрывать друг друга в зависимости от порядка открытия.\n zIndexVar: '--gr-z-dropdown',\n matchWidth: () => props.matchWidth,\n },\n)\n\nwatch(() => props.placement, () => {\n if (isOpen.value)\n updateFloatingPosition()\n})\n\n// Объект якоря стабилен, поэтому смену координат `useFloating` сам не заметит:\n// повторный вызов у другой точки — это пересчёт позиции, а не переоткрытие.\nwatch(() => props.anchor, () => {\n if (isOpen.value)\n updateFloatingPosition()\n}, { deep: true })\n\n/**\n * Слой стека оверлеев: очередь Esc общая с модалками, поэтому поповер, открытый\n * внутри модалки, по Esc закрывает себя, а не её. Возврат фокуса на триггер\n * тоже отсюда — по правилу «только если на момент закрытия фокус ещё внутри».\n *\n * Модальность включается пропом и приходит той же сборкой, что у окна и drawer'а\n * (`useModalOverlay`): ловушка фокуса, `inert` фона, блокировка скролла. При\n * `modal: false` не включается ничего из этого — дефолтный поповер немодален.\n *\n * Корень слоя и панель здесь один элемент: якорный оверлей уезжает в портал сам,\n * без обёртки.\n */\nconst { inertAttr, portalTarget, teleportEnabled, themeAttrs } = useModalOverlay(isOpen, close, {\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc,\n panel: panelEl,\n root: panelEl,\n teleportTo: () => props.teleportTo,\n initialFocus: () => panelEl.value,\n})\n\n// Фокус переносим после отрисовки панели: до `nextTick` её ещё нет в DOM.\n// В модальном режиме перенос обязателен: фон в `inert`, и фокус, оставленный\n// снаружи, попал бы в недоступное поддерево.\nwatch(isOpen, async (next) => {\n if (!next || !(props.autoFocus || props.modal))\n return\n\n await nextTick()\n panelEl.value?.focus()\n})\n\n/** Роли, которые `aria-haspopup` действительно понимает. */\nconst HASPOPUP_ROLES = ['dialog', 'menu', 'listbox', 'grid'] as const\n\n/**\n * Пропсы для реального фокусируемого триггера: `<button v-bind=\"triggerProps\">`.\n *\n * Здесь и ARIA, и **клик**. ARIA — потому что `aria-expanded` обязан жить на том\n * узле, который получает фокус, а не на `div` вокруг него. Клик — потому что\n * обёртка ловит и клики по вложенным элементам: кнопка «Ещё» рядом с триггером,\n * ссылка в карточке-триггере, крестик на чипе открывали бы панель мимо намерения\n * пользователя. То же решение и по той же причине — в `GrDropdown`.\n */\nconst triggerProps = computed(() => ({\n // `aria-haspopup` принимает не любую роль: `group` в его списке нет, и\n // объявленный им триггер отдавал бы невалидный атрибут, который AT просто\n // отбрасывает. Роли вне списка сообщают о панели только через `aria-expanded`.\n 'aria-haspopup': HASPOPUP_ROLES.includes(props.role as (typeof HASPOPUP_ROLES)[number])\n ? (props.role as (typeof HASPOPUP_ROLES)[number])\n : undefined,\n 'aria-expanded': isOpen.value,\n 'aria-controls': isOpen.value ? panelId : undefined,\n 'disabled': props.disabled || undefined,\n 'onClick': onTriggerClick,\n}))\n\nfunction onTriggerClick(): void {\n // `hover` не отменяет клика: с клавиатуры и с тачскрина наведения не бывает,\n // и панель, открываемая только курсором, для них не существует вовсе.\n if (props.trigger === 'click' || props.trigger === 'hover')\n toggle()\n}\n\n/** Привязан ли `triggerProps`: `aria-expanded` он ставит всегда, при любой роли. */\nfunction hasBoundTrigger(): boolean {\n return rootEl.value?.querySelector('[aria-expanded]') != null\n}\n\n/**\n * Клик по обёртке — совместимость, а не механизм.\n *\n * Клик триггера живёт в `triggerProps`. Но слот, оставленный без\n * `v-bind=\"triggerProps\"`, до этой правки открывался кликом по обёртке, и молча\n * отнимать это у тех, кто на это опирался, нельзя. Поэтому обёртка срабатывает\n * ровно тогда, когда привязанного триггера внутри нет.\n *\n * Проверка на месте клика, а не при монтировании: содержимое слота реактивно, и\n * триггер может появиться позже. `querySelector` по одному узлу на клик дешевле\n * подписки на мутации.\n */\nfunction onWrapperClick(): void {\n if (hasBoundTrigger())\n return\n\n onTriggerClick()\n}\n\n/**\n * Открытие по наведению.\n *\n * Таймер один на обе стороны и сбрасывается при каждом событии: курсор,\n * прошедший триггер насквозь, не должен оставить за собой отложенное открытие.\n * Нулевая задержка выполняется сразу, а не через `setTimeout(0)`, — иначе\n * открытие уезжало бы на следующий тик и ломало тесты, которые ждут синхронности.\n */\nfunction scheduleHover(next: boolean, delayMs: number): void {\n clearTimeout(hoverTimer)\n\n if (delayMs <= 0) {\n setOpen(next)\n return\n }\n\n hoverTimer = setTimeout(setOpen, delayMs, next)\n}\n\nfunction onHoverEnter(): void {\n if (props.disabled || props.trigger !== 'hover')\n return\n\n scheduleHover(true, props.openDelay)\n}\n\nfunction onHoverLeave(): void {\n if (props.trigger !== 'hover')\n return\n\n scheduleHover(false, props.closeDelay)\n}\n\n// Триггер без `v-bind=\"triggerProps\"` работает по совместимости, но остаётся без\n// клавиатуры и без ARIA: панель для скринридера не объявлена, и с `Tab` до неё не\n// добраться. Молчать нельзя — снаружи это выглядит как «поповер почти работает».\nonMounted(() => {\n if (!__GR_DEV__ || !hasTrigger.value || hasBoundTrigger())\n return\n\n console.warn(\n '[GrPopover] триггер не привязан: добавьте `v-bind=\"triggerProps\"` на элемент '\n + 'внутри слота #trigger — <template #trigger=\"{ triggerProps }\">'\n + '<GrButton v-bind=\"triggerProps\">…</GrButton></template>. '\n + 'Клик по обёртке пока работает, но у триггера нет ни клавиатуры, ни '\n + 'aria-haspopup/aria-expanded, а клик по вложенным элементам открывает панель.',\n )\n})\n\nonBeforeUnmount(() => {\n clearTimeout(hoverTimer)\n})\n\nfunction onContentClick(): void {\n if (props.closeOnContentClick)\n close()\n}\n\nconst panelClasses = computed(() =>\n grPopoverPanelClass(resolvedSize.value, resolvedPlacement.value, props.contentClass, props.padding),\n)\n\ndefineExpose({ open, close, toggle })\n\ndefineSlots<{\n /**\n * Триггер панели. `triggerProps` обязаны попасть на сам интерактивный\n * элемент, а не на обёртку вокруг него: `aria-expanded` и `aria-controls`\n * читаются с того узла, который получает фокус.\n */\n trigger?: (props: {\n open: boolean\n toggle: () => void\n close: () => void\n triggerProps: Record<string, unknown>\n }) => any\n /** Содержимое панели. */\n content?: (props: { close: () => void }) => any\n}>()\n</script>\n\n<template>\n <div data-gr-popover>\n <div\n v-if=\"hasTrigger\"\n ref=\"rootEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside, exclude: clickOutsideExclude }\"\n data-gr-popover-trigger\n :class=\"block ? 'block w-full' : 'inline-block max-w-full'\"\n @click=\"onWrapperClick\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n :toggle=\"toggle\"\n :close=\"close\"\n :trigger-props=\"triggerProps\"\n />\n </div>\n\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <transition\n :enter-active-class=\"panelPopTransition.enter\"\n :enter-from-class=\"panelPopTransition.enterFrom\"\n :enter-to-class=\"panelPopTransition.enterTo\"\n :leave-active-class=\"panelPopTransition.leave\"\n :leave-from-class=\"panelPopTransition.leaveFrom\"\n :leave-to-class=\"panelPopTransition.leaveTo\"\n >\n <div\n v-show=\"isOpen\"\n :id=\"panelId\"\n ref=\"panelEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside && !hasTrigger }\"\n v-bind=\"themeAttrs\"\n data-gr-popover-panel\n data-gr-overlay-root\n :role=\"role === 'none' ? undefined : role\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :inert=\"inertAttr\"\n :aria-label=\"labelledBy ? undefined : ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n tabindex=\"-1\"\n :class=\"panelClasses\"\n :style=\"floatingStyle\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n @click=\"onContentClick\"\n >\n <slot name=\"content\" :close=\"close\" />\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrPopover — якорный немодальный оверлей с произвольным содержимым.\n *\n * Роль «универсального поповера» до сих пор насильно исполнял `GrDropdown`, но\n * он про меню: жёстко объявляет `role=\"menu\"`, `aria-haspopup=\"menu\"` и водит\n * фокус по пунктам. Для формы, подтверждения или палитры это неверная семантика.\n *\n * Здесь наоборот: позиционирование, слой и закрытие берёт на себя примитив, а\n * клавиатурный паттерн внутри панели остаётся за потребителем — поэтому `role`\n * задаётся пропом. На этом собираются `GrMenu` / `GrContextMenu` /\n * `GrColorPicker` / Popconfirm.\n *\n * A11y:\n * - триггер получает `aria-haspopup`/`aria-expanded`/`aria-controls` через\n * `triggerProps` (биндится на реальный фокусируемый элемент в слоте);\n * - панель — `role=\"dialog\"` по умолчанию и обязательное доступное имя\n * (`ariaLabel` либо `aria-labelledby` через `labelledBy`);\n * - Esc закрывает верхний слой стека, клик вне — закрывает по точке попадания;\n * - **по умолчанию фокус-ловушки нет намеренно**: Tab обязан уводить фокус\n * наружу, иначе немодальный слой запирает пользователя на странице, которая\n * не заблокирована. Проп `modal` включает второй режим — см. ниже.\n */\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, useSlots, watch } from 'vue'\n\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport { createFloatingAnchor, type GrFloatingAnchorRect, useFloating, type UseFloatingPlacement } from '../../composables/useFloating'\nimport { vClickOutside } from '../../directives'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport {\n type GrPopoverPadding,\n type GrPopoverRole,\n type GrPopoverSize,\n grPopoverPanelClass,\n} from './grPopoverStyles'\n\nexport interface GrPopoverProps {\n /**\n * Открыт ли поповер. Без этого пропа компонент ведёт состояние сам\n * (uncontrolled), с ним — слушайте `update:open`.\n */\n open?: boolean\n placement?: UseFloatingPlacement\n /** Зазор между триггером и панелью, px. */\n offsetPx?: number\n size?: GrPopoverSize\n /** Роль панели. Меняется теми, кто строит поверх примитива своё меню/список. */\n role?: GrPopoverRole\n /**\n * Модальный режим: фон уходит в `inert`, Tab ходит по кругу внутри панели,\n * скролл страницы блокируется, а слой встаёт в стек модальным — как окно.\n * Нужен поповеру с формой или подтверждением внутри: без изоляции фона\n * пользователь уводит фокус на страницу, к которой поповер и относится.\n *\n * В этом режиме фокус переносится в панель независимо от `autoFocus`: фон\n * недоступен, и слой без фокуса внутри стал бы клавиатурной ловушкой.\n */\n modal?: boolean\n /** Доступное имя панели. Обязательно для `role=\"dialog\"` без видимого заголовка. */\n ariaLabel?: string\n /** `id` видимого заголовка внутри панели — альтернатива `ariaLabel`. */\n labelledBy?: string\n /**\n * Чем открывается панель.\n *\n * `manual` — только программно (через `v-model:open`): нужно контекстному меню\n * и подтверждениям, где момент открытия решает потребитель. `hover` — по\n * наведению, с задержками из `openDelay` и `closeDelay`; клик и клавиатура в\n * этом режиме продолжают работать.\n */\n trigger?: 'click' | 'manual' | 'hover'\n /**\n * Задержка открытия по наведению, мс.\n *\n * Обе задержки нужны, и каждая по своей причине: без `openDelay` панель\n * выпрыгивает на любое пересечение курсором, без `closeDelay` её не удержать\n * при переходе с триггера на панель — между ними зазор `offsetPx`.\n */\n openDelay?: number\n /** Задержка закрытия после ухода курсора, мс. */\n closeDelay?: number\n closeOnEsc?: boolean\n closeOnClickOutside?: boolean\n /** Закрывать по клику внутри панели — удобно для меню, вредно для формы. */\n closeOnContentClick?: boolean\n /**\n * Переносить фокус на панель при открытии. Именно на панель, а не на первый\n * контрол внутри: сфокусировать поле ввода за пользователя — решение\n * содержимого, а не оболочки.\n */\n autoFocus?: boolean\n /**\n * Точечное переопределение точки монтирования. По умолчанию — общий портал\n * оверлеев (`#gr-portal` либо `portalTarget` из `GrConfigProvider`).\n */\n teleportTo?: string | HTMLElement\n contentClass?: string\n disabled?: boolean\n /**\n * Якорь-прямоугольник в координатах вьюпорта вместо обёртки слота `#trigger`:\n * панель встаёт у точки курсора или у строки списка. Нужен контекстному меню,\n * у которого триггера-элемента нет вовсе.\n *\n * `triggerProps` в этом режиме некому потребить, и своих ARIA-атрибутов\n * поповер никуда не вешает: `aria-haspopup` невалиден вне интерактивного\n * элемента, а `aria-expanded` без хозяина — шум. Связь с содержимым страницы\n * объявляет тот, кто открывает.\n */\n anchor?: GrFloatingAnchorRect | null\n /** Поле панели. `none` — содержимое рисует своё (меню, список опций). */\n padding?: GrPopoverPadding\n /**\n * Брать ширину у триггера: `true` — точно его ширина, `'min'` — не уже его,\n * дальше по содержимому. Панель у поля или у широкой кнопки, оказавшаяся уже\n * своего триггера, читается как ошибка вёрстки.\n *\n * С потолком `--gr-popover-max-width` сочетается, а не спорит: ширину задаёт\n * триггер, потолок её ограничивает — «шириной с триггер, но не шире\n * читаемого». Поэтому это отдельный проп, а не значение одного перечисления\n * вместе с потолком: оси независимы, и сочетание осмысленно.\n */\n matchWidth?: boolean | 'min'\n /**\n * Обёртка триггера занимает всю ширину родителя вместо того, чтобы обжимать\n * содержимое.\n *\n * Нужно форм-контролам: обёртка `inline-block` схлопывается по содержимому, и\n * `w-full` у самого триггера начинает резолвиться относительно неё, а не\n * относительно поля. Контрол, объявивший себя во всю ширину, рисуется по\n * содержимому — рядом с полем ввода это читается как сбитая вёрстка.\n *\n * Имя то же, что у `GrButton` и `GrSegmented`: в ядре это устоявшееся слово\n * для «во всю ширину».\n */\n block?: boolean\n}\n\nexport interface GrPopoverEmits {\n (e: 'update:open', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrPopoverProps>(), {\n open: undefined,\n placement: 'bottom-start',\n offsetPx: 8,\n size: undefined,\n role: 'dialog',\n modal: false,\n ariaLabel: undefined,\n labelledBy: undefined,\n trigger: 'click',\n openDelay: 120,\n closeDelay: 160,\n closeOnEsc: true,\n closeOnClickOutside: true,\n closeOnContentClick: false,\n autoFocus: true,\n teleportTo: undefined,\n contentClass: undefined,\n disabled: false,\n anchor: undefined,\n padding: 'default',\n matchWidth: false,\n block: false,\n})\n\nconst emit = defineEmits<GrPopoverEmits>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrPopover' })\n\nconst { open: isOpen, setOpen } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\nconst panelId = useId()\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hoverTimer: ReturnType<typeof setTimeout> | undefined\n\nfunction open(): void {\n if (props.disabled)\n return\n\n // Явное действие отменяет отложенное наведение: иначе таймер, заведённый\n // курсором, догонит и закроет панель, открытую кликом.\n clearTimeout(hoverTimer)\n setOpen(true)\n}\n\nfunction close(): void {\n clearTimeout(hoverTimer)\n setOpen(false)\n}\n\nfunction toggle(): void {\n isOpen.value ? close() : open()\n}\n\n/**\n * Якорь создаётся один раз и читает координаты геттером: `useFloating`\n * пересоздаёт подписку при смене самой ссылки, а точка меняется на каждый\n * вызов — новый объект рвал бы `autoUpdate` без нужды.\n */\nconst anchorEl = createFloatingAnchor(() => props.anchor)\n\n/** Обёртка триггера существует только вместе со слотом — см. проп `anchor`. */\nconst hasTrigger = computed(() => Boolean(slots.trigger))\n\nconst { floatingStyle, resolvedPlacement, update: updateFloatingPosition } = useFloating(\n () => (props.anchor ? anchorEl : rootEl.value),\n panelEl,\n isOpen,\n {\n placement: () => props.placement,\n offsetPx: props.offsetPx,\n // Своего слоя у поповера нет намеренно: он и дропдаун — один класс якорных\n // немодальных оверлеев и обязаны лежать на одной высоте, иначе начнут\n // перекрывать друг друга в зависимости от порядка открытия.\n zIndexVar: '--gr-z-dropdown',\n matchWidth: () => props.matchWidth,\n },\n)\n\nwatch(() => props.placement, () => {\n if (isOpen.value)\n updateFloatingPosition()\n})\n\n// Объект якоря стабилен, поэтому смену координат `useFloating` сам не заметит:\n// повторный вызов у другой точки — это пересчёт позиции, а не переоткрытие.\nwatch(() => props.anchor, () => {\n if (isOpen.value)\n updateFloatingPosition()\n}, { deep: true })\n\n/**\n * Слой стека оверлеев: очередь Esc общая с модалками, поэтому поповер, открытый\n * внутри модалки, по Esc закрывает себя, а не её. Возврат фокуса на триггер\n * тоже отсюда — по правилу «только если на момент закрытия фокус ещё внутри».\n *\n * Модальность включается пропом и приходит той же сборкой, что у окна и drawer'а\n * (`useModalOverlay`): ловушка фокуса, `inert` фона, блокировка скролла. При\n * `modal: false` не включается ничего из этого — дефолтный поповер немодален.\n *\n * Корень слоя и панель здесь один элемент: якорный оверлей уезжает в портал сам,\n * без обёртки.\n */\nconst { inertAttr, portalTarget, teleportEnabled, themeAttrs } = useModalOverlay(isOpen, close, {\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc,\n panel: panelEl,\n root: panelEl,\n teleportTo: () => props.teleportTo,\n initialFocus: () => panelEl.value,\n})\n\n// Фокус переносим после отрисовки панели: до `nextTick` её ещё нет в DOM.\n// В модальном режиме перенос обязателен: фон в `inert`, и фокус, оставленный\n// снаружи, попал бы в недоступное поддерево.\nwatch(isOpen, async (next) => {\n if (!next || !(props.autoFocus || props.modal))\n return\n\n await nextTick()\n panelEl.value?.focus()\n})\n\n/** Роли, которые `aria-haspopup` действительно понимает. */\nconst HASPOPUP_ROLES = ['dialog', 'menu', 'listbox', 'grid'] as const\n\n/**\n * Пропсы для реального фокусируемого триггера: `<button v-bind=\"triggerProps\">`.\n *\n * Здесь и ARIA, и **клик**. ARIA — потому что `aria-expanded` обязан жить на том\n * узле, который получает фокус, а не на `div` вокруг него. Клик — потому что\n * обёртка ловит и клики по вложенным элементам: кнопка «Ещё» рядом с триггером,\n * ссылка в карточке-триггере, крестик на чипе открывали бы панель мимо намерения\n * пользователя. То же решение и по той же причине — в `GrDropdown`.\n */\nconst triggerProps = computed(() => ({\n // `aria-haspopup` принимает не любую роль: `group` в его списке нет, и\n // объявленный им триггер отдавал бы невалидный атрибут, который AT просто\n // отбрасывает. Роли вне списка сообщают о панели только через `aria-expanded`.\n 'aria-haspopup': HASPOPUP_ROLES.includes(props.role as (typeof HASPOPUP_ROLES)[number])\n ? (props.role as (typeof HASPOPUP_ROLES)[number])\n : undefined,\n 'aria-expanded': isOpen.value,\n 'aria-controls': isOpen.value ? panelId : undefined,\n 'disabled': props.disabled || undefined,\n 'onClick': onTriggerClick,\n}))\n\nfunction onTriggerClick(): void {\n // `hover` не отменяет клика: с клавиатуры и с тачскрина наведения не бывает,\n // и панель, открываемая только курсором, для них не существует вовсе.\n if (props.trigger === 'click' || props.trigger === 'hover')\n toggle()\n}\n\n/** Привязан ли `triggerProps`: `aria-expanded` он ставит всегда, при любой роли. */\nfunction hasBoundTrigger(): boolean {\n return rootEl.value?.querySelector('[aria-expanded]') != null\n}\n\n/**\n * Клик по обёртке — совместимость, а не механизм.\n *\n * Клик триггера живёт в `triggerProps`. Но слот, оставленный без\n * `v-bind=\"triggerProps\"`, до этой правки открывался кликом по обёртке, и молча\n * отнимать это у тех, кто на это опирался, нельзя. Поэтому обёртка срабатывает\n * ровно тогда, когда привязанного триггера внутри нет.\n *\n * Проверка на месте клика, а не при монтировании: содержимое слота реактивно, и\n * триггер может появиться позже. `querySelector` по одному узлу на клик дешевле\n * подписки на мутации.\n */\nfunction onWrapperClick(): void {\n if (hasBoundTrigger())\n return\n\n onTriggerClick()\n}\n\n/**\n * Открытие по наведению.\n *\n * Таймер один на обе стороны и сбрасывается при каждом событии: курсор,\n * прошедший триггер насквозь, не должен оставить за собой отложенное открытие.\n * Нулевая задержка выполняется сразу, а не через `setTimeout(0)`, — иначе\n * открытие уезжало бы на следующий тик и ломало тесты, которые ждут синхронности.\n */\nfunction scheduleHover(next: boolean, delayMs: number): void {\n clearTimeout(hoverTimer)\n\n if (delayMs <= 0) {\n setOpen(next)\n return\n }\n\n hoverTimer = setTimeout(setOpen, delayMs, next)\n}\n\nfunction onHoverEnter(): void {\n if (props.disabled || props.trigger !== 'hover')\n return\n\n scheduleHover(true, props.openDelay)\n}\n\nfunction onHoverLeave(): void {\n if (props.trigger !== 'hover')\n return\n\n scheduleHover(false, props.closeDelay)\n}\n\n// Триггер без `v-bind=\"triggerProps\"` работает по совместимости, но остаётся без\n// клавиатуры и без ARIA: панель для скринридера не объявлена, и с `Tab` до неё не\n// добраться. Молчать нельзя — снаружи это выглядит как «поповер почти работает».\nonMounted(() => {\n if (!__GR_DEV__ || !hasTrigger.value || hasBoundTrigger())\n return\n\n console.warn(\n '[GrPopover] триггер не привязан: добавьте `v-bind=\"triggerProps\"` на элемент '\n + 'внутри слота #trigger — <template #trigger=\"{ triggerProps }\">'\n + '<GrButton v-bind=\"triggerProps\">…</GrButton></template>. '\n + 'Клик по обёртке пока работает, но у триггера нет ни клавиатуры, ни '\n + 'aria-haspopup/aria-expanded, а клик по вложенным элементам открывает панель.',\n )\n})\n\nonBeforeUnmount(() => {\n clearTimeout(hoverTimer)\n})\n\nfunction onContentClick(): void {\n if (props.closeOnContentClick)\n close()\n}\n\nconst panelClasses = computed(() =>\n grPopoverPanelClass(resolvedSize.value, resolvedPlacement.value, props.contentClass, props.padding),\n)\n\ndefineExpose({ open, close, toggle })\n\ndefineSlots<{\n /**\n * Триггер панели. `triggerProps` обязаны попасть на сам интерактивный\n * элемент, а не на обёртку вокруг него: `aria-expanded` и `aria-controls`\n * читаются с того узла, который получает фокус.\n */\n trigger?: (props: {\n open: boolean\n toggle: () => void\n close: () => void\n triggerProps: Record<string, unknown>\n }) => any\n /** Содержимое панели. */\n content?: (props: { close: () => void }) => any\n}>()\n</script>\n\n<template>\n <div data-gr-popover>\n <div\n v-if=\"hasTrigger\"\n ref=\"rootEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside, exclude: clickOutsideExclude }\"\n data-gr-popover-trigger\n :class=\"block ? 'block w-full' : 'inline-block max-w-full'\"\n @click=\"onWrapperClick\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n :toggle=\"toggle\"\n :close=\"close\"\n :trigger-props=\"triggerProps\"\n />\n </div>\n\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <transition\n :enter-active-class=\"panelPopTransition.enter\"\n :enter-from-class=\"panelPopTransition.enterFrom\"\n :enter-to-class=\"panelPopTransition.enterTo\"\n :leave-active-class=\"panelPopTransition.leave\"\n :leave-from-class=\"panelPopTransition.leaveFrom\"\n :leave-to-class=\"panelPopTransition.leaveTo\"\n >\n <div\n v-show=\"isOpen\"\n :id=\"panelId\"\n ref=\"panelEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside && !hasTrigger }\"\n v-bind=\"themeAttrs\"\n data-gr-popover-panel\n data-gr-overlay-root\n :role=\"role === 'none' ? undefined : role\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :inert=\"inertAttr\"\n :aria-label=\"labelledBy ? undefined : ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n tabindex=\"-1\"\n :class=\"panelClasses\"\n :style=\"floatingStyle\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n @click=\"onContentClick\"\n >\n <slot name=\"content\" :close=\"close\" />\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrPopover-BakLcWkX.js","names":[],"sources":["../../../../src/components/GrPopover/GrPopover.vue","../../../../src/components/GrPopover/GrPopover.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrPopover — якорный немодальный оверлей с произвольным содержимым.\n *\n * Роль «универсального поповера» до сих пор насильно исполнял `GrDropdown`, но\n * он про меню: жёстко объявляет `role=\"menu\"`, `aria-haspopup=\"menu\"` и водит\n * фокус по пунктам. Для формы, подтверждения или палитры это неверная семантика.\n *\n * Здесь наоборот: позиционирование, слой и закрытие берёт на себя примитив, а\n * клавиатурный паттерн внутри панели остаётся за потребителем — поэтому `role`\n * задаётся пропом. На этом собираются `GrMenu` / `GrContextMenu` /\n * `GrColorPicker` / Popconfirm.\n *\n * A11y:\n * - триггер получает `aria-haspopup`/`aria-expanded`/`aria-controls` через\n * `triggerProps` (биндится на реальный фокусируемый элемент в слоте);\n * - панель — `role=\"dialog\"` по умолчанию и обязательное доступное имя\n * (`ariaLabel` либо `aria-labelledby` через `labelledBy`);\n * - Esc закрывает верхний слой стека, клик вне — закрывает по точке попадания;\n * - **по умолчанию фокус-ловушки нет намеренно**: Tab обязан уводить фокус\n * наружу, иначе немодальный слой запирает пользователя на странице, которая\n * не заблокирована. Проп `modal` включает второй режим — см. ниже.\n */\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, useSlots, watch } from 'vue'\n\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport { createFloatingAnchor, type GrFloatingAnchorRect, useFloating, type UseFloatingPlacement } from '../../composables/useFloating'\nimport { vClickOutside } from '../../directives'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport {\n type GrPopoverPadding,\n type GrPopoverRole,\n type GrPopoverSize,\n grPopoverPanelClass,\n} from './grPopoverStyles'\n\nexport interface GrPopoverProps {\n /**\n * Открыт ли поповер. Без этого пропа компонент ведёт состояние сам\n * (uncontrolled), с ним — слушайте `update:open`.\n */\n open?: boolean\n placement?: UseFloatingPlacement\n /** Зазор между триггером и панелью, px. */\n offsetPx?: number\n size?: GrPopoverSize\n /** Роль панели. Меняется теми, кто строит поверх примитива своё меню/список. */\n role?: GrPopoverRole\n /**\n * Модальный режим: фон уходит в `inert`, Tab ходит по кругу внутри панели,\n * скролл страницы блокируется, а слой встаёт в стек модальным — как окно.\n * Нужен поповеру с формой или подтверждением внутри: без изоляции фона\n * пользователь уводит фокус на страницу, к которой поповер и относится.\n *\n * В этом режиме фокус переносится в панель независимо от `autoFocus`: фон\n * недоступен, и слой без фокуса внутри стал бы клавиатурной ловушкой.\n */\n modal?: boolean\n /** Доступное имя панели. Обязательно для `role=\"dialog\"` без видимого заголовка. */\n ariaLabel?: string\n /** `id` видимого заголовка внутри панели — альтернатива `ariaLabel`. */\n labelledBy?: string\n /**\n * Чем открывается панель.\n *\n * `manual` — только программно (через `v-model:open`): нужно контекстному меню\n * и подтверждениям, где момент открытия решает потребитель. `hover` — по\n * наведению, с задержками из `openDelay` и `closeDelay`; клик и клавиатура в\n * этом режиме продолжают работать.\n */\n trigger?: 'click' | 'manual' | 'hover'\n /**\n * Задержка открытия по наведению, мс.\n *\n * Обе задержки нужны, и каждая по своей причине: без `openDelay` панель\n * выпрыгивает на любое пересечение курсором, без `closeDelay` её не удержать\n * при переходе с триггера на панель — между ними зазор `offsetPx`.\n */\n openDelay?: number\n /** Задержка закрытия после ухода курсора, мс. */\n closeDelay?: number\n closeOnEsc?: boolean\n closeOnClickOutside?: boolean\n /** Закрывать по клику внутри панели — удобно для меню, вредно для формы. */\n closeOnContentClick?: boolean\n /**\n * Переносить фокус на панель при открытии. Именно на панель, а не на первый\n * контрол внутри: сфокусировать поле ввода за пользователя — решение\n * содержимого, а не оболочки.\n */\n autoFocus?: boolean\n /**\n * Точечное переопределение точки монтирования. По умолчанию — общий портал\n * оверлеев (`#gr-portal` либо `portalTarget` из `GrConfigProvider`).\n */\n teleportTo?: string | HTMLElement\n contentClass?: string\n disabled?: boolean\n /**\n * Якорь-прямоугольник в координатах вьюпорта вместо обёртки слота `#trigger`:\n * панель встаёт у точки курсора или у строки списка. Нужен контекстному меню,\n * у которого триггера-элемента нет вовсе.\n *\n * `triggerProps` в этом режиме некому потребить, и своих ARIA-атрибутов\n * поповер никуда не вешает: `aria-haspopup` невалиден вне интерактивного\n * элемента, а `aria-expanded` без хозяина — шум. Связь с содержимым страницы\n * объявляет тот, кто открывает.\n */\n anchor?: GrFloatingAnchorRect | null\n /** Поле панели. `none` — содержимое рисует своё (меню, список опций). */\n padding?: GrPopoverPadding\n /**\n * Брать ширину у триггера: `true` — точно его ширина, `'min'` — не уже его,\n * дальше по содержимому. Панель у поля или у широкой кнопки, оказавшаяся уже\n * своего триггера, читается как ошибка вёрстки.\n *\n * С потолком `--gr-popover-max-width` сочетается, а не спорит: ширину задаёт\n * триггер, потолок её ограничивает — «шириной с триггер, но не шире\n * читаемого». Поэтому это отдельный проп, а не значение одного перечисления\n * вместе с потолком: оси независимы, и сочетание осмысленно.\n */\n matchWidth?: boolean | 'min'\n /**\n * Обёртка триггера занимает всю ширину родителя вместо того, чтобы обжимать\n * содержимое.\n *\n * Нужно форм-контролам: обёртка `inline-block` схлопывается по содержимому, и\n * `w-full` у самого триггера начинает резолвиться относительно неё, а не\n * относительно поля. Контрол, объявивший себя во всю ширину, рисуется по\n * содержимому — рядом с полем ввода это читается как сбитая вёрстка.\n *\n * Имя то же, что у `GrButton` и `GrSegmented`: в ядре это устоявшееся слово\n * для «во всю ширину».\n */\n block?: boolean\n}\n\nexport interface GrPopoverEmits {\n (e: 'update:open', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrPopoverProps>(), {\n open: undefined,\n placement: 'bottom-start',\n offsetPx: 8,\n size: undefined,\n role: 'dialog',\n modal: false,\n ariaLabel: undefined,\n labelledBy: undefined,\n trigger: 'click',\n openDelay: 120,\n closeDelay: 160,\n closeOnEsc: true,\n closeOnClickOutside: true,\n closeOnContentClick: false,\n autoFocus: true,\n teleportTo: undefined,\n contentClass: undefined,\n disabled: false,\n anchor: undefined,\n padding: 'default',\n matchWidth: false,\n block: false,\n})\n\nconst emit = defineEmits<GrPopoverEmits>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrPopover' })\n\nconst { open: isOpen, setOpen } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\nconst panelId = useId()\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hoverTimer: ReturnType<typeof setTimeout> | undefined\n\nfunction open(): void {\n if (props.disabled)\n return\n\n // Явное действие отменяет отложенное наведение: иначе таймер, заведённый\n // курсором, догонит и закроет панель, открытую кликом.\n clearTimeout(hoverTimer)\n setOpen(true)\n}\n\nfunction close(): void {\n clearTimeout(hoverTimer)\n setOpen(false)\n}\n\nfunction toggle(): void {\n isOpen.value ? close() : open()\n}\n\n/**\n * Якорь создаётся один раз и читает координаты геттером: `useFloating`\n * пересоздаёт подписку при смене самой ссылки, а точка меняется на каждый\n * вызов — новый объект рвал бы `autoUpdate` без нужды.\n */\nconst anchorEl = createFloatingAnchor(() => props.anchor)\n\n/** Обёртка триггера существует только вместе со слотом — см. проп `anchor`. */\nconst hasTrigger = computed(() => Boolean(slots.trigger))\n\nconst { floatingStyle, resolvedPlacement, update: updateFloatingPosition } = useFloating(\n () => (props.anchor ? anchorEl : rootEl.value),\n panelEl,\n isOpen,\n {\n placement: () => props.placement,\n offsetPx: props.offsetPx,\n // Своего слоя у поповера нет намеренно: он и дропдаун — один класс якорных\n // немодальных оверлеев и обязаны лежать на одной высоте, иначе начнут\n // перекрывать друг друга в зависимости от порядка открытия.\n zIndexVar: '--gr-z-dropdown',\n matchWidth: () => props.matchWidth,\n },\n)\n\nwatch(() => props.placement, () => {\n if (isOpen.value)\n updateFloatingPosition()\n})\n\n// Объект якоря стабилен, поэтому смену координат `useFloating` сам не заметит:\n// повторный вызов у другой точки — это пересчёт позиции, а не переоткрытие.\nwatch(() => props.anchor, () => {\n if (isOpen.value)\n updateFloatingPosition()\n}, { deep: true })\n\n/**\n * Слой стека оверлеев: очередь Esc общая с модалками, поэтому поповер, открытый\n * внутри модалки, по Esc закрывает себя, а не её. Возврат фокуса на триггер\n * тоже отсюда — по правилу «только если на момент закрытия фокус ещё внутри».\n *\n * Модальность включается пропом и приходит той же сборкой, что у окна и drawer'а\n * (`useModalOverlay`): ловушка фокуса, `inert` фона, блокировка скролла. При\n * `modal: false` не включается ничего из этого — дефолтный поповер немодален.\n *\n * Корень слоя и панель здесь один элемент: якорный оверлей уезжает в портал сам,\n * без обёртки.\n */\nconst { inertAttr, portalTarget, teleportEnabled, themeAttrs } = useModalOverlay(isOpen, close, {\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc,\n panel: panelEl,\n root: panelEl,\n teleportTo: () => props.teleportTo,\n initialFocus: () => panelEl.value,\n})\n\n// Фокус переносим после отрисовки панели: до `nextTick` её ещё нет в DOM.\n// В модальном режиме перенос обязателен: фон в `inert`, и фокус, оставленный\n// снаружи, попал бы в недоступное поддерево.\nwatch(isOpen, async (next) => {\n if (!next || !(props.autoFocus || props.modal))\n return\n\n await nextTick()\n panelEl.value?.focus()\n})\n\n/** Роли, которые `aria-haspopup` действительно понимает. */\nconst HASPOPUP_ROLES = ['dialog', 'menu', 'listbox', 'grid'] as const\n\n/**\n * Пропсы для реального фокусируемого триггера: `<button v-bind=\"triggerProps\">`.\n *\n * Здесь и ARIA, и **клик**. ARIA — потому что `aria-expanded` обязан жить на том\n * узле, который получает фокус, а не на `div` вокруг него. Клик — потому что\n * обёртка ловит и клики по вложенным элементам: кнопка «Ещё» рядом с триггером,\n * ссылка в карточке-триггере, крестик на чипе открывали бы панель мимо намерения\n * пользователя. То же решение и по той же причине — в `GrDropdown`.\n */\nconst triggerProps = computed(() => ({\n // `aria-haspopup` принимает не любую роль: `group` в его списке нет, и\n // объявленный им триггер отдавал бы невалидный атрибут, который AT просто\n // отбрасывает. Роли вне списка сообщают о панели только через `aria-expanded`.\n 'aria-haspopup': HASPOPUP_ROLES.includes(props.role as (typeof HASPOPUP_ROLES)[number])\n ? (props.role as (typeof HASPOPUP_ROLES)[number])\n : undefined,\n 'aria-expanded': isOpen.value,\n 'aria-controls': isOpen.value ? panelId : undefined,\n 'disabled': props.disabled || undefined,\n 'onClick': onTriggerClick,\n}))\n\nfunction onTriggerClick(): void {\n // `hover` не отменяет клика: с клавиатуры и с тачскрина наведения не бывает,\n // и панель, открываемая только курсором, для них не существует вовсе.\n if (props.trigger === 'click' || props.trigger === 'hover')\n toggle()\n}\n\n/** Привязан ли `triggerProps`: `aria-expanded` он ставит всегда, при любой роли. */\nfunction hasBoundTrigger(): boolean {\n return rootEl.value?.querySelector('[aria-expanded]') != null\n}\n\n/**\n * Клик по обёртке — совместимость, а не механизм.\n *\n * Клик триггера живёт в `triggerProps`. Но слот, оставленный без\n * `v-bind=\"triggerProps\"`, до этой правки открывался кликом по обёртке, и молча\n * отнимать это у тех, кто на это опирался, нельзя. Поэтому обёртка срабатывает\n * ровно тогда, когда привязанного триггера внутри нет.\n *\n * Проверка на месте клика, а не при монтировании: содержимое слота реактивно, и\n * триггер может появиться позже. `querySelector` по одному узлу на клик дешевле\n * подписки на мутации.\n */\nfunction onWrapperClick(): void {\n if (hasBoundTrigger())\n return\n\n onTriggerClick()\n}\n\n/**\n * Открытие по наведению.\n *\n * Таймер один на обе стороны и сбрасывается при каждом событии: курсор,\n * прошедший триггер насквозь, не должен оставить за собой отложенное открытие.\n * Нулевая задержка выполняется сразу, а не через `setTimeout(0)`, — иначе\n * открытие уезжало бы на следующий тик и ломало тесты, которые ждут синхронности.\n */\nfunction scheduleHover(next: boolean, delayMs: number): void {\n clearTimeout(hoverTimer)\n\n if (delayMs <= 0) {\n setOpen(next)\n return\n }\n\n hoverTimer = setTimeout(setOpen, delayMs, next)\n}\n\nfunction onHoverEnter(): void {\n if (props.disabled || props.trigger !== 'hover')\n return\n\n scheduleHover(true, props.openDelay)\n}\n\nfunction onHoverLeave(): void {\n if (props.trigger !== 'hover')\n return\n\n scheduleHover(false, props.closeDelay)\n}\n\n// Триггер без `v-bind=\"triggerProps\"` работает по совместимости, но остаётся без\n// клавиатуры и без ARIA: панель для скринридера не объявлена, и с `Tab` до неё не\n// добраться. Молчать нельзя — снаружи это выглядит как «поповер почти работает».\nonMounted(() => {\n if (!__GR_DEV__ || !hasTrigger.value || hasBoundTrigger())\n return\n\n console.warn(\n '[GrPopover] триггер не привязан: добавьте `v-bind=\"triggerProps\"` на элемент '\n + 'внутри слота #trigger — <template #trigger=\"{ triggerProps }\">'\n + '<GrButton v-bind=\"triggerProps\">…</GrButton></template>. '\n + 'Клик по обёртке пока работает, но у триггера нет ни клавиатуры, ни '\n + 'aria-haspopup/aria-expanded, а клик по вложенным элементам открывает панель.',\n )\n})\n\nonBeforeUnmount(() => {\n clearTimeout(hoverTimer)\n})\n\nfunction onContentClick(): void {\n if (props.closeOnContentClick)\n close()\n}\n\nconst panelClasses = computed(() =>\n grPopoverPanelClass(resolvedSize.value, resolvedPlacement.value, props.contentClass, props.padding),\n)\n\ndefineExpose({ open, close, toggle })\n\ndefineSlots<{\n /**\n * Триггер панели. `triggerProps` обязаны попасть на сам интерактивный\n * элемент, а не на обёртку вокруг него: `aria-expanded` и `aria-controls`\n * читаются с того узла, который получает фокус.\n */\n trigger?: (props: {\n open: boolean\n toggle: () => void\n close: () => void\n triggerProps: Record<string, unknown>\n }) => any\n /** Содержимое панели. */\n content?: (props: { close: () => void }) => any\n}>()\n</script>\n\n<template>\n <div data-gr-popover>\n <div\n v-if=\"hasTrigger\"\n ref=\"rootEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside, exclude: clickOutsideExclude }\"\n data-gr-popover-trigger\n :class=\"block ? 'block w-full' : 'inline-block max-w-full'\"\n @click=\"onWrapperClick\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n :toggle=\"toggle\"\n :close=\"close\"\n :trigger-props=\"triggerProps\"\n />\n </div>\n\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <transition\n :enter-active-class=\"panelPopTransition.enter\"\n :enter-from-class=\"panelPopTransition.enterFrom\"\n :enter-to-class=\"panelPopTransition.enterTo\"\n :leave-active-class=\"panelPopTransition.leave\"\n :leave-from-class=\"panelPopTransition.leaveFrom\"\n :leave-to-class=\"panelPopTransition.leaveTo\"\n >\n <div\n v-show=\"isOpen\"\n :id=\"panelId\"\n ref=\"panelEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside && !hasTrigger }\"\n v-bind=\"themeAttrs\"\n data-gr-popover-panel\n data-gr-overlay-root\n :role=\"role === 'none' ? undefined : role\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :inert=\"inertAttr\"\n :aria-label=\"labelledBy ? undefined : ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n tabindex=\"-1\"\n :class=\"panelClasses\"\n :style=\"floatingStyle\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n @click=\"onContentClick\"\n >\n <slot name=\"content\" :close=\"close\" />\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrPopover — якорный немодальный оверлей с произвольным содержимым.\n *\n * Роль «универсального поповера» до сих пор насильно исполнял `GrDropdown`, но\n * он про меню: жёстко объявляет `role=\"menu\"`, `aria-haspopup=\"menu\"` и водит\n * фокус по пунктам. Для формы, подтверждения или палитры это неверная семантика.\n *\n * Здесь наоборот: позиционирование, слой и закрытие берёт на себя примитив, а\n * клавиатурный паттерн внутри панели остаётся за потребителем — поэтому `role`\n * задаётся пропом. На этом собираются `GrMenu` / `GrContextMenu` /\n * `GrColorPicker` / Popconfirm.\n *\n * A11y:\n * - триггер получает `aria-haspopup`/`aria-expanded`/`aria-controls` через\n * `triggerProps` (биндится на реальный фокусируемый элемент в слоте);\n * - панель — `role=\"dialog\"` по умолчанию и обязательное доступное имя\n * (`ariaLabel` либо `aria-labelledby` через `labelledBy`);\n * - Esc закрывает верхний слой стека, клик вне — закрывает по точке попадания;\n * - **по умолчанию фокус-ловушки нет намеренно**: Tab обязан уводить фокус\n * наружу, иначе немодальный слой запирает пользователя на странице, которая\n * не заблокирована. Проп `modal` включает второй режим — см. ниже.\n */\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, useSlots, watch } from 'vue'\n\nimport { useControlledOpen } from '../../composables/internal/useControlledOpen'\nimport { useModalOverlay } from '../../composables/internal/useModalOverlay'\nimport { createFloatingAnchor, type GrFloatingAnchorRect, useFloating, type UseFloatingPlacement } from '../../composables/useFloating'\nimport { vClickOutside } from '../../directives'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { panelPopTransition } from '../shared/overlayTransition'\nimport {\n type GrPopoverPadding,\n type GrPopoverRole,\n type GrPopoverSize,\n grPopoverPanelClass,\n} from './grPopoverStyles'\n\nexport interface GrPopoverProps {\n /**\n * Открыт ли поповер. Без этого пропа компонент ведёт состояние сам\n * (uncontrolled), с ним — слушайте `update:open`.\n */\n open?: boolean\n placement?: UseFloatingPlacement\n /** Зазор между триггером и панелью, px. */\n offsetPx?: number\n size?: GrPopoverSize\n /** Роль панели. Меняется теми, кто строит поверх примитива своё меню/список. */\n role?: GrPopoverRole\n /**\n * Модальный режим: фон уходит в `inert`, Tab ходит по кругу внутри панели,\n * скролл страницы блокируется, а слой встаёт в стек модальным — как окно.\n * Нужен поповеру с формой или подтверждением внутри: без изоляции фона\n * пользователь уводит фокус на страницу, к которой поповер и относится.\n *\n * В этом режиме фокус переносится в панель независимо от `autoFocus`: фон\n * недоступен, и слой без фокуса внутри стал бы клавиатурной ловушкой.\n */\n modal?: boolean\n /** Доступное имя панели. Обязательно для `role=\"dialog\"` без видимого заголовка. */\n ariaLabel?: string\n /** `id` видимого заголовка внутри панели — альтернатива `ariaLabel`. */\n labelledBy?: string\n /**\n * Чем открывается панель.\n *\n * `manual` — только программно (через `v-model:open`): нужно контекстному меню\n * и подтверждениям, где момент открытия решает потребитель. `hover` — по\n * наведению, с задержками из `openDelay` и `closeDelay`; клик и клавиатура в\n * этом режиме продолжают работать.\n */\n trigger?: 'click' | 'manual' | 'hover'\n /**\n * Задержка открытия по наведению, мс.\n *\n * Обе задержки нужны, и каждая по своей причине: без `openDelay` панель\n * выпрыгивает на любое пересечение курсором, без `closeDelay` её не удержать\n * при переходе с триггера на панель — между ними зазор `offsetPx`.\n */\n openDelay?: number\n /** Задержка закрытия после ухода курсора, мс. */\n closeDelay?: number\n closeOnEsc?: boolean\n closeOnClickOutside?: boolean\n /** Закрывать по клику внутри панели — удобно для меню, вредно для формы. */\n closeOnContentClick?: boolean\n /**\n * Переносить фокус на панель при открытии. Именно на панель, а не на первый\n * контрол внутри: сфокусировать поле ввода за пользователя — решение\n * содержимого, а не оболочки.\n */\n autoFocus?: boolean\n /**\n * Точечное переопределение точки монтирования. По умолчанию — общий портал\n * оверлеев (`#gr-portal` либо `portalTarget` из `GrConfigProvider`).\n */\n teleportTo?: string | HTMLElement\n contentClass?: string\n disabled?: boolean\n /**\n * Якорь-прямоугольник в координатах вьюпорта вместо обёртки слота `#trigger`:\n * панель встаёт у точки курсора или у строки списка. Нужен контекстному меню,\n * у которого триггера-элемента нет вовсе.\n *\n * `triggerProps` в этом режиме некому потребить, и своих ARIA-атрибутов\n * поповер никуда не вешает: `aria-haspopup` невалиден вне интерактивного\n * элемента, а `aria-expanded` без хозяина — шум. Связь с содержимым страницы\n * объявляет тот, кто открывает.\n */\n anchor?: GrFloatingAnchorRect | null\n /** Поле панели. `none` — содержимое рисует своё (меню, список опций). */\n padding?: GrPopoverPadding\n /**\n * Брать ширину у триггера: `true` — точно его ширина, `'min'` — не уже его,\n * дальше по содержимому. Панель у поля или у широкой кнопки, оказавшаяся уже\n * своего триггера, читается как ошибка вёрстки.\n *\n * С потолком `--gr-popover-max-width` сочетается, а не спорит: ширину задаёт\n * триггер, потолок её ограничивает — «шириной с триггер, но не шире\n * читаемого». Поэтому это отдельный проп, а не значение одного перечисления\n * вместе с потолком: оси независимы, и сочетание осмысленно.\n */\n matchWidth?: boolean | 'min'\n /**\n * Обёртка триггера занимает всю ширину родителя вместо того, чтобы обжимать\n * содержимое.\n *\n * Нужно форм-контролам: обёртка `inline-block` схлопывается по содержимому, и\n * `w-full` у самого триггера начинает резолвиться относительно неё, а не\n * относительно поля. Контрол, объявивший себя во всю ширину, рисуется по\n * содержимому — рядом с полем ввода это читается как сбитая вёрстка.\n *\n * Имя то же, что у `GrButton` и `GrSegmented`: в ядре это устоявшееся слово\n * для «во всю ширину».\n */\n block?: boolean\n}\n\nexport interface GrPopoverEmits {\n (e: 'update:open', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrPopoverProps>(), {\n open: undefined,\n placement: 'bottom-start',\n offsetPx: 8,\n size: undefined,\n role: 'dialog',\n modal: false,\n ariaLabel: undefined,\n labelledBy: undefined,\n trigger: 'click',\n openDelay: 120,\n closeDelay: 160,\n closeOnEsc: true,\n closeOnClickOutside: true,\n closeOnContentClick: false,\n autoFocus: true,\n teleportTo: undefined,\n contentClass: undefined,\n disabled: false,\n anchor: undefined,\n padding: 'default',\n matchWidth: false,\n block: false,\n})\n\nconst emit = defineEmits<GrPopoverEmits>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrPopover' })\n\nconst { open: isOpen, setOpen } = useControlledOpen(\n () => props.open,\n next => emit('update:open', next),\n)\n\nconst rootEl = ref<HTMLElement | null>(null)\nconst panelEl = ref<HTMLElement | null>(null)\nconst panelId = useId()\n\nconst clickOutsideExclude = [() => panelEl.value]\n\nlet hoverTimer: ReturnType<typeof setTimeout> | undefined\n\nfunction open(): void {\n if (props.disabled)\n return\n\n // Явное действие отменяет отложенное наведение: иначе таймер, заведённый\n // курсором, догонит и закроет панель, открытую кликом.\n clearTimeout(hoverTimer)\n setOpen(true)\n}\n\nfunction close(): void {\n clearTimeout(hoverTimer)\n setOpen(false)\n}\n\nfunction toggle(): void {\n isOpen.value ? close() : open()\n}\n\n/**\n * Якорь создаётся один раз и читает координаты геттером: `useFloating`\n * пересоздаёт подписку при смене самой ссылки, а точка меняется на каждый\n * вызов — новый объект рвал бы `autoUpdate` без нужды.\n */\nconst anchorEl = createFloatingAnchor(() => props.anchor)\n\n/** Обёртка триггера существует только вместе со слотом — см. проп `anchor`. */\nconst hasTrigger = computed(() => Boolean(slots.trigger))\n\nconst { floatingStyle, resolvedPlacement, update: updateFloatingPosition } = useFloating(\n () => (props.anchor ? anchorEl : rootEl.value),\n panelEl,\n isOpen,\n {\n placement: () => props.placement,\n offsetPx: props.offsetPx,\n // Своего слоя у поповера нет намеренно: он и дропдаун — один класс якорных\n // немодальных оверлеев и обязаны лежать на одной высоте, иначе начнут\n // перекрывать друг друга в зависимости от порядка открытия.\n zIndexVar: '--gr-z-dropdown',\n matchWidth: () => props.matchWidth,\n },\n)\n\nwatch(() => props.placement, () => {\n if (isOpen.value)\n updateFloatingPosition()\n})\n\n// Объект якоря стабилен, поэтому смену координат `useFloating` сам не заметит:\n// повторный вызов у другой точки — это пересчёт позиции, а не переоткрытие.\nwatch(() => props.anchor, () => {\n if (isOpen.value)\n updateFloatingPosition()\n}, { deep: true })\n\n/**\n * Слой стека оверлеев: очередь Esc общая с модалками, поэтому поповер, открытый\n * внутри модалки, по Esc закрывает себя, а не её. Возврат фокуса на триггер\n * тоже отсюда — по правилу «только если на момент закрытия фокус ещё внутри».\n *\n * Модальность включается пропом и приходит той же сборкой, что у окна и drawer'а\n * (`useModalOverlay`): ловушка фокуса, `inert` фона, блокировка скролла. При\n * `modal: false` не включается ничего из этого — дефолтный поповер немодален.\n *\n * Корень слоя и панель здесь один элемент: якорный оверлей уезжает в портал сам,\n * без обёртки.\n */\nconst { inertAttr, portalTarget, teleportEnabled, themeAttrs } = useModalOverlay(isOpen, close, {\n modal: () => props.modal,\n closeOnEscape: () => props.closeOnEsc,\n panel: panelEl,\n root: panelEl,\n teleportTo: () => props.teleportTo,\n initialFocus: () => panelEl.value,\n})\n\n// Фокус переносим после отрисовки панели: до `nextTick` её ещё нет в DOM.\n// В модальном режиме перенос обязателен: фон в `inert`, и фокус, оставленный\n// снаружи, попал бы в недоступное поддерево.\nwatch(isOpen, async (next) => {\n if (!next || !(props.autoFocus || props.modal))\n return\n\n await nextTick()\n panelEl.value?.focus()\n})\n\n/** Роли, которые `aria-haspopup` действительно понимает. */\nconst HASPOPUP_ROLES = ['dialog', 'menu', 'listbox', 'grid'] as const\n\n/**\n * Пропсы для реального фокусируемого триггера: `<button v-bind=\"triggerProps\">`.\n *\n * Здесь и ARIA, и **клик**. ARIA — потому что `aria-expanded` обязан жить на том\n * узле, который получает фокус, а не на `div` вокруг него. Клик — потому что\n * обёртка ловит и клики по вложенным элементам: кнопка «Ещё» рядом с триггером,\n * ссылка в карточке-триггере, крестик на чипе открывали бы панель мимо намерения\n * пользователя. То же решение и по той же причине — в `GrDropdown`.\n */\nconst triggerProps = computed(() => ({\n // `aria-haspopup` принимает не любую роль: `group` в его списке нет, и\n // объявленный им триггер отдавал бы невалидный атрибут, который AT просто\n // отбрасывает. Роли вне списка сообщают о панели только через `aria-expanded`.\n 'aria-haspopup': HASPOPUP_ROLES.includes(props.role as (typeof HASPOPUP_ROLES)[number])\n ? (props.role as (typeof HASPOPUP_ROLES)[number])\n : undefined,\n 'aria-expanded': isOpen.value,\n 'aria-controls': isOpen.value ? panelId : undefined,\n 'disabled': props.disabled || undefined,\n 'onClick': onTriggerClick,\n}))\n\nfunction onTriggerClick(): void {\n // `hover` не отменяет клика: с клавиатуры и с тачскрина наведения не бывает,\n // и панель, открываемая только курсором, для них не существует вовсе.\n if (props.trigger === 'click' || props.trigger === 'hover')\n toggle()\n}\n\n/** Привязан ли `triggerProps`: `aria-expanded` он ставит всегда, при любой роли. */\nfunction hasBoundTrigger(): boolean {\n return rootEl.value?.querySelector('[aria-expanded]') != null\n}\n\n/**\n * Клик по обёртке — совместимость, а не механизм.\n *\n * Клик триггера живёт в `triggerProps`. Но слот, оставленный без\n * `v-bind=\"triggerProps\"`, до этой правки открывался кликом по обёртке, и молча\n * отнимать это у тех, кто на это опирался, нельзя. Поэтому обёртка срабатывает\n * ровно тогда, когда привязанного триггера внутри нет.\n *\n * Проверка на месте клика, а не при монтировании: содержимое слота реактивно, и\n * триггер может появиться позже. `querySelector` по одному узлу на клик дешевле\n * подписки на мутации.\n */\nfunction onWrapperClick(): void {\n if (hasBoundTrigger())\n return\n\n onTriggerClick()\n}\n\n/**\n * Открытие по наведению.\n *\n * Таймер один на обе стороны и сбрасывается при каждом событии: курсор,\n * прошедший триггер насквозь, не должен оставить за собой отложенное открытие.\n * Нулевая задержка выполняется сразу, а не через `setTimeout(0)`, — иначе\n * открытие уезжало бы на следующий тик и ломало тесты, которые ждут синхронности.\n */\nfunction scheduleHover(next: boolean, delayMs: number): void {\n clearTimeout(hoverTimer)\n\n if (delayMs <= 0) {\n setOpen(next)\n return\n }\n\n hoverTimer = setTimeout(setOpen, delayMs, next)\n}\n\nfunction onHoverEnter(): void {\n if (props.disabled || props.trigger !== 'hover')\n return\n\n scheduleHover(true, props.openDelay)\n}\n\nfunction onHoverLeave(): void {\n if (props.trigger !== 'hover')\n return\n\n scheduleHover(false, props.closeDelay)\n}\n\n// Триггер без `v-bind=\"triggerProps\"` работает по совместимости, но остаётся без\n// клавиатуры и без ARIA: панель для скринридера не объявлена, и с `Tab` до неё не\n// добраться. Молчать нельзя — снаружи это выглядит как «поповер почти работает».\nonMounted(() => {\n if (!__GR_DEV__ || !hasTrigger.value || hasBoundTrigger())\n return\n\n console.warn(\n '[GrPopover] триггер не привязан: добавьте `v-bind=\"triggerProps\"` на элемент '\n + 'внутри слота #trigger — <template #trigger=\"{ triggerProps }\">'\n + '<GrButton v-bind=\"triggerProps\">…</GrButton></template>. '\n + 'Клик по обёртке пока работает, но у триггера нет ни клавиатуры, ни '\n + 'aria-haspopup/aria-expanded, а клик по вложенным элементам открывает панель.',\n )\n})\n\nonBeforeUnmount(() => {\n clearTimeout(hoverTimer)\n})\n\nfunction onContentClick(): void {\n if (props.closeOnContentClick)\n close()\n}\n\nconst panelClasses = computed(() =>\n grPopoverPanelClass(resolvedSize.value, resolvedPlacement.value, props.contentClass, props.padding),\n)\n\ndefineExpose({ open, close, toggle })\n\ndefineSlots<{\n /**\n * Триггер панели. `triggerProps` обязаны попасть на сам интерактивный\n * элемент, а не на обёртку вокруг него: `aria-expanded` и `aria-controls`\n * читаются с того узла, который получает фокус.\n */\n trigger?: (props: {\n open: boolean\n toggle: () => void\n close: () => void\n triggerProps: Record<string, unknown>\n }) => any\n /** Содержимое панели. */\n content?: (props: { close: () => void }) => any\n}>()\n</script>\n\n<template>\n <div data-gr-popover>\n <div\n v-if=\"hasTrigger\"\n ref=\"rootEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside, exclude: clickOutsideExclude }\"\n data-gr-popover-trigger\n :class=\"block ? 'block w-full' : 'inline-block max-w-full'\"\n @click=\"onWrapperClick\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n >\n <slot\n name=\"trigger\"\n :open=\"isOpen\"\n :toggle=\"toggle\"\n :close=\"close\"\n :trigger-props=\"triggerProps\"\n />\n </div>\n\n <teleport :to=\"portalTarget\" :disabled=\"!teleportEnabled\">\n <transition\n :enter-active-class=\"panelPopTransition.enter\"\n :enter-from-class=\"panelPopTransition.enterFrom\"\n :enter-to-class=\"panelPopTransition.enterTo\"\n :leave-active-class=\"panelPopTransition.leave\"\n :leave-from-class=\"panelPopTransition.leaveFrom\"\n :leave-to-class=\"panelPopTransition.leaveTo\"\n >\n <div\n v-show=\"isOpen\"\n :id=\"panelId\"\n ref=\"panelEl\"\n v-click-outside=\"{ handler: close, enabled: isOpen && closeOnClickOutside && !hasTrigger }\"\n v-bind=\"themeAttrs\"\n data-gr-popover-panel\n data-gr-overlay-root\n :role=\"role === 'none' ? undefined : role\"\n :aria-modal=\"modal ? 'true' : undefined\"\n :inert=\"inertAttr\"\n :aria-label=\"labelledBy ? undefined : ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n tabindex=\"-1\"\n :class=\"panelClasses\"\n :style=\"floatingStyle\"\n @mouseenter=\"onHoverEnter\"\n @mouseleave=\"onHoverLeave\"\n @click=\"onContentClick\"\n >\n <slot name=\"content\" :close=\"close\" />\n </div>\n </transition>\n </teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrPopover_default } from "./chunks/GrPopover-DEFxDffj.js";
2
- import { n as grPopoverSafelist, t as grPopoverConfig } from "../../chunks/config-DVCNvhIG2.js";
1
+ import { t as GrPopover_default } from "./chunks/GrPopover-BakLcWkX.js";
2
+ import { n as grPopoverSafelist, t as grPopoverConfig } from "../../chunks/config-DVCNvhIG.js";
3
3
  export { GrPopover_default as GrPopover, GrPopover_default as default, grPopoverConfig, grPopoverSafelist };
@@ -1,6 +1,6 @@
1
- import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
1
+ import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
2
2
  import { a as valueTextSizes, i as trackSizes, n as grProgressBarFillClass, r as rowGaps, t as bufferClass } from "../../../chunks/grStyle-CrgLQKKf.js";
3
- import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, toDisplayString, unref } from "vue";
3
+ import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, toDisplayString, unref, watchEffect } from "vue";
4
4
  import '../styles.css';//#region src/components/GrProgressBar/GrProgressBar.vue?vue&type=script&setup=true&lang.ts
5
5
  var _hoisted_1 = [
6
6
  "data-gr-progress-bar-indeterminate",
@@ -43,12 +43,15 @@ var GrProgressBar_default = /* @__PURE__ */ defineComponent({
43
43
  const rowGapClassName = computed(() => rowGaps[resolvedSize.value]);
44
44
  const valueClassName = computed(() => valueTextSizes[resolvedSize.value]);
45
45
  function clampValue(value) {
46
- if (Number.isNaN(value)) return 0;
46
+ if (!Number.isFinite(value)) return 0;
47
47
  return Math.min(100, Math.max(0, value));
48
48
  }
49
49
  const safe = computed(() => clampValue(props.value));
50
50
  const safeBuffer = computed(() => props.buffer === void 0 ? void 0 : clampValue(props.buffer));
51
51
  const fillClassName = computed(() => grProgressBarFillClass(props.tone));
52
+ if (process.env.NODE_ENV !== "production") watchEffect(() => {
53
+ if (!props.indeterminate && !Number.isFinite(props.value)) console.warn(`[granularity] GrProgressBar: обязательный проп \`value\` должен быть числом — получено ${String(props.value)}.`);
54
+ });
52
55
  /**
53
56
  * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax="100"`
54
57
  * диктор и так читает как проценты, дублировать это текстом незачем.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrProgressBar-C3NRBqIP.js","names":[],"sources":["../../../../src/components/GrProgressBar/GrProgressBar.vue","../../../../src/components/GrProgressBar/GrProgressBar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, watchEffect } from 'vue'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport {\n bufferClass,\n grProgressBarFillClass,\n type GrProgressBarSize,\n type GrProgressBarTone,\n rowGaps,\n trackSizes,\n valueTextSizes,\n} from './grStyle'\n\n/**\n * Пропы {@link GrProgressBar}.\n *\n * Линейный индикатор прогресса: определённый режим по `value` и неопределённый\n * по `indeterminate`, необязательный слой буфера и подпись значения.\n */\nexport interface GrProgressBarProps {\n /** Текущее значение `0..100`; выходящие за границы клампятся, нечисловое → `0`. */\n value: number\n /** Загружено с запасом: слой позади заливки, `0..100`. Не задан — слоя нет. */\n buffer?: number\n /** Прогресс неизвестен: полоса бежит, значение наружу не объявляется. */\n indeterminate?: boolean\n /** Показать значение подписью справа от трека. */\n showValue?: boolean\n /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */\n formatValue?: (value: number) => string\n /** Метка для скринридера (обязательна, если рядом нет видимого заголовка). */\n ariaLabel?: string\n /** Цветовая тональность заливки. */\n tone?: GrProgressBarTone\n /** Толщина трека. */\n size?: GrProgressBarSize\n /** Убрать рамку трека: внутри карточки вторая рамка только шумит. */\n borderless?: boolean\n}\n\nconst props = withDefaults(defineProps<GrProgressBarProps>(), {\n buffer: undefined,\n indeterminate: false,\n showValue: false,\n formatValue: undefined,\n ariaLabel: undefined,\n tone: 'primary',\n size: undefined,\n // `undefined`, а не `false`: иначе значение из `componentDefaults` не дошло бы.\n borderless: undefined,\n})\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrProgressBar' })\nconst resolvedBorderless = useGrComponentProp('GrProgressBar', 'borderless', () => props.borderless, false)\nconst trackClassName = computed(() => trackSizes[resolvedSize.value])\nconst rowGapClassName = computed(() => rowGaps[resolvedSize.value])\nconst valueClassName = computed(() => valueTextSizes[resolvedSize.value])\n\n// Проверка именно на конечность, а не на `NaN`: `Number.isNaN(undefined)` —\n// `false`, и не доехавший обязательный проп утёк бы в `aria-valuenow=\"NaN\"`.\nfunction clampValue(value: number): number {\n if (!Number.isFinite(value))\n return 0\n return Math.min(100, Math.max(0, value))\n}\n\nconst safe = computed(() => clampValue(props.value))\nconst safeBuffer = computed(() => (props.buffer === undefined ? undefined : clampValue(props.buffer)))\n\nconst fillClassName = computed(() => grProgressBarFillClass(props.tone))\n\nif (__GR_DEV__) {\n watchEffect(() => {\n if (!props.indeterminate && !Number.isFinite(props.value)) {\n console.warn(\n `[granularity] GrProgressBar: обязательный проп \\`value\\` должен быть числом — получено ${String(props.value)}.`,\n )\n }\n })\n}\n\n/**\n * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax=\"100\"`\n * диктор и так читает как проценты, дублировать это текстом незачем.\n */\nconst valueText = computed(() => (props.formatValue ? props.formatValue(safe.value) : undefined))\nconst valueLabel = computed(() => valueText.value ?? `${Math.round(safe.value)}%`)\n</script>\n\n<template>\n <div\n data-gr-progress-bar\n class=\"w-full flex items-center\"\n :class=\"rowGapClassName\"\n >\n <div\n data-gr-progress-bar-track\n :data-gr-progress-bar-indeterminate=\"indeterminate ? '' : undefined\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"indeterminate ? undefined : safe\"\n :aria-valuetext=\"indeterminate ? undefined : valueText\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n class=\"relative min-w-0 flex-1 rounded-[var(--gr-radius-full)] bg-[var(--gr-muted)] overflow-hidden\"\n :class=\"[trackClassName, resolvedBorderless ? '' : 'border border-[var(--gr-brd)]']\"\n >\n <div\n v-if=\"safeBuffer !== undefined && !indeterminate\"\n data-gr-progress-bar-buffer\n class=\"absolute inset-y-0 left-0\"\n :class=\"bufferClass\"\n :style=\"{ width: `${safeBuffer}%` }\"\n />\n <div\n data-gr-progress-bar-fill\n class=\"absolute inset-y-0 left-0\"\n :class=\"fillClassName\"\n :style=\"indeterminate ? undefined : { width: `${safe}%` }\"\n />\n </div>\n <span\n v-if=\"showValue && !indeterminate\"\n data-gr-progress-bar-value\n class=\"text-[var(--gr-muted-fg)] tabular-nums min-w-[4ch] text-right\"\n :class=\"valueClassName\"\n >{{ valueLabel }}</span>\n </div>\n</template>\n\n<style>\n@keyframes gr-progress-indeterminate {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(250%);\n }\n}\n\n/* Ширина бегущей полосы задаётся здесь, а не инлайном: инлайн-стиль перебил бы\n раскладку под `reduce` ниже. */\n[data-gr-progress-bar-indeterminate] [data-gr-progress-bar-fill] {\n width: 40%;\n animation-name: gr-progress-indeterminate;\n animation-duration: var(--gr-progress-indeterminate-duration, 1.4s);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n}\n\n/* Замерев в исходном кадре, полоса легла бы у левого края и читалась как\n «прогресс 40%». Нейтральная заливка на всю ширину не притворяется ни нулём,\n ни завершением: она говорит «работа идёт, значение неизвестно». */\n@media (prefers-reduced-motion: reduce) {\n [data-gr-progress-bar-indeterminate] [data-gr-progress-bar-fill] {\n width: 100%;\n animation: none;\n background-color: var(--gr-progress-indeterminate-bg, var(--gr-muted-fg));\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, watchEffect } from 'vue'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport {\n bufferClass,\n grProgressBarFillClass,\n type GrProgressBarSize,\n type GrProgressBarTone,\n rowGaps,\n trackSizes,\n valueTextSizes,\n} from './grStyle'\n\n/**\n * Пропы {@link GrProgressBar}.\n *\n * Линейный индикатор прогресса: определённый режим по `value` и неопределённый\n * по `indeterminate`, необязательный слой буфера и подпись значения.\n */\nexport interface GrProgressBarProps {\n /** Текущее значение `0..100`; выходящие за границы клампятся, нечисловое → `0`. */\n value: number\n /** Загружено с запасом: слой позади заливки, `0..100`. Не задан — слоя нет. */\n buffer?: number\n /** Прогресс неизвестен: полоса бежит, значение наружу не объявляется. */\n indeterminate?: boolean\n /** Показать значение подписью справа от трека. */\n showValue?: boolean\n /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */\n formatValue?: (value: number) => string\n /** Метка для скринридера (обязательна, если рядом нет видимого заголовка). */\n ariaLabel?: string\n /** Цветовая тональность заливки. */\n tone?: GrProgressBarTone\n /** Толщина трека. */\n size?: GrProgressBarSize\n /** Убрать рамку трека: внутри карточки вторая рамка только шумит. */\n borderless?: boolean\n}\n\nconst props = withDefaults(defineProps<GrProgressBarProps>(), {\n buffer: undefined,\n indeterminate: false,\n showValue: false,\n formatValue: undefined,\n ariaLabel: undefined,\n tone: 'primary',\n size: undefined,\n // `undefined`, а не `false`: иначе значение из `componentDefaults` не дошло бы.\n borderless: undefined,\n})\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrProgressBar' })\nconst resolvedBorderless = useGrComponentProp('GrProgressBar', 'borderless', () => props.borderless, false)\nconst trackClassName = computed(() => trackSizes[resolvedSize.value])\nconst rowGapClassName = computed(() => rowGaps[resolvedSize.value])\nconst valueClassName = computed(() => valueTextSizes[resolvedSize.value])\n\n// Проверка именно на конечность, а не на `NaN`: `Number.isNaN(undefined)` —\n// `false`, и не доехавший обязательный проп утёк бы в `aria-valuenow=\"NaN\"`.\nfunction clampValue(value: number): number {\n if (!Number.isFinite(value))\n return 0\n return Math.min(100, Math.max(0, value))\n}\n\nconst safe = computed(() => clampValue(props.value))\nconst safeBuffer = computed(() => (props.buffer === undefined ? undefined : clampValue(props.buffer)))\n\nconst fillClassName = computed(() => grProgressBarFillClass(props.tone))\n\nif (__GR_DEV__) {\n watchEffect(() => {\n if (!props.indeterminate && !Number.isFinite(props.value)) {\n console.warn(\n `[granularity] GrProgressBar: обязательный проп \\`value\\` должен быть числом — получено ${String(props.value)}.`,\n )\n }\n })\n}\n\n/**\n * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax=\"100\"`\n * диктор и так читает как проценты, дублировать это текстом незачем.\n */\nconst valueText = computed(() => (props.formatValue ? props.formatValue(safe.value) : undefined))\nconst valueLabel = computed(() => valueText.value ?? `${Math.round(safe.value)}%`)\n</script>\n\n<template>\n <div\n data-gr-progress-bar\n class=\"w-full flex items-center\"\n :class=\"rowGapClassName\"\n >\n <div\n data-gr-progress-bar-track\n :data-gr-progress-bar-indeterminate=\"indeterminate ? '' : undefined\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"indeterminate ? undefined : safe\"\n :aria-valuetext=\"indeterminate ? undefined : valueText\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n class=\"relative min-w-0 flex-1 rounded-[var(--gr-radius-full)] bg-[var(--gr-muted)] overflow-hidden\"\n :class=\"[trackClassName, resolvedBorderless ? '' : 'border border-[var(--gr-brd)]']\"\n >\n <div\n v-if=\"safeBuffer !== undefined && !indeterminate\"\n data-gr-progress-bar-buffer\n class=\"absolute inset-y-0 left-0\"\n :class=\"bufferClass\"\n :style=\"{ width: `${safeBuffer}%` }\"\n />\n <div\n data-gr-progress-bar-fill\n class=\"absolute inset-y-0 left-0\"\n :class=\"fillClassName\"\n :style=\"indeterminate ? undefined : { width: `${safe}%` }\"\n />\n </div>\n <span\n v-if=\"showValue && !indeterminate\"\n data-gr-progress-bar-value\n class=\"text-[var(--gr-muted-fg)] tabular-nums min-w-[4ch] text-right\"\n :class=\"valueClassName\"\n >{{ valueLabel }}</span>\n </div>\n</template>\n\n<style>\n@keyframes gr-progress-indeterminate {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(250%);\n }\n}\n\n/* Ширина бегущей полосы задаётся здесь, а не инлайном: инлайн-стиль перебил бы\n раскладку под `reduce` ниже. */\n[data-gr-progress-bar-indeterminate] [data-gr-progress-bar-fill] {\n width: 40%;\n animation-name: gr-progress-indeterminate;\n animation-duration: var(--gr-progress-indeterminate-duration, 1.4s);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n}\n\n/* Замерев в исходном кадре, полоса легла бы у левого края и читалась как\n «прогресс 40%». Нейтральная заливка на всю ширину не притворяется ни нулём,\n ни завершением: она говорит «работа идёт, значение неизвестно». */\n@media (prefers-reduced-motion: reduce) {\n [data-gr-progress-bar-indeterminate] [data-gr-progress-bar-fill] {\n width: 100%;\n animation: none;\n background-color: var(--gr-progress-indeterminate-bg, var(--gr-muted-fg));\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCA,MAAM,QAAQ;EAYd,MAAM,eAAe,yBAAyB,MAAM,MAAM,EAAE,WAAW,gBAAgB,CAAC;EACxF,MAAM,qBAAqB,mBAAmB,iBAAiB,oBAAoB,MAAM,YAAY,KAAK;EAC1G,MAAM,iBAAiB,eAAe,WAAW,aAAa,MAAM;EACpE,MAAM,kBAAkB,eAAe,QAAQ,aAAa,MAAM;EAClE,MAAM,iBAAiB,eAAe,eAAe,aAAa,MAAM;EAIxE,SAAS,WAAW,OAAuB;GACzC,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,OAAO;GACT,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;EACzC;EAEA,MAAM,OAAO,eAAe,WAAW,MAAM,KAAK,CAAC;EACnD,MAAM,aAAa,eAAgB,MAAM,WAAW,KAAA,IAAY,KAAA,IAAY,WAAW,MAAM,MAAM,CAAE;EAErG,MAAM,gBAAgB,eAAe,uBAAuB,MAAM,IAAI,CAAC;EAEvE,IAAA,QAAA,IAAA,aAAA,cACE,kBAAkB;GAChB,IAAI,CAAC,MAAM,iBAAiB,CAAC,OAAO,SAAS,MAAM,KAAK,GACtD,QAAQ,KACN,0FAA0F,OAAO,MAAM,KAAK,EAAE,EAChH;EAEJ,CAAC;;;;;EAOH,MAAM,YAAY,eAAgB,MAAM,cAAc,MAAM,YAAY,KAAK,KAAK,IAAI,KAAA,CAAU;EAChG,MAAM,aAAa,eAAe,UAAU,SAAS,GAAG,KAAK,MAAM,KAAK,KAAK,EAAE,EAAE;;GAI/E,OAAA,UAAA,GAAA,mBAqCM,OAAA;IApCJ,wBAAA;IACA,OAAK,eAAA,CAAC,4BACE,gBAAA,KAAe,CAAA;GAEvB,GAAA,CAAA,mBAyBM,OAAA;IAxBJ,8BAAA;IACC,sCAAoC,QAAA,gBAAa,KAAQ,KAAA;IAC1D,MAAK;IACJ,cAAY,QAAA;IACZ,iBAAe,QAAA,gBAAgB,KAAA,IAAY,KAAA;IAC3C,kBAAgB,QAAA,gBAAgB,KAAA,IAAY,UAAA;IAC7C,iBAAc;IACd,iBAAc;IACd,OAAK,eAAA,CAAC,gGAA8F,CAC3F,eAAA,OAAgB,MAAA,kBAAA,IAAkB,KAAA,+BAAA,CAAA,CAAA;GAGnC,GAAA,CAAA,WAAA,UAAe,KAAA,KAAS,CAAK,QAAA,iBADrC,UAAA,GAAA,mBAME,OAAA;;IAJA,+BAAA;IACA,OAAK,eAAA,CAAC,6BACE,MAAA,WAAA,CAAW,CAAA;IAClB,OAAK,eAAA,EAAA,OAAA,GAAc,WAAA,MAAU,GAAA,CAAA;GAEhC,GAAA,MAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,GAAA,mBAKE,OAAA;IAJA,6BAAA;IACA,OAAK,eAAA,CAAC,6BACE,cAAA,KAAa,CAAA;IACpB,OAAK,eAAE,QAAA,gBAAgB,KAAA,IAAS,EAAA,OAAA,GAAe,KAAA,MAAI,GAAA,CAAA;GAIhD,GAAA,MAAA,CAAA,CAAA,GAAA,IAAA,UAAA,GAAA,QAAA,aAAS,CAAK,QAAA,iBADtB,UAAA,GAAA,mBAKwB,QAAA;;IAHtB,8BAAA;IACA,OAAK,eAAA,CAAC,iEACE,eAAA,KAAc,CAAA;GACpB,GAAA,gBAAA,WAAA,KAAU,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,CAAA"}
@@ -1,3 +1,3 @@
1
- import { t as GrProgressBar_default } from "./chunks/GrProgressBar-hszUOC8f.js";
1
+ import { t as GrProgressBar_default } from "./chunks/GrProgressBar-C3NRBqIP.js";
2
2
  import { n as grProgressBarSafelist, t as grProgressBarConfig } from "../../chunks/config-DWL81-aM.js";
3
3
  export { GrProgressBar_default as GrProgressBar, GrProgressBar_default as default, grProgressBarConfig, grProgressBarSafelist };
@@ -1,5 +1,5 @@
1
1
  import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
2
- import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
2
+ import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
3
3
  import { t as check_default } from "../../../chunks/check-BZI24Qs4.js";
4
4
  import { n as hasMeaningfulSlotContent } from "../../../chunks/slotNodes-DxNXpC7v.js";
5
5
  import { a as grProgressCircleArcColor, c as svgClass, d as valueTextSizeBySize, i as diameterBySize, l as thicknessBySize, o as rootClass, r as centerClass, s as statusIconSizeBySize, u as valueClass } from "../../../chunks/config-CJzmDHfI.js";
@@ -28,7 +28,7 @@ function clampProgress(value) {
28
28
  * каждую форму, и ошибка в нём видна только глазом на конкретной ступени.
29
29
  */
30
30
  function arcGeometry(shape, thickness, value) {
31
- const radius = 100 / 2 - Math.max(1, Math.min(100 / 2, thickness)) / 2;
31
+ const radius = 50 - Math.max(1, Math.min(50, thickness)) / 2;
32
32
  const circumference = 2 * Math.PI * radius;
33
33
  const arcLength = circumference * ARC_FRACTION[shape];
34
34
  const progress = clampProgress(value) / 100;
@@ -1 +1 @@
1
- {"version":3,"file":"GrProgressCircle-D3yWXYDa.js","names":[],"sources":["../../../../src/components/GrProgressCircle/geometry.ts","../../../../src/components/GrProgressCircle/GrProgressCircle.vue","../../../../src/components/GrProgressCircle/GrProgressCircle.vue"],"sourcesContent":["/**\n * Геометрия дуги прогресса. Без Vue — проверяется без монтирования.\n *\n * Все размеры в единицах `viewBox` 100×100: разметка не зависит от того, каким\n * `size` кольцо выводится, а масштабирование остаётся делом CSS.\n */\n\nexport const GR_PROGRESS_CIRCLE_SHAPES = ['circle', 'dashboard'] as const\n\nexport type GrProgressCircleShape = typeof GR_PROGRESS_CIRCLE_SHAPES[number]\n\n/** Сторона `viewBox`; центр — в её половине. */\nexport const VIEW_BOX = 100\n\n/** Доля окружности под дугой: у «дашборда» снизу вырез в четверть. */\nconst ARC_FRACTION: Record<GrProgressCircleShape, number> = {\n circle: 1,\n dashboard: 0.75,\n}\n\n/**\n * Угол начала дуги. `<circle>` в SVG стартует с трёх часов и идёт по часовой:\n * кольцу нужен старт с двенадцати, «дашборду» — так, чтобы вырез сел строго\n * вниз и симметрично.\n */\nconst ROTATION: Record<GrProgressCircleShape, number> = {\n circle: -90,\n dashboard: 135,\n}\n\nexport interface GrArcGeometry {\n /** Радиус с поправкой на толщину: обводка рисуется по обе стороны линии. */\n radius: number\n circumference: number\n /** Длина дорожки — вся окружность либо её часть у «дашборда». */\n arcLength: number\n /** `stroke-dasharray` дорожки. */\n trackDashArray: string\n /** `stroke-dasharray` дуги значения. */\n valueDashArray: string\n rotation: number\n}\n\nexport function clampProgress(value: number): number {\n if (!Number.isFinite(value))\n return 0\n\n return Math.min(100, Math.max(0, value))\n}\n\n/**\n * Дуга задаётся одним штрихом нужной длины и заведомо большим пробелом за ним,\n * а не парой `dasharray` + `dashoffset`: смещение пришлось бы пересчитывать под\n * каждую форму, и ошибка в нём видна только глазом на конкретной ступени.\n */\nexport function arcGeometry(\n shape: GrProgressCircleShape,\n thickness: number,\n value: number,\n): GrArcGeometry {\n const safeThickness = Math.max(1, Math.min(VIEW_BOX / 2, thickness))\n const radius = VIEW_BOX / 2 - safeThickness / 2\n const circumference = 2 * Math.PI * radius\n const arcLength = circumference * ARC_FRACTION[shape]\n const progress = clampProgress(value) / 100\n\n return {\n radius,\n circumference,\n arcLength,\n trackDashArray: `${arcLength} ${circumference}`,\n valueDashArray: `${arcLength * progress} ${circumference}`,\n rotation: ROTATION[shape],\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconError from '~icons/lucide/x'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { arcGeometry, clampProgress, VIEW_BOX, type GrProgressCircleShape } from './geometry'\nimport {\n centerClass,\n diameterBySize,\n grProgressCircleArcColor,\n rootClass,\n statusIconSizeBySize,\n svgClass,\n thicknessBySize,\n valueClass,\n valueTextSizeBySize,\n type GrProgressCircleSize,\n type GrProgressCircleTone,\n} from './grProgressCircleStyles'\n\nexport type { GrProgressCircleShape } from './geometry'\nexport type { GrProgressCircleSize, GrProgressCircleTone } from './grProgressCircleStyles'\n\n/**\n * Пропы {@link GrProgressCircle}.\n *\n * Круговой индикатор: определённый режим по `value`, неопределённый по\n * `indeterminate`, замкнутое кольцо или дуга-«дашборд».\n */\nexport interface GrProgressCircleProps {\n /** Текущее значение `0..100`; выходящие за границы клампятся, `NaN` → `0`. */\n value?: number\n /** Прогресс неизвестен: дуга бежит по кругу, значение наружу не объявляется. */\n indeterminate?: boolean\n /** Замкнутое кольцо или дуга с вырезом снизу. */\n shape?: GrProgressCircleShape\n /** Показать значение в центре кольца. Слот по умолчанию сильнее. */\n showValue?: boolean\n /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */\n formatValue?: (value: number) => string\n /** На завершении — галочка, при `tone=\"danger\"` — крест вместо значения. */\n statusIcon?: boolean\n /** Метка для скринридера (обязательна, если рядом нет видимого заголовка). */\n ariaLabel?: string\n /** Цветовая тональность дуги. */\n tone?: GrProgressCircleTone\n /** Диаметр кольца по шкале пакета. */\n size?: GrProgressCircleSize\n /** Толщина обводки в процентах диаметра. Не задана — по ступени `size`. */\n thickness?: number\n /** Убрать дорожку: поверх картинки пустая часть кольца только шумит. */\n trackless?: boolean\n}\n\nconst props = withDefaults(defineProps<GrProgressCircleProps>(), {\n value: 0,\n indeterminate: false,\n showValue: false,\n formatValue: undefined,\n statusIcon: false,\n ariaLabel: undefined,\n thickness: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n shape: undefined,\n tone: undefined,\n size: undefined,\n trackless: undefined,\n})\n\ndefineSlots<{\n /** Содержимое центра вместо значения: иконка, две строки, кнопка отмены. */\n default?: (props: { value: number }) => any\n}>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrProgressCircle' })\nconst resolvedTone = useGrComponentProp('GrProgressCircle', 'tone', () => props.tone, 'primary')\nconst resolvedShape = useGrComponentProp('GrProgressCircle', 'shape', () => props.shape, 'circle')\nconst resolvedTrackless = useGrComponentProp('GrProgressCircle', 'trackless', () => props.trackless, false)\n\nconst safe = computed(() => clampProgress(props.value))\n\nconst thickness = computed(() => props.thickness ?? thicknessBySize[resolvedSize.value])\n\nconst arc = computed(() => arcGeometry(resolvedShape.value, thickness.value, safe.value))\n\nconst rootStyle = computed(() => ({\n width: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n height: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n}))\n\nconst arcStyle = computed(() => ({\n transform: `rotate(${arc.value.rotation}deg)`,\n transformOrigin: '50% 50%',\n}))\n\nconst arcColor = computed(() => grProgressCircleArcColor(resolvedTone.value))\n\n/**\n * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax=\"100\"`\n * диктор и так читает как проценты.\n */\nconst valueText = computed(() => (props.formatValue ? props.formatValue(safe.value) : undefined))\nconst valueLabel = computed(() => valueText.value ?? `${Math.round(safe.value)}%`)\n\nconst isComplete = computed(() => !props.indeterminate && safe.value >= 100)\nconst isFailed = computed(() => resolvedTone.value === 'danger')\n\n/**\n * Приоритет центра: слот сильнее иконки итога, иконка итога — значения.\n *\n * Считается по содержимому слота, а не по факту его передачи: слот с `v-if`\n * (кнопка отмены, живущая только на время загрузки) приходит комментарием, и\n * центр остался бы пустым вместо значения.\n */\nconst hasSlotContent = computed(() => hasMeaningfulSlotContent(slots.default?.({ value: safe.value }) ?? []))\nconst showStatusIcon = computed(() => !hasSlotContent.value && props.statusIcon && (isComplete.value || isFailed.value))\nconst showValueLabel = computed(() => !hasSlotContent.value && props.showValue && !props.indeterminate && !showStatusIcon.value)\nconst hasCenter = computed(() => hasSlotContent.value || showStatusIcon.value || showValueLabel.value)\n</script>\n\n<template>\n <div\n data-gr-progress-circle\n :data-tone=\"resolvedTone\"\n :data-shape=\"resolvedShape\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n >\n <div\n data-gr-progress-circle-widget\n :data-gr-progress-circle-indeterminate=\"indeterminate ? '' : undefined\"\n role=\"progressbar\"\n class=\"h-full w-full\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"indeterminate ? undefined : safe\"\n :aria-valuetext=\"indeterminate ? undefined : valueText\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <svg\n :class=\"svgClass\"\n :viewBox=\"`0 0 ${VIEW_BOX} ${VIEW_BOX}`\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle\n v-if=\"!resolvedTrackless\"\n data-gr-progress-circle-track\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"arc.trackDashArray\"\n :style=\"arcStyle\"\n />\n\n <!-- Нулевая дуга при круглом торце нарисовалась бы точкой — «начали». -->\n <circle\n v-if=\"indeterminate || safe > 0\"\n data-gr-progress-circle-arc\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke=\"arcColor\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"indeterminate ? `${arc.circumference * 0.25} ${arc.circumference}` : arc.valueDashArray\"\n :style=\"arcStyle\"\n />\n </svg>\n </div>\n\n <!--\n Центр — сосед виджета, а не его потомок: `role=\"progressbar\"` объявляет\n потомков презентационными, и кнопка «Отменить» внутри кольца стала бы\n `nested-interactive`.\n -->\n <div\n v-if=\"hasCenter\"\n data-gr-progress-circle-center\n :class=\"centerClass\"\n :style=\"{ fontSize: `var(--gr-progress-circle-value-size, ${valueTextSizeBySize[resolvedSize]})` }\"\n >\n <slot v-if=\"hasSlotContent\" :value=\"safe\" />\n\n <component\n :is=\"isComplete ? IconCheck : IconError\"\n v-else-if=\"showStatusIcon\"\n data-gr-progress-circle-status\n aria-hidden=\"true\"\n :class=\"statusIconSizeBySize[resolvedSize]\"\n :style=\"{ color: arcColor }\"\n />\n\n <span\n v-else-if=\"showValueLabel\"\n data-gr-progress-circle-value\n :class=\"valueClass\"\n >{{ valueLabel }}</span>\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-progress-circle-track] {\n stroke: var(--gr-progress-circle-track, var(--gr-muted));\n}\n\n[data-gr-progress-circle-arc] {\n stroke-linecap: var(--gr-progress-circle-cap, round);\n transition: stroke-dasharray var(--gr-duration-base) var(--gr-ease-out);\n}\n\n/* Оба кадра заданы явно: иначе стартом становится инлайновый поворот дуги, и\n каждый оборот заканчивался бы скачком. */\n@keyframes gr-progress-circle-spin {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n[data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation-name: gr-progress-circle-spin;\n animation-duration: var(--gr-progress-indeterminate-duration, 1.4s);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n transition: none;\n}\n\n/*\n * Замерев в исходном кадре, четверть кольца читалась бы как «прогресс 25 %».\n * Замкнутая нейтральная дорожка не притворяется ни нулём, ни завершением: она\n * говорит «работа идёт, значение неизвестно» — тот же приём, что у полосы.\n */\n@media (prefers-reduced-motion: reduce) {\n [data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation: none;\n stroke: var(--gr-progress-indeterminate-bg, var(--gr-muted-fg));\n stroke-dasharray: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconError from '~icons/lucide/x'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { arcGeometry, clampProgress, VIEW_BOX, type GrProgressCircleShape } from './geometry'\nimport {\n centerClass,\n diameterBySize,\n grProgressCircleArcColor,\n rootClass,\n statusIconSizeBySize,\n svgClass,\n thicknessBySize,\n valueClass,\n valueTextSizeBySize,\n type GrProgressCircleSize,\n type GrProgressCircleTone,\n} from './grProgressCircleStyles'\n\nexport type { GrProgressCircleShape } from './geometry'\nexport type { GrProgressCircleSize, GrProgressCircleTone } from './grProgressCircleStyles'\n\n/**\n * Пропы {@link GrProgressCircle}.\n *\n * Круговой индикатор: определённый режим по `value`, неопределённый по\n * `indeterminate`, замкнутое кольцо или дуга-«дашборд».\n */\nexport interface GrProgressCircleProps {\n /** Текущее значение `0..100`; выходящие за границы клампятся, `NaN` → `0`. */\n value?: number\n /** Прогресс неизвестен: дуга бежит по кругу, значение наружу не объявляется. */\n indeterminate?: boolean\n /** Замкнутое кольцо или дуга с вырезом снизу. */\n shape?: GrProgressCircleShape\n /** Показать значение в центре кольца. Слот по умолчанию сильнее. */\n showValue?: boolean\n /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */\n formatValue?: (value: number) => string\n /** На завершении — галочка, при `tone=\"danger\"` — крест вместо значения. */\n statusIcon?: boolean\n /** Метка для скринридера (обязательна, если рядом нет видимого заголовка). */\n ariaLabel?: string\n /** Цветовая тональность дуги. */\n tone?: GrProgressCircleTone\n /** Диаметр кольца по шкале пакета. */\n size?: GrProgressCircleSize\n /** Толщина обводки в процентах диаметра. Не задана — по ступени `size`. */\n thickness?: number\n /** Убрать дорожку: поверх картинки пустая часть кольца только шумит. */\n trackless?: boolean\n}\n\nconst props = withDefaults(defineProps<GrProgressCircleProps>(), {\n value: 0,\n indeterminate: false,\n showValue: false,\n formatValue: undefined,\n statusIcon: false,\n ariaLabel: undefined,\n thickness: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n shape: undefined,\n tone: undefined,\n size: undefined,\n trackless: undefined,\n})\n\ndefineSlots<{\n /** Содержимое центра вместо значения: иконка, две строки, кнопка отмены. */\n default?: (props: { value: number }) => any\n}>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrProgressCircle' })\nconst resolvedTone = useGrComponentProp('GrProgressCircle', 'tone', () => props.tone, 'primary')\nconst resolvedShape = useGrComponentProp('GrProgressCircle', 'shape', () => props.shape, 'circle')\nconst resolvedTrackless = useGrComponentProp('GrProgressCircle', 'trackless', () => props.trackless, false)\n\nconst safe = computed(() => clampProgress(props.value))\n\nconst thickness = computed(() => props.thickness ?? thicknessBySize[resolvedSize.value])\n\nconst arc = computed(() => arcGeometry(resolvedShape.value, thickness.value, safe.value))\n\nconst rootStyle = computed(() => ({\n width: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n height: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n}))\n\nconst arcStyle = computed(() => ({\n transform: `rotate(${arc.value.rotation}deg)`,\n transformOrigin: '50% 50%',\n}))\n\nconst arcColor = computed(() => grProgressCircleArcColor(resolvedTone.value))\n\n/**\n * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax=\"100\"`\n * диктор и так читает как проценты.\n */\nconst valueText = computed(() => (props.formatValue ? props.formatValue(safe.value) : undefined))\nconst valueLabel = computed(() => valueText.value ?? `${Math.round(safe.value)}%`)\n\nconst isComplete = computed(() => !props.indeterminate && safe.value >= 100)\nconst isFailed = computed(() => resolvedTone.value === 'danger')\n\n/**\n * Приоритет центра: слот сильнее иконки итога, иконка итога — значения.\n *\n * Считается по содержимому слота, а не по факту его передачи: слот с `v-if`\n * (кнопка отмены, живущая только на время загрузки) приходит комментарием, и\n * центр остался бы пустым вместо значения.\n */\nconst hasSlotContent = computed(() => hasMeaningfulSlotContent(slots.default?.({ value: safe.value }) ?? []))\nconst showStatusIcon = computed(() => !hasSlotContent.value && props.statusIcon && (isComplete.value || isFailed.value))\nconst showValueLabel = computed(() => !hasSlotContent.value && props.showValue && !props.indeterminate && !showStatusIcon.value)\nconst hasCenter = computed(() => hasSlotContent.value || showStatusIcon.value || showValueLabel.value)\n</script>\n\n<template>\n <div\n data-gr-progress-circle\n :data-tone=\"resolvedTone\"\n :data-shape=\"resolvedShape\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n >\n <div\n data-gr-progress-circle-widget\n :data-gr-progress-circle-indeterminate=\"indeterminate ? '' : undefined\"\n role=\"progressbar\"\n class=\"h-full w-full\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"indeterminate ? undefined : safe\"\n :aria-valuetext=\"indeterminate ? undefined : valueText\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <svg\n :class=\"svgClass\"\n :viewBox=\"`0 0 ${VIEW_BOX} ${VIEW_BOX}`\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle\n v-if=\"!resolvedTrackless\"\n data-gr-progress-circle-track\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"arc.trackDashArray\"\n :style=\"arcStyle\"\n />\n\n <!-- Нулевая дуга при круглом торце нарисовалась бы точкой — «начали». -->\n <circle\n v-if=\"indeterminate || safe > 0\"\n data-gr-progress-circle-arc\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke=\"arcColor\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"indeterminate ? `${arc.circumference * 0.25} ${arc.circumference}` : arc.valueDashArray\"\n :style=\"arcStyle\"\n />\n </svg>\n </div>\n\n <!--\n Центр — сосед виджета, а не его потомок: `role=\"progressbar\"` объявляет\n потомков презентационными, и кнопка «Отменить» внутри кольца стала бы\n `nested-interactive`.\n -->\n <div\n v-if=\"hasCenter\"\n data-gr-progress-circle-center\n :class=\"centerClass\"\n :style=\"{ fontSize: `var(--gr-progress-circle-value-size, ${valueTextSizeBySize[resolvedSize]})` }\"\n >\n <slot v-if=\"hasSlotContent\" :value=\"safe\" />\n\n <component\n :is=\"isComplete ? IconCheck : IconError\"\n v-else-if=\"showStatusIcon\"\n data-gr-progress-circle-status\n aria-hidden=\"true\"\n :class=\"statusIconSizeBySize[resolvedSize]\"\n :style=\"{ color: arcColor }\"\n />\n\n <span\n v-else-if=\"showValueLabel\"\n data-gr-progress-circle-value\n :class=\"valueClass\"\n >{{ valueLabel }}</span>\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-progress-circle-track] {\n stroke: var(--gr-progress-circle-track, var(--gr-muted));\n}\n\n[data-gr-progress-circle-arc] {\n stroke-linecap: var(--gr-progress-circle-cap, round);\n transition: stroke-dasharray var(--gr-duration-base) var(--gr-ease-out);\n}\n\n/* Оба кадра заданы явно: иначе стартом становится инлайновый поворот дуги, и\n каждый оборот заканчивался бы скачком. */\n@keyframes gr-progress-circle-spin {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n[data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation-name: gr-progress-circle-spin;\n animation-duration: var(--gr-progress-indeterminate-duration, 1.4s);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n transition: none;\n}\n\n/*\n * Замерев в исходном кадре, четверть кольца читалась бы как «прогресс 25 %».\n * Замкнутая нейтральная дорожка не притворяется ни нулём, ни завершением: она\n * говорит «работа идёт, значение неизвестно» — тот же приём, что у полосы.\n */\n@media (prefers-reduced-motion: reduce) {\n [data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation: none;\n stroke: var(--gr-progress-indeterminate-bg, var(--gr-muted-fg));\n stroke-dasharray: none;\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrProgressCircle-CdvbINQc.js","names":[],"sources":["../../../../src/components/GrProgressCircle/geometry.ts","../../../../src/components/GrProgressCircle/GrProgressCircle.vue","../../../../src/components/GrProgressCircle/GrProgressCircle.vue"],"sourcesContent":["/**\n * Геометрия дуги прогресса. Без Vue — проверяется без монтирования.\n *\n * Все размеры в единицах `viewBox` 100×100: разметка не зависит от того, каким\n * `size` кольцо выводится, а масштабирование остаётся делом CSS.\n */\n\nexport const GR_PROGRESS_CIRCLE_SHAPES = ['circle', 'dashboard'] as const\n\nexport type GrProgressCircleShape = typeof GR_PROGRESS_CIRCLE_SHAPES[number]\n\n/** Сторона `viewBox`; центр — в её половине. */\nexport const VIEW_BOX = 100\n\n/** Доля окружности под дугой: у «дашборда» снизу вырез в четверть. */\nconst ARC_FRACTION: Record<GrProgressCircleShape, number> = {\n circle: 1,\n dashboard: 0.75,\n}\n\n/**\n * Угол начала дуги. `<circle>` в SVG стартует с трёх часов и идёт по часовой:\n * кольцу нужен старт с двенадцати, «дашборду» — так, чтобы вырез сел строго\n * вниз и симметрично.\n */\nconst ROTATION: Record<GrProgressCircleShape, number> = {\n circle: -90,\n dashboard: 135,\n}\n\nexport interface GrArcGeometry {\n /** Радиус с поправкой на толщину: обводка рисуется по обе стороны линии. */\n radius: number\n circumference: number\n /** Длина дорожки — вся окружность либо её часть у «дашборда». */\n arcLength: number\n /** `stroke-dasharray` дорожки. */\n trackDashArray: string\n /** `stroke-dasharray` дуги значения. */\n valueDashArray: string\n rotation: number\n}\n\nexport function clampProgress(value: number): number {\n if (!Number.isFinite(value))\n return 0\n\n return Math.min(100, Math.max(0, value))\n}\n\n/**\n * Дуга задаётся одним штрихом нужной длины и заведомо большим пробелом за ним,\n * а не парой `dasharray` + `dashoffset`: смещение пришлось бы пересчитывать под\n * каждую форму, и ошибка в нём видна только глазом на конкретной ступени.\n */\nexport function arcGeometry(\n shape: GrProgressCircleShape,\n thickness: number,\n value: number,\n): GrArcGeometry {\n const safeThickness = Math.max(1, Math.min(VIEW_BOX / 2, thickness))\n const radius = VIEW_BOX / 2 - safeThickness / 2\n const circumference = 2 * Math.PI * radius\n const arcLength = circumference * ARC_FRACTION[shape]\n const progress = clampProgress(value) / 100\n\n return {\n radius,\n circumference,\n arcLength,\n trackDashArray: `${arcLength} ${circumference}`,\n valueDashArray: `${arcLength * progress} ${circumference}`,\n rotation: ROTATION[shape],\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconError from '~icons/lucide/x'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { arcGeometry, clampProgress, VIEW_BOX, type GrProgressCircleShape } from './geometry'\nimport {\n centerClass,\n diameterBySize,\n grProgressCircleArcColor,\n rootClass,\n statusIconSizeBySize,\n svgClass,\n thicknessBySize,\n valueClass,\n valueTextSizeBySize,\n type GrProgressCircleSize,\n type GrProgressCircleTone,\n} from './grProgressCircleStyles'\n\nexport type { GrProgressCircleShape } from './geometry'\nexport type { GrProgressCircleSize, GrProgressCircleTone } from './grProgressCircleStyles'\n\n/**\n * Пропы {@link GrProgressCircle}.\n *\n * Круговой индикатор: определённый режим по `value`, неопределённый по\n * `indeterminate`, замкнутое кольцо или дуга-«дашборд».\n */\nexport interface GrProgressCircleProps {\n /** Текущее значение `0..100`; выходящие за границы клампятся, `NaN` → `0`. */\n value?: number\n /** Прогресс неизвестен: дуга бежит по кругу, значение наружу не объявляется. */\n indeterminate?: boolean\n /** Замкнутое кольцо или дуга с вырезом снизу. */\n shape?: GrProgressCircleShape\n /** Показать значение в центре кольца. Слот по умолчанию сильнее. */\n showValue?: boolean\n /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */\n formatValue?: (value: number) => string\n /** На завершении — галочка, при `tone=\"danger\"` — крест вместо значения. */\n statusIcon?: boolean\n /** Метка для скринридера (обязательна, если рядом нет видимого заголовка). */\n ariaLabel?: string\n /** Цветовая тональность дуги. */\n tone?: GrProgressCircleTone\n /** Диаметр кольца по шкале пакета. */\n size?: GrProgressCircleSize\n /** Толщина обводки в процентах диаметра. Не задана — по ступени `size`. */\n thickness?: number\n /** Убрать дорожку: поверх картинки пустая часть кольца только шумит. */\n trackless?: boolean\n}\n\nconst props = withDefaults(defineProps<GrProgressCircleProps>(), {\n value: 0,\n indeterminate: false,\n showValue: false,\n formatValue: undefined,\n statusIcon: false,\n ariaLabel: undefined,\n thickness: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n shape: undefined,\n tone: undefined,\n size: undefined,\n trackless: undefined,\n})\n\ndefineSlots<{\n /** Содержимое центра вместо значения: иконка, две строки, кнопка отмены. */\n default?: (props: { value: number }) => any\n}>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrProgressCircle' })\nconst resolvedTone = useGrComponentProp('GrProgressCircle', 'tone', () => props.tone, 'primary')\nconst resolvedShape = useGrComponentProp('GrProgressCircle', 'shape', () => props.shape, 'circle')\nconst resolvedTrackless = useGrComponentProp('GrProgressCircle', 'trackless', () => props.trackless, false)\n\nconst safe = computed(() => clampProgress(props.value))\n\nconst thickness = computed(() => props.thickness ?? thicknessBySize[resolvedSize.value])\n\nconst arc = computed(() => arcGeometry(resolvedShape.value, thickness.value, safe.value))\n\nconst rootStyle = computed(() => ({\n width: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n height: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n}))\n\nconst arcStyle = computed(() => ({\n transform: `rotate(${arc.value.rotation}deg)`,\n transformOrigin: '50% 50%',\n}))\n\nconst arcColor = computed(() => grProgressCircleArcColor(resolvedTone.value))\n\n/**\n * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax=\"100\"`\n * диктор и так читает как проценты.\n */\nconst valueText = computed(() => (props.formatValue ? props.formatValue(safe.value) : undefined))\nconst valueLabel = computed(() => valueText.value ?? `${Math.round(safe.value)}%`)\n\nconst isComplete = computed(() => !props.indeterminate && safe.value >= 100)\nconst isFailed = computed(() => resolvedTone.value === 'danger')\n\n/**\n * Приоритет центра: слот сильнее иконки итога, иконка итога — значения.\n *\n * Считается по содержимому слота, а не по факту его передачи: слот с `v-if`\n * (кнопка отмены, живущая только на время загрузки) приходит комментарием, и\n * центр остался бы пустым вместо значения.\n */\nconst hasSlotContent = computed(() => hasMeaningfulSlotContent(slots.default?.({ value: safe.value }) ?? []))\nconst showStatusIcon = computed(() => !hasSlotContent.value && props.statusIcon && (isComplete.value || isFailed.value))\nconst showValueLabel = computed(() => !hasSlotContent.value && props.showValue && !props.indeterminate && !showStatusIcon.value)\nconst hasCenter = computed(() => hasSlotContent.value || showStatusIcon.value || showValueLabel.value)\n</script>\n\n<template>\n <div\n data-gr-progress-circle\n :data-tone=\"resolvedTone\"\n :data-shape=\"resolvedShape\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n >\n <div\n data-gr-progress-circle-widget\n :data-gr-progress-circle-indeterminate=\"indeterminate ? '' : undefined\"\n role=\"progressbar\"\n class=\"h-full w-full\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"indeterminate ? undefined : safe\"\n :aria-valuetext=\"indeterminate ? undefined : valueText\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <svg\n :class=\"svgClass\"\n :viewBox=\"`0 0 ${VIEW_BOX} ${VIEW_BOX}`\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle\n v-if=\"!resolvedTrackless\"\n data-gr-progress-circle-track\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"arc.trackDashArray\"\n :style=\"arcStyle\"\n />\n\n <!-- Нулевая дуга при круглом торце нарисовалась бы точкой — «начали». -->\n <circle\n v-if=\"indeterminate || safe > 0\"\n data-gr-progress-circle-arc\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke=\"arcColor\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"indeterminate ? `${arc.circumference * 0.25} ${arc.circumference}` : arc.valueDashArray\"\n :style=\"arcStyle\"\n />\n </svg>\n </div>\n\n <!--\n Центр — сосед виджета, а не его потомок: `role=\"progressbar\"` объявляет\n потомков презентационными, и кнопка «Отменить» внутри кольца стала бы\n `nested-interactive`.\n -->\n <div\n v-if=\"hasCenter\"\n data-gr-progress-circle-center\n :class=\"centerClass\"\n :style=\"{ fontSize: `var(--gr-progress-circle-value-size, ${valueTextSizeBySize[resolvedSize]})` }\"\n >\n <slot v-if=\"hasSlotContent\" :value=\"safe\" />\n\n <component\n :is=\"isComplete ? IconCheck : IconError\"\n v-else-if=\"showStatusIcon\"\n data-gr-progress-circle-status\n aria-hidden=\"true\"\n :class=\"statusIconSizeBySize[resolvedSize]\"\n :style=\"{ color: arcColor }\"\n />\n\n <span\n v-else-if=\"showValueLabel\"\n data-gr-progress-circle-value\n :class=\"valueClass\"\n >{{ valueLabel }}</span>\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-progress-circle-track] {\n stroke: var(--gr-progress-circle-track, var(--gr-muted));\n}\n\n[data-gr-progress-circle-arc] {\n stroke-linecap: var(--gr-progress-circle-cap, round);\n transition: stroke-dasharray var(--gr-duration-base) var(--gr-ease-out);\n}\n\n/* Оба кадра заданы явно: иначе стартом становится инлайновый поворот дуги, и\n каждый оборот заканчивался бы скачком. */\n@keyframes gr-progress-circle-spin {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n[data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation-name: gr-progress-circle-spin;\n animation-duration: var(--gr-progress-indeterminate-duration, 1.4s);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n transition: none;\n}\n\n/*\n * Замерев в исходном кадре, четверть кольца читалась бы как «прогресс 25 %».\n * Замкнутая нейтральная дорожка не притворяется ни нулём, ни завершением: она\n * говорит «работа идёт, значение неизвестно» — тот же приём, что у полосы.\n */\n@media (prefers-reduced-motion: reduce) {\n [data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation: none;\n stroke: var(--gr-progress-indeterminate-bg, var(--gr-muted-fg));\n stroke-dasharray: none;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconError from '~icons/lucide/x'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { arcGeometry, clampProgress, VIEW_BOX, type GrProgressCircleShape } from './geometry'\nimport {\n centerClass,\n diameterBySize,\n grProgressCircleArcColor,\n rootClass,\n statusIconSizeBySize,\n svgClass,\n thicknessBySize,\n valueClass,\n valueTextSizeBySize,\n type GrProgressCircleSize,\n type GrProgressCircleTone,\n} from './grProgressCircleStyles'\n\nexport type { GrProgressCircleShape } from './geometry'\nexport type { GrProgressCircleSize, GrProgressCircleTone } from './grProgressCircleStyles'\n\n/**\n * Пропы {@link GrProgressCircle}.\n *\n * Круговой индикатор: определённый режим по `value`, неопределённый по\n * `indeterminate`, замкнутое кольцо или дуга-«дашборд».\n */\nexport interface GrProgressCircleProps {\n /** Текущее значение `0..100`; выходящие за границы клампятся, `NaN` → `0`. */\n value?: number\n /** Прогресс неизвестен: дуга бежит по кругу, значение наружу не объявляется. */\n indeterminate?: boolean\n /** Замкнутое кольцо или дуга с вырезом снизу. */\n shape?: GrProgressCircleShape\n /** Показать значение в центре кольца. Слот по умолчанию сильнее. */\n showValue?: boolean\n /** Свой формат значения. Управляет и подписью, и `aria-valuetext`. */\n formatValue?: (value: number) => string\n /** На завершении — галочка, при `tone=\"danger\"` — крест вместо значения. */\n statusIcon?: boolean\n /** Метка для скринридера (обязательна, если рядом нет видимого заголовка). */\n ariaLabel?: string\n /** Цветовая тональность дуги. */\n tone?: GrProgressCircleTone\n /** Диаметр кольца по шкале пакета. */\n size?: GrProgressCircleSize\n /** Толщина обводки в процентах диаметра. Не задана — по ступени `size`. */\n thickness?: number\n /** Убрать дорожку: поверх картинки пустая часть кольца только шумит. */\n trackless?: boolean\n}\n\nconst props = withDefaults(defineProps<GrProgressCircleProps>(), {\n value: 0,\n indeterminate: false,\n showValue: false,\n formatValue: undefined,\n statusIcon: false,\n ariaLabel: undefined,\n thickness: undefined,\n // `undefined`, а не готовые значения: иначе `componentDefaults` до них не дошли бы.\n shape: undefined,\n tone: undefined,\n size: undefined,\n trackless: undefined,\n})\n\ndefineSlots<{\n /** Содержимое центра вместо значения: иконка, две строки, кнопка отмены. */\n default?: (props: { value: number }) => any\n}>()\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrProgressCircle' })\nconst resolvedTone = useGrComponentProp('GrProgressCircle', 'tone', () => props.tone, 'primary')\nconst resolvedShape = useGrComponentProp('GrProgressCircle', 'shape', () => props.shape, 'circle')\nconst resolvedTrackless = useGrComponentProp('GrProgressCircle', 'trackless', () => props.trackless, false)\n\nconst safe = computed(() => clampProgress(props.value))\n\nconst thickness = computed(() => props.thickness ?? thicknessBySize[resolvedSize.value])\n\nconst arc = computed(() => arcGeometry(resolvedShape.value, thickness.value, safe.value))\n\nconst rootStyle = computed(() => ({\n width: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n height: `var(--gr-progress-circle-size, ${diameterBySize[resolvedSize.value]})`,\n}))\n\nconst arcStyle = computed(() => ({\n transform: `rotate(${arc.value.rotation}deg)`,\n transformOrigin: '50% 50%',\n}))\n\nconst arcColor = computed(() => grProgressCircleArcColor(resolvedTone.value))\n\n/**\n * `aria-valuetext` нужен только со своим форматом: «45» при `aria-valuemax=\"100\"`\n * диктор и так читает как проценты.\n */\nconst valueText = computed(() => (props.formatValue ? props.formatValue(safe.value) : undefined))\nconst valueLabel = computed(() => valueText.value ?? `${Math.round(safe.value)}%`)\n\nconst isComplete = computed(() => !props.indeterminate && safe.value >= 100)\nconst isFailed = computed(() => resolvedTone.value === 'danger')\n\n/**\n * Приоритет центра: слот сильнее иконки итога, иконка итога — значения.\n *\n * Считается по содержимому слота, а не по факту его передачи: слот с `v-if`\n * (кнопка отмены, живущая только на время загрузки) приходит комментарием, и\n * центр остался бы пустым вместо значения.\n */\nconst hasSlotContent = computed(() => hasMeaningfulSlotContent(slots.default?.({ value: safe.value }) ?? []))\nconst showStatusIcon = computed(() => !hasSlotContent.value && props.statusIcon && (isComplete.value || isFailed.value))\nconst showValueLabel = computed(() => !hasSlotContent.value && props.showValue && !props.indeterminate && !showStatusIcon.value)\nconst hasCenter = computed(() => hasSlotContent.value || showStatusIcon.value || showValueLabel.value)\n</script>\n\n<template>\n <div\n data-gr-progress-circle\n :data-tone=\"resolvedTone\"\n :data-shape=\"resolvedShape\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n >\n <div\n data-gr-progress-circle-widget\n :data-gr-progress-circle-indeterminate=\"indeterminate ? '' : undefined\"\n role=\"progressbar\"\n class=\"h-full w-full\"\n :aria-label=\"ariaLabel\"\n :aria-valuenow=\"indeterminate ? undefined : safe\"\n :aria-valuetext=\"indeterminate ? undefined : valueText\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <svg\n :class=\"svgClass\"\n :viewBox=\"`0 0 ${VIEW_BOX} ${VIEW_BOX}`\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle\n v-if=\"!resolvedTrackless\"\n data-gr-progress-circle-track\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"arc.trackDashArray\"\n :style=\"arcStyle\"\n />\n\n <!-- Нулевая дуга при круглом торце нарисовалась бы точкой — «начали». -->\n <circle\n v-if=\"indeterminate || safe > 0\"\n data-gr-progress-circle-arc\n :cx=\"VIEW_BOX / 2\"\n :cy=\"VIEW_BOX / 2\"\n :r=\"arc.radius\"\n fill=\"none\"\n :stroke=\"arcColor\"\n :stroke-width=\"thickness\"\n :stroke-dasharray=\"indeterminate ? `${arc.circumference * 0.25} ${arc.circumference}` : arc.valueDashArray\"\n :style=\"arcStyle\"\n />\n </svg>\n </div>\n\n <!--\n Центр — сосед виджета, а не его потомок: `role=\"progressbar\"` объявляет\n потомков презентационными, и кнопка «Отменить» внутри кольца стала бы\n `nested-interactive`.\n -->\n <div\n v-if=\"hasCenter\"\n data-gr-progress-circle-center\n :class=\"centerClass\"\n :style=\"{ fontSize: `var(--gr-progress-circle-value-size, ${valueTextSizeBySize[resolvedSize]})` }\"\n >\n <slot v-if=\"hasSlotContent\" :value=\"safe\" />\n\n <component\n :is=\"isComplete ? IconCheck : IconError\"\n v-else-if=\"showStatusIcon\"\n data-gr-progress-circle-status\n aria-hidden=\"true\"\n :class=\"statusIconSizeBySize[resolvedSize]\"\n :style=\"{ color: arcColor }\"\n />\n\n <span\n v-else-if=\"showValueLabel\"\n data-gr-progress-circle-value\n :class=\"valueClass\"\n >{{ valueLabel }}</span>\n </div>\n </div>\n</template>\n\n<style>\n[data-gr-progress-circle-track] {\n stroke: var(--gr-progress-circle-track, var(--gr-muted));\n}\n\n[data-gr-progress-circle-arc] {\n stroke-linecap: var(--gr-progress-circle-cap, round);\n transition: stroke-dasharray var(--gr-duration-base) var(--gr-ease-out);\n}\n\n/* Оба кадра заданы явно: иначе стартом становится инлайновый поворот дуги, и\n каждый оборот заканчивался бы скачком. */\n@keyframes gr-progress-circle-spin {\n from {\n transform: rotate(0deg);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n[data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation-name: gr-progress-circle-spin;\n animation-duration: var(--gr-progress-indeterminate-duration, 1.4s);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n transition: none;\n}\n\n/*\n * Замерев в исходном кадре, четверть кольца читалась бы как «прогресс 25 %».\n * Замкнутая нейтральная дорожка не притворяется ни нулём, ни завершением: она\n * говорит «работа идёт, значение неизвестно» — тот же приём, что у полосы.\n */\n@media (prefers-reduced-motion: reduce) {\n [data-gr-progress-circle-indeterminate] [data-gr-progress-circle-arc] {\n animation: none;\n stroke: var(--gr-progress-indeterminate-bg, var(--gr-muted-fg));\n stroke-dasharray: none;\n }\n}\n</style>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrProgressCircle_default } from "./chunks/GrProgressCircle-D3yWXYDa.js";
1
+ import { t as GrProgressCircle_default } from "./chunks/GrProgressCircle-CdvbINQc.js";
2
2
  import { n as grProgressCircleSafelist, t as grProgressCircleConfig } from "../../chunks/config-CJzmDHfI.js";
3
3
  export { GrProgressCircle_default as GrProgressCircle, GrProgressCircle_default as default, grProgressCircleConfig, grProgressCircleSafelist };
@@ -1,12 +1,12 @@
1
- import { i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
1
+ import { i as useGrComponentProp } from "../../../chunks/context-CPMRfwVr.js";
2
2
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
3
- import { t as GrButton_default } from "../../GrButton/chunks/GrButton-7GP0zObj.js";
4
- import { t as GrInput_default } from "../../GrInput/chunks/GrInput-BLywRZUN.js";
5
- import { t as GrDialog_default } from "../../GrDialog/chunks/GrDialog-C01Hhk6G.js";
6
- import { t as GrResponseErrorBanner_default } from "../../GrResponseErrorBanner/chunks/GrResponseErrorBanner-DMeOWlzj.js";
7
- import { t as GrFormField_default } from "../../GrFormField/chunks/GrFormField-DSylU7IU.js";
8
- import { t as GrTextarea_default } from "../../GrTextarea/chunks/GrTextarea-DinXG12-.js";
9
- import { i as rulesForTrigger, o as runFieldRules, t as createGrFormMessageResolver } from "../../../chunks/validation-5HhpanPP.js";
3
+ import { t as GrButton_default } from "../../GrButton/chunks/GrButton-CS4TqMtG.js";
4
+ import { t as GrInput_default } from "../../GrInput/chunks/GrInput-TFeBm3gQ.js";
5
+ import { t as GrDialog_default } from "../../GrDialog/chunks/GrDialog-CeJubnKJ.js";
6
+ import { t as GrResponseErrorBanner_default } from "../../GrResponseErrorBanner/chunks/GrResponseErrorBanner-NEEJZ8zi.js";
7
+ import { t as GrFormField_default } from "../../GrFormField/chunks/GrFormField-DO61vxpS.js";
8
+ import { t as GrTextarea_default } from "../../GrTextarea/chunks/GrTextarea-BII3w61K.js";
9
+ import { i as rulesForTrigger, o as runFieldRules, t as createGrFormMessageResolver } from "../../../chunks/validation-BDjqsuGB.js";
10
10
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, ref, renderSlot, toDisplayString, unref, watch, withCtx, withKeys } from "vue";
11
11
  //#region src/components/GrPromptDialog/GrPromptDialog.vue?vue&type=script&setup=true&lang.ts
12
12
  var _hoisted_1 = { class: "grid gap-4" };