@feugene/granularity 0.31.0 → 0.32.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 (287) hide show
  1. package/README.md +0 -1
  2. package/dist/chunks/adapter-CAOxmn2G.js.map +1 -1
  3. package/dist/chunks/{config-BHcS5Cwm.js → config-87fszqnD.js} +1 -1
  4. package/dist/chunks/{config-BHcS5Cwm.js.map → config-87fszqnD.js.map} +1 -1
  5. package/dist/chunks/config-A-bBiotF.js.map +1 -1
  6. package/dist/chunks/config-B3J0alyY.js.map +1 -1
  7. package/dist/chunks/config-BhfNgyWL.js.map +1 -1
  8. package/dist/chunks/config-Bjn30smH.js.map +1 -1
  9. package/dist/chunks/config-BqT6PMzO.js.map +1 -1
  10. package/dist/chunks/config-C0Ea9ePP.js.map +1 -1
  11. package/dist/chunks/config-C0Eu8jpG.js.map +1 -1
  12. package/dist/chunks/config-CDat1wXf.js.map +1 -1
  13. package/dist/chunks/config-CQLNjc9X2.js.map +1 -1
  14. package/dist/chunks/config-CbEbLyDE.js.map +1 -1
  15. package/dist/chunks/{config-jyr6AIZt2.js → config-CuQmUkMw2.js} +2 -2
  16. package/dist/chunks/{config-jyr6AIZt2.js.map → config-CuQmUkMw2.js.map} +1 -1
  17. package/dist/chunks/config-DeyT9dJl.js.map +1 -1
  18. package/dist/chunks/config-DnF472Ox.js.map +1 -1
  19. package/dist/chunks/config-DwABJHEo.js.map +1 -1
  20. package/dist/chunks/{config-tiUtEn4Q.js → config-E1cTyRVV.js} +1 -1
  21. package/dist/chunks/{config-tiUtEn4Q.js.map → config-E1cTyRVV.js.map} +1 -1
  22. package/dist/chunks/config-MmPym-Z72.js.map +1 -1
  23. package/dist/chunks/config-T3-DMXYm.js.map +1 -1
  24. package/dist/chunks/config-Yy67uWHY.js.map +1 -1
  25. package/dist/chunks/config-_jbgsFpw.js.map +1 -1
  26. package/dist/chunks/config-g8-JGZ_Y.js.map +1 -1
  27. package/dist/chunks/config-mlheIMtV.js.map +1 -1
  28. package/dist/chunks/config-rLkc9Zn2.js.map +1 -1
  29. package/dist/chunks/config-uzUuosv7.js.map +1 -1
  30. package/dist/chunks/context-CTbuwcYs.js.map +1 -1
  31. package/dist/chunks/deltaTone-B5OoS1vo.js.map +1 -1
  32. package/dist/chunks/es-Do2CNrC2.js.map +1 -1
  33. package/dist/chunks/fileValidation-D5TFBhbv.js.map +1 -1
  34. package/dist/chunks/focusables-BkzK42SQ.js.map +1 -1
  35. package/dist/chunks/{generated-DJ2dJ__C.js → generated-CSyPsWtM.js} +1 -1
  36. package/dist/chunks/{generated-DJ2dJ__C.js.map → generated-CSyPsWtM.js.map} +1 -1
  37. package/dist/chunks/grBadgeStyles-D8Mz73B5.js.map +1 -1
  38. package/dist/chunks/{grButtonStyles-B_-YRE__.js → grButtonStyles-B3wRWW_i.js} +4 -4
  39. package/dist/chunks/grButtonStyles-B3wRWW_i.js.map +1 -0
  40. package/dist/chunks/grLinkStyles-FME_qMpi.js.map +1 -1
  41. package/dist/chunks/grLoadingStyles-CnQaf5ry.js.map +1 -1
  42. package/dist/chunks/{grRadioStyles-D4gnU65n.js → grRadioStyles-DGL2QLy6.js} +1 -1
  43. package/dist/chunks/{grRadioStyles-D4gnU65n.js.map → grRadioStyles-DGL2QLy6.js.map} +1 -1
  44. package/dist/chunks/grSelectStyles-Cdtd10eY.js.map +1 -1
  45. package/dist/chunks/{grSliderStyles-B5uNxNJq.js → grSliderStyles-kaz6VXZ3.js} +9 -1
  46. package/dist/chunks/grSliderStyles-kaz6VXZ3.js.map +1 -0
  47. package/dist/chunks/{granular-provider-yJNX1g1G.js → granular-provider-Da2CJO6j.js} +3 -3
  48. package/dist/chunks/{granular-provider-yJNX1g1G.js.map → granular-provider-Da2CJO6j.js.map} +1 -1
  49. package/dist/chunks/granularityI18n-BC5zsj_d.js.map +1 -1
  50. package/dist/chunks/icon-Dag2tIMs.js.map +1 -1
  51. package/dist/chunks/inert-DIHCCn_1.js.map +1 -1
  52. package/dist/chunks/keyboard-DE2yhz_b.js.map +1 -1
  53. package/dist/chunks/numericStep-Bq2lj4ew.js.map +1 -1
  54. package/dist/chunks/optionFilter-DYw9XPPx.js.map +1 -1
  55. package/dist/chunks/{overlayStack-C8cfsqXa.js → overlayStack-0CZS99Da.js} +40 -6
  56. package/dist/chunks/overlayStack-0CZS99Da.js.map +1 -0
  57. package/dist/chunks/portalRoot-CVhCgdG6.js.map +1 -1
  58. package/dist/chunks/renamedProp-BwcN-SJg.js.map +1 -1
  59. package/dist/chunks/{safelist-BOq5Li7p.js → safelist-DxkMj5IW.js} +1 -1
  60. package/dist/chunks/{safelist-BOq5Li7p.js.map → safelist-DxkMj5IW.js.map} +1 -1
  61. package/dist/chunks/slotNodes-DxNXpC7v.js.map +1 -1
  62. package/dist/chunks/useControlAddons-asUr10Pf.js.map +1 -1
  63. package/dist/chunks/useControlledOpen-DV3SqLTP.js.map +1 -1
  64. package/dist/chunks/useDragSort-0l47h4yb.js.map +1 -1
  65. package/dist/chunks/useFilePreviews-DnwgdyBs.js.map +1 -1
  66. package/dist/chunks/useFocusWithin-BwHE0rzm.js.map +1 -1
  67. package/dist/chunks/{useModalOverlay-Cv5hF63W.js → useModalOverlay-D__CqLGn.js} +3 -0
  68. package/dist/chunks/useModalOverlay-D__CqLGn.js.map +1 -0
  69. package/dist/chunks/usePortalTarget-C0p-mhaM.js.map +1 -1
  70. package/dist/chunks/validation-5HhpanPP.js.map +1 -1
  71. package/dist/components/GrAlert/chunks/GrAlert-FAVf-ksH.js.map +1 -1
  72. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-X6RlmiJQ.js → GrAutocomplete-rYEY15UI.js} +1 -1
  73. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-rYEY15UI.js.map +1 -0
  74. package/dist/components/GrAutocomplete/index.js +1 -1
  75. package/dist/components/GrAutocomplete/styles.css +1 -1
  76. package/dist/components/GrAvatar/chunks/GrAvatar-CNmLmgcr.js.map +1 -1
  77. package/dist/components/GrBadge/chunks/{GrBadge-BsoocpF-.js → GrBadge-D2MfThPz.js} +1 -1
  78. package/dist/components/GrBadge/chunks/GrBadge-D2MfThPz.js.map +1 -0
  79. package/dist/components/GrBadge/index.js +1 -1
  80. package/dist/components/GrBadge/styles.css +1 -1
  81. package/dist/components/GrBadgeWrap/chunks/GrBadgeWrap-B-A3PRkE.js.map +1 -1
  82. package/dist/components/GrBottomNav/chunks/GrBottomNav-wtFatLjB.js.map +1 -1
  83. package/dist/components/GrBreadcrumbs/chunks/GrBreadcrumbs-DRDNan_n.js.map +1 -1
  84. package/dist/components/GrButton/chunks/{GrButton-Bw2AH4uX.js → GrButton-7GP0zObj.js} +1 -1
  85. package/dist/components/GrButton/chunks/GrButton-7GP0zObj.js.map +1 -0
  86. package/dist/components/GrButton/index.js +3 -3
  87. package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CKyiAV8K.js.map +1 -1
  88. package/dist/components/GrCard/chunks/GrCard-BttXz1pQ.js.map +1 -1
  89. package/dist/components/GrCheckbox/chunks/GrCheckbox-CEcHIsXM.js.map +1 -1
  90. package/dist/components/GrCheckboxGroup/chunks/GrCheckboxGroup-BOwrVcFr.js.map +1 -1
  91. package/dist/components/GrChip/chunks/GrChip-C0vU69tf.js.map +1 -1
  92. package/dist/components/GrChipGroup/chunks/GrChipGroup-C78Vcwos.js.map +1 -1
  93. package/dist/components/GrCodeBlock/chunks/{GrCodeBlock-Dkvkr91t.js → GrCodeBlock-Dp0eEBTZ.js} +1 -1
  94. package/dist/components/GrCodeBlock/chunks/GrCodeBlock-Dp0eEBTZ.js.map +1 -0
  95. package/dist/components/GrCodeBlock/index.js +1 -1
  96. package/dist/components/GrCollapse/chunks/GrCollapse-BlW6ybdL.js.map +1 -1
  97. package/dist/components/GrColorPicker/chunks/{GrColorPicker-C7ifyQ0R.js → GrColorPicker-p2XH_8cE.js} +2 -2
  98. package/dist/components/GrColorPicker/chunks/GrColorPicker-p2XH_8cE.js.map +1 -0
  99. package/dist/components/GrColorPicker/index.js +1 -1
  100. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-C5abL2Y7.js → GrCommandPalette-BXbh3q7O.js} +2 -2
  101. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BXbh3q7O.js.map +1 -0
  102. package/dist/components/GrCommandPalette/index.js +1 -1
  103. package/dist/components/GrCommandPalette/styles.css +1 -1
  104. package/dist/components/GrConfigProvider/chunks/GrConfigProvider-BF7R3hgg.js.map +1 -1
  105. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-B9mIU78E.js → GrConfirmDialog-CUP43q__.js} +3 -3
  106. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-CUP43q__.js.map +1 -0
  107. package/dist/components/GrConfirmDialog/index.js +1 -1
  108. package/dist/components/GrContextMenu/chunks/{GrContextMenu-_FKwQvuQ.js → GrContextMenu-ClkVjdcP.js} +1 -1
  109. package/dist/components/GrContextMenu/chunks/GrContextMenu-ClkVjdcP.js.map +1 -0
  110. package/dist/components/GrContextMenu/index.js +1 -1
  111. package/dist/components/GrDataTable/chunks/{GrDataTable-C8a9_nCg.js → GrDataTable-CAGgRk27.js} +5 -3
  112. package/dist/components/GrDataTable/chunks/GrDataTable-CAGgRk27.js.map +1 -0
  113. package/dist/components/GrDataTable/index.js +1 -1
  114. package/dist/components/GrDelta/chunks/GrDelta-BZwkgQW-.js.map +1 -1
  115. package/dist/components/GrDescriptionList/chunks/GrDescriptionList-BMeCgFV3.js.map +1 -1
  116. package/dist/components/GrDialog/chunks/{GrDialog-bOUDYfmh.js → GrDialog-BiMJ9_T4.js} +2 -2
  117. package/dist/components/GrDialog/chunks/{GrDialog-bOUDYfmh.js.map → GrDialog-BiMJ9_T4.js.map} +1 -1
  118. package/dist/components/GrDialog/index.js +1 -1
  119. package/dist/components/GrDialogService/chunks/{GrDialogService-6s2cQ-_6.js → GrDialogService-BxNK6crD.js} +4 -4
  120. package/dist/components/GrDialogService/chunks/GrDialogService-BxNK6crD.js.map +1 -0
  121. package/dist/components/GrDialogService/index.js +1 -1
  122. package/dist/components/GrDivider/chunks/GrDivider-BXavGcMX.js.map +1 -1
  123. package/dist/components/GrDrawer/chunks/{GrDrawer-B7PiAcbU.js → GrDrawer-Ce2l3zaG.js} +6 -5
  124. package/dist/components/GrDrawer/chunks/GrDrawer-Ce2l3zaG.js.map +1 -0
  125. package/dist/components/GrDrawer/index.js +1 -1
  126. package/dist/components/GrDropdown/chunks/GrDropdown-13Wt9eB_.js.map +1 -1
  127. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenu-GOzuAXsi.js.map +1 -1
  128. package/dist/components/GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js.map +1 -1
  129. package/dist/components/GrFilePreview/chunks/GrFilePreview-C9Z7hMK8.js.map +1 -1
  130. package/dist/components/GrFileUpload/chunks/GrFileUpload-NsHkRRIa.js.map +1 -1
  131. package/dist/components/GrForm/chunks/GrForm-CrnfCsgj.js.map +1 -1
  132. package/dist/components/GrFormField/chunks/GrFormField-DSylU7IU.js.map +1 -1
  133. package/dist/components/GrFormFile/chunks/{GrFormFile-CYtXU9HV.js → GrFormFile-B1jGZyIj.js} +2 -2
  134. package/dist/components/GrFormFile/chunks/GrFormFile-B1jGZyIj.js.map +1 -0
  135. package/dist/components/GrFormFile/index.js +1 -1
  136. package/dist/components/GrFormFile/styles.css +1 -1
  137. package/dist/components/GrIcon/chunks/GrIcon-Dmf0c9ba.js.map +1 -1
  138. package/dist/components/GrImageViewer/chunks/{GrImageViewer-CyVN6Zpc.js → GrImageViewer-CG4vUBg_.js} +4 -3
  139. package/dist/components/GrImageViewer/chunks/GrImageViewer-CG4vUBg_.js.map +1 -0
  140. package/dist/components/GrImageViewer/index.js +1 -1
  141. package/dist/components/GrInput/chunks/GrInput-BLywRZUN.js.map +1 -1
  142. package/dist/components/GrInputTag/chunks/GrInputTag-Cj4A9Xgs.js.map +1 -1
  143. package/dist/components/GrJsonViewer/chunks/{GrJsonViewer-Cy2bknHO.js → GrJsonViewer-BCZ7lE2k.js} +2 -2
  144. package/dist/components/GrJsonViewer/chunks/GrJsonViewer-BCZ7lE2k.js.map +1 -0
  145. package/dist/components/GrJsonViewer/index.js +1 -1
  146. package/dist/components/GrKbd/chunks/GrKbd-D2ga1H9i.js.map +1 -1
  147. package/dist/components/GrLink/chunks/GrLink-DYXw3W9w.js.map +1 -1
  148. package/dist/components/GrList/chunks/{GrList-DmT4qzLO.js → GrList-B_CRJB4c.js} +1 -1
  149. package/dist/components/GrList/chunks/GrList-B_CRJB4c.js.map +1 -0
  150. package/dist/components/GrList/index.js +1 -1
  151. package/dist/components/GrList/styles.css +1 -1
  152. package/dist/components/GrModal/chunks/{GrModal-CCoWZuIl.js → GrModal-D0mf1SAx.js} +3 -2
  153. package/dist/components/GrModal/chunks/GrModal-D0mf1SAx.js.map +1 -0
  154. package/dist/components/GrModal/index.js +1 -1
  155. package/dist/components/GrNavbar/chunks/{GrNavbar-C5EjMKaC.js → GrNavbar-_rtHKwTf.js} +1 -1
  156. package/dist/components/GrNavbar/chunks/{GrNavbar-C5EjMKaC.js.map → GrNavbar-_rtHKwTf.js.map} +1 -1
  157. package/dist/components/GrNavbar/index.js +1 -1
  158. package/dist/components/GrNumberInput/chunks/GrNumberInput-DQ59YICu.js.map +1 -1
  159. package/dist/components/GrPagination/chunks/{GrPagination-Cw3R21dp.js → GrPagination-B_kAhoAV.js} +2 -2
  160. package/dist/components/GrPagination/chunks/{GrPagination-Cw3R21dp.js.map → GrPagination-B_kAhoAV.js.map} +1 -1
  161. package/dist/components/GrPagination/index.js +1 -1
  162. package/dist/components/GrPopover/chunks/{GrPopover-CofG-Tfe.js → GrPopover-faJanmGs.js} +1 -1
  163. package/dist/components/GrPopover/chunks/GrPopover-faJanmGs.js.map +1 -0
  164. package/dist/components/GrPopover/index.js +1 -1
  165. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DLcl1xiq.js → GrPromptDialog-C6QGC7QJ.js} +4 -4
  166. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-C6QGC7QJ.js.map +1 -0
  167. package/dist/components/GrPromptDialog/index.js +1 -1
  168. package/dist/components/GrRadio/chunks/{GrRadio-C_rESc5g.js → GrRadio-Aq3v8XgG.js} +1 -1
  169. package/dist/components/GrRadio/chunks/GrRadio-Aq3v8XgG.js.map +1 -0
  170. package/dist/components/GrRadio/index.js +2 -2
  171. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CdQO4G-U.js → GrRadioGroup-y9LVdTWh.js} +1 -1
  172. package/dist/components/GrRadioGroup/chunks/GrRadioGroup-y9LVdTWh.js.map +1 -0
  173. package/dist/components/GrRadioGroup/index.js +1 -1
  174. package/dist/components/GrRating/chunks/GrRating-IEiTOdnF.js.map +1 -1
  175. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-C_skObtv.js → GrResponseErrorBanner-CBVRpgIG.js} +1 -1
  176. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-C_skObtv.js.map → GrResponseErrorBanner-CBVRpgIG.js.map} +1 -1
  177. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-DudGc9LO.js → GrResponseErrorBanner-DMeOWlzj.js} +1 -1
  178. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-DMeOWlzj.js.map +1 -0
  179. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  180. package/dist/components/GrSegmented/chunks/GrSegmented-CB-VR-yL.js.map +1 -1
  181. package/dist/components/GrSelect/chunks/{GrSelect-BiUrSSxc.js → GrSelect-gCeRFgQo.js} +1 -1
  182. package/dist/components/GrSelect/chunks/GrSelect-gCeRFgQo.js.map +1 -0
  183. package/dist/components/GrSelect/index.js +1 -1
  184. package/dist/components/GrSelect/styles.css +1 -1
  185. package/dist/components/GrSidebar/chunks/{GrSidebar-B8EQIlfW.js → GrSidebar-alkwBUzL.js} +1 -1
  186. package/dist/components/GrSidebar/chunks/GrSidebar-alkwBUzL.js.map +1 -0
  187. package/dist/components/GrSidebar/index.js +1 -1
  188. package/dist/components/GrSkeleton/chunks/GrSkeleton-CgfXxPQ2.js.map +1 -1
  189. package/dist/components/GrSlider/chunks/{GrSlider-DJfeEl4h.js → GrSlider-DTTrZTHK.js} +3 -3
  190. package/dist/components/GrSlider/chunks/GrSlider-DTTrZTHK.js.map +1 -0
  191. package/dist/components/GrSlider/index.js +2 -2
  192. package/dist/components/GrSortableList/chunks/GrSortableList-HyKX--rO.js.map +1 -1
  193. package/dist/components/GrSplitter/chunks/GrSplitter-MltjaADn.js.map +1 -1
  194. package/dist/components/GrStatistic/chunks/GrStatistic-qHVasK37.js.map +1 -1
  195. package/dist/components/GrSteps/chunks/GrSteps-C2jxpZoN.js.map +1 -1
  196. package/dist/components/GrSwitch/chunks/{GrSwitch-g_OOSkh7.js → GrSwitch-7Oe5QfQZ.js} +1 -1
  197. package/dist/components/GrSwitch/chunks/GrSwitch-7Oe5QfQZ.js.map +1 -0
  198. package/dist/components/GrSwitch/index.js +1 -1
  199. package/dist/components/GrTabPanels/chunks/GrTabPanels-BZQS8-JM.js.map +1 -1
  200. package/dist/components/GrTable/chunks/GrTable-Zcdz2St_.js.map +1 -1
  201. package/dist/components/GrTextarea/chunks/{GrTextarea-KREK75Bu.js → GrTextarea-DinXG12-.js} +10 -10
  202. package/dist/components/GrTextarea/chunks/GrTextarea-DinXG12-.js.map +1 -0
  203. package/dist/components/GrTextarea/index.js +1 -1
  204. package/dist/components/GrTimeline/chunks/GrTimeline-BiHpArsg.js.map +1 -1
  205. package/dist/components/GrToaster/chunks/{GrToaster-Dp7-4B8k.js → GrToaster-COXIBKzq.js} +2 -2
  206. package/dist/components/GrToaster/chunks/GrToaster-COXIBKzq.js.map +1 -0
  207. package/dist/components/GrToaster/index.js +1 -1
  208. package/dist/components/GrToaster/styles.css +1 -1
  209. package/dist/components/GrTooltip/chunks/GrTooltip-uYETdbCD.js.map +1 -1
  210. package/dist/components/GrTree/chunks/{GrTree-DC89I4AP.js → GrTree-Ci6CZfKR.js} +5 -5
  211. package/dist/components/GrTree/chunks/GrTree-Ci6CZfKR.js.map +1 -0
  212. package/dist/components/GrTree/index.js +1 -1
  213. package/dist/components/GrTree/styles.css +1 -1
  214. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-iJnMl2t9.js → GrTreeSelect-BHwgGJcT.js} +1 -1
  215. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-BHwgGJcT.js.map +1 -0
  216. package/dist/components/GrTreeSelect/index.js +1 -1
  217. package/dist/composables/useAnnouncer.js.map +1 -1
  218. package/dist/composables/useComboboxNavigation.js.map +1 -1
  219. package/dist/composables/useDragGesture.js.map +1 -1
  220. package/dist/composables/useFloating.js +2 -22
  221. package/dist/composables/useFloating.js.map +1 -1
  222. package/dist/composables/useFocusTrap.js.map +1 -1
  223. package/dist/composables/useOverlayLayer.js +10 -3
  224. package/dist/composables/useOverlayLayer.js.map +1 -1
  225. package/dist/composables/useRovingFocus.js.map +1 -1
  226. package/dist/composables/useTheme.js.map +1 -1
  227. package/dist/composables/useToast.js.map +1 -1
  228. package/dist/composables/useVirtualList.js.map +1 -1
  229. package/dist/directives/autofocus.js.map +1 -1
  230. package/dist/directives/autosize.js.map +1 -1
  231. package/dist/directives/clickOutside.js.map +1 -1
  232. package/dist/directives/dropzone.js.map +1 -1
  233. package/dist/directives/hotkey.js.map +1 -1
  234. package/dist/directives/loading.js.map +1 -1
  235. package/dist/granular-provider-node.js +1 -1
  236. package/dist/granular-provider.js +1 -1
  237. package/dist/index.js +37 -37
  238. package/dist/testing.js +2 -2
  239. package/dist/testing.js.map +1 -1
  240. package/dist/theme-apply.js.map +1 -1
  241. package/dist/theme.js +1 -1
  242. package/dist/theme.js.map +1 -1
  243. package/dist/tokens.js +1 -1
  244. package/dist/types/components/GrCodeBlock/tokenizeJson.d.ts +1 -3
  245. package/dist/types/components/GrImageViewer/GrImageViewer.vue.d.ts +1 -1
  246. package/dist/types/components/GrInput/GrInput.vue.d.ts +24 -24
  247. package/dist/types/components/GrSlider/grSliderStyles.d.ts +9 -1
  248. package/dist/types/components/GrTabPanels/GrTabPanel.vue.d.ts +3 -3
  249. package/dist/types/composables/internal/overlayStack.d.ts +30 -0
  250. package/dist/types/composables/internal/useModalOverlay.d.ts +14 -0
  251. package/dist/types/composables/useOverlayLayer.d.ts +8 -0
  252. package/dist/vue/index.js.map +1 -1
  253. package/dist/web-types.json +1 -1
  254. package/package.json +3 -3
  255. package/dist/chunks/grButtonStyles-B_-YRE__.js.map +0 -1
  256. package/dist/chunks/grSliderStyles-B5uNxNJq.js.map +0 -1
  257. package/dist/chunks/overlayStack-C8cfsqXa.js.map +0 -1
  258. package/dist/chunks/useModalOverlay-Cv5hF63W.js.map +0 -1
  259. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-X6RlmiJQ.js.map +0 -1
  260. package/dist/components/GrBadge/chunks/GrBadge-BsoocpF-.js.map +0 -1
  261. package/dist/components/GrButton/chunks/GrButton-Bw2AH4uX.js.map +0 -1
  262. package/dist/components/GrCodeBlock/chunks/GrCodeBlock-Dkvkr91t.js.map +0 -1
  263. package/dist/components/GrColorPicker/chunks/GrColorPicker-C7ifyQ0R.js.map +0 -1
  264. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-C5abL2Y7.js.map +0 -1
  265. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-B9mIU78E.js.map +0 -1
  266. package/dist/components/GrContextMenu/chunks/GrContextMenu-_FKwQvuQ.js.map +0 -1
  267. package/dist/components/GrDataTable/chunks/GrDataTable-C8a9_nCg.js.map +0 -1
  268. package/dist/components/GrDialogService/chunks/GrDialogService-6s2cQ-_6.js.map +0 -1
  269. package/dist/components/GrDrawer/chunks/GrDrawer-B7PiAcbU.js.map +0 -1
  270. package/dist/components/GrFormFile/chunks/GrFormFile-CYtXU9HV.js.map +0 -1
  271. package/dist/components/GrImageViewer/chunks/GrImageViewer-CyVN6Zpc.js.map +0 -1
  272. package/dist/components/GrJsonViewer/chunks/GrJsonViewer-Cy2bknHO.js.map +0 -1
  273. package/dist/components/GrList/chunks/GrList-DmT4qzLO.js.map +0 -1
  274. package/dist/components/GrModal/chunks/GrModal-CCoWZuIl.js.map +0 -1
  275. package/dist/components/GrPopover/chunks/GrPopover-CofG-Tfe.js.map +0 -1
  276. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-DLcl1xiq.js.map +0 -1
  277. package/dist/components/GrRadio/chunks/GrRadio-C_rESc5g.js.map +0 -1
  278. package/dist/components/GrRadioGroup/chunks/GrRadioGroup-CdQO4G-U.js.map +0 -1
  279. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-DudGc9LO.js.map +0 -1
  280. package/dist/components/GrSelect/chunks/GrSelect-BiUrSSxc.js.map +0 -1
  281. package/dist/components/GrSidebar/chunks/GrSidebar-B8EQIlfW.js.map +0 -1
  282. package/dist/components/GrSlider/chunks/GrSlider-DJfeEl4h.js.map +0 -1
  283. package/dist/components/GrSwitch/chunks/GrSwitch-g_OOSkh7.js.map +0 -1
  284. package/dist/components/GrTextarea/chunks/GrTextarea-KREK75Bu.js.map +0 -1
  285. package/dist/components/GrToaster/chunks/GrToaster-Dp7-4B8k.js.map +0 -1
  286. package/dist/components/GrTree/chunks/GrTree-DC89I4AP.js.map +0 -1
  287. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-iJnMl2t9.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrButton-7GP0zObj.js","names":[],"sources":["../../../../src/components/GrButton/GrButton.vue","../../../../src/components/GrButton/GrButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, markRaw, ref, type Component } from 'vue'\n\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrButtonGroup } from '../GrButtonGroup/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport type { GrButtonSize, GrButtonTone, GrButtonVariant } from './grButtonStyles'\n\nimport {\n grButtonBaseClass,\n grButtonClass,\n type GrButtonSize,\n type GrButtonTone,\n type GrButtonVariant,\n} from './grButtonStyles'\n\nexport interface GrButtonProps {\n variant?: GrButtonVariant\n tone?: GrButtonTone\n size?: GrButtonSize\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n disabled?: boolean\n square?: boolean\n /** Кнопка на всю ширину контейнера. */\n block?: boolean\n type?: 'button' | 'submit' | 'reset'\n ariaLabel?: string\n /** Полиморфизм: кастомный корневой тег/компонент (например, RouterLink). */\n as?: string | Component\n /** Рендерит кнопку как `<a href>` (если не задан `as`). */\n href?: string\n target?: string\n rel?: string\n external?: boolean\n}\n\nconst props = withDefaults(\n defineProps<GrButtonProps>(),\n {\n // `variant`/`tone`/`size`/`square` настраиваются через `GrConfigProvider`,\n // поэтому их дефолты живут в резолверах ниже, а не здесь: Vue подставил бы\n // дефолт до того, как компонент успеет заглянуть в конфиг.\n variant: undefined,\n tone: undefined,\n size: undefined,\n loading: false,\n loadingText: undefined,\n disabled: false,\n square: undefined,\n block: false,\n type: 'button',\n ariaLabel: undefined,\n as: undefined,\n href: undefined,\n target: undefined,\n rel: undefined,\n external: false,\n },\n)\n\n// Эффективные значения: проп кнопки → группа → `GrConfigProvider` → дефолт.\n// Группа ближе к кнопке, чем глобальный провайдер, поэтому она подставляется\n// как «локальное» значение — и побеждает конфиг, но не собственный проп.\nconst group = useGrButtonGroup()\n\nconst resolvedSize = useGrComponentSize(() => props.size ?? group?.size.value, { component: 'GrButton' })\nconst resolvedVariant = useGrComponentProp('GrButton', 'variant', () => props.variant ?? group?.variant.value, 'primary')\nconst resolvedTone = useGrComponentProp('GrButton', 'tone', () => props.tone ?? group?.tone.value, 'primary')\nconst isSquare = useGrComponentProp('GrButton', 'square', () => props.square, false)\n\nconst { t } = useGranularityTranslations()\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.button.loading', 'Loading…'))\n\n// Полиморфный корень: `as` → `<a href>` → `<button>`.\nconst isLink = computed(() => Boolean(props.as || props.href))\nconst renderAs = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\n// Неинтерактивно при явном `disabled` ИЛИ во время `loading`.\nconst blocked = computed(() => props.disabled || props.loading)\n\n// Ключевое: `loading` НЕ ставит нативный `disabled` (элемент бы выпал из фокуса и\n// скринридер потерял бы контекст) — вместо этого `aria-disabled` + перехват клика.\n// Нативный `disabled` (только у `<button>`) оставляем лишь для явного `disabled`.\nconst nativeDisabled = computed(() => (renderAs.value === 'button' && props.disabled) ? true : undefined)\nconst ariaDisabled = computed(() => (props.loading || (isLink.value && props.disabled)) ? 'true' : undefined)\n\nconst resolvedTarget = computed(() => props.target ?? (props.external ? '_blank' : undefined))\nconst resolvedRel = computed(() => props.rel ?? (resolvedTarget.value === '_blank' ? 'noopener noreferrer' : undefined))\n\nfunction onClickCapture(e: MouseEvent): void {\n // Блокируем и дефолт (submit/навигация), и внешние обработчики (в т.ч. по Enter/Space),\n // сохраняя фокус на элементе.\n if (blocked.value) {\n e.preventDefault()\n e.stopImmediatePropagation()\n }\n}\n\n// Корень динамический (`as` принимает и тег, и компонент), поэтому ref может\n// оказаться как элементом, так и инстансом — например роутерной ссылкой.\nconst rootEl = ref<HTMLElement | { $el?: HTMLElement } | null>(null)\n\n/**\n * Фокус на кнопку из кода. Нужен там, где окно обязано открываться с фокусом\n * на конкретном действии (`GrConfirmDialog`), и потребителю не должно быть\n * важно, тегом или компонентом отрисован корень.\n */\nfunction focus(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.focus?.()\n}\n\nfunction blur(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.blur?.()\n}\n\ndefineExpose({ focus, blur })\n\nconst className = computed(() => {\n return grButtonClass({\n variant: resolvedVariant.value,\n tone: resolvedTone.value,\n size: resolvedSize.value,\n square: isSquare.value,\n disabled: props.disabled,\n block: props.block,\n })\n})\n\ndefineSlots<{\n /** Содержимое кнопки. */\n default?: () => any\n /** Аддон слева: иконка, счётчик. В состоянии загрузки уступает место спиннеру. */\n prefix?: () => any\n /** Аддон справа: шеврон, счётчик. */\n suffix?: () => any\n}>()\n</script>\n\n<template>\n <component\n :is=\"renderAs\"\n ref=\"rootEl\"\n data-gr-button\n :data-gr-variant=\"resolvedVariant\"\n :data-gr-tone=\"resolvedTone\"\n :type=\"renderAs === 'button' ? props.type : undefined\"\n :disabled=\"nativeDisabled\"\n :href=\"isLink && !props.disabled ? props.href : undefined\"\n :target=\"isLink && !props.disabled ? resolvedTarget : undefined\"\n :rel=\"isLink && !props.disabled ? resolvedRel : undefined\"\n :aria-busy=\"props.loading ? 'true' : undefined\"\n :aria-disabled=\"ariaDisabled\"\n :aria-label=\"props.ariaLabel\"\n :tabindex=\"isLink && props.disabled ? -1 : undefined\"\n :class=\"[grButtonBaseClass, className, blocked ? 'cursor-not-allowed' : '']\"\n @click.capture=\"onClickCapture\"\n >\n <!-- Спиннер занимает место префикса: две иконки рядом читались бы как ошибка. -->\n <IconLoader v-if=\"props.loading\" class=\"h-4 w-4 animate-spin\" aria-hidden=\"true\" />\n <slot v-else name=\"prefix\" />\n\n <slot />\n\n <slot name=\"suffix\" />\n\n <span v-if=\"props.loading\" class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, markRaw, ref, type Component } from 'vue'\n\nimport IconLoader from '~icons/lucide/loader-circle'\n\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrButtonGroup } from '../GrButtonGroup/context'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nexport type { GrButtonSize, GrButtonTone, GrButtonVariant } from './grButtonStyles'\n\nimport {\n grButtonBaseClass,\n grButtonClass,\n type GrButtonSize,\n type GrButtonTone,\n type GrButtonVariant,\n} from './grButtonStyles'\n\nexport interface GrButtonProps {\n variant?: GrButtonVariant\n tone?: GrButtonTone\n size?: GrButtonSize\n loading?: boolean\n /** i18n: что именно грузится. `aria-busy` сам по себе часть AT не объявляет. */\n loadingText?: string\n disabled?: boolean\n square?: boolean\n /** Кнопка на всю ширину контейнера. */\n block?: boolean\n type?: 'button' | 'submit' | 'reset'\n ariaLabel?: string\n /** Полиморфизм: кастомный корневой тег/компонент (например, RouterLink). */\n as?: string | Component\n /** Рендерит кнопку как `<a href>` (если не задан `as`). */\n href?: string\n target?: string\n rel?: string\n external?: boolean\n}\n\nconst props = withDefaults(\n defineProps<GrButtonProps>(),\n {\n // `variant`/`tone`/`size`/`square` настраиваются через `GrConfigProvider`,\n // поэтому их дефолты живут в резолверах ниже, а не здесь: Vue подставил бы\n // дефолт до того, как компонент успеет заглянуть в конфиг.\n variant: undefined,\n tone: undefined,\n size: undefined,\n loading: false,\n loadingText: undefined,\n disabled: false,\n square: undefined,\n block: false,\n type: 'button',\n ariaLabel: undefined,\n as: undefined,\n href: undefined,\n target: undefined,\n rel: undefined,\n external: false,\n },\n)\n\n// Эффективные значения: проп кнопки → группа → `GrConfigProvider` → дефолт.\n// Группа ближе к кнопке, чем глобальный провайдер, поэтому она подставляется\n// как «локальное» значение — и побеждает конфиг, но не собственный проп.\nconst group = useGrButtonGroup()\n\nconst resolvedSize = useGrComponentSize(() => props.size ?? group?.size.value, { component: 'GrButton' })\nconst resolvedVariant = useGrComponentProp('GrButton', 'variant', () => props.variant ?? group?.variant.value, 'primary')\nconst resolvedTone = useGrComponentProp('GrButton', 'tone', () => props.tone ?? group?.tone.value, 'primary')\nconst isSquare = useGrComponentProp('GrButton', 'square', () => props.square, false)\n\nconst { t } = useGranularityTranslations()\nconst resolvedLoadingText = computed(() => props.loadingText ?? t('gr.button.loading', 'Loading…'))\n\n// Полиморфный корень: `as` → `<a href>` → `<button>`.\nconst isLink = computed(() => Boolean(props.as || props.href))\nconst renderAs = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\n// Неинтерактивно при явном `disabled` ИЛИ во время `loading`.\nconst blocked = computed(() => props.disabled || props.loading)\n\n// Ключевое: `loading` НЕ ставит нативный `disabled` (элемент бы выпал из фокуса и\n// скринридер потерял бы контекст) — вместо этого `aria-disabled` + перехват клика.\n// Нативный `disabled` (только у `<button>`) оставляем лишь для явного `disabled`.\nconst nativeDisabled = computed(() => (renderAs.value === 'button' && props.disabled) ? true : undefined)\nconst ariaDisabled = computed(() => (props.loading || (isLink.value && props.disabled)) ? 'true' : undefined)\n\nconst resolvedTarget = computed(() => props.target ?? (props.external ? '_blank' : undefined))\nconst resolvedRel = computed(() => props.rel ?? (resolvedTarget.value === '_blank' ? 'noopener noreferrer' : undefined))\n\nfunction onClickCapture(e: MouseEvent): void {\n // Блокируем и дефолт (submit/навигация), и внешние обработчики (в т.ч. по Enter/Space),\n // сохраняя фокус на элементе.\n if (blocked.value) {\n e.preventDefault()\n e.stopImmediatePropagation()\n }\n}\n\n// Корень динамический (`as` принимает и тег, и компонент), поэтому ref может\n// оказаться как элементом, так и инстансом — например роутерной ссылкой.\nconst rootEl = ref<HTMLElement | { $el?: HTMLElement } | null>(null)\n\n/**\n * Фокус на кнопку из кода. Нужен там, где окно обязано открываться с фокусом\n * на конкретном действии (`GrConfirmDialog`), и потребителю не должно быть\n * важно, тегом или компонентом отрисован корень.\n */\nfunction focus(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.focus?.()\n}\n\nfunction blur(): void {\n const root = rootEl.value\n const el = root instanceof HTMLElement ? root : root?.$el\n el?.blur?.()\n}\n\ndefineExpose({ focus, blur })\n\nconst className = computed(() => {\n return grButtonClass({\n variant: resolvedVariant.value,\n tone: resolvedTone.value,\n size: resolvedSize.value,\n square: isSquare.value,\n disabled: props.disabled,\n block: props.block,\n })\n})\n\ndefineSlots<{\n /** Содержимое кнопки. */\n default?: () => any\n /** Аддон слева: иконка, счётчик. В состоянии загрузки уступает место спиннеру. */\n prefix?: () => any\n /** Аддон справа: шеврон, счётчик. */\n suffix?: () => any\n}>()\n</script>\n\n<template>\n <component\n :is=\"renderAs\"\n ref=\"rootEl\"\n data-gr-button\n :data-gr-variant=\"resolvedVariant\"\n :data-gr-tone=\"resolvedTone\"\n :type=\"renderAs === 'button' ? props.type : undefined\"\n :disabled=\"nativeDisabled\"\n :href=\"isLink && !props.disabled ? props.href : undefined\"\n :target=\"isLink && !props.disabled ? resolvedTarget : undefined\"\n :rel=\"isLink && !props.disabled ? resolvedRel : undefined\"\n :aria-busy=\"props.loading ? 'true' : undefined\"\n :aria-disabled=\"ariaDisabled\"\n :aria-label=\"props.ariaLabel\"\n :tabindex=\"isLink && props.disabled ? -1 : undefined\"\n :class=\"[grButtonBaseClass, className, blocked ? 'cursor-not-allowed' : '']\"\n @click.capture=\"onClickCapture\"\n >\n <!-- Спиннер занимает место префикса: две иконки рядом читались бы как ошибка. -->\n <IconLoader v-if=\"props.loading\" class=\"h-4 w-4 animate-spin\" aria-hidden=\"true\" />\n <slot v-else name=\"prefix\" />\n\n <slot />\n\n <slot name=\"suffix\" />\n\n <span v-if=\"props.loading\" class=\"sr-only\">{{ resolvedLoadingText }}</span>\n </component>\n</template>\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as GrButton_default } from "./chunks/GrButton-Bw2AH4uX.js";
2
- import { t as grButtonSafelist } from "../../chunks/safelist-BOq5Li7p.js";
3
- import { t as grButtonConfig } from "../../chunks/config-BHcS5Cwm.js";
1
+ import { t as GrButton_default } from "./chunks/GrButton-7GP0zObj.js";
2
+ import { t as grButtonSafelist } from "../../chunks/safelist-DxkMj5IW.js";
3
+ import { t as grButtonConfig } from "../../chunks/config-87fszqnD.js";
4
4
  export { GrButton_default as GrButton, GrButton_default as default, grButtonConfig, grButtonSafelist };
@@ -1 +1 @@
1
- {"version":3,"file":"GrButtonGroup-CKyiAV8K.js","names":[],"sources":["../../../../src/components/GrButtonGroup/GrButtonGroup.vue","../../../../src/components/GrButtonGroup/GrButtonGroup.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton/grButtonStyles'\nimport { provideGrButtonGroup } from './context'\n\nexport type GrButtonGroupOrientation = 'horizontal' | 'vertical'\n\nexport interface GrButtonGroupProps {\n /** Доступное имя группы: без него кнопки читаются как несвязанные. */\n ariaLabel?: string\n orientation?: GrButtonGroupOrientation\n /**\n * Склеивать кнопки в один блок. `false` — обычный ряд с зазором: каждая\n * кнопка сохраняет свои радиусы и границы.\n */\n attached?: boolean\n /** Оформление, общее для кнопок группы. Проп самой кнопки сильнее. */\n size?: GrButtonSize\n variant?: GrButtonVariant\n tone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrButtonGroupProps>(), {\n ariaLabel: undefined,\n orientation: 'horizontal',\n attached: true,\n size: undefined,\n variant: undefined,\n tone: undefined,\n})\n\nprovideGrButtonGroup({\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n tone: computed(() => props.tone),\n})\n\ndefineSlots<{\n /** Кнопки группы. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n data-gr-button-group\n class=\"inline-flex\"\n :class=\"[\n orientation === 'vertical' ? 'flex-col items-stretch' : 'items-stretch',\n attached ? '' : 'gap-2',\n ]\"\n :data-orientation=\"orientation\"\n :data-attached=\"attached ? '' : undefined\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <slot />\n </div>\n</template>\n\n<style>\n/*\n * Склейка держится на понятии «звено группы» — прямом потомке, который сам\n * кнопка или содержит кнопку. Обёртка (тултип, `<span v-if>`, роутерная\n * ссылка) поэтому не разрывает ряд, а не-кнопочный потомок (разделитель,\n * подпись) в склейку не попадает и скругление себе не забирает.\n *\n * Края считаются от соседства звеньев, а не от `:first-child`/`:last-child`:\n * ведущий край гасится у звена, перед которым уже было звено, ведомый — у\n * звена, за которым звено ещё будет.\n */\n[data-gr-button-group] {\n --gr-button-group-radius: var(--gr-button-radius, 0.375rem);\n}\n\n[data-gr-button-group][data-attached] [data-gr-button] {\n border-radius: var(--gr-button-group-radius);\n position: relative;\n}\n\n/* Кнопка под курсором или с фокусом — поверх соседей: иначе её граница и\n фокус-кольцо срезаются наложением. */\n[data-gr-button-group] [data-gr-button]:hover,\n[data-gr-button-group] [data-gr-button]:focus-visible {\n z-index: 1;\n}\n\n/* ————— Горизонтальная группа. */\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-inline-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-end-start-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-start-end-radius: 0;\n border-end-end-radius: 0;\n}\n\n/* ————— Вертикальная группа: та же логика, другая ось. */\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-block-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton/grButtonStyles'\nimport { provideGrButtonGroup } from './context'\n\nexport type GrButtonGroupOrientation = 'horizontal' | 'vertical'\n\nexport interface GrButtonGroupProps {\n /** Доступное имя группы: без него кнопки читаются как несвязанные. */\n ariaLabel?: string\n orientation?: GrButtonGroupOrientation\n /**\n * Склеивать кнопки в один блок. `false` — обычный ряд с зазором: каждая\n * кнопка сохраняет свои радиусы и границы.\n */\n attached?: boolean\n /** Оформление, общее для кнопок группы. Проп самой кнопки сильнее. */\n size?: GrButtonSize\n variant?: GrButtonVariant\n tone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrButtonGroupProps>(), {\n ariaLabel: undefined,\n orientation: 'horizontal',\n attached: true,\n size: undefined,\n variant: undefined,\n tone: undefined,\n})\n\nprovideGrButtonGroup({\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n tone: computed(() => props.tone),\n})\n\ndefineSlots<{\n /** Кнопки группы. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <div\n data-gr-button-group\n class=\"inline-flex\"\n :class=\"[\n orientation === 'vertical' ? 'flex-col items-stretch' : 'items-stretch',\n attached ? '' : 'gap-2',\n ]\"\n :data-orientation=\"orientation\"\n :data-attached=\"attached ? '' : undefined\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <slot />\n </div>\n</template>\n\n<style>\n/*\n * Склейка держится на понятии «звено группы» — прямом потомке, который сам\n * кнопка или содержит кнопку. Обёртка (тултип, `<span v-if>`, роутерная\n * ссылка) поэтому не разрывает ряд, а не-кнопочный потомок (разделитель,\n * подпись) в склейку не попадает и скругление себе не забирает.\n *\n * Края считаются от соседства звеньев, а не от `:first-child`/`:last-child`:\n * ведущий край гасится у звена, перед которым уже было звено, ведомый — у\n * звена, за которым звено ещё будет.\n */\n[data-gr-button-group] {\n --gr-button-group-radius: var(--gr-button-radius, 0.375rem);\n}\n\n[data-gr-button-group][data-attached] [data-gr-button] {\n border-radius: var(--gr-button-group-radius);\n position: relative;\n}\n\n/* Кнопка под курсором или с фокусом — поверх соседей: иначе её граница и\n фокус-кольцо срезаются наложением. */\n[data-gr-button-group] [data-gr-button]:hover,\n[data-gr-button-group] [data-gr-button]:focus-visible {\n z-index: 1;\n}\n\n/* ————— Горизонтальная группа. */\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-inline-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-end-start-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-start-end-radius: 0;\n border-end-end-radius: 0;\n}\n\n/* ————— Вертикальная группа: та же логика, другая ось. */\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-block-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,QAAQ;EASd,qBAAqB;GACnB,MAAM,eAAe,MAAM,IAAI;GAC/B,SAAS,eAAe,MAAM,OAAO;GACrC,MAAM,eAAe,MAAM,IAAI;EACjC,CAAC;;uBAUC,mBAaM,OAAA;IAZJ,wBAAA;IACA,OAAK,eAAA,CAAC,eAAa,CACH,QAAA,gBAAW,aAAA,2BAAA,iBAAoE,QAAA,WAAQ,KAAA,OAAA,CAAA,CAAA;IAItG,oBAAkB,QAAA;IAClB,iBAAe,QAAA,WAAQ,KAAQ,KAAA;IAChC,MAAK;IACJ,cAAY,QAAA;OAEb,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,IAAA,UAAA"}
1
+ {"version":3,"file":"GrButtonGroup-CKyiAV8K.js","names":[],"sources":["../../../../src/components/GrButtonGroup/GrButtonGroup.vue","../../../../src/components/GrButtonGroup/GrButtonGroup.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton/grButtonStyles'\nimport { provideGrButtonGroup } from './context'\n\nexport type GrButtonGroupOrientation = 'horizontal' | 'vertical'\n\nexport interface GrButtonGroupProps {\n /** Доступное имя группы: без него кнопки читаются как несвязанные. */\n ariaLabel?: string\n orientation?: GrButtonGroupOrientation\n /**\n * Склеивать кнопки в один блок. `false` — обычный ряд с зазором: каждая\n * кнопка сохраняет свои радиусы и границы.\n */\n attached?: boolean\n /** Оформление, общее для кнопок группы. Проп самой кнопки сильнее. */\n size?: GrButtonSize\n variant?: GrButtonVariant\n tone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrButtonGroupProps>(), {\n ariaLabel: undefined,\n orientation: 'horizontal',\n attached: true,\n size: undefined,\n variant: undefined,\n tone: undefined,\n})\n\nprovideGrButtonGroup({\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n tone: computed(() => props.tone),\n})\n\ndefineSlots<{\n /** Кнопки группы. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <div\n data-gr-button-group\n class=\"inline-flex\"\n :class=\"[\n orientation === 'vertical' ? 'flex-col items-stretch' : 'items-stretch',\n attached ? '' : 'gap-2',\n ]\"\n :data-orientation=\"orientation\"\n :data-attached=\"attached ? '' : undefined\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <slot />\n </div>\n</template>\n\n<style>\n/*\n * Склейка держится на понятии «звено группы» — прямом потомке, который сам\n * кнопка или содержит кнопку. Обёртка (тултип, `<span v-if>`, роутерная\n * ссылка) поэтому не разрывает ряд, а не-кнопочный потомок (разделитель,\n * подпись) в склейку не попадает и скругление себе не забирает.\n *\n * Края считаются от соседства звеньев, а не от `:first-child`/`:last-child`:\n * ведущий край гасится у звена, перед которым уже было звено, ведомый — у\n * звена, за которым звено ещё будет.\n */\n[data-gr-button-group] {\n --gr-button-group-radius: var(--gr-button-radius, 0.375rem);\n}\n\n[data-gr-button-group][data-attached] [data-gr-button] {\n border-radius: var(--gr-button-group-radius);\n position: relative;\n}\n\n/* Кнопка под курсором или с фокусом — поверх соседей: иначе её граница и\n фокус-кольцо срезаются наложением. */\n[data-gr-button-group] [data-gr-button]:hover,\n[data-gr-button-group] [data-gr-button]:focus-visible {\n z-index: 1;\n}\n\n/* ————— Горизонтальная группа. */\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-inline-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-end-start-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-start-end-radius: 0;\n border-end-end-radius: 0;\n}\n\n/* ————— Вертикальная группа: та же логика, другая ось. */\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-block-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton/grButtonStyles'\nimport { provideGrButtonGroup } from './context'\n\nexport type GrButtonGroupOrientation = 'horizontal' | 'vertical'\n\nexport interface GrButtonGroupProps {\n /** Доступное имя группы: без него кнопки читаются как несвязанные. */\n ariaLabel?: string\n orientation?: GrButtonGroupOrientation\n /**\n * Склеивать кнопки в один блок. `false` — обычный ряд с зазором: каждая\n * кнопка сохраняет свои радиусы и границы.\n */\n attached?: boolean\n /** Оформление, общее для кнопок группы. Проп самой кнопки сильнее. */\n size?: GrButtonSize\n variant?: GrButtonVariant\n tone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrButtonGroupProps>(), {\n ariaLabel: undefined,\n orientation: 'horizontal',\n attached: true,\n size: undefined,\n variant: undefined,\n tone: undefined,\n})\n\nprovideGrButtonGroup({\n size: computed(() => props.size),\n variant: computed(() => props.variant),\n tone: computed(() => props.tone),\n})\n\ndefineSlots<{\n /** Кнопки группы. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <div\n data-gr-button-group\n class=\"inline-flex\"\n :class=\"[\n orientation === 'vertical' ? 'flex-col items-stretch' : 'items-stretch',\n attached ? '' : 'gap-2',\n ]\"\n :data-orientation=\"orientation\"\n :data-attached=\"attached ? '' : undefined\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n >\n <slot />\n </div>\n</template>\n\n<style>\n/*\n * Склейка держится на понятии «звено группы» — прямом потомке, который сам\n * кнопка или содержит кнопку. Обёртка (тултип, `<span v-if>`, роутерная\n * ссылка) поэтому не разрывает ряд, а не-кнопочный потомок (разделитель,\n * подпись) в склейку не попадает и скругление себе не забирает.\n *\n * Края считаются от соседства звеньев, а не от `:first-child`/`:last-child`:\n * ведущий край гасится у звена, перед которым уже было звено, ведомый — у\n * звена, за которым звено ещё будет.\n */\n[data-gr-button-group] {\n --gr-button-group-radius: var(--gr-button-radius, 0.375rem);\n}\n\n[data-gr-button-group][data-attached] [data-gr-button] {\n border-radius: var(--gr-button-group-radius);\n position: relative;\n}\n\n/* Кнопка под курсором или с фокусом — поверх соседей: иначе её граница и\n фокус-кольцо срезаются наложением. */\n[data-gr-button-group] [data-gr-button]:hover,\n[data-gr-button-group] [data-gr-button]:focus-visible {\n z-index: 1;\n}\n\n/* ————— Горизонтальная группа. */\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-inline-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-end-start-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='horizontal'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-start-end-radius: 0;\n border-end-end-radius: 0;\n}\n\n/* ————— Вертикальная группа: та же логика, другая ось. */\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :is([data-gr-button], :has([data-gr-button])) {\n margin-block-start: -1px;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ [data-gr-button],\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :is([data-gr-button], :has([data-gr-button])) ~ :has([data-gr-button]) [data-gr-button] {\n border-start-start-radius: 0;\n border-start-end-radius: 0;\n}\n\n[data-gr-button-group][data-attached][data-orientation='vertical'] > [data-gr-button]:has(~ :is([data-gr-button], :has([data-gr-button]))),\n[data-gr-button-group][data-attached][data-orientation='vertical'] > :has([data-gr-button]):has(~ :is([data-gr-button], :has([data-gr-button]))) [data-gr-button] {\n border-end-start-radius: 0;\n border-end-end-radius: 0;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,QAAQ;EASd,qBAAqB;GACnB,MAAM,eAAe,MAAM,IAAI;GAC/B,SAAS,eAAe,MAAM,OAAO;GACrC,MAAM,eAAe,MAAM,IAAI;EACjC,CAAC;;uBASC,mBAaM,OAAA;IAZJ,wBAAA;IACA,OAAK,eAAA,CAAC,eAAa,CACH,QAAA,gBAAW,aAAA,2BAAA,iBAAoE,QAAA,WAAQ,KAAA,OAAA,CAAA,CAAA;IAItG,oBAAkB,QAAA;IAClB,iBAAe,QAAA,WAAQ,KAAQ,KAAA;IAChC,MAAK;IACJ,cAAY,QAAA;OAEb,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,IAAA,UAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"GrCard-BttXz1pQ.js","names":["$slots"],"sources":["../../../../src/components/GrCard/GrCard.vue","../../../../src/components/GrCard/GrCard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n headerActionsClass,\n headerRowClass,\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button') return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\n/**\n * Действия рисуются в **собственной** шапке карточки и включают её наравне с\n * заголовком. Без этого слота карточке с кнопкой приходилось забирать `#header`\n * целиком — а вместе с ним заново писать заголовок, его уровень и отступы. К\n * этому обходу независимо пришли `GrDashboardItem` в этом же кольце и обёртки\n * потребителей; оба теряли настоящий `h2…h6` и шкалу отступов.\n */\nconst hasActions = computed(() => !hasOwnHeader.value && Boolean(slots.actions))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value || hasActions.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || slots.actions || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /**\n * Действия справа в собственной шапке карточки: «⋯», «Обновить»,\n * переключатель периода. Включают шапку так же, как `title`.\n *\n * Со слотом `#header` не сочетается: тот заменяет шапку целиком, и всё, что в\n * ней есть, рисует потребитель.\n */\n actions?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <div :class=\"hasActions ? headerRowClass : undefined\">\n <div class=\"min-w-0\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </div>\n\n <div v-if=\"hasActions\" data-gr-card-actions :class=\"headerActionsClass\">\n <slot name=\"actions\" />\n </div>\n </div>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n headerActionsClass,\n headerRowClass,\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button') return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\n/**\n * Действия рисуются в **собственной** шапке карточки и включают её наравне с\n * заголовком. Без этого слота карточке с кнопкой приходилось забирать `#header`\n * целиком — а вместе с ним заново писать заголовок, его уровень и отступы. К\n * этому обходу независимо пришли `GrDashboardItem` в этом же кольце и обёртки\n * потребителей; оба теряли настоящий `h2…h6` и шкалу отступов.\n */\nconst hasActions = computed(() => !hasOwnHeader.value && Boolean(slots.actions))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value || hasActions.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || slots.actions || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /**\n * Действия справа в собственной шапке карточки: «⋯», «Обновить»,\n * переключатель периода. Включают шапку так же, как `title`.\n *\n * Со слотом `#header` не сочетается: тот заменяет шапку целиком, и всё, что в\n * ней есть, рисует потребитель.\n */\n actions?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <div :class=\"hasActions ? headerRowClass : undefined\">\n <div class=\"min-w-0\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </div>\n\n <div v-if=\"hasActions\" data-gr-card-actions :class=\"headerActionsClass\">\n <slot name=\"actions\" />\n </div>\n </div>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrCard-BttXz1pQ.js","names":["$slots"],"sources":["../../../../src/components/GrCard/GrCard.vue","../../../../src/components/GrCard/GrCard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n headerActionsClass,\n headerRowClass,\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button')\n return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\n/**\n * Действия рисуются в **собственной** шапке карточки и включают её наравне с\n * заголовком. Без этого слота карточке с кнопкой приходилось забирать `#header`\n * целиком — а вместе с ним заново писать заголовок, его уровень и отступы. К\n * этому обходу независимо пришли `GrDashboardItem` в этом же кольце и обёртки\n * потребителей; оба теряли настоящий `h2…h6` и шкалу отступов.\n */\nconst hasActions = computed(() => !hasOwnHeader.value && Boolean(slots.actions))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value || hasActions.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || slots.actions || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /**\n * Действия справа в собственной шапке карточки: «⋯», «Обновить»,\n * переключатель периода. Включают шапку так же, как `title`.\n *\n * Со слотом `#header` не сочетается: тот заменяет шапку целиком, и всё, что в\n * ней есть, рисует потребитель.\n */\n actions?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <div :class=\"hasActions ? headerRowClass : undefined\">\n <div class=\"min-w-0\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </div>\n\n <div v-if=\"hasActions\" data-gr-card-actions :class=\"headerActionsClass\">\n <slot name=\"actions\" />\n </div>\n </div>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, markRaw, useId, useSlots, type Component } from 'vue'\n\nimport { useGrComponentProp } from '../GrConfigProvider/context'\n\nimport {\n headerActionsClass,\n headerRowClass,\n cardDescriptionClass,\n cardTitleClass,\n grCardRootClass,\n ownHeaderPaddingClass,\n paddingClass,\n sectionDividerBottomClass,\n sectionDividerTopClass,\n type GrCardHeadingLevel,\n type GrCardPadding,\n type GrCardVariant,\n} from './grCardStyles'\n\nexport type { GrCardHeadingLevel, GrCardPadding, GrCardVariant } from './grCardStyles'\n\nexport interface GrCardProps {\n /**\n * Внутренние отступы. По умолчанию `none`: карточка — поверхность, а её\n * содержимое (`GrCollapse`, `GrList`) само знает про свои отступы.\n */\n padding?: GrCardPadding\n /** `elevated` — рамка, фон и тень; `outlined` — без тени; `ghost` — без рамки. */\n variant?: GrCardVariant\n /** Свой корневой тег (`RouterLink`, `Link` от Inertia). Сильнее `href`. */\n as?: string | Component\n /** Карточка-ссылка. */\n href?: string\n /** Карточка-кнопка: интерактивна вся поверхность. */\n clickable?: boolean\n /** Подсветка при наведении без интерактивности. */\n hoverable?: boolean\n /** Классы обёртки тела — она появляется вместе с секциями. */\n bodyClass?: string\n /**\n * Заголовок карточки — настоящий `h2`…`h6`, а не жирная строка: отчёт из\n * шести карточек иначе не обойти по структуре, после `h1` страницы в нём\n * нет ни одного заголовка.\n */\n title?: string\n /** Пояснение под заголовком. */\n description?: string\n /** Уровень заголовка под структуру страницы. Не задан — из `GrConfigProvider`, иначе `3`. */\n headingLevel?: GrCardHeadingLevel\n}\n\nexport interface GrCardEmits {\n (e: 'click', event: MouseEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCardProps>(), {\n // Настраивается через `GrConfigProvider`; дефолты — в резолверах ниже.\n padding: undefined,\n variant: undefined,\n as: undefined,\n href: undefined,\n clickable: false,\n hoverable: false,\n bodyClass: undefined,\n title: undefined,\n description: undefined,\n headingLevel: undefined,\n})\n\nconst emit = defineEmits<GrCardEmits>()\n\nconst slots = useSlots()\n\nconst resolvedPadding = useGrComponentProp('GrCard', 'padding', () => props.padding, 'none')\nconst resolvedVariant = useGrComponentProp('GrCard', 'variant', () => props.variant, 'elevated')\n\nconst isInteractive = computed(() => !!props.as || !!props.href || props.clickable)\n\nconst rootTag = computed<string | Component>(() => {\n if (props.as)\n return typeof props.as === 'string' ? props.as : markRaw(props.as)\n\n if (props.href)\n return 'a'\n\n return props.clickable ? 'button' : 'div'\n})\n\n/**\n * Компонент-ссылка (`Link` от Inertia, `RouterLink`) рендерит `<a>` сам, и без\n * `href` он ведёт в никуда. Строковый тег, кроме `a`, атрибут не понимает —\n * там он и гасится.\n */\nconst rootHref = computed(() => (\n typeof rootTag.value === 'string' && rootTag.value !== 'a' ? undefined : props.href\n))\n\nconst headingLevel = useGrComponentProp('GrCard', 'headingLevel', () => props.headingLevel, 3)\n\n/**\n * Заголовок внутри `<button>` невалиден: контент-модель кнопки — phrasing\n * content. Кликабельная карточка печатает подпись `<span>`, а структура\n * страницы в этом случае собирается ссылкой в заголовке рядом с `hoverable`.\n */\nlet headingInButtonWarned = false\n\nconst headingTag = computed(() => {\n if (rootTag.value !== 'button')\n return `h${headingLevel.value}`\n\n if (!headingInButtonWarned && __GR_DEV__) {\n headingInButtonWarned = true\n console.warn(\n '[GrCard] `title` внутри `clickable` печатается `<span>`: заголовок в '\n + '`<button>` невалиден по HTML. Нужен заголовок в структуре страницы — '\n + 'замените `clickable` на `hoverable` и поставьте ссылку в сам заголовок.',\n )\n }\n\n return 'span'\n})\n\nconst titleId = useId()\nconst descriptionId = useId()\n\n// `#header` сильнее пропов: нестандартная шапка не обязана объяснять, почему\n// она не `title`.\nconst hasOwnHeader = computed(() => Boolean(slots.header))\nconst hasTitle = computed(() => !hasOwnHeader.value && Boolean(props.title))\nconst hasDescription = computed(() => !hasOwnHeader.value && Boolean(props.description))\n/**\n * Действия рисуются в **собственной** шапке карточки и включают её наравне с\n * заголовком. Без этого слота карточке с кнопкой приходилось забирать `#header`\n * целиком — а вместе с ним заново писать заголовок, его уровень и отступы. К\n * этому обходу независимо пришли `GrDashboardItem` в этом же кольце и обёртки\n * потребителей; оба теряли настоящий `h2…h6` и шкалу отступов.\n */\nconst hasActions = computed(() => !hasOwnHeader.value && Boolean(slots.actions))\nconst hasHeadingBlock = computed(() => hasTitle.value || hasDescription.value || hasActions.value)\n\n/**\n * Обёртки появляются, только когда их попросили: карточка без секций остаётся\n * одним `<div>` со слотом внутри — ровно тем, что рендерили `GrCollapse` и\n * `GrList` до появления пропов.\n */\nconst hasSections = computed(() => Boolean(\n slots.header || slots.footer || slots.actions || props.bodyClass || hasHeadingBlock.value,\n))\n\n/**\n * Имя карточки-ссылки. Без него доступным именем становится всё содержимое\n * подряд — заголовок, описание и тело одной строкой.\n */\nconst rootLabelledBy = computed(() => (isInteractive.value && hasTitle.value ? titleId : undefined))\nconst rootDescribedBy = computed(() => (isInteractive.value && hasDescription.value ? descriptionId : undefined))\n\nconst rootClass = computed(() => grCardRootClass({\n variant: resolvedVariant.value,\n // С секциями отступ принадлежит каждой из них, а не поверхности целиком.\n padding: hasSections.value ? 'none' : resolvedPadding.value,\n interactive: isInteractive.value,\n hoverable: props.hoverable,\n}))\n\nconst sectionPaddingClass = computed(() => paddingClass[resolvedPadding.value])\n\n/**\n * Карточка отбивает то, что рисует сама. Шапка из `title` — её собственная, и\n * отступ ей полагается независимо от `padding`. Слот `#header` сильнее пропов и\n * заменяет шапку целиком: там отступы принадлежат тому, кто её наполнил, —\n * иначе потребитель со своими отступами внутри слота получил бы двойные.\n */\nconst headerClass = computed(() => [\n hasOwnHeader.value ? sectionPaddingClass.value : ownHeaderPaddingClass,\n sectionDividerBottomClass,\n].filter(Boolean).join(' '))\nconst footerClass = computed(() => [sectionPaddingClass.value, sectionDividerTopClass].filter(Boolean).join(' '))\nconst bodySectionClass = computed(() => [sectionPaddingClass.value, props.bodyClass].filter(Boolean).join(' '))\n\nfunction onClick(event: MouseEvent): void {\n emit('click', event)\n}\n\ndefineSlots<{\n /** Содержимое карточки. */\n default?: () => any\n /** Шапка вместо пропов `title` и `description`. */\n header?: () => any\n /**\n * Действия справа в собственной шапке карточки: «⋯», «Обновить»,\n * переключатель периода. Включают шапку так же, как `title`.\n *\n * Со слотом `#header` не сочетается: тот заменяет шапку целиком, и всё, что в\n * ней есть, рисует потребитель.\n */\n actions?: () => any\n /** Подвал: действия, сводка, пагинация. */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-card\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootHref\"\n :class=\"rootClass\"\n :aria-labelledby=\"rootLabelledBy\"\n :aria-describedby=\"rootDescribedBy\"\n @click=\"onClick\"\n >\n <template v-if=\"hasSections\">\n <div v-if=\"hasOwnHeader || hasHeadingBlock\" data-gr-card-header :class=\"headerClass\">\n <slot name=\"header\">\n <div :class=\"hasActions ? headerRowClass : undefined\">\n <div class=\"min-w-0\">\n <component\n :is=\"headingTag\"\n v-if=\"hasTitle\"\n :id=\"titleId\"\n data-gr-card-title\n :class=\"cardTitleClass\"\n >\n {{ title }}\n </component>\n\n <p\n v-if=\"hasDescription\"\n :id=\"descriptionId\"\n data-gr-card-description\n :class=\"cardDescriptionClass\"\n >\n {{ description }}\n </p>\n </div>\n\n <div v-if=\"hasActions\" data-gr-card-actions :class=\"headerActionsClass\">\n <slot name=\"actions\" />\n </div>\n </div>\n </slot>\n </div>\n\n <div data-gr-card-body :class=\"bodySectionClass\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-card-footer :class=\"footerClass\">\n <slot name=\"footer\" />\n </div>\n </template>\n\n <slot v-else />\n </component>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"GrCheckbox-CEcHIsXM.js","names":[],"sources":["../../../../src/components/GrCheckbox/grCheckboxGroupContext.ts","../../../../src/components/GrCheckbox/GrCheckbox.vue","../../../../src/components/GrCheckbox/GrCheckbox.vue"],"sourcesContent":["import type { ComputedRef, InjectionKey } from 'vue'\n\nimport type { GrCheckboxSize } from './grCheckboxStyles'\n\nexport type GrCheckboxGroupContext = {\n /** Выбранные значения группы. Чекбокс сравнивает с ними свой `value`. */\n modelValue: ComputedRef<string[]>\n name: ComputedRef<string | undefined>\n disabled: ComputedRef<boolean>\n readonly: ComputedRef<boolean>\n invalid: ComputedRef<boolean>\n /**\n * Обязательность группы объявляют её чекбоксы: `role=\"group\"` не поддерживает\n * `aria-required` (axe: `aria-allowed-attr`), а `role=\"checkbox\"` — да.\n */\n required: ComputedRef<boolean>\n size: ComputedRef<GrCheckboxSize>\n /** Добавляет или убирает значение из выбранных. */\n toggle: (value: string, checked: boolean) => void\n}\n\nexport const GR_CHECKBOX_GROUP_CONTEXT: InjectionKey<GrCheckboxGroupContext> = Symbol('GR_CHECKBOX_GROUP_CONTEXT')\n","<script setup lang=\"ts\">\n/**\n * GrCheckbox — GR-примитив чекбокса с нативным скрытым `<input type=\"checkbox\">`\n * для интеграции с HTML-формами (`FormData`, `form`).\n *\n * Источник истины — нативный input: клик по нему (в т.ч. по внешнему\n * `<label for=\"...\">`) слушается через `@change` и эмитит модель. Клик по видимой\n * части компонента переключает через корневой обработчик.\n *\n * Клавиатура: `Space` переключает значение (Enter — намеренно нет, это нестандартно\n * для чекбоксов). Фокус — на самом контроле (квадратике), как у нативного чекбокса.\n *\n * A11y: `role=\"checkbox\"` + `aria-checked` (`true`/`false`/`mixed`) + `aria-disabled`.\n * Роль висит **только на контроле**, а не на всей строке с подписью — по двум причинам:\n * - роль объявляет своих потомков презентационными, поэтому ни нативный input, ни\n * интерактивная подпись (ссылка на политику, кнопка «показать изменения») не могут\n * жить внутри: скринридер теряет их, axe падает на `nested-interactive`;\n * - имя виджета берётся из подписи через `aria-labelledby`, что и позволяет держать\n * её снаружи вместе со всем её интерактивным содержимым.\n *\n * `required` объявляется только через `aria-required`, на скрытый input он не уходит.\n * Нативная проверка потребовала бы фокуса на невалидном контроле, а он невидим и\n * `aria-hidden` — Chrome в таком случае молча отменяет сабмит всей формы\n * («An invalid form control … is not focusable»). Обязательность проверяет\n * `GrForm` правилом `required` — см. `docs/components/GrCheckbox.md`.\n *\n * Внутри `GrCheckboxGroup` значение приходит из группы: свой `modelValue` не\n * задаётся, а `value` сравнивается с массивом выбранных.\n */\nimport { computed, inject, onMounted, ref, useId, useSlots, watch } from 'vue'\nimport IconCheck from '~icons/lucide/check'\nimport IconMinus from '~icons/lucide/minus'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\n\nimport { GR_CHECKBOX_GROUP_CONTEXT } from './grCheckboxGroupContext'\nimport {\n grCheckboxCheckIconClass,\n grCheckboxControlClass,\n grCheckboxIndeterminateIconClass,\n grCheckboxLabelClass,\n grCheckboxRootClass,\n type GrCheckboxLabelPosition,\n type GrCheckboxSize,\n} from './grCheckboxStyles'\n\nexport type { GrCheckboxLabelPosition, GrCheckboxSize } from './grCheckboxStyles'\n\nexport interface GrCheckboxProps {\n /** Не задан внутри `GrCheckboxGroup` — состояние берётся из группы. */\n modelValue?: boolean\n disabled?: boolean\n name?: string\n value?: string\n /** Обязательное поле: объявляется как `aria-required`, нативной проверки нет. */\n required?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n form?: string\n /** Пробрасывается на скрытый нативный `<input>`, чтобы работал `<label for=\"...\">`. */\n id?: string\n /** Промежуточное («смешанное») состояние: `aria-checked=\"mixed\"`, индикатор — тире. */\n indeterminate?: boolean\n /** Имя контрола, когда подписи в слоте нет (или она чисто визуальная). */\n ariaLabel?: string\n /** Сторона подписи относительно контрола. */\n labelPosition?: GrCheckboxLabelPosition\n /** Размер контрола. Не задан — берётся из группы, затем из `GrConfigProvider`, иначе `md`. */\n size?: GrCheckboxSize\n}\n\nexport interface GrCheckboxEmits {\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 hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrCheckboxProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n value: 'on',\n required: false,\n readonly: false,\n invalid: false,\n form: undefined,\n id: undefined,\n indeterminate: false,\n ariaLabel: undefined,\n labelPosition: 'end',\n size: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxEmits>()\ndefineSlots<{\n /** Подпись флажка. Может содержать ссылки: роль остаётся на самом контроле. */\n default?: () => any\n}>()\n\n\nconst slots = useSlots()\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(slots.default))\n\nconst group = inject(GR_CHECKBOX_GROUP_CONTEXT, null)\n\nconst checked = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n if (group)\n return group.modelValue.value.includes(props.value)\n\n return false\n})\n\nconst resolvedName = computed(() => props.name ?? group?.name.value)\n\n// Контекст `GrFormField`. Id поля вешается на `span[role=\"checkbox\"]` — именно он\n// виджет и держит фокус; на скрытом `aria-hidden`-инпуте он был бы бесполезен\n// (клик по подписи уводил бы фокус в невидимый элемент). Роль-виджет не является\n// labelable-элементом, поэтому имя от подписи поля приходит через `aria-labelledby`.\nconst {\n disabled: isDisabled,\n id: fieldControlId,\n labelId: fieldLabelId,\n describedBy,\n invalid: fieldInvalid,\n required: fieldRequired,\n readonly: fieldReadonly,\n} = useGrFormControl(() => props)\n\n// «Или», а не `??`: `isDisabled` уже сведён к булеву (свой проп + контекст\n// поля и формы), и `??` до группы просто не дошёл бы.\nconst resolvedDisabled = computed(() => isDisabled.value || Boolean(group?.disabled.value))\n\n// `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` — объявлять\n// обязательность и режим чтения группы обязаны сами чекбоксы.\nconst isRequired = computed(() => fieldRequired.value || Boolean(group?.required.value))\n\nconst isReadonly = computed(() => fieldReadonly.value || Boolean(group?.readonly.value))\n\n// Ошибка группы красит чекбоксы, но не объявляется на каждом из них: `aria-invalid`\n// уже висит на самой группе, и дублировать его на всех пунктах — значит заставить\n// диктор повторить «неверное значение» столько раз, сколько в группе чекбоксов.\nconst isInvalid = computed(() => fieldInvalid.value)\nconst showsInvalid = computed(() => isInvalid.value || Boolean(group?.invalid.value))\n\nconst labelledBy = computed(() => {\n if (props.ariaLabel) return undefined\n if (hasLabel.value) return labelId\n return fieldLabelId.value\n})\n\n// Эффективный размер: локальный проп → группа → `GrConfigProvider` → `md`.\nconst resolvedSize = useGrComponentSize(\n () => props.size ?? group?.size.value,\n { component: 'GrCheckbox' },\n)\n\nconst rootClassName = computed(() => grCheckboxRootClass({\n size: resolvedSize.value,\n disabled: resolvedDisabled.value,\n labelPosition: props.labelPosition,\n}))\n\nconst controlClassName = computed(() => grCheckboxControlClass({\n size: resolvedSize.value,\n active: checked.value || props.indeterminate,\n disabled: resolvedDisabled.value,\n invalid: showsInvalid.value,\n}))\n\nconst indeterminateIconClassName = computed(() => grCheckboxIndeterminateIconClass(resolvedSize.value))\n\nconst checkIconClassName = computed(() => grCheckboxCheckIconClass({\n size: resolvedSize.value,\n checked: checked.value,\n}))\n\nconst labelClassName = computed(() => grCheckboxLabelClass(resolvedSize.value))\n\n// Держим `.checked` на нативном input синхронно с состоянием — `:checked`-биндинг\n// на скрытом элементе иногда отстаёт при программных обновлениях.\nconst nativeInput = ref<HTMLInputElement | null>(null)\nconst control = ref<HTMLElement | null>(null)\nwatch(\n checked,\n (value) => {\n if (nativeInput.value && nativeInput.value.checked !== value)\n nativeInput.value.checked = value\n },\n)\n\n// `indeterminate` можно выставить только через JS-свойство (не атрибут).\nfunction syncIndeterminate(): void {\n if (nativeInput.value)\n nativeInput.value.indeterminate = props.indeterminate\n}\nwatch(() => props.indeterminate, syncIndeterminate)\nonMounted(syncIndeterminate)\n\nfunction setChecked(next: boolean): void {\n if (resolvedDisabled.value || isReadonly.value) {\n // Нативный input мог уже переключиться от клика по внешнему `<label for>` —\n // возвращаем его к состоянию модели, иначе форма отправит непринятое значение.\n if (nativeInput.value)\n nativeInput.value.checked = checked.value\n return\n }\n\n if (props.modelValue !== undefined || !group) {\n emit('update:modelValue', next)\n emit('change', next)\n return\n }\n\n group.toggle(props.value, next)\n emit('change', next)\n}\n\nfunction toggle(): void {\n // Из промежуточного состояния переключаемся во «включено» (стандартное поведение).\n setChecked(props.indeterminate ? true : !checked.value)\n}\n\n// Клик по нативному input (в т.ч. по внешнему `<label for=\"...\">`) уже переключил его\n// `.checked` — берём значение как источник истины и эмитим модель.\nfunction onNativeChange(e: Event): void {\n setChecked((e.target as HTMLInputElement).checked)\n}\n\n// `<label for>` уводит фокус на скрытый input — визуально фокус пропадает. Возвращаем\n// его на контрол, который этот фокус и показывает.\nfunction onNativeFocus(): void {\n control.value?.focus()\n}\n\nfunction focus(): void {\n control.value?.focus()\n}\n\nfunction blur(): void {\n control.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Подпись держится снаружи роли-виджета именно для того, чтобы могла содержать\n// ссылки и кнопки, — поэтому клик по её интерактивному содержимому чекбокс не\n// переключает. Вложенный `<label>` считается интерактивным: он адресует\n// собственный контрол, и переключение чекбокса «заодно» было бы сюрпризом.\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null\n if (!el)\n return false\n return !!el.closest('a,button,input,select,textarea,label,[role=\"button\"],[role=\"link\"]')\n}\n\nfunction onClick(e: MouseEvent): void {\n if (isInteractiveTarget(e.target))\n return\n toggle()\n}\n</script>\n<template>\n <div\n data-gr-checkbox\n :class=\"rootClassName\"\n @click=\"onClick\"\n >\n <input\n :id=\"id\"\n ref=\"nativeInput\"\n type=\"checkbox\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n @change=\"onNativeChange\"\n @focus=\"onNativeFocus\"\n >\n <span\n :id=\"fieldControlId\"\n ref=\"control\"\n data-gr-checkbox-indicator\n role=\"checkbox\"\n :aria-checked=\"indeterminate ? 'mixed' : (checked ? 'true' : 'false')\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"controlClassName\"\n @keydown.space.prevent=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <IconMinus\n v-if=\"indeterminate\"\n :class=\"indeterminateIconClassName\"\n />\n <IconCheck\n v-else\n :class=\"checkIconClassName\"\n />\n </span>\n <span\n v-if=\"hasLabel\"\n :id=\"labelId\"\n :class=\"labelClassName\"\n >\n <slot />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrCheckbox — GR-примитив чекбокса с нативным скрытым `<input type=\"checkbox\">`\n * для интеграции с HTML-формами (`FormData`, `form`).\n *\n * Источник истины — нативный input: клик по нему (в т.ч. по внешнему\n * `<label for=\"...\">`) слушается через `@change` и эмитит модель. Клик по видимой\n * части компонента переключает через корневой обработчик.\n *\n * Клавиатура: `Space` переключает значение (Enter — намеренно нет, это нестандартно\n * для чекбоксов). Фокус — на самом контроле (квадратике), как у нативного чекбокса.\n *\n * A11y: `role=\"checkbox\"` + `aria-checked` (`true`/`false`/`mixed`) + `aria-disabled`.\n * Роль висит **только на контроле**, а не на всей строке с подписью — по двум причинам:\n * - роль объявляет своих потомков презентационными, поэтому ни нативный input, ни\n * интерактивная подпись (ссылка на политику, кнопка «показать изменения») не могут\n * жить внутри: скринридер теряет их, axe падает на `nested-interactive`;\n * - имя виджета берётся из подписи через `aria-labelledby`, что и позволяет держать\n * её снаружи вместе со всем её интерактивным содержимым.\n *\n * `required` объявляется только через `aria-required`, на скрытый input он не уходит.\n * Нативная проверка потребовала бы фокуса на невалидном контроле, а он невидим и\n * `aria-hidden` — Chrome в таком случае молча отменяет сабмит всей формы\n * («An invalid form control … is not focusable»). Обязательность проверяет\n * `GrForm` правилом `required` — см. `docs/components/GrCheckbox.md`.\n *\n * Внутри `GrCheckboxGroup` значение приходит из группы: свой `modelValue` не\n * задаётся, а `value` сравнивается с массивом выбранных.\n */\nimport { computed, inject, onMounted, ref, useId, useSlots, watch } from 'vue'\nimport IconCheck from '~icons/lucide/check'\nimport IconMinus from '~icons/lucide/minus'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\n\nimport { GR_CHECKBOX_GROUP_CONTEXT } from './grCheckboxGroupContext'\nimport {\n grCheckboxCheckIconClass,\n grCheckboxControlClass,\n grCheckboxIndeterminateIconClass,\n grCheckboxLabelClass,\n grCheckboxRootClass,\n type GrCheckboxLabelPosition,\n type GrCheckboxSize,\n} from './grCheckboxStyles'\n\nexport type { GrCheckboxLabelPosition, GrCheckboxSize } from './grCheckboxStyles'\n\nexport interface GrCheckboxProps {\n /** Не задан внутри `GrCheckboxGroup` — состояние берётся из группы. */\n modelValue?: boolean\n disabled?: boolean\n name?: string\n value?: string\n /** Обязательное поле: объявляется как `aria-required`, нативной проверки нет. */\n required?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n form?: string\n /** Пробрасывается на скрытый нативный `<input>`, чтобы работал `<label for=\"...\">`. */\n id?: string\n /** Промежуточное («смешанное») состояние: `aria-checked=\"mixed\"`, индикатор — тире. */\n indeterminate?: boolean\n /** Имя контрола, когда подписи в слоте нет (или она чисто визуальная). */\n ariaLabel?: string\n /** Сторона подписи относительно контрола. */\n labelPosition?: GrCheckboxLabelPosition\n /** Размер контрола. Не задан — берётся из группы, затем из `GrConfigProvider`, иначе `md`. */\n size?: GrCheckboxSize\n}\n\nexport interface GrCheckboxEmits {\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 hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrCheckboxProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n value: 'on',\n required: false,\n readonly: false,\n invalid: false,\n form: undefined,\n id: undefined,\n indeterminate: false,\n ariaLabel: undefined,\n labelPosition: 'end',\n size: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxEmits>()\ndefineSlots<{\n /** Подпись флажка. Может содержать ссылки: роль остаётся на самом контроле. */\n default?: () => any\n}>()\n\n\nconst slots = useSlots()\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(slots.default))\n\nconst group = inject(GR_CHECKBOX_GROUP_CONTEXT, null)\n\nconst checked = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n if (group)\n return group.modelValue.value.includes(props.value)\n\n return false\n})\n\nconst resolvedName = computed(() => props.name ?? group?.name.value)\n\n// Контекст `GrFormField`. Id поля вешается на `span[role=\"checkbox\"]` — именно он\n// виджет и держит фокус; на скрытом `aria-hidden`-инпуте он был бы бесполезен\n// (клик по подписи уводил бы фокус в невидимый элемент). Роль-виджет не является\n// labelable-элементом, поэтому имя от подписи поля приходит через `aria-labelledby`.\nconst {\n disabled: isDisabled,\n id: fieldControlId,\n labelId: fieldLabelId,\n describedBy,\n invalid: fieldInvalid,\n required: fieldRequired,\n readonly: fieldReadonly,\n} = useGrFormControl(() => props)\n\n// «Или», а не `??`: `isDisabled` уже сведён к булеву (свой проп + контекст\n// поля и формы), и `??` до группы просто не дошёл бы.\nconst resolvedDisabled = computed(() => isDisabled.value || Boolean(group?.disabled.value))\n\n// `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` — объявлять\n// обязательность и режим чтения группы обязаны сами чекбоксы.\nconst isRequired = computed(() => fieldRequired.value || Boolean(group?.required.value))\n\nconst isReadonly = computed(() => fieldReadonly.value || Boolean(group?.readonly.value))\n\n// Ошибка группы красит чекбоксы, но не объявляется на каждом из них: `aria-invalid`\n// уже висит на самой группе, и дублировать его на всех пунктах — значит заставить\n// диктор повторить «неверное значение» столько раз, сколько в группе чекбоксов.\nconst isInvalid = computed(() => fieldInvalid.value)\nconst showsInvalid = computed(() => isInvalid.value || Boolean(group?.invalid.value))\n\nconst labelledBy = computed(() => {\n if (props.ariaLabel) return undefined\n if (hasLabel.value) return labelId\n return fieldLabelId.value\n})\n\n// Эффективный размер: локальный проп → группа → `GrConfigProvider` → `md`.\nconst resolvedSize = useGrComponentSize(\n () => props.size ?? group?.size.value,\n { component: 'GrCheckbox' },\n)\n\nconst rootClassName = computed(() => grCheckboxRootClass({\n size: resolvedSize.value,\n disabled: resolvedDisabled.value,\n labelPosition: props.labelPosition,\n}))\n\nconst controlClassName = computed(() => grCheckboxControlClass({\n size: resolvedSize.value,\n active: checked.value || props.indeterminate,\n disabled: resolvedDisabled.value,\n invalid: showsInvalid.value,\n}))\n\nconst indeterminateIconClassName = computed(() => grCheckboxIndeterminateIconClass(resolvedSize.value))\n\nconst checkIconClassName = computed(() => grCheckboxCheckIconClass({\n size: resolvedSize.value,\n checked: checked.value,\n}))\n\nconst labelClassName = computed(() => grCheckboxLabelClass(resolvedSize.value))\n\n// Держим `.checked` на нативном input синхронно с состоянием — `:checked`-биндинг\n// на скрытом элементе иногда отстаёт при программных обновлениях.\nconst nativeInput = ref<HTMLInputElement | null>(null)\nconst control = ref<HTMLElement | null>(null)\nwatch(\n checked,\n (value) => {\n if (nativeInput.value && nativeInput.value.checked !== value)\n nativeInput.value.checked = value\n },\n)\n\n// `indeterminate` можно выставить только через JS-свойство (не атрибут).\nfunction syncIndeterminate(): void {\n if (nativeInput.value)\n nativeInput.value.indeterminate = props.indeterminate\n}\nwatch(() => props.indeterminate, syncIndeterminate)\nonMounted(syncIndeterminate)\n\nfunction setChecked(next: boolean): void {\n if (resolvedDisabled.value || isReadonly.value) {\n // Нативный input мог уже переключиться от клика по внешнему `<label for>` —\n // возвращаем его к состоянию модели, иначе форма отправит непринятое значение.\n if (nativeInput.value)\n nativeInput.value.checked = checked.value\n return\n }\n\n if (props.modelValue !== undefined || !group) {\n emit('update:modelValue', next)\n emit('change', next)\n return\n }\n\n group.toggle(props.value, next)\n emit('change', next)\n}\n\nfunction toggle(): void {\n // Из промежуточного состояния переключаемся во «включено» (стандартное поведение).\n setChecked(props.indeterminate ? true : !checked.value)\n}\n\n// Клик по нативному input (в т.ч. по внешнему `<label for=\"...\">`) уже переключил его\n// `.checked` — берём значение как источник истины и эмитим модель.\nfunction onNativeChange(e: Event): void {\n setChecked((e.target as HTMLInputElement).checked)\n}\n\n// `<label for>` уводит фокус на скрытый input — визуально фокус пропадает. Возвращаем\n// его на контрол, который этот фокус и показывает.\nfunction onNativeFocus(): void {\n control.value?.focus()\n}\n\nfunction focus(): void {\n control.value?.focus()\n}\n\nfunction blur(): void {\n control.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Подпись держится снаружи роли-виджета именно для того, чтобы могла содержать\n// ссылки и кнопки, — поэтому клик по её интерактивному содержимому чекбокс не\n// переключает. Вложенный `<label>` считается интерактивным: он адресует\n// собственный контрол, и переключение чекбокса «заодно» было бы сюрпризом.\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null\n if (!el)\n return false\n return !!el.closest('a,button,input,select,textarea,label,[role=\"button\"],[role=\"link\"]')\n}\n\nfunction onClick(e: MouseEvent): void {\n if (isInteractiveTarget(e.target))\n return\n toggle()\n}\n</script>\n<template>\n <div\n data-gr-checkbox\n :class=\"rootClassName\"\n @click=\"onClick\"\n >\n <input\n :id=\"id\"\n ref=\"nativeInput\"\n type=\"checkbox\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n @change=\"onNativeChange\"\n @focus=\"onNativeFocus\"\n >\n <span\n :id=\"fieldControlId\"\n ref=\"control\"\n data-gr-checkbox-indicator\n role=\"checkbox\"\n :aria-checked=\"indeterminate ? 'mixed' : (checked ? 'true' : 'false')\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"controlClassName\"\n @keydown.space.prevent=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <IconMinus\n v-if=\"indeterminate\"\n :class=\"indeterminateIconClassName\"\n />\n <IconCheck\n v-else\n :class=\"checkIconClassName\"\n />\n </span>\n <span\n v-if=\"hasLabel\"\n :id=\"labelId\"\n :class=\"labelClassName\"\n >\n <slot />\n </span>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrCheckbox-CEcHIsXM.js","names":[],"sources":["../../../../src/components/GrCheckbox/grCheckboxGroupContext.ts","../../../../src/components/GrCheckbox/GrCheckbox.vue","../../../../src/components/GrCheckbox/GrCheckbox.vue"],"sourcesContent":["import type { ComputedRef, InjectionKey } from 'vue'\n\nimport type { GrCheckboxSize } from './grCheckboxStyles'\n\nexport type GrCheckboxGroupContext = {\n /** Выбранные значения группы. Чекбокс сравнивает с ними свой `value`. */\n modelValue: ComputedRef<string[]>\n name: ComputedRef<string | undefined>\n disabled: ComputedRef<boolean>\n readonly: ComputedRef<boolean>\n invalid: ComputedRef<boolean>\n /**\n * Обязательность группы объявляют её чекбоксы: `role=\"group\"` не поддерживает\n * `aria-required` (axe: `aria-allowed-attr`), а `role=\"checkbox\"` — да.\n */\n required: ComputedRef<boolean>\n size: ComputedRef<GrCheckboxSize>\n /** Добавляет или убирает значение из выбранных. */\n toggle: (value: string, checked: boolean) => void\n}\n\nexport const GR_CHECKBOX_GROUP_CONTEXT: InjectionKey<GrCheckboxGroupContext> = Symbol('GR_CHECKBOX_GROUP_CONTEXT')\n","<script setup lang=\"ts\">\n/**\n * GrCheckbox — GR-примитив чекбокса с нативным скрытым `<input type=\"checkbox\">`\n * для интеграции с HTML-формами (`FormData`, `form`).\n *\n * Источник истины — нативный input: клик по нему (в т.ч. по внешнему\n * `<label for=\"...\">`) слушается через `@change` и эмитит модель. Клик по видимой\n * части компонента переключает через корневой обработчик.\n *\n * Клавиатура: `Space` переключает значение (Enter — намеренно нет, это нестандартно\n * для чекбоксов). Фокус — на самом контроле (квадратике), как у нативного чекбокса.\n *\n * A11y: `role=\"checkbox\"` + `aria-checked` (`true`/`false`/`mixed`) + `aria-disabled`.\n * Роль висит **только на контроле**, а не на всей строке с подписью — по двум причинам:\n * - роль объявляет своих потомков презентационными, поэтому ни нативный input, ни\n * интерактивная подпись (ссылка на политику, кнопка «показать изменения») не могут\n * жить внутри: скринридер теряет их, axe падает на `nested-interactive`;\n * - имя виджета берётся из подписи через `aria-labelledby`, что и позволяет держать\n * её снаружи вместе со всем её интерактивным содержимым.\n *\n * `required` объявляется только через `aria-required`, на скрытый input он не уходит.\n * Нативная проверка потребовала бы фокуса на невалидном контроле, а он невидим и\n * `aria-hidden` — Chrome в таком случае молча отменяет сабмит всей формы\n * («An invalid form control … is not focusable»). Обязательность проверяет\n * `GrForm` правилом `required` — см. `docs/components/GrCheckbox.md`.\n *\n * Внутри `GrCheckboxGroup` значение приходит из группы: свой `modelValue` не\n * задаётся, а `value` сравнивается с массивом выбранных.\n */\nimport { computed, inject, onMounted, ref, useId, useSlots, watch } from 'vue'\nimport IconCheck from '~icons/lucide/check'\nimport IconMinus from '~icons/lucide/minus'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\n\nimport { GR_CHECKBOX_GROUP_CONTEXT } from './grCheckboxGroupContext'\nimport {\n grCheckboxCheckIconClass,\n grCheckboxControlClass,\n grCheckboxIndeterminateIconClass,\n grCheckboxLabelClass,\n grCheckboxRootClass,\n type GrCheckboxLabelPosition,\n type GrCheckboxSize,\n} from './grCheckboxStyles'\n\nexport type { GrCheckboxLabelPosition, GrCheckboxSize } from './grCheckboxStyles'\n\nexport interface GrCheckboxProps {\n /** Не задан внутри `GrCheckboxGroup` — состояние берётся из группы. */\n modelValue?: boolean\n disabled?: boolean\n name?: string\n value?: string\n /** Обязательное поле: объявляется как `aria-required`, нативной проверки нет. */\n required?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n form?: string\n /** Пробрасывается на скрытый нативный `<input>`, чтобы работал `<label for=\"...\">`. */\n id?: string\n /** Промежуточное («смешанное») состояние: `aria-checked=\"mixed\"`, индикатор — тире. */\n indeterminate?: boolean\n /** Имя контрола, когда подписи в слоте нет (или она чисто визуальная). */\n ariaLabel?: string\n /** Сторона подписи относительно контрола. */\n labelPosition?: GrCheckboxLabelPosition\n /** Размер контрола. Не задан — берётся из группы, затем из `GrConfigProvider`, иначе `md`. */\n size?: GrCheckboxSize\n}\n\nexport interface GrCheckboxEmits {\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 hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrCheckboxProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n value: 'on',\n required: false,\n readonly: false,\n invalid: false,\n form: undefined,\n id: undefined,\n indeterminate: false,\n ariaLabel: undefined,\n labelPosition: 'end',\n size: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxEmits>()\ndefineSlots<{\n /** Подпись флажка. Может содержать ссылки: роль остаётся на самом контроле. */\n default?: () => any\n}>()\n\nconst slots = useSlots()\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(slots.default))\n\nconst group = inject(GR_CHECKBOX_GROUP_CONTEXT, null)\n\nconst checked = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n if (group)\n return group.modelValue.value.includes(props.value)\n\n return false\n})\n\nconst resolvedName = computed(() => props.name ?? group?.name.value)\n\n// Контекст `GrFormField`. Id поля вешается на `span[role=\"checkbox\"]` — именно он\n// виджет и держит фокус; на скрытом `aria-hidden`-инпуте он был бы бесполезен\n// (клик по подписи уводил бы фокус в невидимый элемент). Роль-виджет не является\n// labelable-элементом, поэтому имя от подписи поля приходит через `aria-labelledby`.\nconst {\n disabled: isDisabled,\n id: fieldControlId,\n labelId: fieldLabelId,\n describedBy,\n invalid: fieldInvalid,\n required: fieldRequired,\n readonly: fieldReadonly,\n} = useGrFormControl(() => props)\n\n// «Или», а не `??`: `isDisabled` уже сведён к булеву (свой проп + контекст\n// поля и формы), и `??` до группы просто не дошёл бы.\nconst resolvedDisabled = computed(() => isDisabled.value || Boolean(group?.disabled.value))\n\n// `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` — объявлять\n// обязательность и режим чтения группы обязаны сами чекбоксы.\nconst isRequired = computed(() => fieldRequired.value || Boolean(group?.required.value))\n\nconst isReadonly = computed(() => fieldReadonly.value || Boolean(group?.readonly.value))\n\n// Ошибка группы красит чекбоксы, но не объявляется на каждом из них: `aria-invalid`\n// уже висит на самой группе, и дублировать его на всех пунктах — значит заставить\n// диктор повторить «неверное значение» столько раз, сколько в группе чекбоксов.\nconst isInvalid = computed(() => fieldInvalid.value)\nconst showsInvalid = computed(() => isInvalid.value || Boolean(group?.invalid.value))\n\nconst labelledBy = computed(() => {\n if (props.ariaLabel)\n return undefined\n if (hasLabel.value)\n return labelId\n return fieldLabelId.value\n})\n\n// Эффективный размер: локальный проп → группа → `GrConfigProvider` → `md`.\nconst resolvedSize = useGrComponentSize(\n () => props.size ?? group?.size.value,\n { component: 'GrCheckbox' },\n)\n\nconst rootClassName = computed(() => grCheckboxRootClass({\n size: resolvedSize.value,\n disabled: resolvedDisabled.value,\n labelPosition: props.labelPosition,\n}))\n\nconst controlClassName = computed(() => grCheckboxControlClass({\n size: resolvedSize.value,\n active: checked.value || props.indeterminate,\n disabled: resolvedDisabled.value,\n invalid: showsInvalid.value,\n}))\n\nconst indeterminateIconClassName = computed(() => grCheckboxIndeterminateIconClass(resolvedSize.value))\n\nconst checkIconClassName = computed(() => grCheckboxCheckIconClass({\n size: resolvedSize.value,\n checked: checked.value,\n}))\n\nconst labelClassName = computed(() => grCheckboxLabelClass(resolvedSize.value))\n\n// Держим `.checked` на нативном input синхронно с состоянием — `:checked`-биндинг\n// на скрытом элементе иногда отстаёт при программных обновлениях.\nconst nativeInput = ref<HTMLInputElement | null>(null)\nconst control = ref<HTMLElement | null>(null)\nwatch(\n checked,\n (value) => {\n if (nativeInput.value && nativeInput.value.checked !== value)\n nativeInput.value.checked = value\n },\n)\n\n// `indeterminate` можно выставить только через JS-свойство (не атрибут).\nfunction syncIndeterminate(): void {\n if (nativeInput.value)\n nativeInput.value.indeterminate = props.indeterminate\n}\nwatch(() => props.indeterminate, syncIndeterminate)\nonMounted(syncIndeterminate)\n\nfunction setChecked(next: boolean): void {\n if (resolvedDisabled.value || isReadonly.value) {\n // Нативный input мог уже переключиться от клика по внешнему `<label for>` —\n // возвращаем его к состоянию модели, иначе форма отправит непринятое значение.\n if (nativeInput.value)\n nativeInput.value.checked = checked.value\n return\n }\n\n if (props.modelValue !== undefined || !group) {\n emit('update:modelValue', next)\n emit('change', next)\n return\n }\n\n group.toggle(props.value, next)\n emit('change', next)\n}\n\nfunction toggle(): void {\n // Из промежуточного состояния переключаемся во «включено» (стандартное поведение).\n setChecked(props.indeterminate ? true : !checked.value)\n}\n\n// Клик по нативному input (в т.ч. по внешнему `<label for=\"...\">`) уже переключил его\n// `.checked` — берём значение как источник истины и эмитим модель.\nfunction onNativeChange(e: Event): void {\n setChecked((e.target as HTMLInputElement).checked)\n}\n\n// `<label for>` уводит фокус на скрытый input — визуально фокус пропадает. Возвращаем\n// его на контрол, который этот фокус и показывает.\nfunction onNativeFocus(): void {\n control.value?.focus()\n}\n\nfunction focus(): void {\n control.value?.focus()\n}\n\nfunction blur(): void {\n control.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Подпись держится снаружи роли-виджета именно для того, чтобы могла содержать\n// ссылки и кнопки, — поэтому клик по её интерактивному содержимому чекбокс не\n// переключает. Вложенный `<label>` считается интерактивным: он адресует\n// собственный контрол, и переключение чекбокса «заодно» было бы сюрпризом.\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null\n if (!el)\n return false\n return !!el.closest('a,button,input,select,textarea,label,[role=\"button\"],[role=\"link\"]')\n}\n\nfunction onClick(e: MouseEvent): void {\n if (isInteractiveTarget(e.target))\n return\n toggle()\n}\n</script>\n\n<template>\n <div\n data-gr-checkbox\n :class=\"rootClassName\"\n @click=\"onClick\"\n >\n <input\n :id=\"id\"\n ref=\"nativeInput\"\n type=\"checkbox\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n @change=\"onNativeChange\"\n @focus=\"onNativeFocus\"\n >\n <span\n :id=\"fieldControlId\"\n ref=\"control\"\n data-gr-checkbox-indicator\n role=\"checkbox\"\n :aria-checked=\"indeterminate ? 'mixed' : (checked ? 'true' : 'false')\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"controlClassName\"\n @keydown.space.prevent=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <IconMinus\n v-if=\"indeterminate\"\n :class=\"indeterminateIconClassName\"\n />\n <IconCheck\n v-else\n :class=\"checkIconClassName\"\n />\n </span>\n <span\n v-if=\"hasLabel\"\n :id=\"labelId\"\n :class=\"labelClassName\"\n >\n <slot />\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrCheckbox — GR-примитив чекбокса с нативным скрытым `<input type=\"checkbox\">`\n * для интеграции с HTML-формами (`FormData`, `form`).\n *\n * Источник истины — нативный input: клик по нему (в т.ч. по внешнему\n * `<label for=\"...\">`) слушается через `@change` и эмитит модель. Клик по видимой\n * части компонента переключает через корневой обработчик.\n *\n * Клавиатура: `Space` переключает значение (Enter — намеренно нет, это нестандартно\n * для чекбоксов). Фокус — на самом контроле (квадратике), как у нативного чекбокса.\n *\n * A11y: `role=\"checkbox\"` + `aria-checked` (`true`/`false`/`mixed`) + `aria-disabled`.\n * Роль висит **только на контроле**, а не на всей строке с подписью — по двум причинам:\n * - роль объявляет своих потомков презентационными, поэтому ни нативный input, ни\n * интерактивная подпись (ссылка на политику, кнопка «показать изменения») не могут\n * жить внутри: скринридер теряет их, axe падает на `nested-interactive`;\n * - имя виджета берётся из подписи через `aria-labelledby`, что и позволяет держать\n * её снаружи вместе со всем её интерактивным содержимым.\n *\n * `required` объявляется только через `aria-required`, на скрытый input он не уходит.\n * Нативная проверка потребовала бы фокуса на невалидном контроле, а он невидим и\n * `aria-hidden` — Chrome в таком случае молча отменяет сабмит всей формы\n * («An invalid form control … is not focusable»). Обязательность проверяет\n * `GrForm` правилом `required` — см. `docs/components/GrCheckbox.md`.\n *\n * Внутри `GrCheckboxGroup` значение приходит из группы: свой `modelValue` не\n * задаётся, а `value` сравнивается с массивом выбранных.\n */\nimport { computed, inject, onMounted, ref, useId, useSlots, watch } from 'vue'\nimport IconCheck from '~icons/lucide/check'\nimport IconMinus from '~icons/lucide/minus'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\n\nimport { GR_CHECKBOX_GROUP_CONTEXT } from './grCheckboxGroupContext'\nimport {\n grCheckboxCheckIconClass,\n grCheckboxControlClass,\n grCheckboxIndeterminateIconClass,\n grCheckboxLabelClass,\n grCheckboxRootClass,\n type GrCheckboxLabelPosition,\n type GrCheckboxSize,\n} from './grCheckboxStyles'\n\nexport type { GrCheckboxLabelPosition, GrCheckboxSize } from './grCheckboxStyles'\n\nexport interface GrCheckboxProps {\n /** Не задан внутри `GrCheckboxGroup` — состояние берётся из группы. */\n modelValue?: boolean\n disabled?: boolean\n name?: string\n value?: string\n /** Обязательное поле: объявляется как `aria-required`, нативной проверки нет. */\n required?: boolean\n /** Только для чтения: состояние видно, но не переключается. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n form?: string\n /** Пробрасывается на скрытый нативный `<input>`, чтобы работал `<label for=\"...\">`. */\n id?: string\n /** Промежуточное («смешанное») состояние: `aria-checked=\"mixed\"`, индикатор — тире. */\n indeterminate?: boolean\n /** Имя контрола, когда подписи в слоте нет (или она чисто визуальная). */\n ariaLabel?: string\n /** Сторона подписи относительно контрола. */\n labelPosition?: GrCheckboxLabelPosition\n /** Размер контрола. Не задан — берётся из группы, затем из `GrConfigProvider`, иначе `md`. */\n size?: GrCheckboxSize\n}\n\nexport interface GrCheckboxEmits {\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 hiddenInputStyle = {\n position: 'absolute',\n opacity: '0',\n width: '0',\n height: '0',\n pointerEvents: 'none',\n} as const\n\nconst props = withDefaults(defineProps<GrCheckboxProps>(), {\n modelValue: undefined,\n disabled: undefined,\n name: undefined,\n value: 'on',\n required: false,\n readonly: false,\n invalid: false,\n form: undefined,\n id: undefined,\n indeterminate: false,\n ariaLabel: undefined,\n labelPosition: 'end',\n size: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxEmits>()\ndefineSlots<{\n /** Подпись флажка. Может содержать ссылки: роль остаётся на самом контроле. */\n default?: () => any\n}>()\n\nconst slots = useSlots()\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(slots.default))\n\nconst group = inject(GR_CHECKBOX_GROUP_CONTEXT, null)\n\nconst checked = computed(() => {\n if (props.modelValue !== undefined)\n return props.modelValue\n\n if (group)\n return group.modelValue.value.includes(props.value)\n\n return false\n})\n\nconst resolvedName = computed(() => props.name ?? group?.name.value)\n\n// Контекст `GrFormField`. Id поля вешается на `span[role=\"checkbox\"]` — именно он\n// виджет и держит фокус; на скрытом `aria-hidden`-инпуте он был бы бесполезен\n// (клик по подписи уводил бы фокус в невидимый элемент). Роль-виджет не является\n// labelable-элементом, поэтому имя от подписи поля приходит через `aria-labelledby`.\nconst {\n disabled: isDisabled,\n id: fieldControlId,\n labelId: fieldLabelId,\n describedBy,\n invalid: fieldInvalid,\n required: fieldRequired,\n readonly: fieldReadonly,\n} = useGrFormControl(() => props)\n\n// «Или», а не `??`: `isDisabled` уже сведён к булеву (свой проп + контекст\n// поля и формы), и `??` до группы просто не дошёл бы.\nconst resolvedDisabled = computed(() => isDisabled.value || Boolean(group?.disabled.value))\n\n// `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` — объявлять\n// обязательность и режим чтения группы обязаны сами чекбоксы.\nconst isRequired = computed(() => fieldRequired.value || Boolean(group?.required.value))\n\nconst isReadonly = computed(() => fieldReadonly.value || Boolean(group?.readonly.value))\n\n// Ошибка группы красит чекбоксы, но не объявляется на каждом из них: `aria-invalid`\n// уже висит на самой группе, и дублировать его на всех пунктах — значит заставить\n// диктор повторить «неверное значение» столько раз, сколько в группе чекбоксов.\nconst isInvalid = computed(() => fieldInvalid.value)\nconst showsInvalid = computed(() => isInvalid.value || Boolean(group?.invalid.value))\n\nconst labelledBy = computed(() => {\n if (props.ariaLabel)\n return undefined\n if (hasLabel.value)\n return labelId\n return fieldLabelId.value\n})\n\n// Эффективный размер: локальный проп → группа → `GrConfigProvider` → `md`.\nconst resolvedSize = useGrComponentSize(\n () => props.size ?? group?.size.value,\n { component: 'GrCheckbox' },\n)\n\nconst rootClassName = computed(() => grCheckboxRootClass({\n size: resolvedSize.value,\n disabled: resolvedDisabled.value,\n labelPosition: props.labelPosition,\n}))\n\nconst controlClassName = computed(() => grCheckboxControlClass({\n size: resolvedSize.value,\n active: checked.value || props.indeterminate,\n disabled: resolvedDisabled.value,\n invalid: showsInvalid.value,\n}))\n\nconst indeterminateIconClassName = computed(() => grCheckboxIndeterminateIconClass(resolvedSize.value))\n\nconst checkIconClassName = computed(() => grCheckboxCheckIconClass({\n size: resolvedSize.value,\n checked: checked.value,\n}))\n\nconst labelClassName = computed(() => grCheckboxLabelClass(resolvedSize.value))\n\n// Держим `.checked` на нативном input синхронно с состоянием — `:checked`-биндинг\n// на скрытом элементе иногда отстаёт при программных обновлениях.\nconst nativeInput = ref<HTMLInputElement | null>(null)\nconst control = ref<HTMLElement | null>(null)\nwatch(\n checked,\n (value) => {\n if (nativeInput.value && nativeInput.value.checked !== value)\n nativeInput.value.checked = value\n },\n)\n\n// `indeterminate` можно выставить только через JS-свойство (не атрибут).\nfunction syncIndeterminate(): void {\n if (nativeInput.value)\n nativeInput.value.indeterminate = props.indeterminate\n}\nwatch(() => props.indeterminate, syncIndeterminate)\nonMounted(syncIndeterminate)\n\nfunction setChecked(next: boolean): void {\n if (resolvedDisabled.value || isReadonly.value) {\n // Нативный input мог уже переключиться от клика по внешнему `<label for>` —\n // возвращаем его к состоянию модели, иначе форма отправит непринятое значение.\n if (nativeInput.value)\n nativeInput.value.checked = checked.value\n return\n }\n\n if (props.modelValue !== undefined || !group) {\n emit('update:modelValue', next)\n emit('change', next)\n return\n }\n\n group.toggle(props.value, next)\n emit('change', next)\n}\n\nfunction toggle(): void {\n // Из промежуточного состояния переключаемся во «включено» (стандартное поведение).\n setChecked(props.indeterminate ? true : !checked.value)\n}\n\n// Клик по нативному input (в т.ч. по внешнему `<label for=\"...\">`) уже переключил его\n// `.checked` — берём значение как источник истины и эмитим модель.\nfunction onNativeChange(e: Event): void {\n setChecked((e.target as HTMLInputElement).checked)\n}\n\n// `<label for>` уводит фокус на скрытый input — визуально фокус пропадает. Возвращаем\n// его на контрол, который этот фокус и показывает.\nfunction onNativeFocus(): void {\n control.value?.focus()\n}\n\nfunction focus(): void {\n control.value?.focus()\n}\n\nfunction blur(): void {\n control.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Подпись держится снаружи роли-виджета именно для того, чтобы могла содержать\n// ссылки и кнопки, — поэтому клик по её интерактивному содержимому чекбокс не\n// переключает. Вложенный `<label>` считается интерактивным: он адресует\n// собственный контрол, и переключение чекбокса «заодно» было бы сюрпризом.\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null\n if (!el)\n return false\n return !!el.closest('a,button,input,select,textarea,label,[role=\"button\"],[role=\"link\"]')\n}\n\nfunction onClick(e: MouseEvent): void {\n if (isInteractiveTarget(e.target))\n return\n toggle()\n}\n</script>\n\n<template>\n <div\n data-gr-checkbox\n :class=\"rootClassName\"\n @click=\"onClick\"\n >\n <input\n :id=\"id\"\n ref=\"nativeInput\"\n type=\"checkbox\"\n :checked=\"checked\"\n :disabled=\"resolvedDisabled\"\n :name=\"resolvedName\"\n :value=\"value\"\n :form=\"form\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :style=\"hiddenInputStyle\"\n @change=\"onNativeChange\"\n @focus=\"onNativeFocus\"\n >\n <span\n :id=\"fieldControlId\"\n ref=\"control\"\n data-gr-checkbox-indicator\n role=\"checkbox\"\n :aria-checked=\"indeterminate ? 'mixed' : (checked ? 'true' : 'false')\"\n :aria-disabled=\"resolvedDisabled ? 'true' : undefined\"\n :aria-required=\"isRequired ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :tabindex=\"resolvedDisabled ? -1 : 0\"\n :class=\"controlClassName\"\n @keydown.space.prevent=\"toggle\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <IconMinus\n v-if=\"indeterminate\"\n :class=\"indeterminateIconClassName\"\n />\n <IconCheck\n v-else\n :class=\"checkIconClassName\"\n />\n </span>\n <span\n v-if=\"hasLabel\"\n :id=\"labelId\"\n :class=\"labelClassName\"\n >\n <slot />\n </span>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"GrCheckboxGroup-BOwrVcFr.js","names":[],"sources":["../../../../src/components/GrCheckboxGroup/GrCheckboxGroup.vue","../../../../src/components/GrCheckboxGroup/GrCheckboxGroup.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrCheckboxGroup — контейнер группы `GrCheckbox` с общей моделью `string[]`.\n *\n * Работает и через слот (ручной рендер `GrCheckbox` с собственными подписями),\n * и через проп `options`. Дочерние чекбоксы получают из контекста выбранные\n * значения, `name`, `size` и состояния `disabled`/`readonly`/`invalid`, поэтому\n * свой `v-model` им не нужен.\n *\n * A11y: `role=\"group\"` — не `radiogroup`. У группы чекбоксов нет roving tabindex\n * и переезда выбора стрелками: каждый чекбокс независим и остаётся собственной\n * остановкой `Tab`, ровно как набор нативных `<input type=\"checkbox\">`.\n * `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` (axe:\n * `aria-allowed-attr`), поэтому оба состояния объявляют чекбоксы группы.\n */\nimport { computed, provide, ref } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\n\nimport GrCheckbox from '../GrCheckbox/GrCheckbox.vue'\nimport { GR_CHECKBOX_GROUP_CONTEXT } from '../GrCheckbox/grCheckboxGroupContext'\nimport type { GrCheckboxSize } from '../GrCheckbox/grCheckboxStyles'\n\nexport type GrCheckboxGroupDirection = 'vertical' | 'horizontal'\n\nexport interface GrCheckboxGroupOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface GrCheckboxGroupProps {\n modelValue: string[]\n options?: GrCheckboxGroupOption[]\n /** Общее имя для нативной формы: значения уйдут как повторяющиеся поля. */\n name?: string\n disabled?: boolean\n /** Только для чтения: выбор видно, но он не меняется. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки для всей группы. */\n invalid?: boolean\n /** Обязательная группа: `aria-required` объявляют сами чекбоксы. */\n required?: boolean\n direction?: GrCheckboxGroupDirection\n size?: GrCheckboxSize\n ariaLabel?: string\n}\n\nexport interface GrCheckboxGroupEmits {\n (e: 'update:modelValue', value: string[]): void\n (e: 'change', value: string[]): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCheckboxGroupProps>(), {\n options: undefined,\n name: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n direction: 'vertical',\n size: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxGroupEmits>()\ndefineSlots<{\n /** Собственная разметка флажков вместо генерации из `options`. */\n default?: () => any\n}>()\n\n\n// Эффективный размер группы: локальный проп → `GrConfigProvider` → `md`.\n// Дочерние чекбоксы получают уже разрешённое значение через контекст.\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrCheckboxGroup' })\n\n// Контекст `GrFormField`. Группа — не labelable-элемент, поэтому имя приходит\n// через `aria-labelledby` на подпись поля, а не через `<label for>`.\nconst {\n disabled: isDisabled,\n id: fieldId,\n labelId: fieldLabelId,\n describedBy,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst labelledBy = computed(() => (props.ariaLabel ? undefined : fieldLabelId.value))\n\nconst layoutClass = computed(() =>\n props.direction === 'horizontal' ? 'flex flex-wrap items-center gap-4' : 'grid gap-2',\n)\n\nfunction toggle(value: string, checked: boolean): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n if (checked) {\n if (props.modelValue.includes(value))\n return\n commit([...props.modelValue, value])\n return\n }\n\n commit(props.modelValue.filter(item => item !== value))\n}\n\nfunction commit(next: string[]): void {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nconst rootEl = ref<HTMLElement | null>(null)\n\n// Фокус ходит между чекбоксами группы: без границы каждый переход давал бы\n// потребителю пару `blur` + `focus`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n})\n\nfunction firstCheckbox(): HTMLElement | null | undefined {\n return rootEl.value?.querySelector<HTMLElement>('[role=\"checkbox\"]:not([aria-disabled=\"true\"])')\n}\n\nfunction focus(): void {\n firstCheckbox()?.focus()\n}\n\nfunction blur(): void {\n firstCheckbox()?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nprovide(GR_CHECKBOX_GROUP_CONTEXT, {\n modelValue: computed(() => props.modelValue),\n name: computed(() => props.name),\n disabled: computed(() => isDisabled.value),\n readonly: isReadonly,\n invalid: isInvalid,\n size: resolvedSize,\n required: isRequired,\n toggle,\n})\n</script>\n\n<template>\n <div\n :id=\"fieldId\"\n ref=\"rootEl\"\n data-gr-checkbox-group\n role=\"group\"\n :class=\"layoutClass\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot>\n <GrCheckbox\n v-for=\"option in options ?? []\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </GrCheckbox>\n </slot>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrCheckboxGroup — контейнер группы `GrCheckbox` с общей моделью `string[]`.\n *\n * Работает и через слот (ручной рендер `GrCheckbox` с собственными подписями),\n * и через проп `options`. Дочерние чекбоксы получают из контекста выбранные\n * значения, `name`, `size` и состояния `disabled`/`readonly`/`invalid`, поэтому\n * свой `v-model` им не нужен.\n *\n * A11y: `role=\"group\"` — не `radiogroup`. У группы чекбоксов нет roving tabindex\n * и переезда выбора стрелками: каждый чекбокс независим и остаётся собственной\n * остановкой `Tab`, ровно как набор нативных `<input type=\"checkbox\">`.\n * `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` (axe:\n * `aria-allowed-attr`), поэтому оба состояния объявляют чекбоксы группы.\n */\nimport { computed, provide, ref } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\n\nimport GrCheckbox from '../GrCheckbox/GrCheckbox.vue'\nimport { GR_CHECKBOX_GROUP_CONTEXT } from '../GrCheckbox/grCheckboxGroupContext'\nimport type { GrCheckboxSize } from '../GrCheckbox/grCheckboxStyles'\n\nexport type GrCheckboxGroupDirection = 'vertical' | 'horizontal'\n\nexport interface GrCheckboxGroupOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface GrCheckboxGroupProps {\n modelValue: string[]\n options?: GrCheckboxGroupOption[]\n /** Общее имя для нативной формы: значения уйдут как повторяющиеся поля. */\n name?: string\n disabled?: boolean\n /** Только для чтения: выбор видно, но он не меняется. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки для всей группы. */\n invalid?: boolean\n /** Обязательная группа: `aria-required` объявляют сами чекбоксы. */\n required?: boolean\n direction?: GrCheckboxGroupDirection\n size?: GrCheckboxSize\n ariaLabel?: string\n}\n\nexport interface GrCheckboxGroupEmits {\n (e: 'update:modelValue', value: string[]): void\n (e: 'change', value: string[]): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCheckboxGroupProps>(), {\n options: undefined,\n name: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n direction: 'vertical',\n size: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxGroupEmits>()\ndefineSlots<{\n /** Собственная разметка флажков вместо генерации из `options`. */\n default?: () => any\n}>()\n\n\n// Эффективный размер группы: локальный проп → `GrConfigProvider` → `md`.\n// Дочерние чекбоксы получают уже разрешённое значение через контекст.\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrCheckboxGroup' })\n\n// Контекст `GrFormField`. Группа — не labelable-элемент, поэтому имя приходит\n// через `aria-labelledby` на подпись поля, а не через `<label for>`.\nconst {\n disabled: isDisabled,\n id: fieldId,\n labelId: fieldLabelId,\n describedBy,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst labelledBy = computed(() => (props.ariaLabel ? undefined : fieldLabelId.value))\n\nconst layoutClass = computed(() =>\n props.direction === 'horizontal' ? 'flex flex-wrap items-center gap-4' : 'grid gap-2',\n)\n\nfunction toggle(value: string, checked: boolean): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n if (checked) {\n if (props.modelValue.includes(value))\n return\n commit([...props.modelValue, value])\n return\n }\n\n commit(props.modelValue.filter(item => item !== value))\n}\n\nfunction commit(next: string[]): void {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nconst rootEl = ref<HTMLElement | null>(null)\n\n// Фокус ходит между чекбоксами группы: без границы каждый переход давал бы\n// потребителю пару `blur` + `focus`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n})\n\nfunction firstCheckbox(): HTMLElement | null | undefined {\n return rootEl.value?.querySelector<HTMLElement>('[role=\"checkbox\"]:not([aria-disabled=\"true\"])')\n}\n\nfunction focus(): void {\n firstCheckbox()?.focus()\n}\n\nfunction blur(): void {\n firstCheckbox()?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nprovide(GR_CHECKBOX_GROUP_CONTEXT, {\n modelValue: computed(() => props.modelValue),\n name: computed(() => props.name),\n disabled: computed(() => isDisabled.value),\n readonly: isReadonly,\n invalid: isInvalid,\n size: resolvedSize,\n required: isRequired,\n toggle,\n})\n</script>\n\n<template>\n <div\n :id=\"fieldId\"\n ref=\"rootEl\"\n data-gr-checkbox-group\n role=\"group\"\n :class=\"layoutClass\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot>\n <GrCheckbox\n v-for=\"option in options ?? []\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </GrCheckbox>\n </slot>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDA,MAAM,QAAQ;EAYd,MAAM,OAAO;EASb,MAAM,eAAe,yBAAyB,MAAM,MAAM,EAAE,WAAW,kBAAkB,CAAC;EAI1F,MAAM,EACJ,UAAU,YACV,IAAI,SACJ,SAAS,cACT,aACA,SAAS,WACT,UAAU,YACV,UAAU,eACR,uBAAuB,KAAK;EAEhC,MAAM,aAAa,eAAgB,MAAM,YAAY,KAAA,IAAY,aAAa,KAAM;EAEpF,MAAM,cAAc,eAClB,MAAM,cAAc,eAAe,sCAAsC,YAC3E;EAEA,SAAS,OAAO,OAAe,SAAwB;GACrD,IAAI,WAAW,SAAS,WAAW,OACjC;GAEF,IAAI,SAAS;IACX,IAAI,MAAM,WAAW,SAAS,KAAK,GACjC;IACF,OAAO,CAAC,GAAG,MAAM,YAAY,KAAK,CAAC;IACnC;GACF;GAEA,OAAO,MAAM,WAAW,QAAO,SAAQ,SAAS,KAAK,CAAC;EACxD;EAEA,SAAS,OAAO,MAAsB;GACpC,KAAK,qBAAqB,IAAI;GAC9B,KAAK,UAAU,IAAI;EACrB;EAEA,MAAM,SAAS,IAAwB,IAAI;EAI3C,MAAM,EAAE,WAAW,eAAe,eAAe,QAAQ;GACvD,QAAO,UAAS,KAAK,SAAS,KAAK;GACnC,QAAO,UAAS,KAAK,QAAQ,KAAK;EACpC,CAAC;EAED,SAAS,gBAAgD;GACvD,OAAO,OAAO,OAAO,cAA2B,mDAA+C;EACjG;EAEA,SAAS,QAAc;GACrB,cAAc,CAAC,EAAE,MAAM;EACzB;EAEA,SAAS,OAAa;GACpB,cAAc,CAAC,EAAE,KAAK;EACxB;EAEA,SAAa;GAAE;GAAO;EAAK,CAAC;EAE5B,QAAQ,2BAA2B;GACjC,YAAY,eAAe,MAAM,UAAU;GAC3C,MAAM,eAAe,MAAM,IAAI;GAC/B,UAAU,eAAe,WAAW,KAAK;GACzC,UAAU;GACV,SAAS;GACT,MAAM;GACN,UAAU;GACV;EACF,CAAC;;uBAIC,mBAwBM,OAAA;IAvBH,IAAI,MAAA,OAAA;aACD;IAAJ,KAAI;IACJ,0BAAA;IACA,MAAK;IACJ,OAAK,eAAE,YAAA,KAAW;IAClB,cAAY,QAAA;IACZ,mBAAiB,WAAA;IACjB,oBAAkB,MAAA,WAAA;IAClB,gBAAc,MAAA,SAAA,IAAS,SAAY,KAAA;IACnC,iBAAe,MAAA,UAAA,IAAU,SAAY,KAAA;IACrC,WAAO,OAAA,OAAA,OAAA,MAAA,GAAA,SAAE,MAAA,SAAA,KAAA,MAAA,SAAA,CAAA,CAAA,GAAA,IAAA;IACT,YAAQ,OAAA,OAAA,OAAA,MAAA,GAAA,SAAE,MAAA,UAAA,KAAA,MAAA,UAAA,CAAA,CAAA,GAAA,IAAA;OAEX,WASO,KAAA,QAAA,WAAA,CAAA,SAAA,EAAA,UAAA,IAAA,GARL,mBAOa,UAAA,MAAA,WANM,QAAA,WAAO,CAAA,IAAjB,WAAM;wBADf,YAOa,oBAAA;KALV,KAAK,OAAO;KACZ,OAAO,OAAO;KACd,UAAU,OAAO;;4BAEA,CAAA,gBAAA,gBAAf,OAAO,KAAK,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"GrCheckboxGroup-BOwrVcFr.js","names":[],"sources":["../../../../src/components/GrCheckboxGroup/GrCheckboxGroup.vue","../../../../src/components/GrCheckboxGroup/GrCheckboxGroup.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrCheckboxGroup — контейнер группы `GrCheckbox` с общей моделью `string[]`.\n *\n * Работает и через слот (ручной рендер `GrCheckbox` с собственными подписями),\n * и через проп `options`. Дочерние чекбоксы получают из контекста выбранные\n * значения, `name`, `size` и состояния `disabled`/`readonly`/`invalid`, поэтому\n * свой `v-model` им не нужен.\n *\n * A11y: `role=\"group\"` — не `radiogroup`. У группы чекбоксов нет roving tabindex\n * и переезда выбора стрелками: каждый чекбокс независим и остаётся собственной\n * остановкой `Tab`, ровно как набор нативных `<input type=\"checkbox\">`.\n * `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` (axe:\n * `aria-allowed-attr`), поэтому оба состояния объявляют чекбоксы группы.\n */\nimport { computed, provide, ref } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\n\nimport GrCheckbox from '../GrCheckbox/GrCheckbox.vue'\nimport { GR_CHECKBOX_GROUP_CONTEXT } from '../GrCheckbox/grCheckboxGroupContext'\nimport type { GrCheckboxSize } from '../GrCheckbox/grCheckboxStyles'\n\nexport type GrCheckboxGroupDirection = 'vertical' | 'horizontal'\n\nexport interface GrCheckboxGroupOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface GrCheckboxGroupProps {\n modelValue: string[]\n options?: GrCheckboxGroupOption[]\n /** Общее имя для нативной формы: значения уйдут как повторяющиеся поля. */\n name?: string\n disabled?: boolean\n /** Только для чтения: выбор видно, но он не меняется. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки для всей группы. */\n invalid?: boolean\n /** Обязательная группа: `aria-required` объявляют сами чекбоксы. */\n required?: boolean\n direction?: GrCheckboxGroupDirection\n size?: GrCheckboxSize\n ariaLabel?: string\n}\n\nexport interface GrCheckboxGroupEmits {\n (e: 'update:modelValue', value: string[]): void\n (e: 'change', value: string[]): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCheckboxGroupProps>(), {\n options: undefined,\n name: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n direction: 'vertical',\n size: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxGroupEmits>()\ndefineSlots<{\n /** Собственная разметка флажков вместо генерации из `options`. */\n default?: () => any\n}>()\n\n// Эффективный размер группы: локальный проп → `GrConfigProvider` → `md`.\n// Дочерние чекбоксы получают уже разрешённое значение через контекст.\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrCheckboxGroup' })\n\n// Контекст `GrFormField`. Группа — не labelable-элемент, поэтому имя приходит\n// через `aria-labelledby` на подпись поля, а не через `<label for>`.\nconst {\n disabled: isDisabled,\n id: fieldId,\n labelId: fieldLabelId,\n describedBy,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst labelledBy = computed(() => (props.ariaLabel ? undefined : fieldLabelId.value))\n\nconst layoutClass = computed(() =>\n props.direction === 'horizontal' ? 'flex flex-wrap items-center gap-4' : 'grid gap-2',\n)\n\nfunction toggle(value: string, checked: boolean): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n if (checked) {\n if (props.modelValue.includes(value))\n return\n commit([...props.modelValue, value])\n return\n }\n\n commit(props.modelValue.filter(item => item !== value))\n}\n\nfunction commit(next: string[]): void {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nconst rootEl = ref<HTMLElement | null>(null)\n\n// Фокус ходит между чекбоксами группы: без границы каждый переход давал бы\n// потребителю пару `blur` + `focus`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n})\n\nfunction firstCheckbox(): HTMLElement | null | undefined {\n return rootEl.value?.querySelector<HTMLElement>('[role=\"checkbox\"]:not([aria-disabled=\"true\"])')\n}\n\nfunction focus(): void {\n firstCheckbox()?.focus()\n}\n\nfunction blur(): void {\n firstCheckbox()?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nprovide(GR_CHECKBOX_GROUP_CONTEXT, {\n modelValue: computed(() => props.modelValue),\n name: computed(() => props.name),\n disabled: computed(() => isDisabled.value),\n readonly: isReadonly,\n invalid: isInvalid,\n size: resolvedSize,\n required: isRequired,\n toggle,\n})\n</script>\n\n<template>\n <div\n :id=\"fieldId\"\n ref=\"rootEl\"\n data-gr-checkbox-group\n role=\"group\"\n :class=\"layoutClass\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot>\n <GrCheckbox\n v-for=\"option in options ?? []\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </GrCheckbox>\n </slot>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrCheckboxGroup — контейнер группы `GrCheckbox` с общей моделью `string[]`.\n *\n * Работает и через слот (ручной рендер `GrCheckbox` с собственными подписями),\n * и через проп `options`. Дочерние чекбоксы получают из контекста выбранные\n * значения, `name`, `size` и состояния `disabled`/`readonly`/`invalid`, поэтому\n * свой `v-model` им не нужен.\n *\n * A11y: `role=\"group\"` — не `radiogroup`. У группы чекбоксов нет roving tabindex\n * и переезда выбора стрелками: каждый чекбокс независим и остаётся собственной\n * остановкой `Tab`, ровно как набор нативных `<input type=\"checkbox\">`.\n * `role=\"group\"` не поддерживает `aria-required` и `aria-readonly` (axe:\n * `aria-allowed-attr`), поэтому оба состояния объявляют чекбоксы группы.\n */\nimport { computed, provide, ref } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\n\nimport GrCheckbox from '../GrCheckbox/GrCheckbox.vue'\nimport { GR_CHECKBOX_GROUP_CONTEXT } from '../GrCheckbox/grCheckboxGroupContext'\nimport type { GrCheckboxSize } from '../GrCheckbox/grCheckboxStyles'\n\nexport type GrCheckboxGroupDirection = 'vertical' | 'horizontal'\n\nexport interface GrCheckboxGroupOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface GrCheckboxGroupProps {\n modelValue: string[]\n options?: GrCheckboxGroupOption[]\n /** Общее имя для нативной формы: значения уйдут как повторяющиеся поля. */\n name?: string\n disabled?: boolean\n /** Только для чтения: выбор видно, но он не меняется. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки для всей группы. */\n invalid?: boolean\n /** Обязательная группа: `aria-required` объявляют сами чекбоксы. */\n required?: boolean\n direction?: GrCheckboxGroupDirection\n size?: GrCheckboxSize\n ariaLabel?: string\n}\n\nexport interface GrCheckboxGroupEmits {\n (e: 'update:modelValue', value: string[]): void\n (e: 'change', value: string[]): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrCheckboxGroupProps>(), {\n options: undefined,\n name: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n direction: 'vertical',\n size: undefined,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrCheckboxGroupEmits>()\ndefineSlots<{\n /** Собственная разметка флажков вместо генерации из `options`. */\n default?: () => any\n}>()\n\n// Эффективный размер группы: локальный проп → `GrConfigProvider` → `md`.\n// Дочерние чекбоксы получают уже разрешённое значение через контекст.\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrCheckboxGroup' })\n\n// Контекст `GrFormField`. Группа — не labelable-элемент, поэтому имя приходит\n// через `aria-labelledby` на подпись поля, а не через `<label for>`.\nconst {\n disabled: isDisabled,\n id: fieldId,\n labelId: fieldLabelId,\n describedBy,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n} = useGrFormControl(() => props)\n\nconst labelledBy = computed(() => (props.ariaLabel ? undefined : fieldLabelId.value))\n\nconst layoutClass = computed(() =>\n props.direction === 'horizontal' ? 'flex flex-wrap items-center gap-4' : 'grid gap-2',\n)\n\nfunction toggle(value: string, checked: boolean): void {\n if (isDisabled.value || isReadonly.value)\n return\n\n if (checked) {\n if (props.modelValue.includes(value))\n return\n commit([...props.modelValue, value])\n return\n }\n\n commit(props.modelValue.filter(item => item !== value))\n}\n\nfunction commit(next: string[]): void {\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nconst rootEl = ref<HTMLElement | null>(null)\n\n// Фокус ходит между чекбоксами группы: без границы каждый переход давал бы\n// потребителю пару `blur` + `focus`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n})\n\nfunction firstCheckbox(): HTMLElement | null | undefined {\n return rootEl.value?.querySelector<HTMLElement>('[role=\"checkbox\"]:not([aria-disabled=\"true\"])')\n}\n\nfunction focus(): void {\n firstCheckbox()?.focus()\n}\n\nfunction blur(): void {\n firstCheckbox()?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nprovide(GR_CHECKBOX_GROUP_CONTEXT, {\n modelValue: computed(() => props.modelValue),\n name: computed(() => props.name),\n disabled: computed(() => isDisabled.value),\n readonly: isReadonly,\n invalid: isInvalid,\n size: resolvedSize,\n required: isRequired,\n toggle,\n})\n</script>\n\n<template>\n <div\n :id=\"fieldId\"\n ref=\"rootEl\"\n data-gr-checkbox-group\n role=\"group\"\n :class=\"layoutClass\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot>\n <GrCheckbox\n v-for=\"option in options ?? []\"\n :key=\"option.value\"\n :value=\"option.value\"\n :disabled=\"option.disabled\"\n >\n {{ option.label }}\n </GrCheckbox>\n </slot>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDA,MAAM,QAAQ;EAYd,MAAM,OAAO;EAQb,MAAM,eAAe,yBAAyB,MAAM,MAAM,EAAE,WAAW,kBAAkB,CAAC;EAI1F,MAAM,EACJ,UAAU,YACV,IAAI,SACJ,SAAS,cACT,aACA,SAAS,WACT,UAAU,YACV,UAAU,eACR,uBAAuB,KAAK;EAEhC,MAAM,aAAa,eAAgB,MAAM,YAAY,KAAA,IAAY,aAAa,KAAM;EAEpF,MAAM,cAAc,eAClB,MAAM,cAAc,eAAe,sCAAsC,YAC3E;EAEA,SAAS,OAAO,OAAe,SAAwB;GACrD,IAAI,WAAW,SAAS,WAAW,OACjC;GAEF,IAAI,SAAS;IACX,IAAI,MAAM,WAAW,SAAS,KAAK,GACjC;IACF,OAAO,CAAC,GAAG,MAAM,YAAY,KAAK,CAAC;IACnC;GACF;GAEA,OAAO,MAAM,WAAW,QAAO,SAAQ,SAAS,KAAK,CAAC;EACxD;EAEA,SAAS,OAAO,MAAsB;GACpC,KAAK,qBAAqB,IAAI;GAC9B,KAAK,UAAU,IAAI;EACrB;EAEA,MAAM,SAAS,IAAwB,IAAI;EAI3C,MAAM,EAAE,WAAW,eAAe,eAAe,QAAQ;GACvD,QAAO,UAAS,KAAK,SAAS,KAAK;GACnC,QAAO,UAAS,KAAK,QAAQ,KAAK;EACpC,CAAC;EAED,SAAS,gBAAgD;GACvD,OAAO,OAAO,OAAO,cAA2B,mDAA+C;EACjG;EAEA,SAAS,QAAc;GACrB,cAAc,CAAC,EAAE,MAAM;EACzB;EAEA,SAAS,OAAa;GACpB,cAAc,CAAC,EAAE,KAAK;EACxB;EAEA,SAAa;GAAE;GAAO;EAAK,CAAC;EAE5B,QAAQ,2BAA2B;GACjC,YAAY,eAAe,MAAM,UAAU;GAC3C,MAAM,eAAe,MAAM,IAAI;GAC/B,UAAU,eAAe,WAAW,KAAK;GACzC,UAAU;GACV,SAAS;GACT,MAAM;GACN,UAAU;GACV;EACF,CAAC;;uBAIC,mBAwBM,OAAA;IAvBH,IAAI,MAAA,OAAA;aACD;IAAJ,KAAI;IACJ,0BAAA;IACA,MAAK;IACJ,OAAK,eAAE,YAAA,KAAW;IAClB,cAAY,QAAA;IACZ,mBAAiB,WAAA;IACjB,oBAAkB,MAAA,WAAA;IAClB,gBAAc,MAAA,SAAA,IAAS,SAAY,KAAA;IACnC,iBAAe,MAAA,UAAA,IAAU,SAAY,KAAA;IACrC,WAAO,OAAA,OAAA,OAAA,MAAA,GAAA,SAAE,MAAA,SAAA,KAAA,MAAA,SAAA,CAAA,CAAA,GAAA,IAAA;IACT,YAAQ,OAAA,OAAA,OAAA,MAAA,GAAA,SAAE,MAAA,UAAA,KAAA,MAAA,UAAA,CAAA,CAAA,GAAA,IAAA;OAEX,WASO,KAAA,QAAA,WAAA,CAAA,SAAA,EAAA,UAAA,IAAA,GARL,mBAOa,UAAA,MAAA,WANM,QAAA,WAAO,CAAA,IAAjB,WAAM;wBADf,YAOa,oBAAA;KALV,KAAK,OAAO;KACZ,OAAO,OAAO;KACd,UAAU,OAAO;;4BAEA,CAAA,gBAAA,gBAAf,OAAO,KAAK,GAAA,CAAA,CAAA,CAAA"}