@feugene/granularity 0.26.0 → 0.27.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 (578) hide show
  1. package/dist/chunks/classTokens-8v2XC74x.js +16 -0
  2. package/dist/chunks/classTokens-8v2XC74x.js.map +1 -0
  3. package/dist/chunks/{config-Bpt9Xbxm.js → config-2ZHRsdOc.js} +2 -2
  4. package/dist/chunks/config-2ZHRsdOc.js.map +1 -0
  5. package/dist/chunks/{config-D6W1rnlp.js → config-B0uvcTPH.js} +1 -1
  6. package/dist/chunks/{config-D6W1rnlp.js.map → config-B0uvcTPH.js.map} +1 -1
  7. package/dist/chunks/{config-Bsh948nP.js → config-B3J0alyY.js} +1 -1
  8. package/dist/chunks/{config-Bsh948nP.js.map → config-B3J0alyY.js.map} +1 -1
  9. package/dist/chunks/{config-ScuvHw6k.js → config-B5SBUa6u.js} +1 -1
  10. package/dist/chunks/{config-ScuvHw6k.js.map → config-B5SBUa6u.js.map} +1 -1
  11. package/dist/chunks/{config-BeZRuonp.js → config-BDSaD-5p.js} +1 -1
  12. package/dist/chunks/{config-BeZRuonp.js.map → config-BDSaD-5p.js.map} +1 -1
  13. package/dist/chunks/{config-Dgj1Q6JY.js → config-BEO7brpO.js} +3 -3
  14. package/dist/chunks/config-BEO7brpO.js.map +1 -0
  15. package/dist/chunks/{config-B84z1aos.js → config-BHcS5Cwm.js} +1 -1
  16. package/dist/chunks/{config-B84z1aos.js.map → config-BHcS5Cwm.js.map} +1 -1
  17. package/dist/chunks/{config-DA6SnEoy.js → config-BRESvs9g.js} +2 -2
  18. package/dist/chunks/{config-DA6SnEoy.js.map → config-BRESvs9g.js.map} +1 -1
  19. package/dist/chunks/{config-CN2ULSQL.js → config-BTmfQFwi.js} +5 -5
  20. package/dist/chunks/config-BTmfQFwi.js.map +1 -0
  21. package/dist/chunks/{config-DtgYuGUn2.js → config-BTwYMQaz2.js} +5 -3
  22. package/dist/chunks/config-BTwYMQaz2.js.map +1 -0
  23. package/dist/chunks/{config-QJ54_fcM.js → config-BaWANzzB.js} +1 -1
  24. package/dist/chunks/{config-QJ54_fcM.js.map → config-BaWANzzB.js.map} +1 -1
  25. package/dist/chunks/{config-COvrUfhR.js → config-BcXX7S7B.js} +5 -5
  26. package/dist/chunks/config-BcXX7S7B.js.map +1 -0
  27. package/dist/chunks/{config-COpuWGr_.js → config-Bd7QfiGj.js} +1 -1
  28. package/dist/chunks/{config-COpuWGr_.js.map → config-Bd7QfiGj.js.map} +1 -1
  29. package/dist/chunks/{config-BDfTXHo1.js → config-BhfNgyWL.js} +2 -2
  30. package/dist/chunks/{config-BDfTXHo1.js.map → config-BhfNgyWL.js.map} +1 -1
  31. package/dist/chunks/{config-CjnbevbD.js → config-Bjn30smH.js} +1 -1
  32. package/dist/chunks/{config-CjnbevbD.js.map → config-Bjn30smH.js.map} +1 -1
  33. package/dist/chunks/{config-CN970ZcJ.js → config-BlJa1Mj9.js} +13 -13
  34. package/dist/chunks/config-BlJa1Mj9.js.map +1 -0
  35. package/dist/chunks/{config-DU2DNSRx.js → config-BoUI0t-t.js} +1 -1
  36. package/dist/chunks/{config-DU2DNSRx.js.map → config-BoUI0t-t.js.map} +1 -1
  37. package/dist/chunks/{config-BN4sXYXn.js → config-BqT6PMzO.js} +7 -14
  38. package/dist/chunks/config-BqT6PMzO.js.map +1 -0
  39. package/dist/chunks/config-BuGlNPE9.js.map +1 -0
  40. package/dist/chunks/{config-MRvhUl-O.js → config-CJzmDHfI.js} +1 -1
  41. package/dist/chunks/{config-MRvhUl-O.js.map → config-CJzmDHfI.js.map} +1 -1
  42. package/dist/chunks/{config-DGWFal5h.js → config-CLjjjPZj.js} +7 -7
  43. package/dist/chunks/config-CLjjjPZj.js.map +1 -0
  44. package/dist/chunks/{config-Cl4ST6Qd.js → config-CQLNjc9X2.js} +2 -2
  45. package/dist/chunks/config-CQLNjc9X2.js.map +1 -0
  46. package/dist/chunks/{config-vSji8w90.js → config-CWtfxkM9.js} +9 -9
  47. package/dist/chunks/config-CWtfxkM9.js.map +1 -0
  48. package/dist/chunks/{config-DKISz9gR.js → config-CWthWcWY.js} +2 -2
  49. package/dist/chunks/{config-DKISz9gR.js.map → config-CWthWcWY.js.map} +1 -1
  50. package/dist/chunks/{config-Iu684VNI.js → config-CZPDPJlg.js} +1 -1
  51. package/dist/chunks/{config-Iu684VNI.js.map → config-CZPDPJlg.js.map} +1 -1
  52. package/dist/chunks/{config-DAX8Deh1.js → config-CbEbLyDE.js} +3 -3
  53. package/dist/chunks/config-CbEbLyDE.js.map +1 -0
  54. package/dist/chunks/{config-D94Z9po5.js → config-ChPg-BQv.js} +2 -2
  55. package/dist/chunks/config-ChPg-BQv.js.map +1 -0
  56. package/dist/chunks/{config-DSJY6aEl.js → config-CjKpUcmy.js} +17 -17
  57. package/dist/chunks/config-CjKpUcmy.js.map +1 -0
  58. package/dist/chunks/{config-BIa3ilQm.js → config-CjWOTgLL.js} +4 -4
  59. package/dist/chunks/{config-BIa3ilQm.js.map → config-CjWOTgLL.js.map} +1 -1
  60. package/dist/chunks/{config-rkcKArZQ.js → config-CnYdE3HZ2.js} +5 -5
  61. package/dist/chunks/config-CnYdE3HZ2.js.map +1 -0
  62. package/dist/chunks/{config-BE6n20np.js → config-CvbVM4ep.js} +1 -1
  63. package/dist/chunks/{config-BE6n20np.js.map → config-CvbVM4ep.js.map} +1 -1
  64. package/dist/chunks/{config-9PYRZlKE.js → config-D0NzGYaE.js} +6 -6
  65. package/dist/chunks/config-D0NzGYaE.js.map +1 -0
  66. package/dist/chunks/{config-CKULiuvc.js → config-D0W8mGFD.js} +4 -4
  67. package/dist/chunks/{config-CKULiuvc.js.map → config-D0W8mGFD.js.map} +1 -1
  68. package/dist/chunks/{config-CY0_6cMi.js → config-D82r782v.js} +1 -1
  69. package/dist/chunks/{config-CY0_6cMi.js.map → config-D82r782v.js.map} +1 -1
  70. package/dist/chunks/config-DBmdgoVf2.js.map +1 -0
  71. package/dist/chunks/{config-WTNhdh6T.js → config-DCq4JySZ.js} +2 -2
  72. package/dist/chunks/{config-WTNhdh6T.js.map → config-DCq4JySZ.js.map} +1 -1
  73. package/dist/chunks/{config-C8tVRv8i.js → config-DGC00bTp.js} +13 -13
  74. package/dist/chunks/config-DGC00bTp.js.map +1 -0
  75. package/dist/chunks/{config-BsPDQ0dS.js → config-DIDz_E5m.js} +9 -9
  76. package/dist/chunks/config-DIDz_E5m.js.map +1 -0
  77. package/dist/chunks/{config-Dguto_6o.js → config-DM0lsduD.js} +6 -6
  78. package/dist/chunks/config-DM0lsduD.js.map +1 -0
  79. package/dist/chunks/{config-BfsBepkH.js → config-DNDgp9bB.js} +5 -5
  80. package/dist/chunks/config-DNDgp9bB.js.map +1 -0
  81. package/dist/chunks/{config-DpeQchsV.js → config-DO8mjeIo.js} +2 -2
  82. package/dist/chunks/{config-DpeQchsV.js.map → config-DO8mjeIo.js.map} +1 -1
  83. package/dist/chunks/{config-Baj7Wvx-.js → config-DRbojEzO.js} +4 -4
  84. package/dist/chunks/config-DRbojEzO.js.map +1 -0
  85. package/dist/chunks/{config-CQzGyi1C.js → config-DWL81-aM.js} +1 -1
  86. package/dist/chunks/{config-CQzGyi1C.js.map → config-DWL81-aM.js.map} +1 -1
  87. package/dist/chunks/{config-esdviAPL.js → config-DZCUPHPU.js} +1 -1
  88. package/dist/chunks/{config-esdviAPL.js.map → config-DZCUPHPU.js.map} +1 -1
  89. package/dist/chunks/{config-DKdlqXiY.js → config-DcfWZOi5.js} +5 -5
  90. package/dist/chunks/config-DcfWZOi5.js.map +1 -0
  91. package/dist/chunks/{config-BC8d_smz.js → config-DeyT9dJl.js} +3 -3
  92. package/dist/chunks/{config-BC8d_smz.js.map → config-DeyT9dJl.js.map} +1 -1
  93. package/dist/chunks/{config-Cwd3yjRw.js → config-DnF472Ox.js} +6 -4
  94. package/dist/chunks/config-DnF472Ox.js.map +1 -0
  95. package/dist/chunks/{config-B_qi4Fma.js → config-DolULhjJ.js} +5 -5
  96. package/dist/chunks/config-DolULhjJ.js.map +1 -0
  97. package/dist/chunks/{config-CIcynHGr.js → config-DpAYidyY2.js} +1 -1
  98. package/dist/chunks/config-DpAYidyY2.js.map +1 -0
  99. package/dist/chunks/{config-DYgfMrIF.js → config-Dpk-eVkS.js} +1 -1
  100. package/dist/chunks/{config-DYgfMrIF.js.map → config-Dpk-eVkS.js.map} +1 -1
  101. package/dist/chunks/config-Dv_r92GL.js +35 -0
  102. package/dist/chunks/config-Dv_r92GL.js.map +1 -0
  103. package/dist/chunks/{config-B4w5gBD0.js → config-DwABJHEo.js} +2 -2
  104. package/dist/chunks/config-DwABJHEo.js.map +1 -0
  105. package/dist/chunks/{config-zjeAJ4ho2.js → config-MmPym-Z72.js} +5 -5
  106. package/dist/chunks/config-MmPym-Z72.js.map +1 -0
  107. package/dist/chunks/{config-DCFvmHEv.js → config-T3-DMXYm.js} +9 -7
  108. package/dist/chunks/config-T3-DMXYm.js.map +1 -0
  109. package/dist/chunks/{config-BoNR7_PD.js → config-Yy67uWHY.js} +1 -1
  110. package/dist/chunks/{config-BoNR7_PD.js.map → config-Yy67uWHY.js.map} +1 -1
  111. package/dist/chunks/{config-BFJIxE8b.js → config-Z5LeUXys.js} +1 -1
  112. package/dist/chunks/{config-BFJIxE8b.js.map → config-Z5LeUXys.js.map} +1 -1
  113. package/dist/chunks/{config-DWN4x6_e.js → config-_QF0O1vq.js} +9 -9
  114. package/dist/chunks/config-_QF0O1vq.js.map +1 -0
  115. package/dist/chunks/{config-Cp0DE0GH.js → config-_jO3q1Le.js} +1 -1
  116. package/dist/chunks/{config-Cp0DE0GH.js.map → config-_jO3q1Le.js.map} +1 -1
  117. package/dist/chunks/{config-DGCMHPCR.js → config-g8-JGZ_Y.js} +1 -1
  118. package/dist/chunks/{config-DGCMHPCR.js.map → config-g8-JGZ_Y.js.map} +1 -1
  119. package/dist/chunks/{config-BTCOJO5z2.js → config-jyr6AIZt2.js} +3 -3
  120. package/dist/chunks/{config-BTCOJO5z2.js.map → config-jyr6AIZt2.js.map} +1 -1
  121. package/dist/chunks/{config-BtXRpAtq.js → config-mlheIMtV.js} +3 -6
  122. package/dist/chunks/config-mlheIMtV.js.map +1 -0
  123. package/dist/chunks/{config-BEVBsvni2.js → config-rLkc9Zn2.js} +1 -1
  124. package/dist/chunks/config-rLkc9Zn2.js.map +1 -0
  125. package/dist/chunks/{config-T3qdQBgU.js → config-tiUtEn4Q.js} +1 -1
  126. package/dist/chunks/{config-T3qdQBgU.js.map → config-tiUtEn4Q.js.map} +1 -1
  127. package/dist/chunks/{config-BViooYNv.js → config-uzUuosv7.js} +7 -2
  128. package/dist/chunks/config-uzUuosv7.js.map +1 -0
  129. package/dist/chunks/{config-BbY2SKGE.js → config-vYMJ3Cr1.js} +11 -9
  130. package/dist/chunks/config-vYMJ3Cr1.js.map +1 -0
  131. package/dist/chunks/context-BfIQv7m1.js.map +1 -0
  132. package/dist/chunks/{generated-CJe6hdiE.js → generated-DJ2dJ__C.js} +48 -0
  133. package/dist/chunks/generated-DJ2dJ__C.js.map +1 -0
  134. package/dist/chunks/{grBadgeStyles-C1S56Alo.js → grBadgeStyles-D8Mz73B5.js} +4 -4
  135. package/dist/chunks/grBadgeStyles-D8Mz73B5.js.map +1 -0
  136. package/dist/chunks/{config-D7zgE_Gr.js → grChipStyles-3JZApw03.js} +21 -43
  137. package/dist/chunks/grChipStyles-3JZApw03.js.map +1 -0
  138. package/dist/chunks/{grDropdownMenuStyles-D1LOkdVj.js → grDropdownMenuStyles-DG3aYHkT.js} +3 -3
  139. package/dist/chunks/grDropdownMenuStyles-DG3aYHkT.js.map +1 -0
  140. package/dist/chunks/{grIconStyles-BwJrml2L.js → grIconStyles-B6BRqUld.js} +1 -1
  141. package/dist/chunks/{grIconStyles-BwJrml2L.js.map → grIconStyles-B6BRqUld.js.map} +1 -1
  142. package/dist/chunks/{grInputStyles-CJeMhUe5.js → grInputStyles-CAk3xKIb.js} +4 -4
  143. package/dist/chunks/grInputStyles-CAk3xKIb.js.map +1 -0
  144. package/dist/chunks/{grKbdStyles-CeZhGQHr.js → grKbdStyles-DENu8pUK.js} +5 -0
  145. package/dist/chunks/grKbdStyles-DENu8pUK.js.map +1 -0
  146. package/dist/chunks/{grLinkStyles-BoL8QYcV.js → grLinkStyles-FME_qMpi.js} +4 -4
  147. package/dist/chunks/grLinkStyles-FME_qMpi.js.map +1 -0
  148. package/dist/chunks/{grLoadingStyles-DEmji2wv.js → grLoadingStyles-CnQaf5ry.js} +1 -1
  149. package/dist/chunks/{grLoadingStyles-DEmji2wv.js.map → grLoadingStyles-CnQaf5ry.js.map} +1 -1
  150. package/dist/chunks/{grPopoverStyles-Cke_BZsM.js → grPopoverStyles-Djh5RNhn.js} +4 -4
  151. package/dist/chunks/grPopoverStyles-Djh5RNhn.js.map +1 -0
  152. package/dist/chunks/{grRadioStyles-BTjGNhtU.js → grRadioStyles-D4gnU65n.js} +4 -4
  153. package/dist/chunks/grRadioStyles-D4gnU65n.js.map +1 -0
  154. package/dist/chunks/{grSelectStyles-eTz4uPMP.js → grSelectStyles-Cdtd10eY.js} +9 -9
  155. package/dist/chunks/grSelectStyles-Cdtd10eY.js.map +1 -0
  156. package/dist/chunks/{grTableStyles-C-iaqQUN.js → grTableStyles-uuMPSOBR.js} +2 -2
  157. package/dist/chunks/{grTableStyles-C-iaqQUN.js.map → grTableStyles-uuMPSOBR.js.map} +1 -1
  158. package/dist/chunks/{grTextareaStyles-iOcHuVMM.js → grTextareaStyles-Bp35BGna.js} +4 -4
  159. package/dist/chunks/grTextareaStyles-Bp35BGna.js.map +1 -0
  160. package/dist/chunks/{granular-provider-BaHkLjFX.js → granular-provider-DvvRayEh.js} +67 -67
  161. package/dist/chunks/{granular-provider-BaHkLjFX.js.map → granular-provider-DvvRayEh.js.map} +1 -1
  162. package/dist/chunks/numericStep-Bq2lj4ew.js +23 -0
  163. package/dist/chunks/numericStep-Bq2lj4ew.js.map +1 -0
  164. package/dist/chunks/overlayTransition-0Fj5tQbq.js +36 -0
  165. package/dist/chunks/overlayTransition-0Fj5tQbq.js.map +1 -0
  166. package/dist/chunks/{safelist-CudBLyAD.js → safelist-BOq5Li7p.js} +1 -1
  167. package/dist/chunks/{safelist-CudBLyAD.js.map → safelist-BOq5Li7p.js.map} +1 -1
  168. package/dist/chunks/{safelist-DOfCQR5O.js → safelist-CtiHPgrj.js} +2 -2
  169. package/dist/chunks/{safelist-DOfCQR5O.js.map → safelist-CtiHPgrj.js.map} +1 -1
  170. package/dist/chunks/{safelist-CkF4v7DC.js → safelist-Y3zrlhOa.js} +1 -1
  171. package/dist/chunks/{safelist-CkF4v7DC.js.map → safelist-Y3zrlhOa.js.map} +1 -1
  172. package/dist/chunks/{useMenuItemsFocus-OyOnIAlr.js → useMenuItemsFocus-B6TldmGf.js} +1 -43
  173. package/dist/chunks/useMenuItemsFocus-B6TldmGf.js.map +1 -0
  174. package/dist/chunks/useTypeahead-mxPtPBf2.js +44 -0
  175. package/dist/chunks/useTypeahead-mxPtPBf2.js.map +1 -0
  176. package/dist/components/GrAlert/chunks/{GrAlert-B21QGele.js → GrAlert-FAVf-ksH.js} +1 -1
  177. package/dist/components/GrAlert/chunks/{GrAlert-B21QGele.js.map → GrAlert-FAVf-ksH.js.map} +1 -1
  178. package/dist/components/GrAlert/index.js +1 -1
  179. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-D9c9BNFg.js → GrAutocomplete-BwhUTqmG.js} +88 -81
  180. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-BwhUTqmG.js.map +1 -0
  181. package/dist/components/GrAutocomplete/index.js +2 -2
  182. package/dist/components/GrAutocomplete/styles.css +1 -1
  183. package/dist/components/GrAvatar/chunks/{GrAvatar-BbdKRX8i.js → GrAvatar-CNmLmgcr.js} +1 -1
  184. package/dist/components/GrAvatar/chunks/{GrAvatar-BbdKRX8i.js.map → GrAvatar-CNmLmgcr.js.map} +1 -1
  185. package/dist/components/GrAvatar/index.js +2 -2
  186. package/dist/components/GrBadge/chunks/{GrBadge-_9rCHuE1.js → GrBadge-BM3f9PME.js} +2 -2
  187. package/dist/components/GrBadge/chunks/GrBadge-BM3f9PME.js.map +1 -0
  188. package/dist/components/GrBadge/index.js +3 -3
  189. package/dist/components/GrBadge/styles.css +1 -1
  190. package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-DDoFQscR.js → GrBadgeWrap-B-A3PRkE.js} +1 -1
  191. package/dist/components/GrBadgeWrap/chunks/GrBadgeWrap-B-A3PRkE.js.map +1 -0
  192. package/dist/components/GrBadgeWrap/index.js +2 -2
  193. package/dist/components/GrBottomNav/chunks/{GrBottomNav-JUu4ylYv.js → GrBottomNav-wtFatLjB.js} +1 -1
  194. package/dist/components/GrBottomNav/chunks/{GrBottomNav-JUu4ylYv.js.map → GrBottomNav-wtFatLjB.js.map} +1 -1
  195. package/dist/components/GrBottomNav/index.js +2 -2
  196. package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-CQ44iU2o.js → GrBreadcrumbs-jtSnMEtg.js} +2 -2
  197. package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-CQ44iU2o.js.map → GrBreadcrumbs-jtSnMEtg.js.map} +1 -1
  198. package/dist/components/GrBreadcrumbs/index.js +2 -2
  199. package/dist/components/GrButton/chunks/{GrButton-DCz-Wn-V.js → GrButton-Bw2AH4uX.js} +1 -1
  200. package/dist/components/GrButton/chunks/GrButton-Bw2AH4uX.js.map +1 -0
  201. package/dist/components/GrButton/index.js +3 -3
  202. package/dist/components/GrButtonGroup/chunks/{GrButtonGroup-BQo5VQ_c.js → GrButtonGroup-CKyiAV8K.js} +1 -1
  203. package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js.map +1 -0
  204. package/dist/components/GrButtonGroup/index.js +3 -3
  205. package/dist/components/GrCard/chunks/{GrCard-aQIjk6I9.js → GrCard-DR3ehBt8.js} +1 -1
  206. package/dist/components/GrCard/chunks/GrCard-DR3ehBt8.js.map +1 -0
  207. package/dist/components/GrCard/index.js +2 -2
  208. package/dist/components/GrCheckbox/index.js +1 -1
  209. package/dist/components/GrCheckboxGroup/index.js +1 -1
  210. package/dist/components/GrChip/chunks/{GrChip-BnL2FedO.js → GrChip-Df4orxRH.js} +15 -4
  211. package/dist/components/GrChip/chunks/GrChip-Df4orxRH.js.map +1 -0
  212. package/dist/components/GrChip/index.js +2 -2
  213. package/dist/components/GrChipGroup/chunks/{GrChipGroup-DefmSdY9.js → GrChipGroup-C78Vcwos.js} +2 -2
  214. package/dist/components/GrChipGroup/chunks/{GrChipGroup-DefmSdY9.js.map → GrChipGroup-C78Vcwos.js.map} +1 -1
  215. package/dist/components/GrChipGroup/index.js +2 -2
  216. package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-CyptiEo4.js → GrCodeBlock-Dkvkr91t.js} +2 -2
  217. package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-CyptiEo4.js.map → GrCodeBlock-Dkvkr91t.js.map} +1 -1
  218. package/dist/components/GrCodeBlock/index.js +2 -2
  219. package/dist/components/GrCollapse/chunks/{GrCollapse-DUROgAgc.js → GrCollapse-CytiA2Sx.js} +3 -3
  220. package/dist/components/GrCollapse/chunks/{GrCollapse-DUROgAgc.js.map → GrCollapse-CytiA2Sx.js.map} +1 -1
  221. package/dist/components/GrCollapse/index.js +2 -2
  222. package/dist/components/GrColorPicker/chunks/{GrColorPicker-CDaJRVIM.js → GrColorPicker-0n_KGeUy.js} +4 -4
  223. package/dist/components/GrColorPicker/chunks/{GrColorPicker-CDaJRVIM.js.map → GrColorPicker-0n_KGeUy.js.map} +1 -1
  224. package/dist/components/GrColorPicker/index.js +2 -2
  225. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-BPsVN_XU.js → GrCommandPalette-C5abL2Y7.js} +3 -3
  226. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-C5abL2Y7.js.map +1 -0
  227. package/dist/components/GrCommandPalette/index.js +2 -2
  228. package/dist/components/GrCommandPalette/styles.css +1 -1
  229. package/dist/components/GrConfigProvider/chunks/GrConfigProvider-BF7R3hgg.js.map +1 -1
  230. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-CwXNLyzk.js → GrConfirmDialog-B9mIU78E.js} +4 -4
  231. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-B9mIU78E.js.map +1 -0
  232. package/dist/components/GrConfirmDialog/index.js +1 -1
  233. package/dist/components/GrContextMenu/chunks/{GrContextMenu-BbAJholy.js → GrContextMenu-DDAUvrDK.js} +3 -3
  234. package/dist/components/GrContextMenu/chunks/GrContextMenu-DDAUvrDK.js.map +1 -0
  235. package/dist/components/GrContextMenu/index.js +1 -1
  236. package/dist/components/GrDataTable/chunks/{GrDataTable-NRbrXpdx.js → GrDataTable-DU00V44y.js} +14 -4
  237. package/dist/components/GrDataTable/chunks/GrDataTable-DU00V44y.js.map +1 -0
  238. package/dist/components/GrDataTable/index.js +2 -2
  239. package/dist/components/GrDelta/chunks/{GrDelta-NE5HhXoo.js → GrDelta-04j9WmEY.js} +0 -0
  240. package/dist/components/GrDelta/chunks/{GrDelta-NE5HhXoo.js.map → GrDelta-04j9WmEY.js.map} +1 -1
  241. package/dist/components/GrDelta/index.js +2 -2
  242. package/dist/components/GrDescriptionList/chunks/{GrDescriptionList-1mICfrqX.js → GrDescriptionList-BMeCgFV3.js} +1 -1
  243. package/dist/components/GrDescriptionList/chunks/GrDescriptionList-BMeCgFV3.js.map +1 -0
  244. package/dist/components/GrDescriptionList/index.js +2 -2
  245. package/dist/components/GrDialog/chunks/{GrDialog-5Y5K87ss.js → GrDialog-bOUDYfmh.js} +2 -2
  246. package/dist/components/GrDialog/chunks/GrDialog-bOUDYfmh.js.map +1 -0
  247. package/dist/components/GrDialog/index.js +2 -2
  248. package/dist/components/GrDialogService/chunks/{GrDialogService-CHVR4sOk.js → GrDialogService-B--br5so.js} +4 -4
  249. package/dist/components/GrDialogService/chunks/{GrDialogService-CHVR4sOk.js.map → GrDialogService-B--br5so.js.map} +1 -1
  250. package/dist/components/GrDialogService/index.js +1 -1
  251. package/dist/components/GrDivider/chunks/{GrDivider-CAhm9jbE.js → GrDivider-BXavGcMX.js} +1 -1
  252. package/dist/components/GrDivider/chunks/GrDivider-BXavGcMX.js.map +1 -0
  253. package/dist/components/GrDivider/index.js +2 -2
  254. package/dist/components/GrDrawer/chunks/{GrDrawer-CXy3-SVd.js → GrDrawer-BCreL-eq.js} +3 -3
  255. package/dist/components/GrDrawer/chunks/{GrDrawer-CXy3-SVd.js.map → GrDrawer-BCreL-eq.js.map} +1 -1
  256. package/dist/components/GrDrawer/index.js +2 -2
  257. package/dist/components/GrDropdown/chunks/{GrDropdown-BfTmdPyh.js → GrDropdown-13Wt9eB_.js} +16 -8
  258. package/dist/components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js.map +1 -0
  259. package/dist/components/GrDropdown/index.js +2 -2
  260. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-l5HEqzjr.js → GrDropdownMenu-5zoOL8Oj.js} +3 -3
  261. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-5zoOL8Oj.js.map +1 -0
  262. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenuList-BGA_xNVo.js → GrDropdownMenuList-CT_1TQJo.js} +1 -1
  263. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-CT_1TQJo.js.map +1 -0
  264. package/dist/components/GrDropdownMenu/index.js +3 -3
  265. package/dist/components/GrEmptyState/chunks/{GrEmptyState-CS9do8eM.js → GrEmptyState-D4T5pzXA.js} +2 -2
  266. package/dist/components/GrEmptyState/chunks/{GrEmptyState-CS9do8eM.js.map → GrEmptyState-D4T5pzXA.js.map} +1 -1
  267. package/dist/components/GrEmptyState/index.js +2 -2
  268. package/dist/components/GrFilePreview/chunks/{GrFilePreview-D0Bt-0nn.js → GrFilePreview-C9Z7hMK8.js} +1 -1
  269. package/dist/components/GrFilePreview/chunks/{GrFilePreview-D0Bt-0nn.js.map → GrFilePreview-C9Z7hMK8.js.map} +1 -1
  270. package/dist/components/GrFilePreview/index.js +2 -2
  271. package/dist/components/GrFileUpload/chunks/{GrFileUpload-wNXzHb5N.js → GrFileUpload-FjbaYGjL.js} +2 -2
  272. package/dist/components/GrFileUpload/chunks/{GrFileUpload-wNXzHb5N.js.map → GrFileUpload-FjbaYGjL.js.map} +1 -1
  273. package/dist/components/GrFileUpload/index.js +2 -2
  274. package/dist/components/GrForm/chunks/{GrForm-CAlJg-wb.js → GrForm-CrnfCsgj.js} +8 -2
  275. package/dist/components/GrForm/chunks/GrForm-CrnfCsgj.js.map +1 -0
  276. package/dist/components/GrForm/index.js +1 -1
  277. package/dist/components/GrFormField/chunks/GrFormField-DSylU7IU.js.map +1 -1
  278. package/dist/components/GrFormField/index.js +1 -1
  279. package/dist/components/GrFormFile/chunks/{GrFormFile-DhVkB2gm.js → GrFormFile-ChdKlN83.js} +3 -3
  280. package/dist/components/GrFormFile/chunks/{GrFormFile-DhVkB2gm.js.map → GrFormFile-ChdKlN83.js.map} +1 -1
  281. package/dist/components/GrFormFile/index.js +2 -2
  282. package/dist/components/GrFormSection/chunks/{GrFormSection-CdGWvzXO.js → GrFormSection-ejieOg9H.js} +1 -1
  283. package/dist/components/GrFormSection/chunks/{GrFormSection-CdGWvzXO.js.map → GrFormSection-ejieOg9H.js.map} +1 -1
  284. package/dist/components/GrFormSection/index.js +2 -2
  285. package/dist/components/GrIcon/chunks/{GrIcon-bQwtZtYT.js → GrIcon-Bn1XEriL.js} +1 -1
  286. package/dist/components/GrIcon/chunks/GrIcon-Bn1XEriL.js.map +1 -0
  287. package/dist/components/GrIcon/index.js +2 -2
  288. package/dist/components/GrImageViewer/chunks/{GrImageViewer-ng7el4wn.js → GrImageViewer-COUcpOgR.js} +2 -2
  289. package/dist/components/GrImageViewer/chunks/GrImageViewer-COUcpOgR.js.map +1 -0
  290. package/dist/components/GrImageViewer/index.js +2 -2
  291. package/dist/components/GrInput/chunks/{GrInput-Bb_pxqpT.js → GrInput-c53iltz0.js} +1 -1
  292. package/dist/components/GrInput/chunks/{GrInput-Bb_pxqpT.js.map → GrInput-c53iltz0.js.map} +1 -1
  293. package/dist/components/GrInput/index.js +2 -2
  294. package/dist/components/GrInputTag/chunks/{GrInputTag-UI8kIB_F.js → GrInputTag-LP3smqOv.js} +46 -49
  295. package/dist/components/GrInputTag/chunks/GrInputTag-LP3smqOv.js.map +1 -0
  296. package/dist/components/GrInputTag/index.js +2 -2
  297. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-jk3ylOTc.js → GrJsonViewer-ClTvjlFx.js} +4 -4
  298. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-jk3ylOTc.js.map → GrJsonViewer-ClTvjlFx.js.map} +1 -1
  299. package/dist/components/GrJsonViewer/index.js +2 -2
  300. package/dist/components/GrKbd/chunks/{GrKbd-BXbhsH0M.js → GrKbd-D2ga1H9i.js} +1 -1
  301. package/dist/components/GrKbd/chunks/{GrKbd-BXbhsH0M.js.map → GrKbd-D2ga1H9i.js.map} +1 -1
  302. package/dist/components/GrKbd/index.js +2 -2
  303. package/dist/components/GrLink/chunks/{GrLink-BQb7U4so.js → GrLink-DAGCFYO7.js} +2 -2
  304. package/dist/components/GrLink/chunks/GrLink-DAGCFYO7.js.map +1 -0
  305. package/dist/components/GrLink/index.js +2 -2
  306. package/dist/components/GrList/chunks/{GrList-B5bclmHV.js → GrList-DrXrKU37.js} +3 -3
  307. package/dist/components/GrList/chunks/GrList-DrXrKU37.js.map +1 -0
  308. package/dist/components/GrList/index.js +2 -2
  309. package/dist/components/GrList/styles.css +1 -1
  310. package/dist/components/GrLoading/chunks/{GrLoading-DeBFTvFX.js → GrLoading-DDD8WAIH.js} +2 -2
  311. package/dist/components/GrLoading/chunks/{GrLoading-DeBFTvFX.js.map → GrLoading-DDD8WAIH.js.map} +1 -1
  312. package/dist/components/GrLoading/index.js +2 -2
  313. package/dist/components/GrModal/index.js +1 -1
  314. package/dist/components/GrNavbar/chunks/{GrNavbar-DPj30sHX.js → GrNavbar-DhswlYyh.js} +3 -3
  315. package/dist/components/GrNavbar/chunks/{GrNavbar-DPj30sHX.js.map → GrNavbar-DhswlYyh.js.map} +1 -1
  316. package/dist/components/GrNavbar/index.js +2 -2
  317. package/dist/components/GrNumberInput/chunks/{GrNumberInput-V2mZvDDC.js → GrNumberInput-Daud9Jdm.js} +3 -14
  318. package/dist/components/GrNumberInput/chunks/GrNumberInput-Daud9Jdm.js.map +1 -0
  319. package/dist/components/GrNumberInput/index.js +2 -2
  320. package/dist/components/GrPagination/chunks/{GrPagination-DG7kp6VL.js → GrPagination-CaNTZc-v.js} +3 -3
  321. package/dist/components/GrPagination/chunks/{GrPagination-DG7kp6VL.js.map → GrPagination-CaNTZc-v.js.map} +1 -1
  322. package/dist/components/GrPagination/index.js +2 -2
  323. package/dist/components/GrPopover/chunks/{GrPopover-DDChM1jD.js → GrPopover-CofG-Tfe.js} +16 -8
  324. package/dist/components/GrPopover/chunks/GrPopover-CofG-Tfe.js.map +1 -0
  325. package/dist/components/GrPopover/index.js +2 -2
  326. package/dist/components/GrProgressBar/index.js +1 -1
  327. package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-BeUx1g1f.js → GrProgressCircle-D3yWXYDa.js} +1 -1
  328. package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-BeUx1g1f.js.map → GrProgressCircle-D3yWXYDa.js.map} +1 -1
  329. package/dist/components/GrProgressCircle/index.js +2 -2
  330. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-BGuMUzlv.js → GrPromptDialog-DMhALhSS.js} +6 -6
  331. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-DMhALhSS.js.map +1 -0
  332. package/dist/components/GrPromptDialog/index.js +1 -1
  333. package/dist/components/GrRadio/chunks/{GrRadio-BdhknbO8.js → GrRadio-C_rESc5g.js} +1 -1
  334. package/dist/components/GrRadio/chunks/GrRadio-C_rESc5g.js.map +1 -0
  335. package/dist/components/GrRadio/index.js +2 -2
  336. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-7w4bXIg_.js → GrRadioGroup-CdQO4G-U.js} +2 -2
  337. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-7w4bXIg_.js.map → GrRadioGroup-CdQO4G-U.js.map} +1 -1
  338. package/dist/components/GrRadioGroup/index.js +1 -1
  339. package/dist/components/GrRating/chunks/{GrRating-BSEtaibx.js → GrRating-IEiTOdnF.js} +1 -1
  340. package/dist/components/GrRating/chunks/{GrRating-BSEtaibx.js.map → GrRating-IEiTOdnF.js.map} +1 -1
  341. package/dist/components/GrRating/index.js +2 -2
  342. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DA4q90Zt.js → GrResponseErrorBanner-C_skObtv.js} +1 -1
  343. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DA4q90Zt.js.map → GrResponseErrorBanner-C_skObtv.js.map} +1 -1
  344. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-BhP-xw2P.js → GrResponseErrorBanner-DudGc9LO.js} +4 -4
  345. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-BhP-xw2P.js.map → GrResponseErrorBanner-DudGc9LO.js.map} +1 -1
  346. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  347. package/dist/components/GrSegmented/chunks/{GrSegmented-DKpo3cnC.js → GrSegmented-CB-VR-yL.js} +1 -1
  348. package/dist/components/GrSegmented/chunks/{GrSegmented-DKpo3cnC.js.map → GrSegmented-CB-VR-yL.js.map} +1 -1
  349. package/dist/components/GrSegmented/index.js +2 -2
  350. package/dist/components/GrSelect/chunks/{GrSelect-BA1wfX3c.js → GrSelect-BE1VNTiY.js} +96 -89
  351. package/dist/components/GrSelect/chunks/GrSelect-BE1VNTiY.js.map +1 -0
  352. package/dist/components/GrSelect/index.js +2 -2
  353. package/dist/components/GrSelect/styles.css +1 -1
  354. package/dist/components/GrSidebar/chunks/{GrSidebar-DY-LgIbS.js → GrSidebar-DxPhIiWs.js} +3 -3
  355. package/dist/components/GrSidebar/chunks/{GrSidebar-DY-LgIbS.js.map → GrSidebar-DxPhIiWs.js.map} +1 -1
  356. package/dist/components/GrSidebar/index.js +2 -2
  357. package/dist/components/GrSlider/chunks/{GrSlider-s99yAyz6.js → GrSlider-DJfeEl4h.js} +5 -4
  358. package/dist/components/GrSlider/chunks/GrSlider-DJfeEl4h.js.map +1 -0
  359. package/dist/components/GrSlider/index.js +2 -2
  360. package/dist/components/GrSortableList/chunks/{GrSortableList-BMXyxmRc.js → GrSortableList-DGs3Pi2J.js} +2 -2
  361. package/dist/components/GrSortableList/chunks/{GrSortableList-BMXyxmRc.js.map → GrSortableList-DGs3Pi2J.js.map} +1 -1
  362. package/dist/components/GrSortableList/index.js +2 -2
  363. package/dist/components/GrSplitter/chunks/{GrSplitter-B9_JrT7q.js → GrSplitter-MltjaADn.js} +1 -1
  364. package/dist/components/GrSplitter/chunks/{GrSplitter-B9_JrT7q.js.map → GrSplitter-MltjaADn.js.map} +1 -1
  365. package/dist/components/GrSplitter/index.js +2 -2
  366. package/dist/components/GrStatistic/chunks/{GrStatistic-BJQv5aOS.js → GrStatistic-qHVasK37.js} +2 -2
  367. package/dist/components/GrStatistic/chunks/GrStatistic-qHVasK37.js.map +1 -0
  368. package/dist/components/GrStatistic/index.js +2 -2
  369. package/dist/components/GrSteps/chunks/{GrSteps-Cce4rfr3.js → GrSteps-C2jxpZoN.js} +1 -1
  370. package/dist/components/GrSteps/chunks/{GrSteps-Cce4rfr3.js.map → GrSteps-C2jxpZoN.js.map} +1 -1
  371. package/dist/components/GrSteps/index.js +2 -2
  372. package/dist/components/GrSwitch/chunks/{GrSwitch-CHiIj9GT.js → GrSwitch-KRlRMwgp.js} +1 -1
  373. package/dist/components/GrSwitch/chunks/{GrSwitch-CHiIj9GT.js.map → GrSwitch-KRlRMwgp.js.map} +1 -1
  374. package/dist/components/GrSwitch/index.js +2 -2
  375. package/dist/components/GrTabPanels/chunks/GrTabPanels-BZQS8-JM.js.map +1 -1
  376. package/dist/components/GrTable/chunks/{GrTable-f3qCWa99.js → GrTable-Zcdz2St_.js} +1 -1
  377. package/dist/components/GrTable/chunks/GrTable-Zcdz2St_.js.map +1 -0
  378. package/dist/components/GrTable/index.js +2 -2
  379. package/dist/components/GrTabs/chunks/{GrTabs-CBHZkOFY.js → GrTabs-ugDnkk-2.js} +2 -2
  380. package/dist/components/GrTabs/chunks/{GrTabs-CBHZkOFY.js.map → GrTabs-ugDnkk-2.js.map} +1 -1
  381. package/dist/components/GrTabs/index.js +2 -2
  382. package/dist/components/GrTextarea/chunks/{GrTextarea-CNnkcIG1.js → GrTextarea-KREK75Bu.js} +1 -1
  383. package/dist/components/GrTextarea/chunks/{GrTextarea-CNnkcIG1.js.map → GrTextarea-KREK75Bu.js.map} +1 -1
  384. package/dist/components/GrTextarea/index.js +2 -2
  385. package/dist/components/GrTimeline/chunks/{GrTimeline-DIDdkTn7.js → GrTimeline-BiHpArsg.js} +1 -1
  386. package/dist/components/GrTimeline/chunks/{GrTimeline-DIDdkTn7.js.map → GrTimeline-BiHpArsg.js.map} +1 -1
  387. package/dist/components/GrTimeline/index.js +2 -2
  388. package/dist/components/GrToaster/chunks/{GrToaster-CC49q3a4.js → GrToaster-CUi3ldJ0.js} +6 -6
  389. package/dist/components/GrToaster/chunks/GrToaster-CUi3ldJ0.js.map +1 -0
  390. package/dist/components/GrToaster/index.js +2 -2
  391. package/dist/components/GrToaster/styles.css +1 -1
  392. package/dist/components/GrTooltip/chunks/{GrTooltip-B6AwE_UX.js → GrTooltip-BKFjqu0E.js} +4 -4
  393. package/dist/components/GrTooltip/chunks/GrTooltip-BKFjqu0E.js.map +1 -0
  394. package/dist/components/GrTooltip/index.js +2 -2
  395. package/dist/components/GrTree/chunks/{GrTree-J5q8aCya.js → GrTree-D5ozu6U4.js} +15 -25
  396. package/dist/components/GrTree/chunks/GrTree-D5ozu6U4.js.map +1 -0
  397. package/dist/components/GrTree/index.js +1 -1
  398. package/dist/components/GrTree/styles.css +1 -1
  399. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DEfxWAc3.js → GrTreeSelect-Db_uKdNa.js} +18 -10
  400. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-Db_uKdNa.js.map +1 -0
  401. package/dist/components/GrTreeSelect/index.js +2 -2
  402. package/dist/components/GrValue/chunks/{GrValue-CZsuZ4x-.js → GrValue-ezkQM05Q.js} +1 -1
  403. package/dist/components/GrValue/chunks/{GrValue-CZsuZ4x-.js.map → GrValue-ezkQM05Q.js.map} +1 -1
  404. package/dist/components/GrValue/index.js +2 -2
  405. package/dist/directives/loading.js +1 -1
  406. package/dist/granular-provider-node.js +1 -1
  407. package/dist/granular-provider.js +1 -1
  408. package/dist/index.js +143 -143
  409. package/dist/styles/tokens.css +11 -0
  410. package/dist/theme.js +1 -1
  411. package/dist/tokens.js +1 -1
  412. package/dist/types/components/GrAutocomplete/GrAutocomplete.vue.d.ts +4 -3
  413. package/dist/types/components/GrAutocomplete/grAutocompleteStyles.d.ts +2 -2
  414. package/dist/types/components/GrBadge/GrBadge.vue.d.ts +3 -3
  415. package/dist/types/components/GrBadgeWrap/GrBadgeWrap.vue.d.ts +3 -3
  416. package/dist/types/components/GrBadgeWrap/grBadgeWrapStyles.d.ts +1 -1
  417. package/dist/types/components/GrBottomNav/grBottomNavStyles.d.ts +1 -1
  418. package/dist/types/components/GrButton/GrButton.vue.d.ts +7 -7
  419. package/dist/types/components/GrButtonGroup/GrButtonGroup.vue.d.ts +3 -3
  420. package/dist/types/components/GrCard/GrCard.vue.d.ts +7 -9
  421. package/dist/types/components/GrCheckbox/GrCheckbox.vue.d.ts +1 -1
  422. package/dist/types/components/GrCheckboxGroup/GrCheckboxGroup.vue.d.ts +1 -1
  423. package/dist/types/components/GrChip/GrChip.vue.d.ts +19 -1
  424. package/dist/types/components/GrChip/grChipStyles.d.ts +10 -6
  425. package/dist/types/components/GrChipGroup/GrChipGroup.vue.d.ts +2 -2
  426. package/dist/types/components/GrCollapse/GrCollapseItem.vue.d.ts +9 -11
  427. package/dist/types/components/GrColorPicker/GrColorPicker.vue.d.ts +1 -1
  428. package/dist/types/components/GrCommandPalette/GrCommandPalette.vue.d.ts +13 -13
  429. package/dist/types/components/GrCommandPalette/grCommandPaletteStyles.d.ts +5 -5
  430. package/dist/types/components/GrConfigProvider/GrConfigProvider.vue.d.ts +3 -3
  431. package/dist/types/components/GrConfirmDialog/GrConfirmDialog.vue.d.ts +9 -9
  432. package/dist/types/components/GrContextMenu/GrContextMenu.vue.d.ts +9 -9
  433. package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +9 -17
  434. package/dist/types/components/GrDescriptionList/GrDescriptionList.vue.d.ts +16 -13
  435. package/dist/types/components/GrDialog/GrDialogFooter.vue.d.ts +3 -3
  436. package/dist/types/components/GrDivider/GrDivider.vue.d.ts +3 -3
  437. package/dist/types/components/GrDrawer/grDrawerStyles.d.ts +1 -1
  438. package/dist/types/components/GrDropdown/GrDropdown.vue.d.ts +16 -20
  439. package/dist/types/components/GrDropdownMenu/GrDropdownMenu.vue.d.ts +16 -19
  440. package/dist/types/components/GrDropdownMenu/GrDropdownMenuColumn.vue.d.ts +3 -3
  441. package/dist/types/components/GrDropdownMenu/GrDropdownMenuColumns.vue.d.ts +3 -3
  442. package/dist/types/components/GrDropdownMenu/GrDropdownMenuGroup.vue.d.ts +3 -3
  443. package/dist/types/components/GrDropdownMenu/GrDropdownMenuHeader.vue.d.ts +3 -3
  444. package/dist/types/components/GrDropdownMenu/GrDropdownMenuItem.vue.d.ts +7 -7
  445. package/dist/types/components/GrDropdownMenu/GrDropdownMenuList.vue.d.ts +3 -3
  446. package/dist/types/components/GrDropdownMenu/grDropdownMenuStyles.d.ts +3 -3
  447. package/dist/types/components/GrForm/GrForm.vue.d.ts +5 -1
  448. package/dist/types/components/GrFormField/GrFormField.vue.d.ts +11 -11
  449. package/dist/types/components/GrFormFile/GrFormFile.vue.d.ts +1 -1
  450. package/dist/types/components/GrFormSection/grFormSectionStyles.d.ts +2 -2
  451. package/dist/types/components/GrIcon/GrIcon.vue.d.ts +3 -3
  452. package/dist/types/components/GrImageViewer/GrImageViewer.vue.d.ts +6 -25
  453. package/dist/types/components/GrInput/GrInput.vue.d.ts +1 -1
  454. package/dist/types/components/GrInput/grInputStyles.d.ts +4 -4
  455. package/dist/types/components/GrInputTag/GrInputTag.vue.d.ts +2 -2
  456. package/dist/types/components/GrInputTag/grInputTagStyles.d.ts +0 -6
  457. package/dist/types/components/GrKbd/GrKbd.vue.d.ts +3 -3
  458. package/dist/types/components/GrKbd/grKbdStyles.d.ts +5 -0
  459. package/dist/types/components/GrLink/GrLink.vue.d.ts +3 -3
  460. package/dist/types/components/GrList/GrList.vue.d.ts +12 -6
  461. package/dist/types/components/GrList/GrListItem.vue.d.ts +9 -9
  462. package/dist/types/components/GrList/grListStyles.d.ts +3 -3
  463. package/dist/types/components/GrNavbar/grNavbarStyles.d.ts +1 -1
  464. package/dist/types/components/GrNumberInput/GrNumberInput.vue.d.ts +1 -1
  465. package/dist/types/components/GrNumberInput/numberInputMath.d.ts +1 -6
  466. package/dist/types/components/GrPopover/GrPopover.vue.d.ts +16 -17
  467. package/dist/types/components/GrPromptDialog/GrPromptDialog.vue.d.ts +9 -9
  468. package/dist/types/components/GrRadio/GrRadio.vue.d.ts +6 -8
  469. package/dist/types/components/GrRadioGroup/GrRadioGroup.vue.d.ts +1 -1
  470. package/dist/types/components/GrRating/GrRating.vue.d.ts +1 -1
  471. package/dist/types/components/GrSegmented/GrSegmented.vue.d.ts +1 -1
  472. package/dist/types/components/GrSelect/grSelectStyles.d.ts +1 -1
  473. package/dist/types/components/GrSidebar/GrSidebar.vue.d.ts +7 -7
  474. package/dist/types/components/GrSidebar/grSidebarStyles.d.ts +4 -4
  475. package/dist/types/components/GrSlider/GrSlider.vue.d.ts +1 -1
  476. package/dist/types/components/GrSortableList/grSortableListStyles.d.ts +2 -2
  477. package/dist/types/components/GrSplitter/GrSplitter.vue.d.ts +1 -1
  478. package/dist/types/components/GrStatistic/GrStatistic.vue.d.ts +13 -13
  479. package/dist/types/components/GrSteps/grStepsStyles.d.ts +2 -2
  480. package/dist/types/components/GrSwitch/GrSwitch.vue.d.ts +1 -1
  481. package/dist/types/components/GrTabPanels/GrTabPanel.vue.d.ts +3 -3
  482. package/dist/types/components/GrTabPanels/GrTabPanels.vue.d.ts +3 -3
  483. package/dist/types/components/GrTable/GrTable.vue.d.ts +13 -13
  484. package/dist/types/components/GrTextarea/GrTextarea.vue.d.ts +1 -1
  485. package/dist/types/components/GrTreeSelect/grTreeSelectStyles.d.ts +1 -1
  486. package/dist/types/components/shared/classTokens.d.ts +8 -0
  487. package/dist/types/components/shared/numericStep.d.ts +14 -0
  488. package/dist/types/components/shared/overlayTransition.d.ts +33 -0
  489. package/dist/web-types.json +292 -218
  490. package/package.json +2 -2
  491. package/tokens/foundation.json +41 -1
  492. package/dist/chunks/classTokens-BzazaERD.js +0 -6
  493. package/dist/chunks/classTokens-BzazaERD.js.map +0 -1
  494. package/dist/chunks/config-9PYRZlKE.js.map +0 -1
  495. package/dist/chunks/config-B4w5gBD0.js.map +0 -1
  496. package/dist/chunks/config-BEVBsvni2.js.map +0 -1
  497. package/dist/chunks/config-BN4sXYXn.js.map +0 -1
  498. package/dist/chunks/config-BViooYNv.js.map +0 -1
  499. package/dist/chunks/config-B_qi4Fma.js.map +0 -1
  500. package/dist/chunks/config-Baj7Wvx-.js.map +0 -1
  501. package/dist/chunks/config-BbY2SKGE.js.map +0 -1
  502. package/dist/chunks/config-BfsBepkH.js.map +0 -1
  503. package/dist/chunks/config-Bpt9Xbxm.js.map +0 -1
  504. package/dist/chunks/config-BsPDQ0dS.js.map +0 -1
  505. package/dist/chunks/config-BtXRpAtq.js.map +0 -1
  506. package/dist/chunks/config-BuGlNPE92.js.map +0 -1
  507. package/dist/chunks/config-C8tVRv8i.js.map +0 -1
  508. package/dist/chunks/config-CIcynHGr.js.map +0 -1
  509. package/dist/chunks/config-CN2ULSQL.js.map +0 -1
  510. package/dist/chunks/config-CN970ZcJ.js.map +0 -1
  511. package/dist/chunks/config-COvrUfhR.js.map +0 -1
  512. package/dist/chunks/config-Cl4ST6Qd.js.map +0 -1
  513. package/dist/chunks/config-Cwd3yjRw.js.map +0 -1
  514. package/dist/chunks/config-D7zgE_Gr.js.map +0 -1
  515. package/dist/chunks/config-D94Z9po5.js.map +0 -1
  516. package/dist/chunks/config-DAX8Deh1.js.map +0 -1
  517. package/dist/chunks/config-DBmdgoVf.js.map +0 -1
  518. package/dist/chunks/config-DCFvmHEv.js.map +0 -1
  519. package/dist/chunks/config-DGWFal5h.js.map +0 -1
  520. package/dist/chunks/config-DKdlqXiY.js.map +0 -1
  521. package/dist/chunks/config-DSJY6aEl.js.map +0 -1
  522. package/dist/chunks/config-DWN4x6_e.js.map +0 -1
  523. package/dist/chunks/config-Dgj1Q6JY.js.map +0 -1
  524. package/dist/chunks/config-Dguto_6o.js.map +0 -1
  525. package/dist/chunks/config-DtgYuGUn2.js.map +0 -1
  526. package/dist/chunks/config-rkcKArZQ.js.map +0 -1
  527. package/dist/chunks/config-vSji8w90.js.map +0 -1
  528. package/dist/chunks/config-zjeAJ4ho2.js.map +0 -1
  529. package/dist/chunks/context-BfIQv7m12.js.map +0 -1
  530. package/dist/chunks/generated-CJe6hdiE.js.map +0 -1
  531. package/dist/chunks/grBadgeStyles-C1S56Alo.js.map +0 -1
  532. package/dist/chunks/grDropdownMenuStyles-D1LOkdVj.js.map +0 -1
  533. package/dist/chunks/grInputStyles-CJeMhUe5.js.map +0 -1
  534. package/dist/chunks/grKbdStyles-CeZhGQHr.js.map +0 -1
  535. package/dist/chunks/grLinkStyles-BoL8QYcV.js.map +0 -1
  536. package/dist/chunks/grPopoverStyles-Cke_BZsM.js.map +0 -1
  537. package/dist/chunks/grRadioStyles-BTjGNhtU.js.map +0 -1
  538. package/dist/chunks/grSelectStyles-eTz4uPMP.js.map +0 -1
  539. package/dist/chunks/grTextareaStyles-iOcHuVMM.js.map +0 -1
  540. package/dist/chunks/useMenuItemsFocus-OyOnIAlr.js.map +0 -1
  541. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-D9c9BNFg.js.map +0 -1
  542. package/dist/components/GrBadge/chunks/GrBadge-_9rCHuE1.js.map +0 -1
  543. package/dist/components/GrBadgeWrap/chunks/GrBadgeWrap-DDoFQscR.js.map +0 -1
  544. package/dist/components/GrButton/chunks/GrButton-DCz-Wn-V.js.map +0 -1
  545. package/dist/components/GrButtonGroup/chunks/GrButtonGroup-BQo5VQ_c.js.map +0 -1
  546. package/dist/components/GrCard/chunks/GrCard-aQIjk6I9.js.map +0 -1
  547. package/dist/components/GrChip/chunks/GrChip-BnL2FedO.js.map +0 -1
  548. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BPsVN_XU.js.map +0 -1
  549. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-CwXNLyzk.js.map +0 -1
  550. package/dist/components/GrContextMenu/chunks/GrContextMenu-BbAJholy.js.map +0 -1
  551. package/dist/components/GrDataTable/chunks/GrDataTable-NRbrXpdx.js.map +0 -1
  552. package/dist/components/GrDescriptionList/chunks/GrDescriptionList-1mICfrqX.js.map +0 -1
  553. package/dist/components/GrDialog/chunks/GrDialog-5Y5K87ss.js.map +0 -1
  554. package/dist/components/GrDivider/chunks/GrDivider-CAhm9jbE.js.map +0 -1
  555. package/dist/components/GrDropdown/chunks/GrDropdown-BfTmdPyh.js.map +0 -1
  556. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-l5HEqzjr.js.map +0 -1
  557. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-BGA_xNVo.js.map +0 -1
  558. package/dist/components/GrForm/chunks/GrForm-CAlJg-wb.js.map +0 -1
  559. package/dist/components/GrIcon/chunks/GrIcon-bQwtZtYT.js.map +0 -1
  560. package/dist/components/GrImageViewer/chunks/GrImageViewer-ng7el4wn.js.map +0 -1
  561. package/dist/components/GrInputTag/chunks/GrInputTag-UI8kIB_F.js.map +0 -1
  562. package/dist/components/GrLink/chunks/GrLink-BQb7U4so.js.map +0 -1
  563. package/dist/components/GrList/chunks/GrList-B5bclmHV.js.map +0 -1
  564. package/dist/components/GrNumberInput/chunks/GrNumberInput-V2mZvDDC.js.map +0 -1
  565. package/dist/components/GrPopover/chunks/GrPopover-DDChM1jD.js.map +0 -1
  566. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-BGuMUzlv.js.map +0 -1
  567. package/dist/components/GrRadio/chunks/GrRadio-BdhknbO8.js.map +0 -1
  568. package/dist/components/GrSelect/chunks/GrSelect-BA1wfX3c.js.map +0 -1
  569. package/dist/components/GrSlider/chunks/GrSlider-s99yAyz6.js.map +0 -1
  570. package/dist/components/GrStatistic/chunks/GrStatistic-BJQv5aOS.js.map +0 -1
  571. package/dist/components/GrTable/chunks/GrTable-f3qCWa99.js.map +0 -1
  572. package/dist/components/GrToaster/chunks/GrToaster-CC49q3a4.js.map +0 -1
  573. package/dist/components/GrTooltip/chunks/GrTooltip-B6AwE_UX.js.map +0 -1
  574. package/dist/components/GrTree/chunks/GrTree-J5q8aCya.js.map +0 -1
  575. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-DEfxWAc3.js.map +0 -1
  576. /package/dist/chunks/{config-BuGlNPE92.js → config-BuGlNPE9.js} +0 -0
  577. /package/dist/chunks/{config-DBmdgoVf.js → config-DBmdgoVf2.js} +0 -0
  578. /package/dist/chunks/{context-BfIQv7m12.js → context-BfIQv7m1.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"GrSwitch-CHiIj9GT.js","names":["$attrs","$slots"],"sources":["../../../../src/components/GrSwitch/GrSwitch.vue","../../../../src/components/GrSwitch/GrSwitch.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n grSwitchLabelClass,\n grSwitchRootClass,\n grSwitchSpinnerClass,\n grSwitchThumbClass,\n grSwitchTrackClass,\n type GrSwitchLabelPosition,\n type GrSwitchSize,\n} from './grSwitchStyles'\n\nexport type { GrSwitchLabelPosition, GrSwitchSize } from './grSwitchStyles'\n\n/**\n * Пропсы публичного GR-примитива «Switch».\n */\nexport interface GrSwitchProps {\n modelValue: boolean\n disabled?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n ariaLabel?: string\n size?: GrSwitchSize\n /** Сторона подписи относительно дорожки. */\n labelPosition?: GrSwitchLabelPosition\n /** Идёт сохранение: бегунок показывает спиннер, переключение заблокировано. */\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n /** Имя поля для нативной отправки формы. Без него скрытое поле не рендерится. */\n name?: string\n /** Значение, уходящее в форму во включённом состоянии. */\n value?: string\n /** `id` формы, если переключатель лежит вне неё. */\n form?: string\n /** Кастомный цвет фона в активном состоянии. Если не задан — `var(--gr-primary)`. */\n activeBackgroundColor?: string\n /** Кастомный цвет фона в неактивном состоянии. Если не задан — `var(--gr-muted)`. */\n inactiveBackgroundColor?: string\n}\n\nexport interface GrSwitchEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'change', value: boolean): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst getCustomColor = (value?: string) => value?.trim() || undefined\n\n// Скрытое поле — сосед кнопки, а не её потомок: интерактивный контент внутри\n// `<button>` невалиден. Из-за этого корень компонента — фрагмент, и атрибуты\n// потребителя надо донести до кнопки руками.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<GrSwitchProps>(),\n {\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n size: undefined,\n labelPosition: 'end',\n loading: false,\n loadingText: undefined,\n name: undefined,\n value: 'on',\n form: undefined,\n activeBackgroundColor: undefined,\n inactiveBackgroundColor: undefined,\n },\n)\n\n// Контекст `GrFormField`: id для `<label for>`, описание ошибкой, невалидность.\n// `<button>` — labelable-элемент, поэтому клик по подписи фокусирует переключатель.\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst describedBy = computed(() => field?.describedById.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst { t } = useGranularityTranslations()\n\nconst rootEl = ref<HTMLButtonElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrSwitch',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrSwitchEmits>()\ndefineSlots<{\n /** Подпись переключателя. */\n default?: () => any\n}>()\n\n\nconst rootClass = computed(() => grSwitchRootClass(props.labelPosition))\n\nconst trackClass = computed(() => grSwitchTrackClass(resolvedSize.value))\n\nconst trackStyle = computed(() => {\n const isChecked = props.modelValue\n const defaultBackgroundColor = isChecked ? 'var(--gr-primary)' : 'var(--gr-muted)'\n const customBackgroundColor = getCustomColor(\n isChecked ? props.activeBackgroundColor : props.inactiveBackgroundColor,\n )\n // Недоступность гасится токеном и перебивает кастомный цвет: иначе выключенный\n // переключатель остался бы таким же ярким, как рабочий.\n const backgroundColor = isDisabled.value\n ? 'var(--gr-disabled-bg)'\n : customBackgroundColor ?? defaultBackgroundColor\n\n return {\n '--gr-switch-track-bg': backgroundColor,\n '--gr-switch-track-brd': isDisabled.value\n ? 'var(--gr-disabled-brd)'\n : customBackgroundColor\n ? backgroundColor\n : isChecked\n ? 'var(--gr-primary)'\n : 'var(--gr-brd)',\n backgroundColor: 'var(--gr-switch-track-bg)',\n }\n})\n\nconst thumbClass = computed(() => grSwitchThumbClass({size: resolvedSize.value, checked: props.modelValue}))\n\nconst spinnerClass = computed(() => grSwitchSpinnerClass(resolvedSize.value))\n\nconst labelClass = computed(() => grSwitchLabelClass(resolvedSize.value, isDisabled.value))\n\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.switch.loading', 'Saving…'))\n\n// Выключенный переключатель не отправляется вовсе — так устроен чекбокс в HTML,\n// и сервер отличает «выкл» по отсутствию ключа.\nconst submitsValue = computed(\n () => props.modelValue && !isDisabled.value && Boolean(props.name),\n)\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value || props.loading) {\n return\n }\n\n const next = !props.modelValue\n emit('update:modelValue', next)\n emit('change', next)\n}\n</script>\n\n<template>\n <input\n v-if=\"submitsValue\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"value\"\n :form=\"form\"\n >\n\n <button\n :id=\"fieldId\"\n ref=\"rootEl\"\n v-bind=\"$attrs\"\n type=\"button\"\n role=\"switch\"\n data-gr-switch\n :aria-checked=\"modelValue ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-busy=\"loading ? 'true' : undefined\"\n :disabled=\"isDisabled\"\n :class=\"rootClass\"\n @click=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <span\n data-testid=\"gr-switch-track\"\n data-gr-switch-track\n :class=\"trackClass\"\n :style=\"trackStyle\"\n >\n <span\n data-testid=\"gr-switch-thumb\"\n data-gr-switch-thumb\n :class=\"thumbClass\"\n aria-hidden=\"true\"\n >\n <IconLoader v-if=\"loading\" data-gr-switch-spinner :class=\"spinnerClass\" />\n </span>\n </span>\n <span\n v-if=\"$slots.default\"\n data-gr-switch-label\n :class=\"labelClass\"\n >\n <slot />\n </span>\n <span v-if=\"loading\" data-gr-switch-loading-text class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n grSwitchLabelClass,\n grSwitchRootClass,\n grSwitchSpinnerClass,\n grSwitchThumbClass,\n grSwitchTrackClass,\n type GrSwitchLabelPosition,\n type GrSwitchSize,\n} from './grSwitchStyles'\n\nexport type { GrSwitchLabelPosition, GrSwitchSize } from './grSwitchStyles'\n\n/**\n * Пропсы публичного GR-примитива «Switch».\n */\nexport interface GrSwitchProps {\n modelValue: boolean\n disabled?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n ariaLabel?: string\n size?: GrSwitchSize\n /** Сторона подписи относительно дорожки. */\n labelPosition?: GrSwitchLabelPosition\n /** Идёт сохранение: бегунок показывает спиннер, переключение заблокировано. */\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n /** Имя поля для нативной отправки формы. Без него скрытое поле не рендерится. */\n name?: string\n /** Значение, уходящее в форму во включённом состоянии. */\n value?: string\n /** `id` формы, если переключатель лежит вне неё. */\n form?: string\n /** Кастомный цвет фона в активном состоянии. Если не задан — `var(--gr-primary)`. */\n activeBackgroundColor?: string\n /** Кастомный цвет фона в неактивном состоянии. Если не задан — `var(--gr-muted)`. */\n inactiveBackgroundColor?: string\n}\n\nexport interface GrSwitchEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'change', value: boolean): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst getCustomColor = (value?: string) => value?.trim() || undefined\n\n// Скрытое поле — сосед кнопки, а не её потомок: интерактивный контент внутри\n// `<button>` невалиден. Из-за этого корень компонента — фрагмент, и атрибуты\n// потребителя надо донести до кнопки руками.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<GrSwitchProps>(),\n {\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n size: undefined,\n labelPosition: 'end',\n loading: false,\n loadingText: undefined,\n name: undefined,\n value: 'on',\n form: undefined,\n activeBackgroundColor: undefined,\n inactiveBackgroundColor: undefined,\n },\n)\n\n// Контекст `GrFormField`: id для `<label for>`, описание ошибкой, невалидность.\n// `<button>` — labelable-элемент, поэтому клик по подписи фокусирует переключатель.\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst describedBy = computed(() => field?.describedById.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst { t } = useGranularityTranslations()\n\nconst rootEl = ref<HTMLButtonElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrSwitch',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrSwitchEmits>()\ndefineSlots<{\n /** Подпись переключателя. */\n default?: () => any\n}>()\n\n\nconst rootClass = computed(() => grSwitchRootClass(props.labelPosition))\n\nconst trackClass = computed(() => grSwitchTrackClass(resolvedSize.value))\n\nconst trackStyle = computed(() => {\n const isChecked = props.modelValue\n const defaultBackgroundColor = isChecked ? 'var(--gr-primary)' : 'var(--gr-muted)'\n const customBackgroundColor = getCustomColor(\n isChecked ? props.activeBackgroundColor : props.inactiveBackgroundColor,\n )\n // Недоступность гасится токеном и перебивает кастомный цвет: иначе выключенный\n // переключатель остался бы таким же ярким, как рабочий.\n const backgroundColor = isDisabled.value\n ? 'var(--gr-disabled-bg)'\n : customBackgroundColor ?? defaultBackgroundColor\n\n return {\n '--gr-switch-track-bg': backgroundColor,\n '--gr-switch-track-brd': isDisabled.value\n ? 'var(--gr-disabled-brd)'\n : customBackgroundColor\n ? backgroundColor\n : isChecked\n ? 'var(--gr-primary)'\n : 'var(--gr-brd)',\n backgroundColor: 'var(--gr-switch-track-bg)',\n }\n})\n\nconst thumbClass = computed(() => grSwitchThumbClass({size: resolvedSize.value, checked: props.modelValue}))\n\nconst spinnerClass = computed(() => grSwitchSpinnerClass(resolvedSize.value))\n\nconst labelClass = computed(() => grSwitchLabelClass(resolvedSize.value, isDisabled.value))\n\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.switch.loading', 'Saving…'))\n\n// Выключенный переключатель не отправляется вовсе — так устроен чекбокс в HTML,\n// и сервер отличает «выкл» по отсутствию ключа.\nconst submitsValue = computed(\n () => props.modelValue && !isDisabled.value && Boolean(props.name),\n)\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value || props.loading) {\n return\n }\n\n const next = !props.modelValue\n emit('update:modelValue', next)\n emit('change', next)\n}\n</script>\n\n<template>\n <input\n v-if=\"submitsValue\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"value\"\n :form=\"form\"\n >\n\n <button\n :id=\"fieldId\"\n ref=\"rootEl\"\n v-bind=\"$attrs\"\n type=\"button\"\n role=\"switch\"\n data-gr-switch\n :aria-checked=\"modelValue ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-busy=\"loading ? 'true' : undefined\"\n :disabled=\"isDisabled\"\n :class=\"rootClass\"\n @click=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <span\n data-testid=\"gr-switch-track\"\n data-gr-switch-track\n :class=\"trackClass\"\n :style=\"trackStyle\"\n >\n <span\n data-testid=\"gr-switch-thumb\"\n data-gr-switch-thumb\n :class=\"thumbClass\"\n aria-hidden=\"true\"\n >\n <IconLoader v-if=\"loading\" data-gr-switch-spinner :class=\"spinnerClass\" />\n </span>\n </span>\n <span\n v-if=\"$slots.default\"\n data-gr-switch-label\n :class=\"labelClass\"\n >\n <slot />\n </span>\n <span v-if=\"loading\" data-gr-switch-loading-text class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </button>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrSwitch-KRlRMwgp.js","names":["$attrs","$slots"],"sources":["../../../../src/components/GrSwitch/GrSwitch.vue","../../../../src/components/GrSwitch/GrSwitch.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n grSwitchLabelClass,\n grSwitchRootClass,\n grSwitchSpinnerClass,\n grSwitchThumbClass,\n grSwitchTrackClass,\n type GrSwitchLabelPosition,\n type GrSwitchSize,\n} from './grSwitchStyles'\n\nexport type { GrSwitchLabelPosition, GrSwitchSize } from './grSwitchStyles'\n\n/**\n * Пропсы публичного GR-примитива «Switch».\n */\nexport interface GrSwitchProps {\n modelValue: boolean\n disabled?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n ariaLabel?: string\n size?: GrSwitchSize\n /** Сторона подписи относительно дорожки. */\n labelPosition?: GrSwitchLabelPosition\n /** Идёт сохранение: бегунок показывает спиннер, переключение заблокировано. */\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n /** Имя поля для нативной отправки формы. Без него скрытое поле не рендерится. */\n name?: string\n /** Значение, уходящее в форму во включённом состоянии. */\n value?: string\n /** `id` формы, если переключатель лежит вне неё. */\n form?: string\n /** Кастомный цвет фона в активном состоянии. Если не задан — `var(--gr-primary)`. */\n activeBackgroundColor?: string\n /** Кастомный цвет фона в неактивном состоянии. Если не задан — `var(--gr-muted)`. */\n inactiveBackgroundColor?: string\n}\n\nexport interface GrSwitchEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'change', value: boolean): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst getCustomColor = (value?: string) => value?.trim() || undefined\n\n// Скрытое поле — сосед кнопки, а не её потомок: интерактивный контент внутри\n// `<button>` невалиден. Из-за этого корень компонента — фрагмент, и атрибуты\n// потребителя надо донести до кнопки руками.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<GrSwitchProps>(),\n {\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n size: undefined,\n labelPosition: 'end',\n loading: false,\n loadingText: undefined,\n name: undefined,\n value: 'on',\n form: undefined,\n activeBackgroundColor: undefined,\n inactiveBackgroundColor: undefined,\n },\n)\n\n// Контекст `GrFormField`: id для `<label for>`, описание ошибкой, невалидность.\n// `<button>` — labelable-элемент, поэтому клик по подписи фокусирует переключатель.\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst describedBy = computed(() => field?.describedById.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst { t } = useGranularityTranslations()\n\nconst rootEl = ref<HTMLButtonElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrSwitch',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrSwitchEmits>()\ndefineSlots<{\n /** Подпись переключателя. */\n default?: () => any\n}>()\n\n\nconst rootClass = computed(() => grSwitchRootClass(props.labelPosition))\n\nconst trackClass = computed(() => grSwitchTrackClass(resolvedSize.value))\n\nconst trackStyle = computed(() => {\n const isChecked = props.modelValue\n const defaultBackgroundColor = isChecked ? 'var(--gr-primary)' : 'var(--gr-muted)'\n const customBackgroundColor = getCustomColor(\n isChecked ? props.activeBackgroundColor : props.inactiveBackgroundColor,\n )\n // Недоступность гасится токеном и перебивает кастомный цвет: иначе выключенный\n // переключатель остался бы таким же ярким, как рабочий.\n const backgroundColor = isDisabled.value\n ? 'var(--gr-disabled-bg)'\n : customBackgroundColor ?? defaultBackgroundColor\n\n return {\n '--gr-switch-track-bg': backgroundColor,\n '--gr-switch-track-brd': isDisabled.value\n ? 'var(--gr-disabled-brd)'\n : customBackgroundColor\n ? backgroundColor\n : isChecked\n ? 'var(--gr-primary)'\n : 'var(--gr-brd)',\n backgroundColor: 'var(--gr-switch-track-bg)',\n }\n})\n\nconst thumbClass = computed(() => grSwitchThumbClass({size: resolvedSize.value, checked: props.modelValue}))\n\nconst spinnerClass = computed(() => grSwitchSpinnerClass(resolvedSize.value))\n\nconst labelClass = computed(() => grSwitchLabelClass(resolvedSize.value, isDisabled.value))\n\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.switch.loading', 'Saving…'))\n\n// Выключенный переключатель не отправляется вовсе — так устроен чекбокс в HTML,\n// и сервер отличает «выкл» по отсутствию ключа.\nconst submitsValue = computed(\n () => props.modelValue && !isDisabled.value && Boolean(props.name),\n)\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value || props.loading) {\n return\n }\n\n const next = !props.modelValue\n emit('update:modelValue', next)\n emit('change', next)\n}\n</script>\n\n<template>\n <input\n v-if=\"submitsValue\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"value\"\n :form=\"form\"\n >\n\n <button\n :id=\"fieldId\"\n ref=\"rootEl\"\n v-bind=\"$attrs\"\n type=\"button\"\n role=\"switch\"\n data-gr-switch\n :aria-checked=\"modelValue ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-busy=\"loading ? 'true' : undefined\"\n :disabled=\"isDisabled\"\n :class=\"rootClass\"\n @click=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <span\n data-testid=\"gr-switch-track\"\n data-gr-switch-track\n :class=\"trackClass\"\n :style=\"trackStyle\"\n >\n <span\n data-testid=\"gr-switch-thumb\"\n data-gr-switch-thumb\n :class=\"thumbClass\"\n aria-hidden=\"true\"\n >\n <IconLoader v-if=\"loading\" data-gr-switch-spinner :class=\"spinnerClass\" />\n </span>\n </span>\n <span\n v-if=\"$slots.default\"\n data-gr-switch-label\n :class=\"labelClass\"\n >\n <slot />\n </span>\n <span v-if=\"loading\" data-gr-switch-loading-text class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </button>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n grSwitchLabelClass,\n grSwitchRootClass,\n grSwitchSpinnerClass,\n grSwitchThumbClass,\n grSwitchTrackClass,\n type GrSwitchLabelPosition,\n type GrSwitchSize,\n} from './grSwitchStyles'\n\nexport type { GrSwitchLabelPosition, GrSwitchSize } from './grSwitchStyles'\n\n/**\n * Пропсы публичного GR-примитива «Switch».\n */\nexport interface GrSwitchProps {\n modelValue: boolean\n disabled?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n ariaLabel?: string\n size?: GrSwitchSize\n /** Сторона подписи относительно дорожки. */\n labelPosition?: GrSwitchLabelPosition\n /** Идёт сохранение: бегунок показывает спиннер, переключение заблокировано. */\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n /** Имя поля для нативной отправки формы. Без него скрытое поле не рендерится. */\n name?: string\n /** Значение, уходящее в форму во включённом состоянии. */\n value?: string\n /** `id` формы, если переключатель лежит вне неё. */\n form?: string\n /** Кастомный цвет фона в активном состоянии. Если не задан — `var(--gr-primary)`. */\n activeBackgroundColor?: string\n /** Кастомный цвет фона в неактивном состоянии. Если не задан — `var(--gr-muted)`. */\n inactiveBackgroundColor?: string\n}\n\nexport interface GrSwitchEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'change', value: boolean): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst getCustomColor = (value?: string) => value?.trim() || undefined\n\n// Скрытое поле — сосед кнопки, а не её потомок: интерактивный контент внутри\n// `<button>` невалиден. Из-за этого корень компонента — фрагмент, и атрибуты\n// потребителя надо донести до кнопки руками.\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<GrSwitchProps>(),\n {\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n size: undefined,\n labelPosition: 'end',\n loading: false,\n loadingText: undefined,\n name: undefined,\n value: 'on',\n form: undefined,\n activeBackgroundColor: undefined,\n inactiveBackgroundColor: undefined,\n },\n)\n\n// Контекст `GrFormField`: id для `<label for>`, описание ошибкой, невалидность.\n// `<button>` — labelable-элемент, поэтому клик по подписи фокусирует переключатель.\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst describedBy = computed(() => field?.describedById.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst { t } = useGranularityTranslations()\n\nconst rootEl = ref<HTMLButtonElement | null>(null)\n\nfunction focus(): void {\n rootEl.value?.focus()\n}\n\nfunction blur(): void {\n rootEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrSwitch',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrSwitchEmits>()\ndefineSlots<{\n /** Подпись переключателя. */\n default?: () => any\n}>()\n\n\nconst rootClass = computed(() => grSwitchRootClass(props.labelPosition))\n\nconst trackClass = computed(() => grSwitchTrackClass(resolvedSize.value))\n\nconst trackStyle = computed(() => {\n const isChecked = props.modelValue\n const defaultBackgroundColor = isChecked ? 'var(--gr-primary)' : 'var(--gr-muted)'\n const customBackgroundColor = getCustomColor(\n isChecked ? props.activeBackgroundColor : props.inactiveBackgroundColor,\n )\n // Недоступность гасится токеном и перебивает кастомный цвет: иначе выключенный\n // переключатель остался бы таким же ярким, как рабочий.\n const backgroundColor = isDisabled.value\n ? 'var(--gr-disabled-bg)'\n : customBackgroundColor ?? defaultBackgroundColor\n\n return {\n '--gr-switch-track-bg': backgroundColor,\n '--gr-switch-track-brd': isDisabled.value\n ? 'var(--gr-disabled-brd)'\n : customBackgroundColor\n ? backgroundColor\n : isChecked\n ? 'var(--gr-primary)'\n : 'var(--gr-brd)',\n backgroundColor: 'var(--gr-switch-track-bg)',\n }\n})\n\nconst thumbClass = computed(() => grSwitchThumbClass({size: resolvedSize.value, checked: props.modelValue}))\n\nconst spinnerClass = computed(() => grSwitchSpinnerClass(resolvedSize.value))\n\nconst labelClass = computed(() => grSwitchLabelClass(resolvedSize.value, isDisabled.value))\n\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.switch.loading', 'Saving…'))\n\n// Выключенный переключатель не отправляется вовсе — так устроен чекбокс в HTML,\n// и сервер отличает «выкл» по отсутствию ключа.\nconst submitsValue = computed(\n () => props.modelValue && !isDisabled.value && Boolean(props.name),\n)\n\nfunction toggle(): void {\n if (isDisabled.value || isReadonly.value || props.loading) {\n return\n }\n\n const next = !props.modelValue\n emit('update:modelValue', next)\n emit('change', next)\n}\n</script>\n\n<template>\n <input\n v-if=\"submitsValue\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"value\"\n :form=\"form\"\n >\n\n <button\n :id=\"fieldId\"\n ref=\"rootEl\"\n v-bind=\"$attrs\"\n type=\"button\"\n role=\"switch\"\n data-gr-switch\n :aria-checked=\"modelValue ? 'true' : 'false'\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-busy=\"loading ? 'true' : undefined\"\n :disabled=\"isDisabled\"\n :class=\"rootClass\"\n @click=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <span\n data-testid=\"gr-switch-track\"\n data-gr-switch-track\n :class=\"trackClass\"\n :style=\"trackStyle\"\n >\n <span\n data-testid=\"gr-switch-thumb\"\n data-gr-switch-thumb\n :class=\"thumbClass\"\n aria-hidden=\"true\"\n >\n <IconLoader v-if=\"loading\" data-gr-switch-spinner :class=\"spinnerClass\" />\n </span>\n </span>\n <span\n v-if=\"$slots.default\"\n data-gr-switch-label\n :class=\"labelClass\"\n >\n <slot />\n </span>\n <span v-if=\"loading\" data-gr-switch-loading-text class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </button>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { n as grSwitchSafelist, t as grSwitchConfig } from "../../chunks/config-BoNR7_PD.js";
2
- import { t as GrSwitch_default } from "./chunks/GrSwitch-CHiIj9GT.js";
1
+ import { n as grSwitchSafelist, t as grSwitchConfig } from "../../chunks/config-Yy67uWHY.js";
2
+ import { t as GrSwitch_default } from "./chunks/GrSwitch-KRlRMwgp.js";
3
3
  export { GrSwitch_default as GrSwitch, GrSwitch_default as default, grSwitchConfig, grSwitchSafelist };
@@ -1 +1 @@
1
- {"version":3,"file":"GrTabPanels-BZQS8-JM.js","names":[],"sources":["../../../../src/components/GrTabPanels/context.ts","../../../../src/components/GrTabPanels/GrTabPanels.vue","../../../../src/components/GrTabPanels/GrTabPanels.vue","../../../../src/components/GrTabPanels/GrTabPanel.vue","../../../../src/components/GrTabPanels/GrTabPanel.vue"],"sourcesContent":["import type { ComputedRef, InjectionKey } from 'vue'\n\n/** Контекст, который `GrTabPanels` предоставляет своим `GrTabPanel`. */\nexport interface GrTabPanelsContext {\n /** Значение активной вкладки (совпадает с `modelValue` у `GrTabs`). */\n activeValue: ComputedRef<string>\n /** Общая база id для связки `tab`↔`tabpanel` (см. проп `idBase` у `GrTabs`). */\n idBase: ComputedRef<string>\n}\n\nexport const GR_TAB_PANELS_KEY: InjectionKey<GrTabPanelsContext> = Symbol('gr-tab-panels')\n","<script setup lang=\"ts\">\nimport { computed, provide, useId } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelsProps {\n modelValue: string\n idBase?: string\n}\n\n/**\n * GrTabPanels — контейнер `tabpanel`-ов, companion к `GrTabs`.\n *\n * Показывает панель, чьё `value` совпадает с `modelValue`, и связывает её с\n * соответствующей вкладкой по ARIA (`role=\"tabpanel\"`, `aria-labelledby`).\n *\n * Для полной связки `tab`↔`tabpanel` передайте **одинаковый `idBase`** и в\n * `GrTabs`, и в `GrTabPanels` — тогда id вкладок и панелей совпадут\n * (`aria-controls` ↔ `aria-labelledby`).\n */\nconst props = withDefaults(\n defineProps<GrTabPanelsProps>(),\n {\n idBase: undefined,\n },\n)\n\nconst generatedIdBase = useId()\n// `computed`, а не значение: `idBase` — реактивный проп, и вычисленный один раз\n// при setup он оставил бы панели со старыми id, пока `GrTabs` уехал бы на новые.\n// Связка `aria-controls` ↔ `aria-labelledby` разъезжается молча.\nconst resolvedIdBase = computed(() => props.idBase ?? generatedIdBase)\n\nprovide(GR_TAB_PANELS_KEY, {\n activeValue: computed(() => props.modelValue),\n idBase: resolvedIdBase,\n})\n</script>\n\n<template>\n <div data-gr-tab-panels>\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useId } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelsProps {\n modelValue: string\n idBase?: string\n}\n\n/**\n * GrTabPanels — контейнер `tabpanel`-ов, companion к `GrTabs`.\n *\n * Показывает панель, чьё `value` совпадает с `modelValue`, и связывает её с\n * соответствующей вкладкой по ARIA (`role=\"tabpanel\"`, `aria-labelledby`).\n *\n * Для полной связки `tab`↔`tabpanel` передайте **одинаковый `idBase`** и в\n * `GrTabs`, и в `GrTabPanels` — тогда id вкладок и панелей совпадут\n * (`aria-controls` ↔ `aria-labelledby`).\n */\nconst props = withDefaults(\n defineProps<GrTabPanelsProps>(),\n {\n idBase: undefined,\n },\n)\n\nconst generatedIdBase = useId()\n// `computed`, а не значение: `idBase` — реактивный проп, и вычисленный один раз\n// при setup он оставил бы панели со старыми id, пока `GrTabs` уехал бы на новые.\n// Связка `aria-controls` ↔ `aria-labelledby` разъезжается молча.\nconst resolvedIdBase = computed(() => props.idBase ?? generatedIdBase)\n\nprovide(GR_TAB_PANELS_KEY, {\n activeValue: computed(() => props.modelValue),\n idBase: resolvedIdBase,\n})\n</script>\n\n<template>\n <div data-gr-tab-panels>\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref, watch } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelProps {\n value: string\n keepAlive?: boolean\n /**\n * Не монтировать содержимое, пока панель не показали впервые. Имеет смысл\n * вместе с `keepAlive`: без него неактивная панель и так не в DOM.\n */\n lazy?: boolean\n}\n\n/**\n * GrTabPanel — одна панель внутри `GrTabPanels`. Показывается, когда её `value`\n * равно активной вкладке. `keepAlive` оставляет неактивные панели в DOM\n * (скрытыми через `hidden`) — полезно, чтобы не терять состояние форм.\n */\nconst props = withDefaults(\n defineProps<GrTabPanelProps>(),\n {\n keepAlive: false,\n lazy: false,\n },\n)\n\nconst ctx = inject(GR_TAB_PANELS_KEY, null)\n\nconst isActive = computed(() => (ctx ? ctx.activeValue.value === props.value : true))\n// id совпадают с id вкладок `GrTabs` при одинаковом `idBase` → корректная ARIA-связка.\nconst panelId = computed(() => (ctx ? `${ctx.idBase.value}-panel-${props.value}` : undefined))\nconst tabId = computed(() => (ctx ? `${ctx.idBase.value}-tab-${props.value}` : undefined))\n\nconst wasActive = ref(isActive.value)\nwatch(isActive, (active) => {\n if (active) wasActive.value = true\n})\n\nconst shouldRender = computed(() => {\n if (isActive.value) return true\n if (!props.keepAlive) return false\n return props.lazy ? wasActive.value : true\n})\n\n/**\n * Панель ссылается на вкладку по id, а существует ли вкладка — знает только\n * приложение: `GrTabs` с другим (или отсутствующим) `idBase` оставит\n * `aria-labelledby` висеть в пустоту. Проверяем это в dev, как `GrFormField`\n * проверяет забытый контрол.\n */\nif (__GR_DEV__) {\n onMounted(() => {\n if (!tabId.value || !isActive.value) return\n if (document.getElementById(tabId.value)) return\n\n console.warn(\n `[GrTabPanel] Вкладки с id \"${tabId.value}\" нет в документе: `\n + '`aria-labelledby` ссылается в пустоту. Передайте один и тот же `idBase` в `GrTabs` и `GrTabPanels`.',\n )\n })\n}\n</script>\n\n<template>\n <div\n v-if=\"shouldRender\"\n :id=\"panelId\"\n role=\"tabpanel\"\n data-gr-tab-panel\n :aria-labelledby=\"tabId\"\n :hidden=\"keepAlive && !isActive ? true : undefined\"\n :tabindex=\"isActive ? 0 : undefined\"\n class=\"rounded-[var(--gr-radius-md)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref, watch } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelProps {\n value: string\n keepAlive?: boolean\n /**\n * Не монтировать содержимое, пока панель не показали впервые. Имеет смысл\n * вместе с `keepAlive`: без него неактивная панель и так не в DOM.\n */\n lazy?: boolean\n}\n\n/**\n * GrTabPanel — одна панель внутри `GrTabPanels`. Показывается, когда её `value`\n * равно активной вкладке. `keepAlive` оставляет неактивные панели в DOM\n * (скрытыми через `hidden`) — полезно, чтобы не терять состояние форм.\n */\nconst props = withDefaults(\n defineProps<GrTabPanelProps>(),\n {\n keepAlive: false,\n lazy: false,\n },\n)\n\nconst ctx = inject(GR_TAB_PANELS_KEY, null)\n\nconst isActive = computed(() => (ctx ? ctx.activeValue.value === props.value : true))\n// id совпадают с id вкладок `GrTabs` при одинаковом `idBase` → корректная ARIA-связка.\nconst panelId = computed(() => (ctx ? `${ctx.idBase.value}-panel-${props.value}` : undefined))\nconst tabId = computed(() => (ctx ? `${ctx.idBase.value}-tab-${props.value}` : undefined))\n\nconst wasActive = ref(isActive.value)\nwatch(isActive, (active) => {\n if (active) wasActive.value = true\n})\n\nconst shouldRender = computed(() => {\n if (isActive.value) return true\n if (!props.keepAlive) return false\n return props.lazy ? wasActive.value : true\n})\n\n/**\n * Панель ссылается на вкладку по id, а существует ли вкладка — знает только\n * приложение: `GrTabs` с другим (или отсутствующим) `idBase` оставит\n * `aria-labelledby` висеть в пустоту. Проверяем это в dev, как `GrFormField`\n * проверяет забытый контрол.\n */\nif (__GR_DEV__) {\n onMounted(() => {\n if (!tabId.value || !isActive.value) return\n if (document.getElementById(tabId.value)) return\n\n console.warn(\n `[GrTabPanel] Вкладки с id \"${tabId.value}\" нет в документе: `\n + '`aria-labelledby` ссылается в пустоту. Передайте один и тот же `idBase` в `GrTabs` и `GrTabPanels`.',\n )\n })\n}\n</script>\n\n<template>\n <div\n v-if=\"shouldRender\"\n :id=\"panelId\"\n role=\"tabpanel\"\n data-gr-tab-panel\n :aria-labelledby=\"tabId\"\n :hidden=\"keepAlive && !isActive ? true : undefined\"\n :tabindex=\"isActive ? 0 : undefined\"\n class=\"rounded-[var(--gr-radius-md)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":";;AAUA,IAAa,oBAAsD,OAAO,eAAe;;;;;;;;;;;;;ECUzF,MAAM,QAAQ;EAOd,MAAM,kBAAkB,MAAM;EAI9B,MAAM,iBAAiB,eAAe,MAAM,UAAU,eAAe;EAErE,QAAQ,mBAAmB;GACzB,aAAa,eAAe,MAAM,UAAU;GAC5C,QAAQ;EACV,CAAC;;uBAIC,mBAEM,OAFN,cAEM,CADJ,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;EErBZ,MAAM,QAAQ;EAQd,MAAM,MAAM,OAAO,mBAAmB,IAAI;EAE1C,MAAM,WAAW,eAAgB,MAAM,IAAI,YAAY,UAAU,MAAM,QAAQ,IAAK;EAEpF,MAAM,UAAU,eAAgB,MAAM,GAAG,IAAI,OAAO,MAAM,SAAS,MAAM,UAAU,KAAA,CAAU;EAC7F,MAAM,QAAQ,eAAgB,MAAM,GAAG,IAAI,OAAO,MAAM,OAAO,MAAM,UAAU,KAAA,CAAU;EAEzF,MAAM,YAAY,IAAI,SAAS,KAAK;EACpC,MAAM,WAAW,WAAW;GAC1B,IAAI,QAAQ,UAAU,QAAQ;EAChC,CAAC;EAED,MAAM,eAAe,eAAe;GAClC,IAAI,SAAS,OAAO,OAAO;GAC3B,IAAI,CAAC,MAAM,WAAW,OAAO;GAC7B,OAAO,MAAM,OAAO,UAAU,QAAQ;EACxC,CAAC;;;;;;;EAQD,IAAA,OAAA,YAAA,eAAA,QAAA,IAAA,aAAA,cACE,gBAAgB;GACd,IAAI,CAAC,MAAM,SAAS,CAAC,SAAS,OAAO;GACrC,IAAI,SAAS,eAAe,MAAM,KAAK,GAAG;GAE1C,QAAQ,KACN,8BAA8B,MAAM,MAAM,+HAE5C;EACF,CAAC;;UAMO,aAAA,SAAA,UAAA,GADR,mBAWM,OAAA;;IATH,IAAI,QAAA;IACL,MAAK;IACL,qBAAA;IACC,mBAAiB,MAAA;IACjB,QAAQ,QAAA,aAAS,CAAK,SAAA,QAAQ,OAAU,KAAA;IACxC,UAAU,SAAA,QAAQ,IAAO,KAAA;IAC1B,OAAM;OAEN,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA"}
1
+ {"version":3,"file":"GrTabPanels-BZQS8-JM.js","names":[],"sources":["../../../../src/components/GrTabPanels/context.ts","../../../../src/components/GrTabPanels/GrTabPanels.vue","../../../../src/components/GrTabPanels/GrTabPanels.vue","../../../../src/components/GrTabPanels/GrTabPanel.vue","../../../../src/components/GrTabPanels/GrTabPanel.vue"],"sourcesContent":["import type { ComputedRef, InjectionKey } from 'vue'\n\n/** Контекст, который `GrTabPanels` предоставляет своим `GrTabPanel`. */\nexport interface GrTabPanelsContext {\n /** Значение активной вкладки (совпадает с `modelValue` у `GrTabs`). */\n activeValue: ComputedRef<string>\n /** Общая база id для связки `tab`↔`tabpanel` (см. проп `idBase` у `GrTabs`). */\n idBase: ComputedRef<string>\n}\n\nexport const GR_TAB_PANELS_KEY: InjectionKey<GrTabPanelsContext> = Symbol('gr-tab-panels')\n","<script setup lang=\"ts\">\nimport { computed, provide, useId } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelsProps {\n modelValue: string\n idBase?: string\n}\n\n/**\n * GrTabPanels — контейнер `tabpanel`-ов, companion к `GrTabs`.\n *\n * Показывает панель, чьё `value` совпадает с `modelValue`, и связывает её с\n * соответствующей вкладкой по ARIA (`role=\"tabpanel\"`, `aria-labelledby`).\n *\n * Для полной связки `tab`↔`tabpanel` передайте **одинаковый `idBase`** и в\n * `GrTabs`, и в `GrTabPanels` — тогда id вкладок и панелей совпадут\n * (`aria-controls` ↔ `aria-labelledby`).\n */\nconst props = withDefaults(\n defineProps<GrTabPanelsProps>(),\n {\n idBase: undefined,\n },\n)\n\nconst generatedIdBase = useId()\n// `computed`, а не значение: `idBase` — реактивный проп, и вычисленный один раз\n// при setup он оставил бы панели со старыми id, пока `GrTabs` уехал бы на новые.\n// Связка `aria-controls` ↔ `aria-labelledby` разъезжается молча.\nconst resolvedIdBase = computed(() => props.idBase ?? generatedIdBase)\n\nprovide(GR_TAB_PANELS_KEY, {\n activeValue: computed(() => props.modelValue),\n idBase: resolvedIdBase,\n})\n\ndefineSlots<{\n /** Панели (`GrTabPanel`). */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div data-gr-tab-panels>\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, provide, useId } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelsProps {\n modelValue: string\n idBase?: string\n}\n\n/**\n * GrTabPanels — контейнер `tabpanel`-ов, companion к `GrTabs`.\n *\n * Показывает панель, чьё `value` совпадает с `modelValue`, и связывает её с\n * соответствующей вкладкой по ARIA (`role=\"tabpanel\"`, `aria-labelledby`).\n *\n * Для полной связки `tab`↔`tabpanel` передайте **одинаковый `idBase`** и в\n * `GrTabs`, и в `GrTabPanels` — тогда id вкладок и панелей совпадут\n * (`aria-controls` ↔ `aria-labelledby`).\n */\nconst props = withDefaults(\n defineProps<GrTabPanelsProps>(),\n {\n idBase: undefined,\n },\n)\n\nconst generatedIdBase = useId()\n// `computed`, а не значение: `idBase` — реактивный проп, и вычисленный один раз\n// при setup он оставил бы панели со старыми id, пока `GrTabs` уехал бы на новые.\n// Связка `aria-controls` ↔ `aria-labelledby` разъезжается молча.\nconst resolvedIdBase = computed(() => props.idBase ?? generatedIdBase)\n\nprovide(GR_TAB_PANELS_KEY, {\n activeValue: computed(() => props.modelValue),\n idBase: resolvedIdBase,\n})\n\ndefineSlots<{\n /** Панели (`GrTabPanel`). */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div data-gr-tab-panels>\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref, watch } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelProps {\n value: string\n keepAlive?: boolean\n /**\n * Не монтировать содержимое, пока панель не показали впервые. Имеет смысл\n * вместе с `keepAlive`: без него неактивная панель и так не в DOM.\n */\n lazy?: boolean\n}\n\n/**\n * GrTabPanel — одна панель внутри `GrTabPanels`. Показывается, когда её `value`\n * равно активной вкладке. `keepAlive` оставляет неактивные панели в DOM\n * (скрытыми через `hidden`) — полезно, чтобы не терять состояние форм.\n */\nconst props = withDefaults(\n defineProps<GrTabPanelProps>(),\n {\n keepAlive: false,\n lazy: false,\n },\n)\n\nconst ctx = inject(GR_TAB_PANELS_KEY, null)\n\nconst isActive = computed(() => (ctx ? ctx.activeValue.value === props.value : true))\n// id совпадают с id вкладок `GrTabs` при одинаковом `idBase` → корректная ARIA-связка.\nconst panelId = computed(() => (ctx ? `${ctx.idBase.value}-panel-${props.value}` : undefined))\nconst tabId = computed(() => (ctx ? `${ctx.idBase.value}-tab-${props.value}` : undefined))\n\nconst wasActive = ref(isActive.value)\nwatch(isActive, (active) => {\n if (active) wasActive.value = true\n})\n\nconst shouldRender = computed(() => {\n if (isActive.value) return true\n if (!props.keepAlive) return false\n return props.lazy ? wasActive.value : true\n})\n\n/**\n * Панель ссылается на вкладку по id, а существует ли вкладка — знает только\n * приложение: `GrTabs` с другим (или отсутствующим) `idBase` оставит\n * `aria-labelledby` висеть в пустоту. Проверяем это в dev, как `GrFormField`\n * проверяет забытый контрол.\n */\nif (__GR_DEV__) {\n onMounted(() => {\n if (!tabId.value || !isActive.value) return\n if (document.getElementById(tabId.value)) return\n\n console.warn(\n `[GrTabPanel] Вкладки с id \"${tabId.value}\" нет в документе: `\n + '`aria-labelledby` ссылается в пустоту. Передайте один и тот же `idBase` в `GrTabs` и `GrTabPanels`.',\n )\n })\n}\n\ndefineSlots<{\n /** Содержимое панели. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n v-if=\"shouldRender\"\n :id=\"panelId\"\n role=\"tabpanel\"\n data-gr-tab-panel\n :aria-labelledby=\"tabId\"\n :hidden=\"keepAlive && !isActive ? true : undefined\"\n :tabindex=\"isActive ? 0 : undefined\"\n class=\"rounded-[var(--gr-radius-md)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n >\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref, watch } from 'vue'\n\nimport { GR_TAB_PANELS_KEY } from './context'\n\nexport interface GrTabPanelProps {\n value: string\n keepAlive?: boolean\n /**\n * Не монтировать содержимое, пока панель не показали впервые. Имеет смысл\n * вместе с `keepAlive`: без него неактивная панель и так не в DOM.\n */\n lazy?: boolean\n}\n\n/**\n * GrTabPanel — одна панель внутри `GrTabPanels`. Показывается, когда её `value`\n * равно активной вкладке. `keepAlive` оставляет неактивные панели в DOM\n * (скрытыми через `hidden`) — полезно, чтобы не терять состояние форм.\n */\nconst props = withDefaults(\n defineProps<GrTabPanelProps>(),\n {\n keepAlive: false,\n lazy: false,\n },\n)\n\nconst ctx = inject(GR_TAB_PANELS_KEY, null)\n\nconst isActive = computed(() => (ctx ? ctx.activeValue.value === props.value : true))\n// id совпадают с id вкладок `GrTabs` при одинаковом `idBase` → корректная ARIA-связка.\nconst panelId = computed(() => (ctx ? `${ctx.idBase.value}-panel-${props.value}` : undefined))\nconst tabId = computed(() => (ctx ? `${ctx.idBase.value}-tab-${props.value}` : undefined))\n\nconst wasActive = ref(isActive.value)\nwatch(isActive, (active) => {\n if (active) wasActive.value = true\n})\n\nconst shouldRender = computed(() => {\n if (isActive.value) return true\n if (!props.keepAlive) return false\n return props.lazy ? wasActive.value : true\n})\n\n/**\n * Панель ссылается на вкладку по id, а существует ли вкладка — знает только\n * приложение: `GrTabs` с другим (или отсутствующим) `idBase` оставит\n * `aria-labelledby` висеть в пустоту. Проверяем это в dev, как `GrFormField`\n * проверяет забытый контрол.\n */\nif (__GR_DEV__) {\n onMounted(() => {\n if (!tabId.value || !isActive.value) return\n if (document.getElementById(tabId.value)) return\n\n console.warn(\n `[GrTabPanel] Вкладки с id \"${tabId.value}\" нет в документе: `\n + '`aria-labelledby` ссылается в пустоту. Передайте один и тот же `idBase` в `GrTabs` и `GrTabPanels`.',\n )\n })\n}\n\ndefineSlots<{\n /** Содержимое панели. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n v-if=\"shouldRender\"\n :id=\"panelId\"\n role=\"tabpanel\"\n data-gr-tab-panel\n :aria-labelledby=\"tabId\"\n :hidden=\"keepAlive && !isActive ? true : undefined\"\n :tabindex=\"isActive ? 0 : undefined\"\n class=\"rounded-[var(--gr-radius-md)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":";;AAUA,IAAa,oBAAsD,OAAO,eAAe;;;;;;;;;;;;;ECUzF,MAAM,QAAQ;EAOd,MAAM,kBAAkB,MAAM;EAI9B,MAAM,iBAAiB,eAAe,MAAM,UAAU,eAAe;EAErE,QAAQ,mBAAmB;GACzB,aAAa,eAAe,MAAM,UAAU;GAC5C,QAAQ;EACV,CAAC;;uBAUC,mBAEM,OAFN,cAEM,CADJ,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;EE3BZ,MAAM,QAAQ;EAQd,MAAM,MAAM,OAAO,mBAAmB,IAAI;EAE1C,MAAM,WAAW,eAAgB,MAAM,IAAI,YAAY,UAAU,MAAM,QAAQ,IAAK;EAEpF,MAAM,UAAU,eAAgB,MAAM,GAAG,IAAI,OAAO,MAAM,SAAS,MAAM,UAAU,KAAA,CAAU;EAC7F,MAAM,QAAQ,eAAgB,MAAM,GAAG,IAAI,OAAO,MAAM,OAAO,MAAM,UAAU,KAAA,CAAU;EAEzF,MAAM,YAAY,IAAI,SAAS,KAAK;EACpC,MAAM,WAAW,WAAW;GAC1B,IAAI,QAAQ,UAAU,QAAQ;EAChC,CAAC;EAED,MAAM,eAAe,eAAe;GAClC,IAAI,SAAS,OAAO,OAAO;GAC3B,IAAI,CAAC,MAAM,WAAW,OAAO;GAC7B,OAAO,MAAM,OAAO,UAAU,QAAQ;EACxC,CAAC;;;;;;;EAQD,IAAA,OAAA,YAAA,eAAA,QAAA,IAAA,aAAA,cACE,gBAAgB;GACd,IAAI,CAAC,MAAM,SAAS,CAAC,SAAS,OAAO;GACrC,IAAI,SAAS,eAAe,MAAM,KAAK,GAAG;GAE1C,QAAQ,KACN,8BAA8B,MAAM,MAAM,+HAE5C;EACF,CAAC;;UAYO,aAAA,SAAA,UAAA,GADR,mBAWM,OAAA;;IATH,IAAI,QAAA;IACL,MAAK;IACL,qBAAA;IACC,mBAAiB,MAAA;IACjB,QAAQ,QAAA,aAAS,CAAK,SAAA,QAAQ,OAAU,KAAA;IACxC,UAAU,SAAA,QAAQ,IAAO,KAAA;IAC1B,OAAM;OAEN,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA"}
@@ -2,7 +2,7 @@ import { a as useGrComponentSize } from "../../../chunks/context-CTbuwcYs.js";
2
2
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
3
3
  import { t as GrSkeleton_default } from "../../GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js";
4
4
  import { n as hasMeaningfulSlotContent } from "../../../chunks/slotNodes-DxNXpC7v.js";
5
- import { a as tableSizes, i as stripedClass, n as hoverableClass, r as loadingRowCellClass, t as emptyCellClass } from "../../../chunks/grTableStyles-C-iaqQUN.js";
5
+ import { a as tableSizes, i as stripedClass, n as hoverableClass, r as loadingRowCellClass, t as emptyCellClass } from "../../../chunks/grTableStyles-uuMPSOBR.js";
6
6
  import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useSlots } from "vue";
7
7
  //#region src/components/GrTable/GrTable.vue?vue&type=script&setup=true&lang.ts
8
8
  var _hoisted_1 = [
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrTable-Zcdz2St_.js","names":[],"sources":["../../../../src/components/GrTable/GrTable.vue","../../../../src/components/GrTable/GrTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, useSlots } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n emptyCellClass,\n hoverableClass,\n loadingRowCellClass,\n stripedClass,\n tableSizes,\n type GrTableSize,\n} from './grTableStyles'\n\nexport interface GrTableProps {\n /**\n * Размер таблицы — базовый кегль текста. Паддинги ячеек оставлены за\n * консьюмером (GrTable — «тонкий» контейнер).\n */\n size?: GrTableSize\n /**\n * Текст caption для screen reader'ов. Рендерится как `<caption class=\"sr-only\">`,\n * если не передан слот `#caption`.\n */\n caption?: string\n /** Прямой ARIA-label для `<table>`. Игнорируется, если задан `ariaLabelledby`. */\n ariaLabel?: string\n /** ID элемента-заголовка, связанного с `<table>` через `aria-labelledby`. */\n ariaLabelledby?: string\n /**\n * ARIA-label для скролл-контейнера. Включает `role=\"region\"`; сам скролл\n * достижим с клавиатуры всегда, независимо от метки.\n */\n regionLabel?: string\n /** Идёт загрузка: вместо строк — скелетоны, контейнер помечен `aria-busy`. */\n loading?: boolean\n /** Сколько строк-заглушек показать при `loading`. */\n loadingRows?: number\n /** Сколько колонок занимает служебная строка (пустое состояние и скелетоны). */\n columnCount?: number\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Таблица пуста. По умолчанию определяется по содержимому слота. */\n empty?: boolean\n /** Чередование строк. */\n striped?: boolean\n /** Подсветка строки под курсором. */\n hoverable?: boolean\n /**\n * Прилипающий заголовок: `<thead>` остаётся видимым при вертикальном скролле.\n * Осмысленно вместе с `maxHeight` (иначе таблица не скроллится вертикально).\n */\n stickyHeader?: boolean\n /**\n * Полное число строк набора, включая строки заголовка (`aria-rowcount`).\n *\n * Нужен, когда в DOM не весь набор — например, при виртуализации: диктор\n * считает строки по разметке и объявил бы «5 из 20» на таблице в десять\n * тысяч. Строки при этом обязаны нести `aria-rowindex`.\n */\n rowCount?: number\n /**\n * Фиксированная раскладка (`table-layout: fixed`): ширины колонок берутся из\n * первой строки, а не из содержимого всех.\n *\n * Обязателен, если в DOM не весь набор: иначе ширины считаются по\n * отрисованному окну и прыгают на каждой прокрутке.\n *\n * Класс — arbitrary-значение, а не `table-fixed`: такого правила в\n * `presetMini` нет, и класс молча не превратился бы в CSS.\n */\n fixedLayout?: boolean\n /**\n * Минимальная ширина самой таблицы (число — пиксели).\n *\n * Нужна при `fixedLayout`: с фиксированной раскладкой и шириной `auto`\n * браузер вписывает таблицу в контейнер и делит место между колонками\n * пропорционально — то есть заданные ширины молча ужимаются, а\n * горизонтальной прокрутки, на которой держатся закреплённые колонки, не\n * возникает вовсе.\n */\n tableMinWidth?: string | number\n /**\n * Максимальная высота скролл-контейнера (включает вертикальный скролл).\n * Число трактуется как пиксели. Нужен для работы `stickyHeader`.\n */\n maxHeight?: string | number\n}\n\n/**\n * `GrTable` — «тонкий» GR-контейнер для табличных данных.\n *\n * Рендерит `<table>` внутри скролл-обёртки и даёт слоты `#caption`, `#header`,\n * default (tbody) и `#footer`. Стили ячеек (`<th>`/`<td>` паддинги, выравнивание)\n * оставлены на консьюмере.\n *\n * ВАЖНО: `min-w-full` сам по себе не даст горизонтального скролла. Для него\n * консьюмеру нужны `white-space: nowrap` на ячейках или явные ширины колонок.\n */\nconst props = withDefaults(defineProps<GrTableProps>(), {\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n loading: false,\n loadingRows: 3,\n columnCount: 1,\n emptyText: undefined,\n empty: undefined,\n striped: false,\n hoverable: false,\n stickyHeader: false,\n maxHeight: undefined,\n rowCount: undefined,\n fixedLayout: false,\n tableMinWidth: undefined,\n})\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTable' })\nconst tableTextClass = computed(() => tableSizes[resolvedSize.value])\nconst hasCaption = computed(() => Boolean(slots.caption) || Boolean(props.caption))\n\nconst { t } = useGranularityTranslations()\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.table.empty', 'Nothing here yet'))\n\n// Пустоту видно по слоту: `v-for` по пустому массиву оставляет фрагмент без\n// узлов, `v-if` — комментарий, и ни то ни другое строкой не является.\nconst isEmpty = computed(() => {\n if (props.empty !== undefined)\n return props.empty\n\n return !hasMeaningfulSlotContent(slots.default?.() ?? [])\n})\n\nconst showRows = computed(() => !props.loading && !isEmpty.value)\nconst loadingRowCount = computed(() => Math.max(1, Math.trunc(props.loadingRows)))\nconst serviceColSpan = computed(() => Math.max(1, Math.trunc(props.columnCount)))\n\nconst tbodyClass = computed(() => [\n 'text-[var(--gr-fg)]',\n props.striped && showRows.value ? stripedClass : '',\n props.hoverable && showRows.value ? hoverableClass : '',\n].filter(Boolean).join(' '))\n\nconst scrollStyle = computed(() => {\n // Неполный набор в DOM (`rowCount`) означает виртуализацию, а с ней обязан\n // быть выключен браузерный scroll anchoring: он подправляет `scrollTop`,\n // когда меняется высота содержимого выше видимого узла, — а окно меняет её\n // на каждом кадре прокрутки, и список уезжает.\n const anchor = props.rowCount === undefined ? undefined : { overflowAnchor: 'none' as const }\n\n if (props.maxHeight === undefined)\n return anchor\n\n const value = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n return { ...anchor, maxHeight: value, overflowY: 'auto' as const }\n})\n\n// Прилипающий заголовок: `<thead>` на `position: sticky`; фон обязателен, иначе\n// сквозь него будут просвечивать строки при скролле.\nconst theadClass = computed(() => [\n 'bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]',\n props.stickyHeader ? 'sticky top-0 z-[1]' : '',\n].filter(Boolean).join(' '))\n\nconst tableStyle = computed(() => {\n if (props.tableMinWidth === undefined) return undefined\n\n const value = typeof props.tableMinWidth === 'number' ? `${props.tableMinWidth}px` : props.tableMinWidth\n\n return { minWidth: value }\n})\n\nconst scrollEl = ref<HTMLElement | null>(null)\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl.value?.scrollTo(options)\n}\n\n// Только верхний уровень собственного tbody: вложенная таблица в ячейке не\n// должна сдвигать индексацию строк.\nfunction contentRows(): HTMLElement[] {\n if (!showRows.value) return []\n const el = scrollEl.value\n if (!el) return []\n return Array.from(el.querySelectorAll<HTMLElement>(':scope > table > tbody > tr'))\n}\n\nfunction scrollToRow(index: number, options?: ScrollIntoViewOptions): boolean {\n const row = contentRows()[index]\n if (!row) return false\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\ndefineExpose({\n /** Прокрутить скролл-контейнер таблицы — тот же контракт, что у `GrDataTable`. */\n scrollTo,\n /** Прокрутить к строке содержимого по её индексу в разметке. `false` — строки нет в DOM. */\n scrollToRow,\n})\n\ndefineSlots<{\n /** Строки таблицы, когда разметка пишется руками вместо `data`. */\n default?: () => any\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Шапка вместо построенной по `columns`. */\n header?: () => any\n /** Содержимое, пока едут данные, — вместо строк-заглушек. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Итоговая строка под таблицей. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n ref=\"scrollEl\"\n data-gr-table-scroll\n :role=\"regionLabel ? 'region' : undefined\"\n :aria-label=\"regionLabel\"\n :aria-busy=\"loading ? 'true' : undefined\"\n tabindex=\"0\"\n class=\"overflow-x-auto rounded-[var(--gr-radius-lg)] border border-[var(--gr-brd)] bg-[var(--gr-card)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :style=\"scrollStyle\"\n >\n <table\n data-gr-table\n class=\"min-w-full\" :class=\"[tableTextClass, fixedLayout ? '[table-layout:fixed]' : '']\"\n :style=\"tableStyle\"\n :aria-label=\"ariaLabelledby ? undefined : ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-rowcount=\"rowCount\"\n >\n <caption v-if=\"hasCaption\" class=\"sr-only\">\n <slot name=\"caption\">\n{{ caption }}\n</slot>\n </caption>\n <thead :class=\"theadClass\">\n <slot name=\"header\" />\n </thead>\n <tbody :class=\"tbodyClass\">\n <template v-if=\"loading\">\n <slot name=\"loading\">\n <tr v-for=\"row in loadingRowCount\" :key=\"row\" data-gr-table-loading-row>\n <td :colspan=\"serviceColSpan\" :class=\"loadingRowCellClass\">\n <GrSkeleton />\n </td>\n </tr>\n </slot>\n </template>\n\n <tr v-else-if=\"isEmpty\" data-gr-table-empty>\n <td :colspan=\"serviceColSpan\" :class=\"emptyCellClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n\n <slot v-else />\n </tbody>\n <tfoot v-if=\"slots.footer\" class=\"text-[var(--gr-fg)]\">\n <slot name=\"footer\" />\n </tfoot>\n </table>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, useSlots } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport GrSkeleton from '../GrSkeleton/GrSkeleton.vue'\nimport { hasMeaningfulSlotContent } from '../shared/slotNodes'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport {\n emptyCellClass,\n hoverableClass,\n loadingRowCellClass,\n stripedClass,\n tableSizes,\n type GrTableSize,\n} from './grTableStyles'\n\nexport interface GrTableProps {\n /**\n * Размер таблицы — базовый кегль текста. Паддинги ячеек оставлены за\n * консьюмером (GrTable — «тонкий» контейнер).\n */\n size?: GrTableSize\n /**\n * Текст caption для screen reader'ов. Рендерится как `<caption class=\"sr-only\">`,\n * если не передан слот `#caption`.\n */\n caption?: string\n /** Прямой ARIA-label для `<table>`. Игнорируется, если задан `ariaLabelledby`. */\n ariaLabel?: string\n /** ID элемента-заголовка, связанного с `<table>` через `aria-labelledby`. */\n ariaLabelledby?: string\n /**\n * ARIA-label для скролл-контейнера. Включает `role=\"region\"`; сам скролл\n * достижим с клавиатуры всегда, независимо от метки.\n */\n regionLabel?: string\n /** Идёт загрузка: вместо строк — скелетоны, контейнер помечен `aria-busy`. */\n loading?: boolean\n /** Сколько строк-заглушек показать при `loading`. */\n loadingRows?: number\n /** Сколько колонок занимает служебная строка (пустое состояние и скелетоны). */\n columnCount?: number\n /** Текст пустого состояния. Слот `#empty` сильнее. */\n emptyText?: string\n /** Таблица пуста. По умолчанию определяется по содержимому слота. */\n empty?: boolean\n /** Чередование строк. */\n striped?: boolean\n /** Подсветка строки под курсором. */\n hoverable?: boolean\n /**\n * Прилипающий заголовок: `<thead>` остаётся видимым при вертикальном скролле.\n * Осмысленно вместе с `maxHeight` (иначе таблица не скроллится вертикально).\n */\n stickyHeader?: boolean\n /**\n * Полное число строк набора, включая строки заголовка (`aria-rowcount`).\n *\n * Нужен, когда в DOM не весь набор — например, при виртуализации: диктор\n * считает строки по разметке и объявил бы «5 из 20» на таблице в десять\n * тысяч. Строки при этом обязаны нести `aria-rowindex`.\n */\n rowCount?: number\n /**\n * Фиксированная раскладка (`table-layout: fixed`): ширины колонок берутся из\n * первой строки, а не из содержимого всех.\n *\n * Обязателен, если в DOM не весь набор: иначе ширины считаются по\n * отрисованному окну и прыгают на каждой прокрутке.\n *\n * Класс — arbitrary-значение, а не `table-fixed`: такого правила в\n * `presetMini` нет, и класс молча не превратился бы в CSS.\n */\n fixedLayout?: boolean\n /**\n * Минимальная ширина самой таблицы (число — пиксели).\n *\n * Нужна при `fixedLayout`: с фиксированной раскладкой и шириной `auto`\n * браузер вписывает таблицу в контейнер и делит место между колонками\n * пропорционально — то есть заданные ширины молча ужимаются, а\n * горизонтальной прокрутки, на которой держатся закреплённые колонки, не\n * возникает вовсе.\n */\n tableMinWidth?: string | number\n /**\n * Максимальная высота скролл-контейнера (включает вертикальный скролл).\n * Число трактуется как пиксели. Нужен для работы `stickyHeader`.\n */\n maxHeight?: string | number\n}\n\n/**\n * `GrTable` — «тонкий» GR-контейнер для табличных данных.\n *\n * Рендерит `<table>` внутри скролл-обёртки и даёт слоты `#caption`, `#header`,\n * default (tbody) и `#footer`. Стили ячеек (`<th>`/`<td>` паддинги, выравнивание)\n * оставлены на консьюмере.\n *\n * ВАЖНО: `min-w-full` сам по себе не даст горизонтального скролла. Для него\n * консьюмеру нужны `white-space: nowrap` на ячейках или явные ширины колонок.\n */\nconst props = withDefaults(defineProps<GrTableProps>(), {\n size: undefined,\n caption: undefined,\n ariaLabel: undefined,\n ariaLabelledby: undefined,\n regionLabel: undefined,\n loading: false,\n loadingRows: 3,\n columnCount: 1,\n emptyText: undefined,\n empty: undefined,\n striped: false,\n hoverable: false,\n stickyHeader: false,\n maxHeight: undefined,\n rowCount: undefined,\n fixedLayout: false,\n tableMinWidth: undefined,\n})\n\nconst slots = useSlots()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTable' })\nconst tableTextClass = computed(() => tableSizes[resolvedSize.value])\nconst hasCaption = computed(() => Boolean(slots.caption) || Boolean(props.caption))\n\nconst { t } = useGranularityTranslations()\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.table.empty', 'Nothing here yet'))\n\n// Пустоту видно по слоту: `v-for` по пустому массиву оставляет фрагмент без\n// узлов, `v-if` — комментарий, и ни то ни другое строкой не является.\nconst isEmpty = computed(() => {\n if (props.empty !== undefined)\n return props.empty\n\n return !hasMeaningfulSlotContent(slots.default?.() ?? [])\n})\n\nconst showRows = computed(() => !props.loading && !isEmpty.value)\nconst loadingRowCount = computed(() => Math.max(1, Math.trunc(props.loadingRows)))\nconst serviceColSpan = computed(() => Math.max(1, Math.trunc(props.columnCount)))\n\nconst tbodyClass = computed(() => [\n 'text-[var(--gr-fg)]',\n props.striped && showRows.value ? stripedClass : '',\n props.hoverable && showRows.value ? hoverableClass : '',\n].filter(Boolean).join(' '))\n\nconst scrollStyle = computed(() => {\n // Неполный набор в DOM (`rowCount`) означает виртуализацию, а с ней обязан\n // быть выключен браузерный scroll anchoring: он подправляет `scrollTop`,\n // когда меняется высота содержимого выше видимого узла, — а окно меняет её\n // на каждом кадре прокрутки, и список уезжает.\n const anchor = props.rowCount === undefined ? undefined : { overflowAnchor: 'none' as const }\n\n if (props.maxHeight === undefined)\n return anchor\n\n const value = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n return { ...anchor, maxHeight: value, overflowY: 'auto' as const }\n})\n\n// Прилипающий заголовок: `<thead>` на `position: sticky`; фон обязателен, иначе\n// сквозь него будут просвечивать строки при скролле.\nconst theadClass = computed(() => [\n 'bg-[var(--gr-muted)] text-[var(--gr-muted-fg)]',\n props.stickyHeader ? 'sticky top-0 z-[1]' : '',\n].filter(Boolean).join(' '))\n\nconst tableStyle = computed(() => {\n if (props.tableMinWidth === undefined) return undefined\n\n const value = typeof props.tableMinWidth === 'number' ? `${props.tableMinWidth}px` : props.tableMinWidth\n\n return { minWidth: value }\n})\n\nconst scrollEl = ref<HTMLElement | null>(null)\n\nfunction scrollTo(options: ScrollToOptions): void {\n scrollEl.value?.scrollTo(options)\n}\n\n// Только верхний уровень собственного tbody: вложенная таблица в ячейке не\n// должна сдвигать индексацию строк.\nfunction contentRows(): HTMLElement[] {\n if (!showRows.value) return []\n const el = scrollEl.value\n if (!el) return []\n return Array.from(el.querySelectorAll<HTMLElement>(':scope > table > tbody > tr'))\n}\n\nfunction scrollToRow(index: number, options?: ScrollIntoViewOptions): boolean {\n const row = contentRows()[index]\n if (!row) return false\n row.scrollIntoView(options ?? { block: 'nearest' })\n return true\n}\n\ndefineExpose({\n /** Прокрутить скролл-контейнер таблицы — тот же контракт, что у `GrDataTable`. */\n scrollTo,\n /** Прокрутить к строке содержимого по её индексу в разметке. `false` — строки нет в DOM. */\n scrollToRow,\n})\n\ndefineSlots<{\n /** Строки таблицы, когда разметка пишется руками вместо `data`. */\n default?: () => any\n /** Подпись таблицы — `<caption>`, читается диктором первой. */\n caption?: () => any\n /** Шапка вместо построенной по `columns`. */\n header?: () => any\n /** Содержимое, пока едут данные, — вместо строк-заглушек. */\n loading?: () => any\n /** Пустое состояние вместо текста по умолчанию. */\n empty?: () => any\n /** Итоговая строка под таблицей. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n ref=\"scrollEl\"\n data-gr-table-scroll\n :role=\"regionLabel ? 'region' : undefined\"\n :aria-label=\"regionLabel\"\n :aria-busy=\"loading ? 'true' : undefined\"\n tabindex=\"0\"\n class=\"overflow-x-auto rounded-[var(--gr-radius-lg)] border border-[var(--gr-brd)] bg-[var(--gr-card)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--gr-ring)]\"\n :style=\"scrollStyle\"\n >\n <table\n data-gr-table\n class=\"min-w-full\" :class=\"[tableTextClass, fixedLayout ? '[table-layout:fixed]' : '']\"\n :style=\"tableStyle\"\n :aria-label=\"ariaLabelledby ? undefined : ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-rowcount=\"rowCount\"\n >\n <caption v-if=\"hasCaption\" class=\"sr-only\">\n <slot name=\"caption\">\n{{ caption }}\n</slot>\n </caption>\n <thead :class=\"theadClass\">\n <slot name=\"header\" />\n </thead>\n <tbody :class=\"tbodyClass\">\n <template v-if=\"loading\">\n <slot name=\"loading\">\n <tr v-for=\"row in loadingRowCount\" :key=\"row\" data-gr-table-loading-row>\n <td :colspan=\"serviceColSpan\" :class=\"loadingRowCellClass\">\n <GrSkeleton />\n </td>\n </tr>\n </slot>\n </template>\n\n <tr v-else-if=\"isEmpty\" data-gr-table-empty>\n <td :colspan=\"serviceColSpan\" :class=\"emptyCellClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </td>\n </tr>\n\n <slot v-else />\n </tbody>\n <tfoot v-if=\"slots.footer\" class=\"text-[var(--gr-fg)]\">\n <slot name=\"footer\" />\n </tfoot>\n </table>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrTable_default } from "./chunks/GrTable-f3qCWa99.js";
2
- import { n as grTableSafelist, t as grTableConfig } from "../../chunks/config-WTNhdh6T.js";
1
+ import { t as GrTable_default } from "./chunks/GrTable-Zcdz2St_.js";
2
+ import { n as grTableSafelist, t as grTableConfig } from "../../chunks/config-DCq4JySZ.js";
3
3
  export { GrTable_default as GrTable, GrTable_default as default, grTableConfig, grTableSafelist };
@@ -1,9 +1,9 @@
1
1
  import { t as x_default } from "../../../chunks/x-2KXnqxiD.js";
2
2
  import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
3
3
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
4
- import { n as iconTag, t as iconClass } from "../../../chunks/icon-Dag2tIMs.js";
5
4
  import { useRovingFocus } from "../../../composables/useRovingFocus.js";
6
- import { a as grTabsEmptyClass, c as tabCloseIconSizes, i as grTabsCloseClass, l as tabContentClass, o as grTabsListClass, r as grTabsBadgeClass, s as grTabsTabClass, u as tabIconClass } from "../../../chunks/config-DWN4x6_e.js";
5
+ import { n as iconTag, t as iconClass } from "../../../chunks/icon-Dag2tIMs.js";
6
+ import { a as grTabsEmptyClass, c as tabCloseIconSizes, i as grTabsCloseClass, l as tabContentClass, o as grTabsListClass, r as grTabsBadgeClass, s as grTabsTabClass, u as tabIconClass } from "../../../chunks/config-_QF0O1vq.js";
7
7
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, watch } from "vue";
8
8
  //#region src/components/GrTabs/GrTabs.vue?vue&type=script&setup=true&lang.ts
9
9
  var _hoisted_1 = ["aria-orientation"];
@@ -1 +1 @@
1
- {"version":3,"file":"GrTabs-CBHZkOFY.js","names":[],"sources":["../../../../src/components/GrTabs/GrTabs.vue","../../../../src/components/GrTabs/GrTabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch, type Component } from 'vue'\n\nimport IconX from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { iconClass, iconTag } from '../shared/icon'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport {\n grTabsBadgeClass,\n grTabsCloseClass,\n grTabsEmptyClass,\n grTabsListClass,\n grTabsTabClass,\n tabCloseIconSizes,\n tabContentClass,\n tabIconClass,\n type GrTabsOrientation,\n type GrTabsSize,\n type GrTabsVariant,\n} from './grTabsStyles'\n\nexport interface GrTab {\n value: string\n label: string\n badge?: string\n /**\n * Иконка слева от подписи: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-user'` — тогда нужен ваш `presetIcons`, см. `docs/installation.md`).\n */\n icon?: string | Component\n disabled?: boolean\n /** Перекрывает `closable` ряда в обе стороны: закрепить вкладку или закрыть одну её. */\n closable?: boolean\n}\n\nexport interface GrTabsProps {\n modelValue: string\n tabs: GrTab[]\n /**\n * База id для ARIA-связки с `GrTabPanels`. Если задана, каждая вкладка\n * получает `id=\"<idBase>-tab-<value>\"` и `aria-controls=\"<idBase>-panel-<value>\"`.\n * Передайте тот же `idBase` в `GrTabPanels`, чтобы связать `tab`↔`tabpanel`.\n */\n idBase?: string\n size?: GrTabsSize\n /** Вид ряда: обойма с таблетками или ряд с подчёркиванием. */\n variant?: GrTabsVariant\n /**\n * `automatic` (по умолчанию) — стрелка сразу переключает вкладку;\n * `manual` — стрелка двигает только фокус, выбор подтверждается\n * `Enter`/`Space`. Второй режим для вкладок с тяжёлой загрузкой: перебор\n * стрелками иначе тянет каждую панель.\n */\n activationMode?: GrTabsActivationMode\n /** Горизонтальный (по умолчанию) или вертикальный список вкладок. */\n orientation?: GrTabsOrientation\n /**\n * Крестик на вкладках и закрытие по `Delete`/`Backspace`. Точечно снимается\n * `closable: false` у самой вкладки.\n */\n closable?: boolean\n /** Текст, когда список вкладок пуст. Слот `#empty` сильнее. */\n emptyText?: string\n}\n\nexport interface GrTabsEmits {\n (e: 'update:modelValue', value: string): void\n /**\n * Просьба закрыть вкладку. Компонент список не трогает: `tabs` — проп, и\n * закрытие может не состояться («сохранить изменения?»).\n */\n (e: 'close', value: string): void\n}\n\nexport type GrTabsActivationMode = 'automatic' | 'manual'\n\nexport type { GrTabsOrientation, GrTabsVariant } from './grTabsStyles'\n\n/**\n * GrTabs — горизонтальная группа вкладок с паттерном WAI-ARIA `tablist`.\n *\n * A11y:\n * - `role=\"tablist\"` на корне, `role=\"tab\"` на каждой вкладке.\n * - Roving `tabindex`: активная вкладка `0`, остальные `-1`.\n * - Клавиатура: `ArrowLeft`/`ArrowRight` — цикличный переход, `Home`/`End` — к первой/последней.\n * - При переключении стрелками DOM-фокус программно переносится на новую вкладку.\n *\n * Сам компонент не рендерит `tabpanel` — это ответственность консьюмера (по `aria-controls`/внешней разметке).\n */\nconst props = withDefaults(defineProps<GrTabsProps>(), {\n idBase: undefined,\n size: undefined,\n // Дефолт живёт в резолвере: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n variant: undefined,\n activationMode: 'automatic',\n orientation: 'horizontal',\n closable: false,\n emptyText: undefined,\n})\n\ndefineSlots<{\n /** Содержимое вкладки целиком — вместо подписи, иконки и счётчика. Крестик остаётся. */\n tab?: (props: { tab: GrTab, active: boolean, disabled: boolean }) => unknown\n /** Пустой ряд — вместо текста из локали. */\n empty?: () => unknown\n}>()\n\nconst emit = defineEmits<GrTabsEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTabs' })\nconst resolvedVariant = useGrComponentProp('GrTabs', 'variant', () => props.variant, 'pills')\n\nconst tablistClass = computed(() => grTabsListClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n orientation: props.orientation,\n}))\n\nfunction tabClass(tab: GrTab): string {\n return grTabsTabClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n active: tab.value === props.modelValue,\n disabled: Boolean(tab.disabled),\n })\n}\n\nconst badgeClass = computed(() => grTabsBadgeClass(resolvedSize.value))\nconst closeClass = computed(() => grTabsCloseClass(resolvedSize.value))\nconst closeIconClass = computed(() => tabCloseIconSizes[resolvedSize.value])\nconst emptyClass = computed(() => grTabsEmptyClass(resolvedSize.value))\n\nconst isEmpty = computed(() => props.tabs.length === 0)\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.tabs.empty', 'Nothing here yet'))\nconst closeTitle = computed(() => t('gr.tabs.close', 'Close tab'))\n\n/** Отключённая вкладка не принимает взаимодействия, а закрытие — тоже взаимодействие. */\nfunction isClosable(tab: GrTab): boolean {\n return !tab.disabled && (tab.closable ?? props.closable)\n}\n\nconst buttonRefs = ref<HTMLButtonElement[]>([])\n\n/**\n * Vue зовёт ref-функцию с `null`, когда узел исчез. Игнорировать такой вызов\n * нельзя: в массиве оставались отсоединённые от DOM кнопки, и `focus()` по\n * сократившемуся списку молча проваливался в `<body>`.\n */\nfunction setButtonRef(el: unknown, index: number): void {\n if (el instanceof HTMLButtonElement)\n buttonRefs.value[index] = el\n else\n delete buttonRefs.value[index]\n\n if (buttonRefs.value.length > props.tabs.length)\n buttonRefs.value.length = props.tabs.length\n}\n\nconst activeIndex = computed(() => props.tabs.findIndex(t => t.value === props.modelValue))\n\nfunction isEnabled(tab: GrTab): boolean {\n return !tab.disabled\n}\n\nconst tabIndexes = computed(() => props.tabs.map((_, index) => index))\n\n/**\n * Кольцо roving-фокуса. При `activationMode: 'manual'` фокус уезжает вперёд\n * выбора — это и есть разница между `activeKey` примитива и `initialKey`:\n * первый ведёт фокус, второй подставляет выбранную вкладку, пока фокус не\n * трогали.\n *\n * Выбор стрелка **не** переносит: этим заведует `onKeydown` по\n * `activationMode`. Через `onMove` это выразить нельзя — клик тоже зовёт\n * `focusKey`, и выбор эмитился бы дважды.\n */\nconst roving = useRovingFocus<number>({\n items: () => tabIndexes.value,\n elementFor: index => buttonRefs.value[index],\n isDisabled: index => Boolean(props.tabs[index]?.disabled),\n orientation: () => (props.orientation === 'vertical' ? 'vertical' : 'horizontal'),\n skipDisabled: () => true,\n /**\n * Пока фокус не трогали, остановку `Tab` держит выбранная вкладка. Если\n * `modelValue` не совпал ни с одной (пустое начальное значение, асинхронный\n * список, удалённая активная вкладка), примитив ставит её на первую\n * доступную — иначе tablist выпал бы из обхода целиком и молча.\n *\n * Выключенность здесь не проверяется намеренно: на кнопке `aria-disabled`, а\n * не нативный `disabled`, поэтому выключенная вкладка фокусируется и держать\n * остановку вправе.\n */\n initialKey: () => (activeIndex.value >= 0 ? activeIndex.value : undefined),\n /**\n * Прокрутка до фокуса, а не после: иначе браузер доскроллит сам по-своему, и\n * ряд дёрнется дважды. Синхронно — фокус обязан остаться в том же такте, что\n * и раньше: тик, где он нужен, добавляет `focusIndex`.\n */\n beforeFocus: index => scrollIntoView(index),\n})\n\n/**\n * Фокус после перерисовки — для путей, где список только что изменился\n * (закрытие вкладки). Клавиатура идёт через примитив напрямую: там ряд уже\n * отрисован, и лишний тик только отложил бы фокус.\n */\nasync function focusIndex(index: number): Promise<void> {\n await nextTick()\n await roving.focusKey(index)\n}\n\n/**\n * Ряд прокручивается, а не переносится, поэтому активная вкладка может уехать\n * за край — например, когда её выбрали снаружи. `scrollIntoView` нет в jsdom и\n * в старых движках, поэтому вызов необязательный.\n */\nfunction scrollIntoView(index: number): void {\n buttonRefs.value[index]?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' })\n}\n\nwatch(() => props.modelValue, async () => {\n await nextTick()\n if (activeIndex.value >= 0)\n scrollIntoView(activeIndex.value)\n})\n\nasync function selectByIndex(index: number, focus = false): Promise<void> {\n const tab = props.tabs[index]\n if (!tab || !isEnabled(tab))\n return\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n if (focus)\n await focusIndex(index)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.tabs.length === 0)\n return\n\n const currentIndex = roving.rovingKey.value ?? 0\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n // В ручном режиме выбор подтверждается явно — на той вкладке, где фокус.\n if (props.activationMode === 'manual') {\n event.preventDefault()\n void selectByIndex(currentIndex, false)\n }\n return\n case 'Delete':\n case 'Backspace': {\n // Единственный клавиатурный путь к закрытию: крестик в таб-порядке не стоит.\n const tab = props.tabs[currentIndex]\n if (tab && isClosable(tab)) {\n event.preventDefault()\n requestClose(currentIndex)\n }\n return\n }\n }\n\n // Стрелки, `Home`, `End` — фокус ведёт примитив по объявленной ориентации.\n if (!roving.handleNavigationKeys(event))\n return\n\n // `automatic`: выбор едет за фокусом. `manual`: ждёт `Enter`/`Space`.\n if (props.activationMode !== 'manual')\n void selectByIndex(roving.rovingKey.value ?? currentIndex, false)\n}\n\n/**\n * Закрытая вкладка, которая держала фокус. Компонент список не укорачивает —\n * это делает потребитель, — поэтому фокус возвращается только после того, как\n * `tabs` действительно стал короче.\n */\nlet pendingClose: { index: number, value: string } | null = null\n\nfunction requestClose(index: number): void {\n const tab = props.tabs[index]\n if (!tab || !isClosable(tab))\n return\n\n const held = buttonRefs.value[index] === document.activeElement\n pendingClose = held ? { index, value: tab.value } : null\n\n emit('close', tab.value)\n}\n\n// Без этого клавиатурное закрытие роняет фокус в `<body>`: кнопка, на которой\n// он стоял, исчезает из DOM вместе со вкладкой.\nwatch(() => props.tabs.length, async (next, prev) => {\n const pending = pendingClose\n pendingClose = null\n\n if (!pending || next >= prev)\n return\n // Ушла не та вкладка — потребитель поменял список по своей причине.\n if (props.tabs.some(tab => tab.value === pending.value))\n return\n\n await nextTick()\n\n const target = Math.min(pending.index, next - 1)\n if (target >= 0)\n void focusIndex(target)\n else\n roving.reset()\n})\n\nfunction onClick(event: MouseEvent, tab: GrTab, index: number): void {\n if (!isEnabled(tab))\n return\n\n // Крестик — не кнопка, поэтому его клик приходит сюда же и разбирается по цели.\n if (event.target instanceof Element && event.target.closest('[data-gr-tab-close]')) {\n requestClose(index)\n return\n }\n\n roving.setActive(index)\n\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n}\n</script>\n\n<template>\n <!--\n Пустой ряд — не пустой `tablist`: роль обязана владеть потомками `tab`,\n и текст внутри неё был бы нарушением, а не пустым состоянием.\n -->\n <div v-if=\"isEmpty\" data-gr-tabs-empty :class=\"emptyClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-else\n role=\"tablist\"\n data-gr-tabs\n :aria-orientation=\"orientation\"\n :class=\"tablistClass\"\n @keydown=\"onKeydown\"\n >\n <button\n v-for=\"(tab, index) in tabs\"\n :id=\"idBase ? `${idBase}-tab-${tab.value}` : undefined\"\n :key=\"tab.value\"\n :ref=\"el => setButtonRef(el, index)\"\n type=\"button\"\n role=\"tab\"\n data-gr-tab\n :aria-controls=\"idBase ? `${idBase}-panel-${tab.value}` : undefined\"\n :aria-selected=\"tab.value === modelValue ? 'true' : 'false'\"\n :aria-disabled=\"tab.disabled ? 'true' : undefined\"\n :aria-keyshortcuts=\"isClosable(tab) ? 'Delete' : undefined\"\n :tabindex=\"roving.tabindexFor(index)\"\n :class=\"tabClass(tab)\"\n @click=\"onClick($event, tab, index)\"\n >\n <span :class=\"tabContentClass\">\n <slot\n name=\"tab\"\n :tab=\"tab\"\n :active=\"tab.value === modelValue\"\n :disabled=\"Boolean(tab.disabled)\"\n >\n <component\n :is=\"iconTag(tab.icon)\"\n v-if=\"tab.icon\"\n :class=\"[tabIconClass, iconClass(tab.icon)]\"\n aria-hidden=\"true\"\n />\n <span>{{ tab.label }}</span>\n <span v-if=\"tab.badge\" :class=\"badgeClass\">\n {{ tab.badge }}\n </span>\n </slot>\n\n <!-- Снаружи слота: своя разметка вкладки не должна отнимать закрытие. -->\n <span\n v-if=\"isClosable(tab)\"\n data-gr-tab-close\n :class=\"closeClass\"\n :title=\"closeTitle\"\n aria-hidden=\"true\"\n >\n <IconX :class=\"closeIconClass\" />\n </span>\n </span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch, type Component } from 'vue'\n\nimport IconX from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { iconClass, iconTag } from '../shared/icon'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport {\n grTabsBadgeClass,\n grTabsCloseClass,\n grTabsEmptyClass,\n grTabsListClass,\n grTabsTabClass,\n tabCloseIconSizes,\n tabContentClass,\n tabIconClass,\n type GrTabsOrientation,\n type GrTabsSize,\n type GrTabsVariant,\n} from './grTabsStyles'\n\nexport interface GrTab {\n value: string\n label: string\n badge?: string\n /**\n * Иконка слева от подписи: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-user'` — тогда нужен ваш `presetIcons`, см. `docs/installation.md`).\n */\n icon?: string | Component\n disabled?: boolean\n /** Перекрывает `closable` ряда в обе стороны: закрепить вкладку или закрыть одну её. */\n closable?: boolean\n}\n\nexport interface GrTabsProps {\n modelValue: string\n tabs: GrTab[]\n /**\n * База id для ARIA-связки с `GrTabPanels`. Если задана, каждая вкладка\n * получает `id=\"<idBase>-tab-<value>\"` и `aria-controls=\"<idBase>-panel-<value>\"`.\n * Передайте тот же `idBase` в `GrTabPanels`, чтобы связать `tab`↔`tabpanel`.\n */\n idBase?: string\n size?: GrTabsSize\n /** Вид ряда: обойма с таблетками или ряд с подчёркиванием. */\n variant?: GrTabsVariant\n /**\n * `automatic` (по умолчанию) — стрелка сразу переключает вкладку;\n * `manual` — стрелка двигает только фокус, выбор подтверждается\n * `Enter`/`Space`. Второй режим для вкладок с тяжёлой загрузкой: перебор\n * стрелками иначе тянет каждую панель.\n */\n activationMode?: GrTabsActivationMode\n /** Горизонтальный (по умолчанию) или вертикальный список вкладок. */\n orientation?: GrTabsOrientation\n /**\n * Крестик на вкладках и закрытие по `Delete`/`Backspace`. Точечно снимается\n * `closable: false` у самой вкладки.\n */\n closable?: boolean\n /** Текст, когда список вкладок пуст. Слот `#empty` сильнее. */\n emptyText?: string\n}\n\nexport interface GrTabsEmits {\n (e: 'update:modelValue', value: string): void\n /**\n * Просьба закрыть вкладку. Компонент список не трогает: `tabs` — проп, и\n * закрытие может не состояться («сохранить изменения?»).\n */\n (e: 'close', value: string): void\n}\n\nexport type GrTabsActivationMode = 'automatic' | 'manual'\n\nexport type { GrTabsOrientation, GrTabsVariant } from './grTabsStyles'\n\n/**\n * GrTabs — горизонтальная группа вкладок с паттерном WAI-ARIA `tablist`.\n *\n * A11y:\n * - `role=\"tablist\"` на корне, `role=\"tab\"` на каждой вкладке.\n * - Roving `tabindex`: активная вкладка `0`, остальные `-1`.\n * - Клавиатура: `ArrowLeft`/`ArrowRight` — цикличный переход, `Home`/`End` — к первой/последней.\n * - При переключении стрелками DOM-фокус программно переносится на новую вкладку.\n *\n * Сам компонент не рендерит `tabpanel` — это ответственность консьюмера (по `aria-controls`/внешней разметке).\n */\nconst props = withDefaults(defineProps<GrTabsProps>(), {\n idBase: undefined,\n size: undefined,\n // Дефолт живёт в резолвере: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n variant: undefined,\n activationMode: 'automatic',\n orientation: 'horizontal',\n closable: false,\n emptyText: undefined,\n})\n\ndefineSlots<{\n /** Содержимое вкладки целиком — вместо подписи, иконки и счётчика. Крестик остаётся. */\n tab?: (props: { tab: GrTab, active: boolean, disabled: boolean }) => unknown\n /** Пустой ряд — вместо текста из локали. */\n empty?: () => unknown\n}>()\n\nconst emit = defineEmits<GrTabsEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTabs' })\nconst resolvedVariant = useGrComponentProp('GrTabs', 'variant', () => props.variant, 'pills')\n\nconst tablistClass = computed(() => grTabsListClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n orientation: props.orientation,\n}))\n\nfunction tabClass(tab: GrTab): string {\n return grTabsTabClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n active: tab.value === props.modelValue,\n disabled: Boolean(tab.disabled),\n })\n}\n\nconst badgeClass = computed(() => grTabsBadgeClass(resolvedSize.value))\nconst closeClass = computed(() => grTabsCloseClass(resolvedSize.value))\nconst closeIconClass = computed(() => tabCloseIconSizes[resolvedSize.value])\nconst emptyClass = computed(() => grTabsEmptyClass(resolvedSize.value))\n\nconst isEmpty = computed(() => props.tabs.length === 0)\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.tabs.empty', 'Nothing here yet'))\nconst closeTitle = computed(() => t('gr.tabs.close', 'Close tab'))\n\n/** Отключённая вкладка не принимает взаимодействия, а закрытие — тоже взаимодействие. */\nfunction isClosable(tab: GrTab): boolean {\n return !tab.disabled && (tab.closable ?? props.closable)\n}\n\nconst buttonRefs = ref<HTMLButtonElement[]>([])\n\n/**\n * Vue зовёт ref-функцию с `null`, когда узел исчез. Игнорировать такой вызов\n * нельзя: в массиве оставались отсоединённые от DOM кнопки, и `focus()` по\n * сократившемуся списку молча проваливался в `<body>`.\n */\nfunction setButtonRef(el: unknown, index: number): void {\n if (el instanceof HTMLButtonElement)\n buttonRefs.value[index] = el\n else\n delete buttonRefs.value[index]\n\n if (buttonRefs.value.length > props.tabs.length)\n buttonRefs.value.length = props.tabs.length\n}\n\nconst activeIndex = computed(() => props.tabs.findIndex(t => t.value === props.modelValue))\n\nfunction isEnabled(tab: GrTab): boolean {\n return !tab.disabled\n}\n\nconst tabIndexes = computed(() => props.tabs.map((_, index) => index))\n\n/**\n * Кольцо roving-фокуса. При `activationMode: 'manual'` фокус уезжает вперёд\n * выбора — это и есть разница между `activeKey` примитива и `initialKey`:\n * первый ведёт фокус, второй подставляет выбранную вкладку, пока фокус не\n * трогали.\n *\n * Выбор стрелка **не** переносит: этим заведует `onKeydown` по\n * `activationMode`. Через `onMove` это выразить нельзя — клик тоже зовёт\n * `focusKey`, и выбор эмитился бы дважды.\n */\nconst roving = useRovingFocus<number>({\n items: () => tabIndexes.value,\n elementFor: index => buttonRefs.value[index],\n isDisabled: index => Boolean(props.tabs[index]?.disabled),\n orientation: () => (props.orientation === 'vertical' ? 'vertical' : 'horizontal'),\n skipDisabled: () => true,\n /**\n * Пока фокус не трогали, остановку `Tab` держит выбранная вкладка. Если\n * `modelValue` не совпал ни с одной (пустое начальное значение, асинхронный\n * список, удалённая активная вкладка), примитив ставит её на первую\n * доступную — иначе tablist выпал бы из обхода целиком и молча.\n *\n * Выключенность здесь не проверяется намеренно: на кнопке `aria-disabled`, а\n * не нативный `disabled`, поэтому выключенная вкладка фокусируется и держать\n * остановку вправе.\n */\n initialKey: () => (activeIndex.value >= 0 ? activeIndex.value : undefined),\n /**\n * Прокрутка до фокуса, а не после: иначе браузер доскроллит сам по-своему, и\n * ряд дёрнется дважды. Синхронно — фокус обязан остаться в том же такте, что\n * и раньше: тик, где он нужен, добавляет `focusIndex`.\n */\n beforeFocus: index => scrollIntoView(index),\n})\n\n/**\n * Фокус после перерисовки — для путей, где список только что изменился\n * (закрытие вкладки). Клавиатура идёт через примитив напрямую: там ряд уже\n * отрисован, и лишний тик только отложил бы фокус.\n */\nasync function focusIndex(index: number): Promise<void> {\n await nextTick()\n await roving.focusKey(index)\n}\n\n/**\n * Ряд прокручивается, а не переносится, поэтому активная вкладка может уехать\n * за край — например, когда её выбрали снаружи. `scrollIntoView` нет в jsdom и\n * в старых движках, поэтому вызов необязательный.\n */\nfunction scrollIntoView(index: number): void {\n buttonRefs.value[index]?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' })\n}\n\nwatch(() => props.modelValue, async () => {\n await nextTick()\n if (activeIndex.value >= 0)\n scrollIntoView(activeIndex.value)\n})\n\nasync function selectByIndex(index: number, focus = false): Promise<void> {\n const tab = props.tabs[index]\n if (!tab || !isEnabled(tab))\n return\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n if (focus)\n await focusIndex(index)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.tabs.length === 0)\n return\n\n const currentIndex = roving.rovingKey.value ?? 0\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n // В ручном режиме выбор подтверждается явно — на той вкладке, где фокус.\n if (props.activationMode === 'manual') {\n event.preventDefault()\n void selectByIndex(currentIndex, false)\n }\n return\n case 'Delete':\n case 'Backspace': {\n // Единственный клавиатурный путь к закрытию: крестик в таб-порядке не стоит.\n const tab = props.tabs[currentIndex]\n if (tab && isClosable(tab)) {\n event.preventDefault()\n requestClose(currentIndex)\n }\n return\n }\n }\n\n // Стрелки, `Home`, `End` — фокус ведёт примитив по объявленной ориентации.\n if (!roving.handleNavigationKeys(event))\n return\n\n // `automatic`: выбор едет за фокусом. `manual`: ждёт `Enter`/`Space`.\n if (props.activationMode !== 'manual')\n void selectByIndex(roving.rovingKey.value ?? currentIndex, false)\n}\n\n/**\n * Закрытая вкладка, которая держала фокус. Компонент список не укорачивает —\n * это делает потребитель, — поэтому фокус возвращается только после того, как\n * `tabs` действительно стал короче.\n */\nlet pendingClose: { index: number, value: string } | null = null\n\nfunction requestClose(index: number): void {\n const tab = props.tabs[index]\n if (!tab || !isClosable(tab))\n return\n\n const held = buttonRefs.value[index] === document.activeElement\n pendingClose = held ? { index, value: tab.value } : null\n\n emit('close', tab.value)\n}\n\n// Без этого клавиатурное закрытие роняет фокус в `<body>`: кнопка, на которой\n// он стоял, исчезает из DOM вместе со вкладкой.\nwatch(() => props.tabs.length, async (next, prev) => {\n const pending = pendingClose\n pendingClose = null\n\n if (!pending || next >= prev)\n return\n // Ушла не та вкладка — потребитель поменял список по своей причине.\n if (props.tabs.some(tab => tab.value === pending.value))\n return\n\n await nextTick()\n\n const target = Math.min(pending.index, next - 1)\n if (target >= 0)\n void focusIndex(target)\n else\n roving.reset()\n})\n\nfunction onClick(event: MouseEvent, tab: GrTab, index: number): void {\n if (!isEnabled(tab))\n return\n\n // Крестик — не кнопка, поэтому его клик приходит сюда же и разбирается по цели.\n if (event.target instanceof Element && event.target.closest('[data-gr-tab-close]')) {\n requestClose(index)\n return\n }\n\n roving.setActive(index)\n\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n}\n</script>\n\n<template>\n <!--\n Пустой ряд — не пустой `tablist`: роль обязана владеть потомками `tab`,\n и текст внутри неё был бы нарушением, а не пустым состоянием.\n -->\n <div v-if=\"isEmpty\" data-gr-tabs-empty :class=\"emptyClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-else\n role=\"tablist\"\n data-gr-tabs\n :aria-orientation=\"orientation\"\n :class=\"tablistClass\"\n @keydown=\"onKeydown\"\n >\n <button\n v-for=\"(tab, index) in tabs\"\n :id=\"idBase ? `${idBase}-tab-${tab.value}` : undefined\"\n :key=\"tab.value\"\n :ref=\"el => setButtonRef(el, index)\"\n type=\"button\"\n role=\"tab\"\n data-gr-tab\n :aria-controls=\"idBase ? `${idBase}-panel-${tab.value}` : undefined\"\n :aria-selected=\"tab.value === modelValue ? 'true' : 'false'\"\n :aria-disabled=\"tab.disabled ? 'true' : undefined\"\n :aria-keyshortcuts=\"isClosable(tab) ? 'Delete' : undefined\"\n :tabindex=\"roving.tabindexFor(index)\"\n :class=\"tabClass(tab)\"\n @click=\"onClick($event, tab, index)\"\n >\n <span :class=\"tabContentClass\">\n <slot\n name=\"tab\"\n :tab=\"tab\"\n :active=\"tab.value === modelValue\"\n :disabled=\"Boolean(tab.disabled)\"\n >\n <component\n :is=\"iconTag(tab.icon)\"\n v-if=\"tab.icon\"\n :class=\"[tabIconClass, iconClass(tab.icon)]\"\n aria-hidden=\"true\"\n />\n <span>{{ tab.label }}</span>\n <span v-if=\"tab.badge\" :class=\"badgeClass\">\n {{ tab.badge }}\n </span>\n </slot>\n\n <!-- Снаружи слота: своя разметка вкладки не должна отнимать закрытие. -->\n <span\n v-if=\"isClosable(tab)\"\n data-gr-tab-close\n :class=\"closeClass\"\n :title=\"closeTitle\"\n aria-hidden=\"true\"\n >\n <IconX :class=\"closeIconClass\" />\n </span>\n </span>\n </button>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrTabs-ugDnkk-2.js","names":[],"sources":["../../../../src/components/GrTabs/GrTabs.vue","../../../../src/components/GrTabs/GrTabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch, type Component } from 'vue'\n\nimport IconX from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { iconClass, iconTag } from '../shared/icon'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport {\n grTabsBadgeClass,\n grTabsCloseClass,\n grTabsEmptyClass,\n grTabsListClass,\n grTabsTabClass,\n tabCloseIconSizes,\n tabContentClass,\n tabIconClass,\n type GrTabsOrientation,\n type GrTabsSize,\n type GrTabsVariant,\n} from './grTabsStyles'\n\nexport interface GrTab {\n value: string\n label: string\n badge?: string\n /**\n * Иконка слева от подписи: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-user'` — тогда нужен ваш `presetIcons`, см. `docs/installation.md`).\n */\n icon?: string | Component\n disabled?: boolean\n /** Перекрывает `closable` ряда в обе стороны: закрепить вкладку или закрыть одну её. */\n closable?: boolean\n}\n\nexport interface GrTabsProps {\n modelValue: string\n tabs: GrTab[]\n /**\n * База id для ARIA-связки с `GrTabPanels`. Если задана, каждая вкладка\n * получает `id=\"<idBase>-tab-<value>\"` и `aria-controls=\"<idBase>-panel-<value>\"`.\n * Передайте тот же `idBase` в `GrTabPanels`, чтобы связать `tab`↔`tabpanel`.\n */\n idBase?: string\n size?: GrTabsSize\n /** Вид ряда: обойма с таблетками или ряд с подчёркиванием. */\n variant?: GrTabsVariant\n /**\n * `automatic` (по умолчанию) — стрелка сразу переключает вкладку;\n * `manual` — стрелка двигает только фокус, выбор подтверждается\n * `Enter`/`Space`. Второй режим для вкладок с тяжёлой загрузкой: перебор\n * стрелками иначе тянет каждую панель.\n */\n activationMode?: GrTabsActivationMode\n /** Горизонтальный (по умолчанию) или вертикальный список вкладок. */\n orientation?: GrTabsOrientation\n /**\n * Крестик на вкладках и закрытие по `Delete`/`Backspace`. Точечно снимается\n * `closable: false` у самой вкладки.\n */\n closable?: boolean\n /** Текст, когда список вкладок пуст. Слот `#empty` сильнее. */\n emptyText?: string\n}\n\nexport interface GrTabsEmits {\n (e: 'update:modelValue', value: string): void\n /**\n * Просьба закрыть вкладку. Компонент список не трогает: `tabs` — проп, и\n * закрытие может не состояться («сохранить изменения?»).\n */\n (e: 'close', value: string): void\n}\n\nexport type GrTabsActivationMode = 'automatic' | 'manual'\n\nexport type { GrTabsOrientation, GrTabsVariant } from './grTabsStyles'\n\n/**\n * GrTabs — горизонтальная группа вкладок с паттерном WAI-ARIA `tablist`.\n *\n * A11y:\n * - `role=\"tablist\"` на корне, `role=\"tab\"` на каждой вкладке.\n * - Roving `tabindex`: активная вкладка `0`, остальные `-1`.\n * - Клавиатура: `ArrowLeft`/`ArrowRight` — цикличный переход, `Home`/`End` — к первой/последней.\n * - При переключении стрелками DOM-фокус программно переносится на новую вкладку.\n *\n * Сам компонент не рендерит `tabpanel` — это ответственность консьюмера (по `aria-controls`/внешней разметке).\n */\nconst props = withDefaults(defineProps<GrTabsProps>(), {\n idBase: undefined,\n size: undefined,\n // Дефолт живёт в резолвере: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n variant: undefined,\n activationMode: 'automatic',\n orientation: 'horizontal',\n closable: false,\n emptyText: undefined,\n})\n\ndefineSlots<{\n /** Содержимое вкладки целиком — вместо подписи, иконки и счётчика. Крестик остаётся. */\n tab?: (props: { tab: GrTab, active: boolean, disabled: boolean }) => unknown\n /** Пустой ряд — вместо текста из локали. */\n empty?: () => unknown\n}>()\n\nconst emit = defineEmits<GrTabsEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTabs' })\nconst resolvedVariant = useGrComponentProp('GrTabs', 'variant', () => props.variant, 'pills')\n\nconst tablistClass = computed(() => grTabsListClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n orientation: props.orientation,\n}))\n\nfunction tabClass(tab: GrTab): string {\n return grTabsTabClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n active: tab.value === props.modelValue,\n disabled: Boolean(tab.disabled),\n })\n}\n\nconst badgeClass = computed(() => grTabsBadgeClass(resolvedSize.value))\nconst closeClass = computed(() => grTabsCloseClass(resolvedSize.value))\nconst closeIconClass = computed(() => tabCloseIconSizes[resolvedSize.value])\nconst emptyClass = computed(() => grTabsEmptyClass(resolvedSize.value))\n\nconst isEmpty = computed(() => props.tabs.length === 0)\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.tabs.empty', 'Nothing here yet'))\nconst closeTitle = computed(() => t('gr.tabs.close', 'Close tab'))\n\n/** Отключённая вкладка не принимает взаимодействия, а закрытие — тоже взаимодействие. */\nfunction isClosable(tab: GrTab): boolean {\n return !tab.disabled && (tab.closable ?? props.closable)\n}\n\nconst buttonRefs = ref<HTMLButtonElement[]>([])\n\n/**\n * Vue зовёт ref-функцию с `null`, когда узел исчез. Игнорировать такой вызов\n * нельзя: в массиве оставались отсоединённые от DOM кнопки, и `focus()` по\n * сократившемуся списку молча проваливался в `<body>`.\n */\nfunction setButtonRef(el: unknown, index: number): void {\n if (el instanceof HTMLButtonElement)\n buttonRefs.value[index] = el\n else\n delete buttonRefs.value[index]\n\n if (buttonRefs.value.length > props.tabs.length)\n buttonRefs.value.length = props.tabs.length\n}\n\nconst activeIndex = computed(() => props.tabs.findIndex(t => t.value === props.modelValue))\n\nfunction isEnabled(tab: GrTab): boolean {\n return !tab.disabled\n}\n\nconst tabIndexes = computed(() => props.tabs.map((_, index) => index))\n\n/**\n * Кольцо roving-фокуса. При `activationMode: 'manual'` фокус уезжает вперёд\n * выбора — это и есть разница между `activeKey` примитива и `initialKey`:\n * первый ведёт фокус, второй подставляет выбранную вкладку, пока фокус не\n * трогали.\n *\n * Выбор стрелка **не** переносит: этим заведует `onKeydown` по\n * `activationMode`. Через `onMove` это выразить нельзя — клик тоже зовёт\n * `focusKey`, и выбор эмитился бы дважды.\n */\nconst roving = useRovingFocus<number>({\n items: () => tabIndexes.value,\n elementFor: index => buttonRefs.value[index],\n isDisabled: index => Boolean(props.tabs[index]?.disabled),\n orientation: () => (props.orientation === 'vertical' ? 'vertical' : 'horizontal'),\n skipDisabled: () => true,\n /**\n * Пока фокус не трогали, остановку `Tab` держит выбранная вкладка. Если\n * `modelValue` не совпал ни с одной (пустое начальное значение, асинхронный\n * список, удалённая активная вкладка), примитив ставит её на первую\n * доступную — иначе tablist выпал бы из обхода целиком и молча.\n *\n * Выключенность здесь не проверяется намеренно: на кнопке `aria-disabled`, а\n * не нативный `disabled`, поэтому выключенная вкладка фокусируется и держать\n * остановку вправе.\n */\n initialKey: () => (activeIndex.value >= 0 ? activeIndex.value : undefined),\n /**\n * Прокрутка до фокуса, а не после: иначе браузер доскроллит сам по-своему, и\n * ряд дёрнется дважды. Синхронно — фокус обязан остаться в том же такте, что\n * и раньше: тик, где он нужен, добавляет `focusIndex`.\n */\n beforeFocus: index => scrollIntoView(index),\n})\n\n/**\n * Фокус после перерисовки — для путей, где список только что изменился\n * (закрытие вкладки). Клавиатура идёт через примитив напрямую: там ряд уже\n * отрисован, и лишний тик только отложил бы фокус.\n */\nasync function focusIndex(index: number): Promise<void> {\n await nextTick()\n await roving.focusKey(index)\n}\n\n/**\n * Ряд прокручивается, а не переносится, поэтому активная вкладка может уехать\n * за край — например, когда её выбрали снаружи. `scrollIntoView` нет в jsdom и\n * в старых движках, поэтому вызов необязательный.\n */\nfunction scrollIntoView(index: number): void {\n buttonRefs.value[index]?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' })\n}\n\nwatch(() => props.modelValue, async () => {\n await nextTick()\n if (activeIndex.value >= 0)\n scrollIntoView(activeIndex.value)\n})\n\nasync function selectByIndex(index: number, focus = false): Promise<void> {\n const tab = props.tabs[index]\n if (!tab || !isEnabled(tab))\n return\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n if (focus)\n await focusIndex(index)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.tabs.length === 0)\n return\n\n const currentIndex = roving.rovingKey.value ?? 0\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n // В ручном режиме выбор подтверждается явно — на той вкладке, где фокус.\n if (props.activationMode === 'manual') {\n event.preventDefault()\n void selectByIndex(currentIndex, false)\n }\n return\n case 'Delete':\n case 'Backspace': {\n // Единственный клавиатурный путь к закрытию: крестик в таб-порядке не стоит.\n const tab = props.tabs[currentIndex]\n if (tab && isClosable(tab)) {\n event.preventDefault()\n requestClose(currentIndex)\n }\n return\n }\n }\n\n // Стрелки, `Home`, `End` — фокус ведёт примитив по объявленной ориентации.\n if (!roving.handleNavigationKeys(event))\n return\n\n // `automatic`: выбор едет за фокусом. `manual`: ждёт `Enter`/`Space`.\n if (props.activationMode !== 'manual')\n void selectByIndex(roving.rovingKey.value ?? currentIndex, false)\n}\n\n/**\n * Закрытая вкладка, которая держала фокус. Компонент список не укорачивает —\n * это делает потребитель, — поэтому фокус возвращается только после того, как\n * `tabs` действительно стал короче.\n */\nlet pendingClose: { index: number, value: string } | null = null\n\nfunction requestClose(index: number): void {\n const tab = props.tabs[index]\n if (!tab || !isClosable(tab))\n return\n\n const held = buttonRefs.value[index] === document.activeElement\n pendingClose = held ? { index, value: tab.value } : null\n\n emit('close', tab.value)\n}\n\n// Без этого клавиатурное закрытие роняет фокус в `<body>`: кнопка, на которой\n// он стоял, исчезает из DOM вместе со вкладкой.\nwatch(() => props.tabs.length, async (next, prev) => {\n const pending = pendingClose\n pendingClose = null\n\n if (!pending || next >= prev)\n return\n // Ушла не та вкладка — потребитель поменял список по своей причине.\n if (props.tabs.some(tab => tab.value === pending.value))\n return\n\n await nextTick()\n\n const target = Math.min(pending.index, next - 1)\n if (target >= 0)\n void focusIndex(target)\n else\n roving.reset()\n})\n\nfunction onClick(event: MouseEvent, tab: GrTab, index: number): void {\n if (!isEnabled(tab))\n return\n\n // Крестик — не кнопка, поэтому его клик приходит сюда же и разбирается по цели.\n if (event.target instanceof Element && event.target.closest('[data-gr-tab-close]')) {\n requestClose(index)\n return\n }\n\n roving.setActive(index)\n\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n}\n</script>\n\n<template>\n <!--\n Пустой ряд — не пустой `tablist`: роль обязана владеть потомками `tab`,\n и текст внутри неё был бы нарушением, а не пустым состоянием.\n -->\n <div v-if=\"isEmpty\" data-gr-tabs-empty :class=\"emptyClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-else\n role=\"tablist\"\n data-gr-tabs\n :aria-orientation=\"orientation\"\n :class=\"tablistClass\"\n @keydown=\"onKeydown\"\n >\n <button\n v-for=\"(tab, index) in tabs\"\n :id=\"idBase ? `${idBase}-tab-${tab.value}` : undefined\"\n :key=\"tab.value\"\n :ref=\"el => setButtonRef(el, index)\"\n type=\"button\"\n role=\"tab\"\n data-gr-tab\n :aria-controls=\"idBase ? `${idBase}-panel-${tab.value}` : undefined\"\n :aria-selected=\"tab.value === modelValue ? 'true' : 'false'\"\n :aria-disabled=\"tab.disabled ? 'true' : undefined\"\n :aria-keyshortcuts=\"isClosable(tab) ? 'Delete' : undefined\"\n :tabindex=\"roving.tabindexFor(index)\"\n :class=\"tabClass(tab)\"\n @click=\"onClick($event, tab, index)\"\n >\n <span :class=\"tabContentClass\">\n <slot\n name=\"tab\"\n :tab=\"tab\"\n :active=\"tab.value === modelValue\"\n :disabled=\"Boolean(tab.disabled)\"\n >\n <component\n :is=\"iconTag(tab.icon)\"\n v-if=\"tab.icon\"\n :class=\"[tabIconClass, iconClass(tab.icon)]\"\n aria-hidden=\"true\"\n />\n <span>{{ tab.label }}</span>\n <span v-if=\"tab.badge\" :class=\"badgeClass\">\n {{ tab.badge }}\n </span>\n </slot>\n\n <!-- Снаружи слота: своя разметка вкладки не должна отнимать закрытие. -->\n <span\n v-if=\"isClosable(tab)\"\n data-gr-tab-close\n :class=\"closeClass\"\n :title=\"closeTitle\"\n aria-hidden=\"true\"\n >\n <IconX :class=\"closeIconClass\" />\n </span>\n </span>\n </button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch, type Component } from 'vue'\n\nimport IconX from '~icons/lucide/x'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useRovingFocus } from '../../composables/useRovingFocus'\nimport { iconClass, iconTag } from '../shared/icon'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport {\n grTabsBadgeClass,\n grTabsCloseClass,\n grTabsEmptyClass,\n grTabsListClass,\n grTabsTabClass,\n tabCloseIconSizes,\n tabContentClass,\n tabIconClass,\n type GrTabsOrientation,\n type GrTabsSize,\n type GrTabsVariant,\n} from './grTabsStyles'\n\nexport interface GrTab {\n value: string\n label: string\n badge?: string\n /**\n * Иконка слева от подписи: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-user'` — тогда нужен ваш `presetIcons`, см. `docs/installation.md`).\n */\n icon?: string | Component\n disabled?: boolean\n /** Перекрывает `closable` ряда в обе стороны: закрепить вкладку или закрыть одну её. */\n closable?: boolean\n}\n\nexport interface GrTabsProps {\n modelValue: string\n tabs: GrTab[]\n /**\n * База id для ARIA-связки с `GrTabPanels`. Если задана, каждая вкладка\n * получает `id=\"<idBase>-tab-<value>\"` и `aria-controls=\"<idBase>-panel-<value>\"`.\n * Передайте тот же `idBase` в `GrTabPanels`, чтобы связать `tab`↔`tabpanel`.\n */\n idBase?: string\n size?: GrTabsSize\n /** Вид ряда: обойма с таблетками или ряд с подчёркиванием. */\n variant?: GrTabsVariant\n /**\n * `automatic` (по умолчанию) — стрелка сразу переключает вкладку;\n * `manual` — стрелка двигает только фокус, выбор подтверждается\n * `Enter`/`Space`. Второй режим для вкладок с тяжёлой загрузкой: перебор\n * стрелками иначе тянет каждую панель.\n */\n activationMode?: GrTabsActivationMode\n /** Горизонтальный (по умолчанию) или вертикальный список вкладок. */\n orientation?: GrTabsOrientation\n /**\n * Крестик на вкладках и закрытие по `Delete`/`Backspace`. Точечно снимается\n * `closable: false` у самой вкладки.\n */\n closable?: boolean\n /** Текст, когда список вкладок пуст. Слот `#empty` сильнее. */\n emptyText?: string\n}\n\nexport interface GrTabsEmits {\n (e: 'update:modelValue', value: string): void\n /**\n * Просьба закрыть вкладку. Компонент список не трогает: `tabs` — проп, и\n * закрытие может не состояться («сохранить изменения?»).\n */\n (e: 'close', value: string): void\n}\n\nexport type GrTabsActivationMode = 'automatic' | 'manual'\n\nexport type { GrTabsOrientation, GrTabsVariant } from './grTabsStyles'\n\n/**\n * GrTabs — горизонтальная группа вкладок с паттерном WAI-ARIA `tablist`.\n *\n * A11y:\n * - `role=\"tablist\"` на корне, `role=\"tab\"` на каждой вкладке.\n * - Roving `tabindex`: активная вкладка `0`, остальные `-1`.\n * - Клавиатура: `ArrowLeft`/`ArrowRight` — цикличный переход, `Home`/`End` — к первой/последней.\n * - При переключении стрелками DOM-фокус программно переносится на новую вкладку.\n *\n * Сам компонент не рендерит `tabpanel` — это ответственность консьюмера (по `aria-controls`/внешней разметке).\n */\nconst props = withDefaults(defineProps<GrTabsProps>(), {\n idBase: undefined,\n size: undefined,\n // Дефолт живёт в резолвере: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n variant: undefined,\n activationMode: 'automatic',\n orientation: 'horizontal',\n closable: false,\n emptyText: undefined,\n})\n\ndefineSlots<{\n /** Содержимое вкладки целиком — вместо подписи, иконки и счётчика. Крестик остаётся. */\n tab?: (props: { tab: GrTab, active: boolean, disabled: boolean }) => unknown\n /** Пустой ряд — вместо текста из локали. */\n empty?: () => unknown\n}>()\n\nconst emit = defineEmits<GrTabsEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrTabs' })\nconst resolvedVariant = useGrComponentProp('GrTabs', 'variant', () => props.variant, 'pills')\n\nconst tablistClass = computed(() => grTabsListClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n orientation: props.orientation,\n}))\n\nfunction tabClass(tab: GrTab): string {\n return grTabsTabClass({\n variant: resolvedVariant.value,\n size: resolvedSize.value,\n active: tab.value === props.modelValue,\n disabled: Boolean(tab.disabled),\n })\n}\n\nconst badgeClass = computed(() => grTabsBadgeClass(resolvedSize.value))\nconst closeClass = computed(() => grTabsCloseClass(resolvedSize.value))\nconst closeIconClass = computed(() => tabCloseIconSizes[resolvedSize.value])\nconst emptyClass = computed(() => grTabsEmptyClass(resolvedSize.value))\n\nconst isEmpty = computed(() => props.tabs.length === 0)\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.tabs.empty', 'Nothing here yet'))\nconst closeTitle = computed(() => t('gr.tabs.close', 'Close tab'))\n\n/** Отключённая вкладка не принимает взаимодействия, а закрытие — тоже взаимодействие. */\nfunction isClosable(tab: GrTab): boolean {\n return !tab.disabled && (tab.closable ?? props.closable)\n}\n\nconst buttonRefs = ref<HTMLButtonElement[]>([])\n\n/**\n * Vue зовёт ref-функцию с `null`, когда узел исчез. Игнорировать такой вызов\n * нельзя: в массиве оставались отсоединённые от DOM кнопки, и `focus()` по\n * сократившемуся списку молча проваливался в `<body>`.\n */\nfunction setButtonRef(el: unknown, index: number): void {\n if (el instanceof HTMLButtonElement)\n buttonRefs.value[index] = el\n else\n delete buttonRefs.value[index]\n\n if (buttonRefs.value.length > props.tabs.length)\n buttonRefs.value.length = props.tabs.length\n}\n\nconst activeIndex = computed(() => props.tabs.findIndex(t => t.value === props.modelValue))\n\nfunction isEnabled(tab: GrTab): boolean {\n return !tab.disabled\n}\n\nconst tabIndexes = computed(() => props.tabs.map((_, index) => index))\n\n/**\n * Кольцо roving-фокуса. При `activationMode: 'manual'` фокус уезжает вперёд\n * выбора — это и есть разница между `activeKey` примитива и `initialKey`:\n * первый ведёт фокус, второй подставляет выбранную вкладку, пока фокус не\n * трогали.\n *\n * Выбор стрелка **не** переносит: этим заведует `onKeydown` по\n * `activationMode`. Через `onMove` это выразить нельзя — клик тоже зовёт\n * `focusKey`, и выбор эмитился бы дважды.\n */\nconst roving = useRovingFocus<number>({\n items: () => tabIndexes.value,\n elementFor: index => buttonRefs.value[index],\n isDisabled: index => Boolean(props.tabs[index]?.disabled),\n orientation: () => (props.orientation === 'vertical' ? 'vertical' : 'horizontal'),\n skipDisabled: () => true,\n /**\n * Пока фокус не трогали, остановку `Tab` держит выбранная вкладка. Если\n * `modelValue` не совпал ни с одной (пустое начальное значение, асинхронный\n * список, удалённая активная вкладка), примитив ставит её на первую\n * доступную — иначе tablist выпал бы из обхода целиком и молча.\n *\n * Выключенность здесь не проверяется намеренно: на кнопке `aria-disabled`, а\n * не нативный `disabled`, поэтому выключенная вкладка фокусируется и держать\n * остановку вправе.\n */\n initialKey: () => (activeIndex.value >= 0 ? activeIndex.value : undefined),\n /**\n * Прокрутка до фокуса, а не после: иначе браузер доскроллит сам по-своему, и\n * ряд дёрнется дважды. Синхронно — фокус обязан остаться в том же такте, что\n * и раньше: тик, где он нужен, добавляет `focusIndex`.\n */\n beforeFocus: index => scrollIntoView(index),\n})\n\n/**\n * Фокус после перерисовки — для путей, где список только что изменился\n * (закрытие вкладки). Клавиатура идёт через примитив напрямую: там ряд уже\n * отрисован, и лишний тик только отложил бы фокус.\n */\nasync function focusIndex(index: number): Promise<void> {\n await nextTick()\n await roving.focusKey(index)\n}\n\n/**\n * Ряд прокручивается, а не переносится, поэтому активная вкладка может уехать\n * за край — например, когда её выбрали снаружи. `scrollIntoView` нет в jsdom и\n * в старых движках, поэтому вызов необязательный.\n */\nfunction scrollIntoView(index: number): void {\n buttonRefs.value[index]?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' })\n}\n\nwatch(() => props.modelValue, async () => {\n await nextTick()\n if (activeIndex.value >= 0)\n scrollIntoView(activeIndex.value)\n})\n\nasync function selectByIndex(index: number, focus = false): Promise<void> {\n const tab = props.tabs[index]\n if (!tab || !isEnabled(tab))\n return\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n if (focus)\n await focusIndex(index)\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n if (props.tabs.length === 0)\n return\n\n const currentIndex = roving.rovingKey.value ?? 0\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n // В ручном режиме выбор подтверждается явно — на той вкладке, где фокус.\n if (props.activationMode === 'manual') {\n event.preventDefault()\n void selectByIndex(currentIndex, false)\n }\n return\n case 'Delete':\n case 'Backspace': {\n // Единственный клавиатурный путь к закрытию: крестик в таб-порядке не стоит.\n const tab = props.tabs[currentIndex]\n if (tab && isClosable(tab)) {\n event.preventDefault()\n requestClose(currentIndex)\n }\n return\n }\n }\n\n // Стрелки, `Home`, `End` — фокус ведёт примитив по объявленной ориентации.\n if (!roving.handleNavigationKeys(event))\n return\n\n // `automatic`: выбор едет за фокусом. `manual`: ждёт `Enter`/`Space`.\n if (props.activationMode !== 'manual')\n void selectByIndex(roving.rovingKey.value ?? currentIndex, false)\n}\n\n/**\n * Закрытая вкладка, которая держала фокус. Компонент список не укорачивает —\n * это делает потребитель, — поэтому фокус возвращается только после того, как\n * `tabs` действительно стал короче.\n */\nlet pendingClose: { index: number, value: string } | null = null\n\nfunction requestClose(index: number): void {\n const tab = props.tabs[index]\n if (!tab || !isClosable(tab))\n return\n\n const held = buttonRefs.value[index] === document.activeElement\n pendingClose = held ? { index, value: tab.value } : null\n\n emit('close', tab.value)\n}\n\n// Без этого клавиатурное закрытие роняет фокус в `<body>`: кнопка, на которой\n// он стоял, исчезает из DOM вместе со вкладкой.\nwatch(() => props.tabs.length, async (next, prev) => {\n const pending = pendingClose\n pendingClose = null\n\n if (!pending || next >= prev)\n return\n // Ушла не та вкладка — потребитель поменял список по своей причине.\n if (props.tabs.some(tab => tab.value === pending.value))\n return\n\n await nextTick()\n\n const target = Math.min(pending.index, next - 1)\n if (target >= 0)\n void focusIndex(target)\n else\n roving.reset()\n})\n\nfunction onClick(event: MouseEvent, tab: GrTab, index: number): void {\n if (!isEnabled(tab))\n return\n\n // Крестик — не кнопка, поэтому его клик приходит сюда же и разбирается по цели.\n if (event.target instanceof Element && event.target.closest('[data-gr-tab-close]')) {\n requestClose(index)\n return\n }\n\n roving.setActive(index)\n\n if (tab.value !== props.modelValue)\n emit('update:modelValue', tab.value)\n}\n</script>\n\n<template>\n <!--\n Пустой ряд — не пустой `tablist`: роль обязана владеть потомками `tab`,\n и текст внутри неё был бы нарушением, а не пустым состоянием.\n -->\n <div v-if=\"isEmpty\" data-gr-tabs-empty :class=\"emptyClass\">\n <slot name=\"empty\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div\n v-else\n role=\"tablist\"\n data-gr-tabs\n :aria-orientation=\"orientation\"\n :class=\"tablistClass\"\n @keydown=\"onKeydown\"\n >\n <button\n v-for=\"(tab, index) in tabs\"\n :id=\"idBase ? `${idBase}-tab-${tab.value}` : undefined\"\n :key=\"tab.value\"\n :ref=\"el => setButtonRef(el, index)\"\n type=\"button\"\n role=\"tab\"\n data-gr-tab\n :aria-controls=\"idBase ? `${idBase}-panel-${tab.value}` : undefined\"\n :aria-selected=\"tab.value === modelValue ? 'true' : 'false'\"\n :aria-disabled=\"tab.disabled ? 'true' : undefined\"\n :aria-keyshortcuts=\"isClosable(tab) ? 'Delete' : undefined\"\n :tabindex=\"roving.tabindexFor(index)\"\n :class=\"tabClass(tab)\"\n @click=\"onClick($event, tab, index)\"\n >\n <span :class=\"tabContentClass\">\n <slot\n name=\"tab\"\n :tab=\"tab\"\n :active=\"tab.value === modelValue\"\n :disabled=\"Boolean(tab.disabled)\"\n >\n <component\n :is=\"iconTag(tab.icon)\"\n v-if=\"tab.icon\"\n :class=\"[tabIconClass, iconClass(tab.icon)]\"\n aria-hidden=\"true\"\n />\n <span>{{ tab.label }}</span>\n <span v-if=\"tab.badge\" :class=\"badgeClass\">\n {{ tab.badge }}\n </span>\n </slot>\n\n <!-- Снаружи слота: своя разметка вкладки не должна отнимать закрытие. -->\n <span\n v-if=\"isClosable(tab)\"\n data-gr-tab-close\n :class=\"closeClass\"\n :title=\"closeTitle\"\n aria-hidden=\"true\"\n >\n <IconX :class=\"closeIconClass\" />\n </span>\n </span>\n </button>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { n as grTabsSafelist, t as grTabsConfig } from "../../chunks/config-DWN4x6_e.js";
2
- import { t as GrTabs_default } from "./chunks/GrTabs-CBHZkOFY.js";
1
+ import { n as grTabsSafelist, t as grTabsConfig } from "../../chunks/config-_QF0O1vq.js";
2
+ import { t as GrTabs_default } from "./chunks/GrTabs-ugDnkk-2.js";
3
3
  export { GrTabs_default as GrTabs, GrTabs_default as default, grTabsConfig, grTabsSafelist };
@@ -4,7 +4,7 @@ import { n as useGranularityTranslations } from "../../../chunks/granularityI18n
4
4
  import { vAutosize } from "../../../directives/autosize.js";
5
5
  import { n as useGrFormFieldContext } from "../../../chunks/context-DdNIxa1w.js";
6
6
  import { useGrFormControl } from "../../../composables/useGrFormControl.js";
7
- import { a as enabledSurfaceClass, c as lineCountClass, i as disabledSurfaceClass, l as resizeClass, n as countClass, o as grTextareaClass, r as countRowClass, u as sizes } from "../../../chunks/grTextareaStyles-iOcHuVMM.js";
7
+ import { a as enabledSurfaceClass, c as lineCountClass, i as disabledSurfaceClass, l as resizeClass, n as countClass, o as grTextareaClass, r as countRowClass, u as sizes } from "../../../chunks/grTextareaStyles-Bp35BGna.js";
8
8
  import { computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, normalizeClass, openBlock, ref, toDisplayString, unref, useId, withDirectives } from "vue";
9
9
  //#region src/components/GrTextarea/GrTextarea.vue?vue&type=script&setup=true&lang.ts
10
10
  var _hoisted_1 = {