@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
@@ -3,8 +3,8 @@ import { n as useGranularityTranslations } from "../../../chunks/granularityI18n
3
3
  import { n as useGrFormFieldContext } from "../../../chunks/context-DdNIxa1w.js";
4
4
  import { useGrFormControl } from "../../../composables/useGrFormControl.js";
5
5
  import { t as GrInput_default } from "../../GrInput/chunks/GrInput-BLywRZUN.js";
6
- import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-CofG-Tfe.js";
7
- import { t as GrSlider_default } from "../../GrSlider/chunks/GrSlider-DJfeEl4h.js";
6
+ import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-faJanmGs.js";
7
+ import { t as GrSlider_default } from "../../GrSlider/chunks/GrSlider-DTTrZTHK.js";
8
8
  import { a as grColorPickerPresetClass, c as previewClass, d as rowValueClass, f as swatchBaseClass, h as triggerValueClass, i as grColorPickerPanelClass, l as rowClass, m as triggerSwatchSizeBySize, o as grColorPickerTriggerClass, p as swatchFillClass, r as checkerClass, s as presetsGridClass, u as rowLabelClass } from "../../../chunks/config-DIDz_E5m.js";
9
9
  import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, isRef, mergeProps, nextTick, normalizeClass, normalizeStyle, openBlock, ref, renderList, toDisplayString, unref, useId, watch, withCtx, withKeys } from "vue";
10
10
  import '../styles.css';//#region src/components/GrColorPicker/color.ts
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrColorPicker-p2XH_8cE.js","names":[],"sources":["../../../../src/components/GrColorPicker/color.ts","../../../../src/components/GrColorPicker/GrColorPicker.vue","../../../../src/components/GrColorPicker/GrColorPicker.vue"],"sourcesContent":["/**\n * Арифметика цвета для `GrColorPicker` — чистый модуль без Vue.\n *\n * Модель компонента — hex-строка (в такой форме цвет лежит в токенах темы),\n * а панель работает в HSL: у оттенка, насыщенности и светлоты есть шкала, по\n * которой можно вести слайдер, а у каналов RGB её нет.\n *\n * Свой парсер, а не `__tests__/cssContrast.ts`: тот — инфраструктура гейтов, и\n * тянуть тестовый модуль в поставляемый код нельзя.\n */\n\nexport type GrHsla = {\n /** Оттенок, 0…359 (круговой: 360 — это 0). */\n h: number\n /** Насыщенность, 0…100. */\n s: number\n /** Светлота, 0…100. */\n l: number\n /** Непрозрачность, 0…1. */\n a: number\n}\n\ntype Rgb = { r: number, g: number, b: number }\n\nconst HEX_PATTERN = /^#?([0-9a-f]{3,8})$/i\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n}\n\n/**\n * Оттенок цикличен: 360° — тот же цвет, что 0°.\n *\n * Округления здесь нет намеренно: `#3b82f6` даёт 217.22°, и округлив его до\n * целого, обратное преобразование вернуло бы `#3b83f6` — компонент молча\n * переписывал бы чужой цвет при первом же открытии панели. Целые градусы\n * появляются там, где они и нужны, — на шкале слайдера (`normalizeHsla`).\n */\nfunction normalizeHue(hue: number): number {\n if (!Number.isFinite(hue))\n return 0\n return ((hue % 360) + 360) % 360\n}\n\n/** Короткая форма `#abc` разворачивается в `#aabbcc` — так её читает и CSS. */\nfunction expandShorthand(hex: string): string | null {\n if (hex.length === 3 || hex.length === 4)\n return [...hex].map(char => char + char).join('')\n\n if (hex.length === 6 || hex.length === 8)\n return hex\n\n return null\n}\n\nfunction rgbToHsl({ r, g, b }: Rgb): { h: number, s: number, l: number } {\n const red = r / 255\n const green = g / 255\n const blue = b / 255\n\n const max = Math.max(red, green, blue)\n const min = Math.min(red, green, blue)\n const delta = max - min\n const lightness = (max + min) / 2\n\n if (delta === 0)\n return { h: 0, s: 0, l: lightness * 100 }\n\n const saturation = delta / (1 - Math.abs(2 * lightness - 1))\n\n let hue: number\n if (max === red)\n hue = ((green - blue) / delta) % 6\n else if (max === green)\n hue = (blue - red) / delta + 2\n else hue = (red - green) / delta + 4\n\n return { h: normalizeHue(hue * 60), s: saturation * 100, l: lightness * 100 }\n}\n\nfunction hslToRgb({ h, s, l }: Omit<GrHsla, 'a'>): Rgb {\n const saturation = clamp(s, 0, 100) / 100\n const lightness = clamp(l, 0, 100) / 100\n const hue = normalizeHue(h)\n\n const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation\n const second = chroma * (1 - Math.abs(((hue / 60) % 2) - 1))\n const match = lightness - chroma / 2\n\n const [red, green, blue] = ((): [number, number, number] => {\n if (hue < 60)\n return [chroma, second, 0]\n if (hue < 120)\n return [second, chroma, 0]\n if (hue < 180)\n return [0, chroma, second]\n if (hue < 240)\n return [0, second, chroma]\n if (hue < 300)\n return [second, 0, chroma]\n return [chroma, 0, second]\n })()\n\n return {\n r: Math.round((red + match) * 255),\n g: Math.round((green + match) * 255),\n b: Math.round((blue + match) * 255),\n }\n}\n\nfunction toHexPair(value: number): string {\n return clamp(Math.round(value), 0, 255).toString(16).padStart(2, '0')\n}\n\n/**\n * Разбирает hex любой из четырёх форм (`#abc`, `#abcd`, `#aabbcc`, `#aabbccdd`),\n * регистр и решётка необязательны.\n *\n * Мусор возвращает `null`, а не бросает: значение приходит из модели снаружи и\n * из поля ввода, и упавший компонент — худший ответ на опечатку.\n */\nexport function parseHexColor(value: unknown): GrHsla | null {\n if (typeof value !== 'string')\n return null\n\n const match = HEX_PATTERN.exec(value.trim())\n if (!match)\n return null\n\n const hex = expandShorthand(match[1])\n if (!hex)\n return null\n\n const rgb: Rgb = {\n r: Number.parseInt(hex.slice(0, 2), 16),\n g: Number.parseInt(hex.slice(2, 4), 16),\n b: Number.parseInt(hex.slice(4, 6), 16),\n }\n\n const alpha = hex.length === 8 ? Number.parseInt(hex.slice(6, 8), 16) / 255 : 1\n\n return { ...rgbToHsl(rgb), a: alpha }\n}\n\n/**\n * Собирает hex обратно. `withAlpha: false` альфу отбрасывает, а не округляет до\n * непрозрачного: компонент без пропа `alpha` не вправе отдавать восьмизначную\n * форму, которую потребитель не ждёт.\n */\nexport function formatHexColor(color: GrHsla, withAlpha = false): string {\n const { r, g, b } = hslToRgb(color)\n const base = `#${toHexPair(r)}${toHexPair(g)}${toHexPair(b)}`\n\n if (!withAlpha)\n return base\n\n return `${base}${toHexPair(clamp(color.a, 0, 1) * 255)}`\n}\n\n/** Короткая запись числа: целое остаётся целым, дробь обрезается до сотых. */\nfunction trim(value: number): number {\n return Math.round(value * 100) / 100\n}\n\n/** CSS-запись цвета для превью и градиентов. */\nexport function hslaToCss(color: GrHsla): string {\n const h = trim(normalizeHue(color.h))\n const s = trim(clamp(color.s, 0, 100))\n const l = trim(clamp(color.l, 0, 100))\n\n return `hsl(${h} ${s}% ${l}% / ${trim(clamp(color.a, 0, 1))})`\n}\n\n/** Приводит произвольный объект к валидному диапазону каналов. */\nexport function normalizeHsla(color: GrHsla): GrHsla {\n return {\n h: Math.round(normalizeHue(color.h)) % 360,\n s: clamp(Math.round(color.s), 0, 100),\n l: clamp(Math.round(color.l), 0, 100),\n a: clamp(color.a, 0, 1),\n }\n}\n","<script setup lang=\"ts\">\n/**\n * GrColorPicker — поле выбора цвета: образец с текущим значением, панель с\n * оттенком, насыщенностью, светлотой и прозрачностью, поле hex и палитра.\n *\n * Прямой сценарий — настройки темы и брендирования, поэтому модель хранит hex:\n * в такой форме цвет лежит в токенах и его понимает CSS.\n *\n * A11y: каждый канал — отдельный `GrSlider`, то есть настоящий `role=\"slider\"`\n * с полной клавиатурой и `aria-valuetext`. Двумерная область saturation/value\n * не берётся намеренно: это свой виджет со своей клавиатурой по двум осям, и\n * доступность там пришлось бы собирать с нуля.\n */\nimport { computed, nextTick, ref, useId, watch } from 'vue'\n\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrPopover from '../GrPopover/GrPopover.vue'\nimport GrSlider from '../GrSlider/GrSlider.vue'\n\nimport { formatHexColor, hslaToCss, normalizeHsla, parseHexColor, type GrHsla } from './color'\nimport {\n checkerClass,\n grColorPickerPanelClass,\n grColorPickerPresetClass,\n grColorPickerTriggerClass,\n presetsGridClass,\n previewClass,\n rowClass,\n rowLabelClass,\n rowValueClass,\n swatchBaseClass,\n swatchFillClass,\n triggerSwatchSizeBySize,\n triggerValueClass,\n type GrColorPickerSize,\n} from './grColorPickerStyles'\n\nexport type { GrColorPickerSize } from './grColorPickerStyles'\n\nexport interface GrColorPickerProps {\n /** Цвет в hex: `#RRGGBB`, а при `alpha` — `#RRGGBBAA`. Мусор не роняет компонент. */\n modelValue: string\n /** Четвёртый слайдер и восьмизначная форма hex. */\n alpha?: boolean\n /** Палитра быстрого выбора. Пусто — блок не рендерится. */\n presets?: string[]\n size?: GrColorPickerSize\n /** Контролируемое состояние панели (`v-model:open`). */\n open?: boolean\n /** Сторона, с которой раскрывается панель. */\n placement?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'\n /** Имя для нативной формы: значение уходит скрытым полем. */\n name?: string\n disabled?: boolean\n /** Только для чтения: цвет видно, панель открывается, но значение не меняется. */\n readonly?: boolean\n invalid?: boolean\n required?: boolean\n ariaLabel?: string\n}\n\nexport interface GrColorPickerEmits {\n (e: 'update:modelValue', value: string): void\n (e: 'change', value: string): void\n (e: 'update:open', value: boolean): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrColorPickerProps>(), {\n alpha: false,\n presets: () => [],\n // Дефолт живёт в резолвере: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n size: undefined,\n open: undefined,\n placement: 'bottom-start',\n name: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrColorPickerEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrColorPicker' })\n\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n // «Ввод не принимается» — `disabled` или `readonly`: значение видно, но не меняется.\n locked: isLocked,\n} = useGrFormControl(() => props)\n\n/**\n * `aria-required` и `aria-readonly` роль `button` не поддерживает — axe роняет\n * это как critical `aria-allowed-attr`. Состояния уходят в описание триггера:\n * иначе они пропали бы для диктора совсем (маркер `*` у `GrFormField`\n * декоративен и скрыт).\n */\nconst stateHintId = useId()\nconst stateHint = computed(() => [\n isRequired.value ? t('gr.form.required', 'This field is required') : undefined,\n isReadonly.value ? t('gr.form.readonly', 'Read only') : undefined,\n].filter(Boolean).join('. ') || undefined)\n\nconst describedBy = computed(() => [\n field?.describedById.value,\n stateHint.value ? stateHintId : undefined,\n].filter(Boolean).join(' ') || undefined)\n\nconst triggerEl = ref<HTMLElement | null>(null)\n\nfunction focus(): void {\n triggerEl.value?.focus()\n}\n\nfunction blur(): void {\n triggerEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nconst FALLBACK: GrHsla = { h: 0, s: 0, l: 0, a: 1 }\n\n/**\n * Рабочее состояние панели.\n *\n * Держать его отдельно от модели обязательно: hex — проекция с потерями. У\n * серого нет оттенка, и без собственного состояния бегунок оттенка прыгал бы\n * обратно на 0° при каждом движении.\n */\nconst state = ref<GrHsla>(parseHexColor(props.modelValue) ?? FALLBACK)\n\n/** Последнее отданное значение: вернувшись в проп, оно не должно сбрасывать состояние. */\nlet lastEmitted = ''\n\nwatch(() => props.modelValue, (next) => {\n if (next === lastEmitted)\n return\n\n const parsed = parseHexColor(next)\n if (parsed)\n state.value = parsed\n})\n\nconst cssColor = computed(() => hslaToCss(state.value))\nconst hexValue = computed(() => formatHexColor(state.value, props.alpha))\n\nfunction commit(next: GrHsla): void {\n if (isLocked.value)\n return\n\n state.value = normalizeHsla(next)\n\n const hex = formatHexColor(state.value, props.alpha)\n lastEmitted = hex\n emit('update:modelValue', hex)\n emit('change', hex)\n}\n\n/** Канал панели: слайдер читает состояние и коммитит новое значение целиком. */\nfunction channel(key: 'h' | 's' | 'l' | 'a', scale = 1) {\n return computed<number>({\n get: () => Math.round(state.value[key] * scale),\n set: value => commit({ ...state.value, [key]: value / scale }),\n })\n}\n\nconst hue = channel('h')\nconst saturation = channel('s')\nconst lightness = channel('l')\n// Альфа хранится долей, а слайдер ходит по процентам — иначе шаг был бы 0.01.\nconst opacity = channel('a', 100)\n\nconst degrees = (value: number): string => `${value}°`\nconst percent = (value: number): string => `${value}%`\n\n/** Текст поля hex редактируется свободно и коммитится только валидным. */\nconst hexDraft = ref(hexValue.value)\n\nwatch(hexValue, (next) => {\n hexDraft.value = next\n})\n\nfunction commitHex(): void {\n const parsed = parseHexColor(hexDraft.value)\n\n // Мусор откатывается к текущему значению: держать в поле невалидный текст\n // после коммита — значит показывать цвет, которого нет.\n //\n // Откат идёт следующим тиком намеренно: вернув значение синхронно, мы отдали\n // бы Vue то же самое, что он уже отрисовал, — патча не случилось бы, и в поле\n // остался бы набранный мусор.\n if (!parsed) {\n void nextTick(() => {\n hexDraft.value = hexValue.value\n })\n return\n }\n\n commit(props.alpha ? parsed : { ...parsed, a: state.value.a })\n}\n\nconst isOpen = ref(false)\nconst panelOpen = computed({\n get: () => props.open ?? isOpen.value,\n set: (value) => {\n isOpen.value = value\n emit('update:open', value)\n },\n})\n\nconst presetList = computed(() => props.presets.filter(preset => parseHexColor(preset) !== null))\n\nfunction isPresetSelected(preset: string): boolean {\n const parsed = parseHexColor(preset)\n return parsed ? formatHexColor(parsed, props.alpha) === hexValue.value : false\n}\n\nfunction selectPreset(preset: string): void {\n const parsed = parseHexColor(preset)\n if (parsed)\n commit(parsed)\n}\n\nconst triggerClass = computed(() => grColorPickerTriggerClass({\n size: resolvedSize.value,\n disabled: isDisabled.value,\n invalid: isInvalid.value,\n}))\n\nconst panelClass = computed(() => grColorPickerPanelClass(resolvedSize.value))\nconst swatchSizeClass = computed(() => triggerSwatchSizeBySize[resolvedSize.value])\n\n/**\n * Градиенты дорожек. Через `--gr-slider-rail` их не подать: хук уходит в\n * `background-color`, а градиент там не работает — поэтому значения приезжают\n * переменными, а красит дорожки собственный `<style>` компонента.\n *\n * Переменные висят на самой панели, а не на корне: панель уезжает в портал, и\n * наследование от корня до неё не доходит.\n */\nconst trackVars = computed<Record<string, string>>(() => {\n const { h, s, l } = state.value\n const solid = hslaToCss({ h, s, l, a: 1 })\n\n return {\n '--gr-color-picker-track-hue': 'linear-gradient(to right, hsl(0 100% 50%), hsl(60 100% 50%), hsl(120 100% 50%), hsl(180 100% 50%), hsl(240 100% 50%), hsl(300 100% 50%), hsl(360 100% 50%))',\n '--gr-color-picker-track-saturation': `linear-gradient(to right, hsl(${Math.round(h)} 0% ${Math.round(l)}%), hsl(${Math.round(h)} 100% ${Math.round(l)}%))`,\n '--gr-color-picker-track-lightness': `linear-gradient(to right, hsl(${Math.round(h)} ${Math.round(s)}% 0%), hsl(${Math.round(h)} ${Math.round(s)}% 50%), hsl(${Math.round(h)} ${Math.round(s)}% 100%))`,\n '--gr-color-picker-track-alpha': `linear-gradient(to right, transparent, ${solid})`,\n }\n})\n</script>\n\n<template>\n <div data-gr-color-picker>\n <!-- Значение для нативной формы уходит скрытым полем: интерактивного\n контрола внутри виджета быть не должно. -->\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"hexValue\">\n\n <span v-if=\"stateHint\" :id=\"stateHintId\" class=\"sr-only\">{{ stateHint }}</span>\n\n <GrPopover\n v-model:open=\"panelOpen\"\n :size=\"resolvedSize\"\n :placement=\"placement\"\n :disabled=\"isDisabled\"\n :aria-label=\"t('gr.colorPicker.panelLabel', 'Color picker')\"\n :close-on-content-click=\"false\"\n >\n <template #trigger=\"{ triggerProps }\">\n <button\n :id=\"fieldId\"\n ref=\"triggerEl\"\n v-bind=\"triggerProps\"\n data-gr-color-picker-trigger\n type=\"button\"\n :class=\"triggerClass\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <span\n data-gr-color-picker-swatch\n aria-hidden=\"true\"\n :class=\"[swatchBaseClass, swatchSizeClass, checkerClass]\"\n >\n <span :class=\"swatchFillClass\" :style=\"{ background: cssColor }\" />\n </span>\n\n <span :class=\"triggerValueClass\">{{ hexValue }}</span>\n </button>\n </template>\n\n <template #content>\n <div data-gr-color-picker-panel :class=\"panelClass\" :style=\"trackVars\">\n <div\n data-gr-color-picker-preview\n aria-hidden=\"true\"\n :class=\"[previewClass, checkerClass]\"\n >\n <span :class=\"swatchFillClass\" :style=\"{ background: cssColor }\" />\n </div>\n\n <div data-gr-color-picker-channel=\"hue\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">H</span>\n <GrSlider\n v-model=\"hue\"\n :min=\"0\"\n :max=\"359\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"degrees\"\n :aria-label=\"t('gr.colorPicker.hue', 'Hue')\"\n />\n <span :class=\"rowValueClass\">{{ degrees(hue) }}</span>\n </div>\n\n <div data-gr-color-picker-channel=\"saturation\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">S</span>\n <GrSlider\n v-model=\"saturation\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"percent\"\n :aria-label=\"t('gr.colorPicker.saturation', 'Saturation')\"\n />\n <span :class=\"rowValueClass\">{{ percent(saturation) }}</span>\n </div>\n\n <div data-gr-color-picker-channel=\"lightness\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">L</span>\n <GrSlider\n v-model=\"lightness\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"percent\"\n :aria-label=\"t('gr.colorPicker.lightness', 'Lightness')\"\n />\n <span :class=\"rowValueClass\">{{ percent(lightness) }}</span>\n </div>\n\n <div v-if=\"alpha\" data-gr-color-picker-channel=\"alpha\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">A</span>\n <GrSlider\n v-model=\"opacity\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"percent\"\n :aria-label=\"t('gr.colorPicker.opacity', 'Opacity')\"\n />\n <span :class=\"rowValueClass\">{{ percent(opacity) }}</span>\n </div>\n\n <GrInput\n v-model=\"hexDraft\"\n data-gr-color-picker-hex\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :aria-label=\"t('gr.colorPicker.hexLabel', 'Hex value')\"\n @change=\"commitHex\"\n @keydown.enter=\"commitHex\"\n />\n\n <div\n v-if=\"presetList.length\"\n data-gr-color-picker-presets\n :class=\"presetsGridClass\"\n role=\"group\"\n :aria-label=\"t('gr.colorPicker.presetsLabel', 'Color presets')\"\n >\n <button\n v-for=\"preset in presetList\"\n :key=\"preset\"\n data-gr-color-picker-preset\n type=\"button\"\n :class=\"[grColorPickerPresetClass(isPresetSelected(preset)), checkerClass]\"\n :aria-label=\"t('gr.colorPicker.swatchLabel', 'Color {color}', { color: preset })\"\n :aria-pressed=\"isPresetSelected(preset) ? 'true' : 'false'\"\n :disabled=\"isLocked\"\n @click=\"selectPreset(preset)\"\n >\n <span :class=\"swatchFillClass\" :style=\"{ background: preset }\" />\n </button>\n </div>\n </div>\n </template>\n </GrPopover>\n </div>\n</template>\n\n<style>\n/*\n * Шахматка под прозрачным цветом. Двумя `conic-gradient` — в утилите такое не\n * выражается, а без подложки прозрачный образец сливается с панелью.\n */\n.gr-color-picker-checker {\n background-image:\n conic-gradient(\n from 90deg,\n var(--gr-color-picker-checker-light, var(--gr-bg)) 0 25%,\n var(--gr-color-picker-checker-dark, var(--gr-muted)) 0 50%,\n var(--gr-color-picker-checker-light, var(--gr-bg)) 0 75%,\n var(--gr-color-picker-checker-dark, var(--gr-muted)) 0\n );\n background-size:\n calc(var(--gr-color-picker-checker-size, 6px) * 2)\n calc(var(--gr-color-picker-checker-size, 6px) * 2);\n /* Рамка образца полупрозрачна, и без обрезки шахматка просвечивает сквозь неё. */\n background-clip: padding-box;\n}\n\n/*\n * Дорожки каналов. Красим `[data-gr-slider-track]` потому, что хук\n * `--gr-slider-rail` уходит в `background-color`, а градиент там не работает.\n * Сами градиенты компонент подаёт переменными — CSS остаётся статичной.\n */\n[data-gr-color-picker-channel] [data-gr-slider-track] {\n border-radius: var(--gr-radius-full);\n}\n\n[data-gr-color-picker-channel='hue'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-hue);\n}\n\n[data-gr-color-picker-channel='saturation'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-saturation);\n}\n\n[data-gr-color-picker-channel='lightness'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-lightness);\n}\n\n[data-gr-color-picker-channel='alpha'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-alpha);\n}\n\n/* Заливка канала прозрачна: шкалу показывает сама дорожка. */\n[data-gr-color-picker-channel] [data-gr-slider-fill] {\n background-color: transparent;\n}\n</style>\n","<script setup lang=\"ts\">\n/**\n * GrColorPicker — поле выбора цвета: образец с текущим значением, панель с\n * оттенком, насыщенностью, светлотой и прозрачностью, поле hex и палитра.\n *\n * Прямой сценарий — настройки темы и брендирования, поэтому модель хранит hex:\n * в такой форме цвет лежит в токенах и его понимает CSS.\n *\n * A11y: каждый канал — отдельный `GrSlider`, то есть настоящий `role=\"slider\"`\n * с полной клавиатурой и `aria-valuetext`. Двумерная область saturation/value\n * не берётся намеренно: это свой виджет со своей клавиатурой по двум осям, и\n * доступность там пришлось бы собирать с нуля.\n */\nimport { computed, nextTick, ref, useId, watch } from 'vue'\n\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentSize } from '../GrConfigProvider/context'\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport GrInput from '../GrInput/GrInput.vue'\nimport GrPopover from '../GrPopover/GrPopover.vue'\nimport GrSlider from '../GrSlider/GrSlider.vue'\n\nimport { formatHexColor, hslaToCss, normalizeHsla, parseHexColor, type GrHsla } from './color'\nimport {\n checkerClass,\n grColorPickerPanelClass,\n grColorPickerPresetClass,\n grColorPickerTriggerClass,\n presetsGridClass,\n previewClass,\n rowClass,\n rowLabelClass,\n rowValueClass,\n swatchBaseClass,\n swatchFillClass,\n triggerSwatchSizeBySize,\n triggerValueClass,\n type GrColorPickerSize,\n} from './grColorPickerStyles'\n\nexport type { GrColorPickerSize } from './grColorPickerStyles'\n\nexport interface GrColorPickerProps {\n /** Цвет в hex: `#RRGGBB`, а при `alpha` — `#RRGGBBAA`. Мусор не роняет компонент. */\n modelValue: string\n /** Четвёртый слайдер и восьмизначная форма hex. */\n alpha?: boolean\n /** Палитра быстрого выбора. Пусто — блок не рендерится. */\n presets?: string[]\n size?: GrColorPickerSize\n /** Контролируемое состояние панели (`v-model:open`). */\n open?: boolean\n /** Сторона, с которой раскрывается панель. */\n placement?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'\n /** Имя для нативной формы: значение уходит скрытым полем. */\n name?: string\n disabled?: boolean\n /** Только для чтения: цвет видно, панель открывается, но значение не меняется. */\n readonly?: boolean\n invalid?: boolean\n required?: boolean\n ariaLabel?: string\n}\n\nexport interface GrColorPickerEmits {\n (e: 'update:modelValue', value: string): void\n (e: 'change', value: string): void\n (e: 'update:open', value: boolean): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(defineProps<GrColorPickerProps>(), {\n alpha: false,\n presets: () => [],\n // Дефолт живёт в резолвере: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n size: undefined,\n open: undefined,\n placement: 'bottom-start',\n name: undefined,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n ariaLabel: undefined,\n})\n\nconst emit = defineEmits<GrColorPickerEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrColorPicker' })\n\nconst field = useGrFormFieldContext()\nconst fieldId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid,\n required: isRequired,\n readonly: isReadonly,\n // «Ввод не принимается» — `disabled` или `readonly`: значение видно, но не меняется.\n locked: isLocked,\n} = useGrFormControl(() => props)\n\n/**\n * `aria-required` и `aria-readonly` роль `button` не поддерживает — axe роняет\n * это как critical `aria-allowed-attr`. Состояния уходят в описание триггера:\n * иначе они пропали бы для диктора совсем (маркер `*` у `GrFormField`\n * декоративен и скрыт).\n */\nconst stateHintId = useId()\nconst stateHint = computed(() => [\n isRequired.value ? t('gr.form.required', 'This field is required') : undefined,\n isReadonly.value ? t('gr.form.readonly', 'Read only') : undefined,\n].filter(Boolean).join('. ') || undefined)\n\nconst describedBy = computed(() => [\n field?.describedById.value,\n stateHint.value ? stateHintId : undefined,\n].filter(Boolean).join(' ') || undefined)\n\nconst triggerEl = ref<HTMLElement | null>(null)\n\nfunction focus(): void {\n triggerEl.value?.focus()\n}\n\nfunction blur(): void {\n triggerEl.value?.blur()\n}\n\ndefineExpose({ focus, blur })\n\nconst FALLBACK: GrHsla = { h: 0, s: 0, l: 0, a: 1 }\n\n/**\n * Рабочее состояние панели.\n *\n * Держать его отдельно от модели обязательно: hex — проекция с потерями. У\n * серого нет оттенка, и без собственного состояния бегунок оттенка прыгал бы\n * обратно на 0° при каждом движении.\n */\nconst state = ref<GrHsla>(parseHexColor(props.modelValue) ?? FALLBACK)\n\n/** Последнее отданное значение: вернувшись в проп, оно не должно сбрасывать состояние. */\nlet lastEmitted = ''\n\nwatch(() => props.modelValue, (next) => {\n if (next === lastEmitted)\n return\n\n const parsed = parseHexColor(next)\n if (parsed)\n state.value = parsed\n})\n\nconst cssColor = computed(() => hslaToCss(state.value))\nconst hexValue = computed(() => formatHexColor(state.value, props.alpha))\n\nfunction commit(next: GrHsla): void {\n if (isLocked.value)\n return\n\n state.value = normalizeHsla(next)\n\n const hex = formatHexColor(state.value, props.alpha)\n lastEmitted = hex\n emit('update:modelValue', hex)\n emit('change', hex)\n}\n\n/** Канал панели: слайдер читает состояние и коммитит новое значение целиком. */\nfunction channel(key: 'h' | 's' | 'l' | 'a', scale = 1) {\n return computed<number>({\n get: () => Math.round(state.value[key] * scale),\n set: value => commit({ ...state.value, [key]: value / scale }),\n })\n}\n\nconst hue = channel('h')\nconst saturation = channel('s')\nconst lightness = channel('l')\n// Альфа хранится долей, а слайдер ходит по процентам — иначе шаг был бы 0.01.\nconst opacity = channel('a', 100)\n\nconst degrees = (value: number): string => `${value}°`\nconst percent = (value: number): string => `${value}%`\n\n/** Текст поля hex редактируется свободно и коммитится только валидным. */\nconst hexDraft = ref(hexValue.value)\n\nwatch(hexValue, (next) => {\n hexDraft.value = next\n})\n\nfunction commitHex(): void {\n const parsed = parseHexColor(hexDraft.value)\n\n // Мусор откатывается к текущему значению: держать в поле невалидный текст\n // после коммита — значит показывать цвет, которого нет.\n //\n // Откат идёт следующим тиком намеренно: вернув значение синхронно, мы отдали\n // бы Vue то же самое, что он уже отрисовал, — патча не случилось бы, и в поле\n // остался бы набранный мусор.\n if (!parsed) {\n void nextTick(() => {\n hexDraft.value = hexValue.value\n })\n return\n }\n\n commit(props.alpha ? parsed : { ...parsed, a: state.value.a })\n}\n\nconst isOpen = ref(false)\nconst panelOpen = computed({\n get: () => props.open ?? isOpen.value,\n set: (value) => {\n isOpen.value = value\n emit('update:open', value)\n },\n})\n\nconst presetList = computed(() => props.presets.filter(preset => parseHexColor(preset) !== null))\n\nfunction isPresetSelected(preset: string): boolean {\n const parsed = parseHexColor(preset)\n return parsed ? formatHexColor(parsed, props.alpha) === hexValue.value : false\n}\n\nfunction selectPreset(preset: string): void {\n const parsed = parseHexColor(preset)\n if (parsed)\n commit(parsed)\n}\n\nconst triggerClass = computed(() => grColorPickerTriggerClass({\n size: resolvedSize.value,\n disabled: isDisabled.value,\n invalid: isInvalid.value,\n}))\n\nconst panelClass = computed(() => grColorPickerPanelClass(resolvedSize.value))\nconst swatchSizeClass = computed(() => triggerSwatchSizeBySize[resolvedSize.value])\n\n/**\n * Градиенты дорожек. Через `--gr-slider-rail` их не подать: хук уходит в\n * `background-color`, а градиент там не работает — поэтому значения приезжают\n * переменными, а красит дорожки собственный `<style>` компонента.\n *\n * Переменные висят на самой панели, а не на корне: панель уезжает в портал, и\n * наследование от корня до неё не доходит.\n */\nconst trackVars = computed<Record<string, string>>(() => {\n const { h, s, l } = state.value\n const solid = hslaToCss({ h, s, l, a: 1 })\n\n return {\n '--gr-color-picker-track-hue': 'linear-gradient(to right, hsl(0 100% 50%), hsl(60 100% 50%), hsl(120 100% 50%), hsl(180 100% 50%), hsl(240 100% 50%), hsl(300 100% 50%), hsl(360 100% 50%))',\n '--gr-color-picker-track-saturation': `linear-gradient(to right, hsl(${Math.round(h)} 0% ${Math.round(l)}%), hsl(${Math.round(h)} 100% ${Math.round(l)}%))`,\n '--gr-color-picker-track-lightness': `linear-gradient(to right, hsl(${Math.round(h)} ${Math.round(s)}% 0%), hsl(${Math.round(h)} ${Math.round(s)}% 50%), hsl(${Math.round(h)} ${Math.round(s)}% 100%))`,\n '--gr-color-picker-track-alpha': `linear-gradient(to right, transparent, ${solid})`,\n }\n})\n</script>\n\n<template>\n <div data-gr-color-picker>\n <!-- Значение для нативной формы уходит скрытым полем: интерактивного\n контрола внутри виджета быть не должно. -->\n <input v-if=\"name\" type=\"hidden\" :name=\"name\" :value=\"hexValue\">\n\n <span v-if=\"stateHint\" :id=\"stateHintId\" class=\"sr-only\">{{ stateHint }}</span>\n\n <GrPopover\n v-model:open=\"panelOpen\"\n :size=\"resolvedSize\"\n :placement=\"placement\"\n :disabled=\"isDisabled\"\n :aria-label=\"t('gr.colorPicker.panelLabel', 'Color picker')\"\n :close-on-content-click=\"false\"\n >\n <template #trigger=\"{ triggerProps }\">\n <button\n :id=\"fieldId\"\n ref=\"triggerEl\"\n v-bind=\"triggerProps\"\n data-gr-color-picker-trigger\n type=\"button\"\n :class=\"triggerClass\"\n :aria-label=\"ariaLabel\"\n :aria-describedby=\"describedBy\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n @focus=\"emit('focus', $event)\"\n @blur=\"emit('blur', $event)\"\n >\n <span\n data-gr-color-picker-swatch\n aria-hidden=\"true\"\n :class=\"[swatchBaseClass, swatchSizeClass, checkerClass]\"\n >\n <span :class=\"swatchFillClass\" :style=\"{ background: cssColor }\" />\n </span>\n\n <span :class=\"triggerValueClass\">{{ hexValue }}</span>\n </button>\n </template>\n\n <template #content>\n <div data-gr-color-picker-panel :class=\"panelClass\" :style=\"trackVars\">\n <div\n data-gr-color-picker-preview\n aria-hidden=\"true\"\n :class=\"[previewClass, checkerClass]\"\n >\n <span :class=\"swatchFillClass\" :style=\"{ background: cssColor }\" />\n </div>\n\n <div data-gr-color-picker-channel=\"hue\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">H</span>\n <GrSlider\n v-model=\"hue\"\n :min=\"0\"\n :max=\"359\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"degrees\"\n :aria-label=\"t('gr.colorPicker.hue', 'Hue')\"\n />\n <span :class=\"rowValueClass\">{{ degrees(hue) }}</span>\n </div>\n\n <div data-gr-color-picker-channel=\"saturation\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">S</span>\n <GrSlider\n v-model=\"saturation\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"percent\"\n :aria-label=\"t('gr.colorPicker.saturation', 'Saturation')\"\n />\n <span :class=\"rowValueClass\">{{ percent(saturation) }}</span>\n </div>\n\n <div data-gr-color-picker-channel=\"lightness\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">L</span>\n <GrSlider\n v-model=\"lightness\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"percent\"\n :aria-label=\"t('gr.colorPicker.lightness', 'Lightness')\"\n />\n <span :class=\"rowValueClass\">{{ percent(lightness) }}</span>\n </div>\n\n <div v-if=\"alpha\" data-gr-color-picker-channel=\"alpha\" :class=\"rowClass\">\n <span :class=\"rowLabelClass\" aria-hidden=\"true\">A</span>\n <GrSlider\n v-model=\"opacity\"\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :format-tooltip=\"percent\"\n :aria-label=\"t('gr.colorPicker.opacity', 'Opacity')\"\n />\n <span :class=\"rowValueClass\">{{ percent(opacity) }}</span>\n </div>\n\n <GrInput\n v-model=\"hexDraft\"\n data-gr-color-picker-hex\n :size=\"resolvedSize\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadonly\"\n :aria-label=\"t('gr.colorPicker.hexLabel', 'Hex value')\"\n @change=\"commitHex\"\n @keydown.enter=\"commitHex\"\n />\n\n <div\n v-if=\"presetList.length\"\n data-gr-color-picker-presets\n :class=\"presetsGridClass\"\n role=\"group\"\n :aria-label=\"t('gr.colorPicker.presetsLabel', 'Color presets')\"\n >\n <button\n v-for=\"preset in presetList\"\n :key=\"preset\"\n data-gr-color-picker-preset\n type=\"button\"\n :class=\"[grColorPickerPresetClass(isPresetSelected(preset)), checkerClass]\"\n :aria-label=\"t('gr.colorPicker.swatchLabel', 'Color {color}', { color: preset })\"\n :aria-pressed=\"isPresetSelected(preset) ? 'true' : 'false'\"\n :disabled=\"isLocked\"\n @click=\"selectPreset(preset)\"\n >\n <span :class=\"swatchFillClass\" :style=\"{ background: preset }\" />\n </button>\n </div>\n </div>\n </template>\n </GrPopover>\n </div>\n</template>\n\n<style>\n/*\n * Шахматка под прозрачным цветом. Двумя `conic-gradient` — в утилите такое не\n * выражается, а без подложки прозрачный образец сливается с панелью.\n */\n.gr-color-picker-checker {\n background-image:\n conic-gradient(\n from 90deg,\n var(--gr-color-picker-checker-light, var(--gr-bg)) 0 25%,\n var(--gr-color-picker-checker-dark, var(--gr-muted)) 0 50%,\n var(--gr-color-picker-checker-light, var(--gr-bg)) 0 75%,\n var(--gr-color-picker-checker-dark, var(--gr-muted)) 0\n );\n background-size:\n calc(var(--gr-color-picker-checker-size, 6px) * 2)\n calc(var(--gr-color-picker-checker-size, 6px) * 2);\n /* Рамка образца полупрозрачна, и без обрезки шахматка просвечивает сквозь неё. */\n background-clip: padding-box;\n}\n\n/*\n * Дорожки каналов. Красим `[data-gr-slider-track]` потому, что хук\n * `--gr-slider-rail` уходит в `background-color`, а градиент там не работает.\n * Сами градиенты компонент подаёт переменными — CSS остаётся статичной.\n */\n[data-gr-color-picker-channel] [data-gr-slider-track] {\n border-radius: var(--gr-radius-full);\n}\n\n[data-gr-color-picker-channel='hue'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-hue);\n}\n\n[data-gr-color-picker-channel='saturation'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-saturation);\n}\n\n[data-gr-color-picker-channel='lightness'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-lightness);\n}\n\n[data-gr-color-picker-channel='alpha'] [data-gr-slider-track] {\n background-image: var(--gr-color-picker-track-alpha);\n}\n\n/* Заливка канала прозрачна: шкалу показывает сама дорожка. */\n[data-gr-color-picker-channel] [data-gr-slider-fill] {\n background-color: transparent;\n}\n</style>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrColorPicker_default } from "./chunks/GrColorPicker-C7ifyQ0R.js";
1
+ import { t as GrColorPicker_default } from "./chunks/GrColorPicker-p2XH_8cE.js";
2
2
  import { n as grColorPickerSafelist, t as grColorPickerConfig } from "../../chunks/config-DIDz_E5m.js";
3
3
  export { GrColorPicker_default as GrColorPicker, GrColorPicker_default as default, grColorPickerConfig, grColorPickerSafelist };
@@ -8,7 +8,7 @@ import { i as normalizeOptionQuery, r as matchesQueryParts } from "../../../chun
8
8
  import { t as _plugin_vue_export_helper_default } from "../../../chunks/_plugin-vue_export-helper-BOaGB7Aw.js";
9
9
  import { n as iconTag, t as iconClass } from "../../../chunks/icon-Dag2tIMs.js";
10
10
  import { i as parseCommandHotkey, n as formatCommandHotkey, r as matchesCommandHotkey, t as GrKbd_default } from "../../GrKbd/chunks/GrKbd-D2ga1H9i.js";
11
- import { t as GrModal_default } from "../../GrModal/chunks/GrModal-CCoWZuIl.js";
11
+ import { t as GrModal_default } from "../../GrModal/chunks/GrModal-D0mf1SAx.js";
12
12
  import { a as commandGroupLabelClass, c as commandItemMutedClass, d as commandSearchInputClass, f as commandSearchRowClass, i as commandFooterClass, l as commandMatchClass, o as commandItemClass, r as commandEmptyClass, s as commandItemDescriptionClass, u as commandPaletteModalSizeBySize } from "../../../chunks/config-D0NzGYaE.js";
13
13
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, markRaw, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useId, watch, withCtx } from "vue";
14
14
  import '../styles.css';//#region src/components/GrCommandPalette/filtering.ts
@@ -586,6 +586,6 @@ var GrCommandPalette_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/
586
586
  }, 8, ["model-value", "size"]);
587
587
  };
588
588
  }
589
- }), [["__scopeId", "data-v-dcf84986"]]);
589
+ }), [["__scopeId", "data-v-041dfab7"]]);
590
590
  //#endregion
591
591
  export { GrCommandPalette_default as t };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrCommandPalette-BXbh3q7O.js","names":["$emit","$slots"],"sources":["../../../../src/components/GrCommandPalette/filtering.ts","../../../../src/components/GrCommandPalette/GrCommandPalette.vue","../../../../src/components/GrCommandPalette/GrCommandPalette.vue"],"sourcesContent":["import type { Component } from 'vue'\n\nimport { matchesQueryParts, normalizeOptionQuery } from '../shared/optionFilter'\n\n/** Команда палитры. `id` обязателен — он же ключ рендера и цель `aria-activedescendant`. */\nexport type GrCommandItem = {\n id: string\n label: string\n /** Пояснение под меткой. */\n description?: string\n /**\n * Иконка команды: Vue-компонент либо класс иконки вашей UnoCSS-сборки\n * (`'i-lucide-file-plus'` — тогда нужен ваш `presetIcons`).\n */\n icon?: string | Component\n /** Подсказка сочетания клавиш — массив клавиш, каждая рисуется отдельным `GrKbd`. */\n shortcut?: string[]\n /** Заголовок группы, под которой команда показывается в списке. */\n group?: string\n /** Дополнительные слова для поиска (синонимы, транслитерация). */\n keywords?: string[]\n disabled?: boolean\n}\n\n/** Команды, сгруппированные для рендера: порядок групп — порядок первого вхождения. */\nexport type GrCommandGroup = {\n /** `undefined` — команды без группы (рендерятся без заголовка). */\n name: string | undefined\n items: GrCommandItem[]\n}\n\nexport type GrCommandFilter = (item: GrCommandItem, query: string) => boolean\n\n/**\n * Матчер по умолчанию: подстрока (без учёта регистра) в метке, описании,\n * названии группы или ключевых словах.\n *\n * Набор полей у команды шире, чем у опции списка, а сам подстрочный матч — тот\n * же самый на весь пакет (`shared/optionFilter.ts`).\n */\nexport function matchCommandItem(item: GrCommandItem, query: string): boolean {\n const parts = [item.label, item.description, item.group, ...(item.keywords ?? [])]\n\n return matchesQueryParts(parts, normalizeOptionQuery(query))\n}\n\nexport function filterCommandItems(\n items: GrCommandItem[],\n query: string,\n filter: GrCommandFilter = matchCommandItem,\n): GrCommandItem[] {\n if (!query.trim())\n return items\n return items.filter(item => filter(item, query))\n}\n\n/**\n * Раскладывает плоский список по группам, сохраняя порядок первого появления\n * группы. Команды без `group` собираются в единственную безымянную группу,\n * которая остаётся на своём месте в общем порядке.\n */\nexport function groupCommandItems(items: GrCommandItem[]): GrCommandGroup[] {\n const groups: GrCommandGroup[] = []\n const byName = new Map<string | undefined, GrCommandGroup>()\n\n for (const item of items) {\n const name = item.group || undefined\n let group = byName.get(name)\n if (!group) {\n group = { name, items: [] }\n byName.set(name, group)\n groups.push(group)\n }\n group.items.push(item)\n }\n\n return groups\n}\n\n/** Кусок текста для подсветки: `match` — попал в запрос. */\nexport type GrCommandMatchSegment = {\n text: string\n match: boolean\n}\n\n/**\n * Режет текст на сегменты по вхождению запроса (без учёта регистра).\n *\n * Совпадения нет — один сегмент целиком: свой `filter` вправе матчить по\n * `keywords`, и тогда в метке подсвечивать нечего. Регистр исходного текста\n * сохраняется — подсветка не должна менять то, что читает пользователь.\n */\nexport function splitCommandMatch(text: string, query: string): GrCommandMatchSegment[] {\n const needle = query.trim().toLowerCase()\n if (!needle || !text)\n return [{ text, match: false }]\n\n const segments: GrCommandMatchSegment[] = []\n const haystack = text.toLowerCase()\n let from = 0\n\n while (from < text.length) {\n const at = haystack.indexOf(needle, from)\n if (at < 0)\n break\n\n if (at > from)\n segments.push({ text: text.slice(from, at), match: false })\n segments.push({ text: text.slice(at, at + needle.length), match: true })\n from = at + needle.length\n }\n\n if (!segments.length)\n return [{ text, match: false }]\n if (from < text.length)\n segments.push({ text: text.slice(from), match: false })\n\n return segments\n}\n\n/**\n * Поднимает «недавние» команды в отдельную группу наверх, сохраняя порядок\n * `recentIds`, и убирает их из остального списка — иначе одна и та же команда\n * оказалась бы в списке дважды, а `id` у неё один.\n */\nexport function withRecentCommands(\n groups: GrCommandGroup[],\n items: GrCommandItem[],\n recentIds: string[],\n title: string,\n): GrCommandGroup[] {\n if (!recentIds.length)\n return groups\n\n const byId = new Map(items.map(item => [item.id, item]))\n const recent: GrCommandItem[] = []\n const taken = new Set<string>()\n\n for (const id of recentIds) {\n const item = byId.get(id)\n if (!item || taken.has(id))\n continue\n recent.push(item)\n taken.add(id)\n }\n\n if (!recent.length)\n return groups\n\n const rest = groups\n .map(group => ({ ...group, items: group.items.filter(item => !taken.has(item.id)) }))\n .filter(group => group.items.length > 0)\n\n return [{ name: title, items: recent }, ...rest]\n}\n\n/** Идентификаторы, встретившиеся больше одного раза. */\nexport function findDuplicateCommandIds(items: GrCommandItem[]): string[] {\n const seen = new Set<string>()\n const duplicates = new Set<string>()\n\n for (const item of items) {\n if (seen.has(item.id))\n duplicates.add(item.id)\n else seen.add(item.id)\n }\n\n return [...duplicates]\n}\n","<script setup lang=\"ts\">\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, watch } from 'vue'\n\nimport { useVirtualList } from '../../composables/useVirtualList'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { isComposingEvent } from '../../internal/keyboard'\nimport { useComboboxNavigation } from '../../composables/useComboboxNavigation'\nimport { iconClass, iconTag } from '../shared/icon'\nimport GrKbd from '../GrKbd/GrKbd.vue'\nimport GrModal from '../GrModal/GrModal.vue'\n\nimport {\n filterCommandItems,\n findDuplicateCommandIds,\n groupCommandItems,\n matchCommandItem,\n splitCommandMatch,\n withRecentCommands,\n type GrCommandFilter,\n type GrCommandItem,\n} from './filtering'\nimport {\n formatCommandHotkey,\n isAppleDevice,\n matchesCommandHotkey,\n parseCommandHotkey,\n} from '../shared/hotkey'\nimport {\n commandEmptyClass,\n commandFooterClass,\n commandGroupLabelClass,\n commandItemClass,\n commandItemDescriptionClass,\n commandItemMutedClass,\n commandMatchClass,\n commandPaletteModalSizeBySize,\n commandSearchInputClass,\n commandSearchRowClass,\n type GrCommandPaletteSize,\n} from './grCommandPaletteStyles'\n\nimport IconLoaderCircle from '~icons/lucide/loader-circle'\nimport IconSearch from '~icons/lucide/search'\n\nexport type { GrCommandFilter, GrCommandGroup, GrCommandItem } from './filtering'\nexport type { GrCommandPaletteSize } from './grCommandPaletteStyles'\n\n/**\n * Публичный GR-примитив «Command palette» (⌘K) — модальный поиск по командам\n * приложения с группировкой, подсказками сочетаний и клавиатурной навигацией.\n *\n * A11y: WAI-ARIA combobox поверх модалки — `role=\"combobox\"` на поле ввода,\n * `role=\"listbox\"` на списке, `aria-activedescendant` на активной команде\n * (фокус остаётся в поле). Esc, фокус-ловушка и блокировка скролла приходят\n * из `GrModal`.\n *\n * Открытие по глобальному сочетанию (`hotkey`, по умолчанию `mod+k` — Cmd на\n * macOS, Ctrl на прочих) компонент берёт на себя; передайте `hotkey: null`,\n * чтобы управлять открытием только через `v-model`.\n */\nexport interface GrCommandPaletteProps {\n /** Открыта ли палитра. */\n modelValue: boolean\n /** Плоский список команд; группировка — по полю `group` самой команды. */\n items?: GrCommandItem[]\n /**\n * Недавние команды: пока запрос пуст, они поднимаются отдельной группой\n * наверх в этом порядке и не дублируются ниже.\n */\n recentIds?: string[]\n placeholder?: string\n size?: GrCommandPaletteSize\n /** Глобальное сочетание открытия. `null` — не вешать слушатель. */\n hotkey?: string | null\n /** Локальная фильтрация по запросу. `false` — фильтрует владелец по событию `search`. */\n filterable?: boolean\n /** Кастомный матчер локальной фильтрации. */\n filter?: GrCommandFilter\n /** Внешне управляемое состояние загрузки (для remote-поиска). */\n loading?: boolean\n /** Закрывать палитру после выбора команды. */\n closeOnSelect?: boolean\n /** Максимальная высота списка, px. */\n maxHeight?: number\n /**\n * Виртуализация списка: в DOM живёт только окно вокруг вьюпорта. Высоту окна\n * задаёт `maxHeight`.\n *\n * Включается осознанно: на сотне команд выигрыша нет, а в разметке остаётся\n * только окно — вместе с ним меняется и то, что находит `querySelector`\n * потребителя. Профильный сценарий — палитра приложения на тысячи команд.\n */\n virtual?: boolean\n /** Показывать подсказку сочетания в поле ввода. */\n showHotkeyHint?: boolean\n emptyText?: string\n ariaLabel?: string\n}\n\nexport interface GrCommandPaletteEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Команда выбрана (клик или Enter). */\n (e: 'select', item: GrCommandItem): void\n /** Поисковый запрос изменился — точка входа для remote-поиска. */\n (e: 'search', query: string): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(\n defineProps<GrCommandPaletteProps>(),\n {\n items: undefined,\n recentIds: undefined,\n placeholder: undefined,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n hotkey: 'mod+k',\n filterable: true,\n filter: undefined,\n loading: false,\n closeOnSelect: true,\n maxHeight: 360,\n virtual: false,\n showHotkeyHint: true,\n emptyText: undefined,\n ariaLabel: undefined,\n },\n)\n\nconst emit = defineEmits<GrCommandPaletteEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedPlaceholder = computed(() => props.placeholder ?? t('gr.commandPalette.placeholder', 'Type a command or search…'))\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.commandPalette.empty', 'Nothing found'))\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.commandPalette.label', 'Command palette'))\nconst loadingText = computed(() => t('gr.commandPalette.loading', 'Loading…'))\nconst recentTitle = computed(() => t('gr.commandPalette.recent', 'Recent'))\n\nconst query = ref('')\nconst inputEl = ref<HTMLInputElement | null>(null)\nconst listboxId = useId()\n\nconst itemsResolved = computed<GrCommandItem[]>(() => props.items ?? [])\n\nconst filteredItems = computed<GrCommandItem[]>(() =>\n props.filterable\n ? filterCommandItems(itemsResolved.value, query.value, props.filter ?? matchCommandItem)\n : itemsResolved.value,\n)\n\nconst groups = computed(() => {\n const grouped = groupCommandItems(filteredItems.value)\n\n // С непустым запросом секции «недавние» нет: там правит релевантность, а не\n // история — иначе первая же буква уводила бы взгляд не туда.\n if (query.value.trim())\n return grouped\n\n return withRecentCommands(grouped, filteredItems.value, props.recentIds ?? [], recentTitle.value)\n})\n\n/**\n * Порядок обхода стрелками совпадает с порядком на экране: «недавние» стоят\n * первыми, значит и первая стрелка ведёт туда же.\n */\nconst orderedItems = computed(() => groups.value.flatMap(group => group.items))\n\n/** Плоский список того, что реально выбирается — по нему ходят стрелки. */\nconst navigableItems = computed(() => orderedItems.value.filter(item => !item.disabled))\n\nfunction itemDomId(id: string): string {\n return `${listboxId}-item-${id}`\n}\n\n/**\n * Виртуализация списка.\n *\n * Набор — плоский поток строк экрана: заголовок группы занимает такую же\n * строку, как команда, поэтому входит в него наравне. Вложенную структуру\n * рендер пересобирает уже из окна.\n */\n\n/** Оценки высоты строк. Команда крупнее заголовка; дальше уточняются замером. */\nconst ITEM_SIZE_ESTIMATE = 44\nconst GROUP_LABEL_SIZE_ESTIMATE = 28\n\ntype PaletteRow\n = | { kind: 'label', groupIndex: number }\n | { kind: 'item', groupIndex: number, item: GrCommandItem, posInSet: number, setSize: number }\n\nconst listEl = ref<HTMLElement | null>(null)\n\nconst paletteRows = computed<PaletteRow[]>(() => {\n const rows: PaletteRow[] = []\n\n groups.value.forEach((group, groupIndex) => {\n if (group.name)\n rows.push({ kind: 'label', groupIndex })\n\n group.items.forEach((item, index) => {\n rows.push({\n kind: 'item',\n groupIndex,\n item,\n // Набор — группа, а не весь список: по ARIA позиция отсчитывается от неё.\n posInSet: index + 1,\n setSize: group.items.length,\n })\n })\n })\n\n return rows\n})\n\nconst virtualizer = useVirtualList({\n container: listEl,\n count: () => (props.virtual ? paletteRows.value.length : 0),\n // Запрос пересобирает набор строк — замеры прошлого набора невалидны.\n source: () => paletteRows.value,\n itemSize: index => (paletteRows.value[index]?.kind === 'label' ? GROUP_LABEL_SIZE_ESTIMATE : ITEM_SIZE_ESTIMATE),\n // Список закрытой палитры не смонтирован вовсе: `clientHeight` взять неоткуда.\n // `maxHeight` можно перебить `--gr-command-list-max-height` — тогда точная\n // высота приедет с первым замером, а это останется оценкой первого рендера.\n viewportSize: () => props.maxHeight,\n})\n\n/**\n * Группы к отрисовке. При виртуализации пересобираются из среза `paletteRows`:\n * группа, начатая выше окна, всё равно открывается — иначе её команды остались\n * бы прямыми потомками listbox'а, что роль запрещает.\n */\ntype RenderedGroup = {\n key: string\n groupIndex: number\n name: string | undefined\n labelVisible: boolean\n /** Позиция строки заголовка в `paletteRows` — по ней его замеряет виртуализатор. */\n labelRowIndex?: number\n items: { item: GrCommandItem, rowIndex: number, posInSet: number, setSize: number }[]\n}\n\nconst renderedGroups = computed<RenderedGroup[]>(() => {\n const rows = paletteRows.value\n\n const from = props.virtual ? virtualizer.range.value.start : 0\n const to = props.virtual ? Math.min(rows.length, virtualizer.range.value.end) : rows.length\n\n const result: RenderedGroup[] = []\n let current: RenderedGroup | undefined\n\n for (let rowIndex = from; rowIndex < to; rowIndex++) {\n const row = rows[rowIndex]!\n const group = groups.value[row.groupIndex]\n\n if (!current || current.groupIndex !== row.groupIndex) {\n current = {\n key: group?.name ?? `__ungrouped-${row.groupIndex}`,\n groupIndex: row.groupIndex,\n name: group?.name,\n labelVisible: false,\n items: [],\n }\n result.push(current)\n }\n\n if (row.kind === 'label') {\n current.labelVisible = true\n current.labelRowIndex = rowIndex\n continue\n }\n\n current.items.push({ item: row.item, rowIndex, posInSet: row.posInSet, setSize: row.setSize })\n }\n\n return result\n})\n\n/** ARIA набора: объявляем только при виртуализации — иначе набор виден по DOM. */\nfunction itemSetProps(entry: { posInSet: number, setSize: number }): Record<string, number> | undefined {\n if (!props.virtual)\n return undefined\n return { 'aria-setsize': entry.setSize, 'aria-posinset': entry.posInSet }\n}\n\n/** Сегменты подсветки: совпавшее с запросом рисуется `<mark>`. */\nfunction matchSegments(text: string): ReturnType<typeof splitCommandMatch> {\n return splitCommandMatch(text, props.filterable ? query.value : '')\n}\n\nasync function scrollActiveIntoView(item: GrCommandItem): Promise<void> {\n // Вне окна активной команды в DOM нет: `getElementById` вернул бы `null`,\n // прокрутка не случилась бы, а `aria-activedescendant` указал бы в пустоту.\n if (props.virtual) {\n const rowIndex = paletteRows.value.findIndex(row => row.kind === 'item' && row.item.id === item.id)\n if (rowIndex >= 0)\n virtualizer.scrollToIndex(rowIndex)\n }\n\n await nextTick()\n document.getElementById(itemDomId(item.id))?.scrollIntoView?.({ block: 'nearest' })\n}\n\nconst {\n activeItem,\n activeDescendantId,\n setActive,\n reset: resetActive,\n handleNavigationKeys,\n} = useComboboxNavigation<GrCommandItem>({\n items: () => navigableItems.value,\n open: () => props.modelValue,\n idOf: item => itemDomId(item.id),\n scrollTo: item => scrollActiveIntoView(item),\n})\n\n// Палитра всегда стартует с первой команды — и при монтировании открытой тоже.\nresetActive(0)\n\nfunction isActive(item: GrCommandItem): boolean {\n return activeItem.value?.id === item.id\n}\n\n// Активной становится первая команда, когда список изменился **по содержимому**.\n// Следить за идентичностью массива нельзя: родитель, отдающий `:items` инлайн-\n// выражением, пересоздаёт его на каждый посторонний ререндер — и выбранная\n// стрелками команда прыгала бы в начало.\n// Разделитель — пробел, а не запятая: `id` вправе её содержать, и «a,b» + «c»\n// дало бы тот же ключ, что «a» + «b,c».\nwatch(\n () => orderedItems.value.map(item => item.id).join(' '),\n () => resetActive(0),\n)\n\n// `id` — ключ рендера и цель `aria-activedescendant`: дубли дают одинаковые\n// DOM-id, и фокус уезжает не на ту команду.\nwatch(\n itemsResolved,\n (items) => {\n if (!__GR_DEV__)\n return\n const duplicates = findDuplicateCommandIds(items)\n if (!duplicates.length)\n return\n\n console.warn(\n `[GrCommandPalette] повторяющиеся id команд: ${duplicates.join(', ')}. `\n + 'Из-за одинаковых DOM-id `aria-activedescendant` укажет не на ту команду.',\n )\n },\n { immediate: true },\n)\n\nfunction open(): void {\n emit('update:modelValue', true)\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\nfunction toggle(): void {\n emit('update:modelValue', !props.modelValue)\n}\n\nfunction selectItem(item: GrCommandItem): void {\n if (item.disabled)\n return\n emit('select', item)\n if (props.closeOnSelect)\n close()\n}\n\nfunction onItemHover(item: GrCommandItem): void {\n const index = navigableItems.value.indexOf(item)\n if (index >= 0)\n setActive(index)\n}\n\nfunction onInput(event: Event): void {\n query.value = (event.target as HTMLInputElement).value\n emit('search', query.value.trim())\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n // Клавиша во время IME-композиции принадлежит композиции: Enter коммитит её,\n // стрелки ходят по кандидатам.\n if (isComposingEvent(event))\n return\n\n if (handleNavigationKeys(event))\n return\n\n switch (event.key) {\n case 'Enter':\n if (!activeItem.value)\n break\n event.preventDefault()\n selectItem(activeItem.value)\n break\n }\n}\n\n// ————— Открытие: сброс запроса и выбора.\nwatch(\n () => props.modelValue,\n (open) => {\n if (!open)\n return\n\n query.value = ''\n resetActive(0)\n },\n)\n\n// Фокус в поле — отдельным наблюдателем, и по появлению самого поля: содержимое\n// панели рождается вместе с ней, и по одному лишь пропу фокусировать нечего.\n// Ловушка фокуса `GrModal` этот выбор не перебивает — фокус, уже стоящий внутри\n// слоя, она считает осознанным.\nwatch(\n [() => props.modelValue, inputEl],\n ([open]) => {\n if (open)\n inputEl.value?.focus()\n },\n { flush: 'post' },\n)\n\n// ————— Глобальное сочетание открытия.\nconst parsedHotkey = computed(() => (props.hotkey ? parseCommandHotkey(props.hotkey) : null))\n\n// Платформа определяется только после монтирования: на сервере `navigator` нет,\n// и первый рендер обязан совпасть с серверным. Иначе сервер отдаёт `Ctrl`,\n// клиент на macOS рисует `⌘`, и гидрация расходится по тексту подсказки.\nconst isApple = ref(false)\n\nconst hotkeyHint = computed(() =>\n props.showHotkeyHint && parsedHotkey.value ? formatCommandHotkey(parsedHotkey.value, isApple.value) : [],\n)\n\nfunction onWindowKeydown(event: KeyboardEvent): void {\n const hotkey = parsedHotkey.value\n if (!hotkey || !matchesCommandHotkey(event, hotkey, isApple.value))\n return\n event.preventDefault()\n toggle()\n}\n\nonMounted(() => {\n if (typeof window === 'undefined')\n return\n isApple.value = isAppleDevice()\n window.addEventListener('keydown', onWindowKeydown)\n})\n\nonBeforeUnmount(() => {\n if (typeof window !== 'undefined')\n window.removeEventListener('keydown', onWindowKeydown)\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrCommandPalette', 'size', () => props.size, 'lg')\n\nconst modalSize = computed(() => commandPaletteModalSizeBySize[resolvedSize.value])\nconst listStyle = computed(() => ({ maxHeight: `var(--gr-command-list-max-height, ${props.maxHeight}px)` }))\n\nconst listStyleWithSpacers = computed(() => {\n const base = listStyle.value\n if (!props.virtual)\n return base\n\n return {\n ...base,\n ...virtualizer.spacerStyle.value,\n }\n})\n\ndefineExpose({ open, close, toggle })\n\ndefineSlots<{\n /** Строка списка вместо стандартной. */\n item?: (props: { item: GrCommandItem, active: boolean }) => any\n /** Пустое состояние: получает запрос, чтобы предложить действие по нему. */\n empty?: (props: { query: string }) => any\n /** Подвал палитры: подсказки по клавишам, счётчик. */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrModal\n :model-value=\"modelValue\"\n :size=\"modalSize\"\n @update:model-value=\"$emit('update:modelValue', $event)\"\n >\n <div data-gr-command-palette :aria-label=\"resolvedAriaLabel\">\n <div data-gr-command-palette-search :class=\"commandSearchRowClass\">\n <IconSearch class=\"block h-4 w-4 shrink-0 text-[var(--gr-muted-fg)]\" aria-hidden=\"true\" />\n\n <input\n ref=\"inputEl\"\n data-gr-command-palette-input\n data-testid=\"gr-command-palette-input\"\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n :aria-label=\"resolvedAriaLabel\"\n :aria-controls=\"listboxId\"\n :aria-activedescendant=\"activeDescendantId\"\n :value=\"query\"\n :placeholder=\"resolvedPlaceholder\"\n :class=\"commandSearchInputClass\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n >\n\n <span v-if=\"loading\" class=\"shrink-0 text-[var(--gr-muted-fg)]\" aria-hidden=\"true\">\n <IconLoaderCircle class=\"block h-4 w-4 animate-spin\" />\n </span>\n <span v-else-if=\"hotkeyHint.length\" class=\"shrink-0\" aria-hidden=\"true\">\n <GrKbd :keys=\"hotkeyHint\" size=\"sm\" />\n </span>\n </div>\n\n <div\n :id=\"listboxId\"\n ref=\"listEl\"\n data-gr-command-palette-list\n data-testid=\"gr-command-palette-list\"\n :data-gr-virtual=\"virtual ? '' : undefined\"\n class=\"overflow-y-auto p-2\"\n :style=\"listStyleWithSpacers\"\n role=\"listbox\"\n :aria-label=\"resolvedAriaLabel\"\n >\n <!-- Прямыми потомками listbox могут быть только `role=\"group\"`: заголовок\n группы лежит внутри неё и объявлен презентационным (имя группе он\n даёт через `aria-labelledby`), иначе ломается `aria-required-children`.\n\n При виртуализации окно может начаться ниже заголовка — тогда его в\n DOM нет, и имя группы идёт напрямую в `aria-label`. -->\n <div\n v-for=\"group in renderedGroups\"\n :key=\"group.key\"\n role=\"group\"\n :aria-labelledby=\"group.name && group.labelVisible ? `${listboxId}-group-${group.groupIndex}` : undefined\"\n :aria-label=\"group.name && !group.labelVisible ? group.name : undefined\"\n >\n <div\n v-if=\"group.name && group.labelVisible\"\n :id=\"`${listboxId}-group-${group.groupIndex}`\"\n :ref=\"(el) => virtual && group.labelRowIndex !== undefined && virtualizer.measure(group.labelRowIndex, el as Element | null)\"\n data-gr-command-palette-group\n role=\"presentation\"\n :class=\"commandGroupLabelClass\"\n >\n {{ group.name }}\n </div>\n\n <div>\n <div\n v-for=\"entry in group.items\"\n :id=\"itemDomId(entry.item.id)\"\n :key=\"entry.item.id\"\n :ref=\"(el) => virtual && virtualizer.measure(entry.rowIndex, el as Element | null)\"\n data-gr-command-palette-item\n :data-testid=\"`gr-command-palette-item-${entry.item.id}`\"\n role=\"option\"\n v-bind=\"itemSetProps(entry)\"\n :aria-selected=\"isActive(entry.item) ? 'true' : 'false'\"\n :aria-disabled=\"entry.item.disabled ? 'true' : undefined\"\n :class=\"commandItemClass({ active: isActive(entry.item), disabled: Boolean(entry.item.disabled) })\"\n @click=\"selectItem(entry.item)\"\n @mousemove=\"onItemHover(entry.item)\"\n >\n <slot name=\"item\" :item=\"entry.item\" :active=\"isActive(entry.item)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n class=\"block h-4 w-4 shrink-0\"\n :class=\"[iconClass(entry.item.icon), commandItemMutedClass(Boolean(entry.item.disabled))]\"\n aria-hidden=\"true\"\n />\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate\">\n <template v-for=\"(segment, index) in matchSegments(entry.item.label)\" :key=\"index\">\n <mark v-if=\"segment.match\" :class=\"commandMatchClass\">{{ segment.text }}</mark>\n <template v-else>{{ segment.text }}</template>\n </template>\n </span>\n <span\n v-if=\"entry.item.description\"\n :class=\"[commandItemDescriptionClass, commandItemMutedClass(Boolean(entry.item.disabled))]\"\n >\n <template v-for=\"(segment, index) in matchSegments(entry.item.description)\" :key=\"index\">\n <mark v-if=\"segment.match\" :class=\"commandMatchClass\">{{ segment.text }}</mark>\n <template v-else>{{ segment.text }}</template>\n </template>\n </span>\n </span>\n <span v-if=\"entry.item.shortcut?.length\" class=\"shrink-0\">\n <GrKbd :keys=\"entry.item.shortcut\" size=\"sm\" />\n </span>\n </slot>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Состояния объявляются живым регионом: `aria-label` на generic-элементе\n большинство AT игнорируют, и загрузка осталась бы неозвученной. Регион\n один на оба состояния и лежит вне listbox — внутри он стал бы его\n недопустимым потомком. -->\n <div\n v-if=\"loading || !filteredItems.length\"\n data-gr-command-palette-empty\n data-testid=\"gr-command-palette-empty\"\n role=\"status\"\n aria-live=\"polite\"\n :class=\"commandEmptyClass\"\n >\n <template v-if=\"loading\">\n {{ loadingText }}\n </template>\n <slot v-else name=\"empty\" :query=\"query\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-command-palette-footer :class=\"commandFooterClass\">\n <slot name=\"footer\" />\n </div>\n </div>\n </GrModal>\n</template>\n\n<style scoped>\n/*\n * Распорки виртуального списка.\n *\n * Не `padding` контейнера: `max-height` меряет ту же коробку. Не обёртка внутри\n * listbox'а: прямыми потомками роли обязаны быть только группы. Не отступы\n * крайних строк: при прыжке прокрутки строки заменяются целиком, и распорка\n * исчезла бы вместе с ними.\n *\n * `display: block` обязателен: список палитры — блочный поток, а псевдоэлемент\n * по умолчанию строчный, и строчная коробка игнорирует `height` — распорка\n * молча не создалась бы вовсе.\n */\n[data-gr-virtual]::before,\n[data-gr-virtual]::after {\n content: '';\n display: block;\n flex: none;\n}\n\n[data-gr-virtual]::before {\n height: var(--gr-virtual-before, 0px);\n}\n\n[data-gr-virtual]::after {\n height: var(--gr-virtual-after, 0px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useId, watch } from 'vue'\n\nimport { useVirtualList } from '../../composables/useVirtualList'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { isComposingEvent } from '../../internal/keyboard'\nimport { useComboboxNavigation } from '../../composables/useComboboxNavigation'\nimport { iconClass, iconTag } from '../shared/icon'\nimport GrKbd from '../GrKbd/GrKbd.vue'\nimport GrModal from '../GrModal/GrModal.vue'\n\nimport {\n filterCommandItems,\n findDuplicateCommandIds,\n groupCommandItems,\n matchCommandItem,\n splitCommandMatch,\n withRecentCommands,\n type GrCommandFilter,\n type GrCommandItem,\n} from './filtering'\nimport {\n formatCommandHotkey,\n isAppleDevice,\n matchesCommandHotkey,\n parseCommandHotkey,\n} from '../shared/hotkey'\nimport {\n commandEmptyClass,\n commandFooterClass,\n commandGroupLabelClass,\n commandItemClass,\n commandItemDescriptionClass,\n commandItemMutedClass,\n commandMatchClass,\n commandPaletteModalSizeBySize,\n commandSearchInputClass,\n commandSearchRowClass,\n type GrCommandPaletteSize,\n} from './grCommandPaletteStyles'\n\nimport IconLoaderCircle from '~icons/lucide/loader-circle'\nimport IconSearch from '~icons/lucide/search'\n\nexport type { GrCommandFilter, GrCommandGroup, GrCommandItem } from './filtering'\nexport type { GrCommandPaletteSize } from './grCommandPaletteStyles'\n\n/**\n * Публичный GR-примитив «Command palette» (⌘K) — модальный поиск по командам\n * приложения с группировкой, подсказками сочетаний и клавиатурной навигацией.\n *\n * A11y: WAI-ARIA combobox поверх модалки — `role=\"combobox\"` на поле ввода,\n * `role=\"listbox\"` на списке, `aria-activedescendant` на активной команде\n * (фокус остаётся в поле). Esc, фокус-ловушка и блокировка скролла приходят\n * из `GrModal`.\n *\n * Открытие по глобальному сочетанию (`hotkey`, по умолчанию `mod+k` — Cmd на\n * macOS, Ctrl на прочих) компонент берёт на себя; передайте `hotkey: null`,\n * чтобы управлять открытием только через `v-model`.\n */\nexport interface GrCommandPaletteProps {\n /** Открыта ли палитра. */\n modelValue: boolean\n /** Плоский список команд; группировка — по полю `group` самой команды. */\n items?: GrCommandItem[]\n /**\n * Недавние команды: пока запрос пуст, они поднимаются отдельной группой\n * наверх в этом порядке и не дублируются ниже.\n */\n recentIds?: string[]\n placeholder?: string\n size?: GrCommandPaletteSize\n /** Глобальное сочетание открытия. `null` — не вешать слушатель. */\n hotkey?: string | null\n /** Локальная фильтрация по запросу. `false` — фильтрует владелец по событию `search`. */\n filterable?: boolean\n /** Кастомный матчер локальной фильтрации. */\n filter?: GrCommandFilter\n /** Внешне управляемое состояние загрузки (для remote-поиска). */\n loading?: boolean\n /** Закрывать палитру после выбора команды. */\n closeOnSelect?: boolean\n /** Максимальная высота списка, px. */\n maxHeight?: number\n /**\n * Виртуализация списка: в DOM живёт только окно вокруг вьюпорта. Высоту окна\n * задаёт `maxHeight`.\n *\n * Включается осознанно: на сотне команд выигрыша нет, а в разметке остаётся\n * только окно — вместе с ним меняется и то, что находит `querySelector`\n * потребителя. Профильный сценарий — палитра приложения на тысячи команд.\n */\n virtual?: boolean\n /** Показывать подсказку сочетания в поле ввода. */\n showHotkeyHint?: boolean\n emptyText?: string\n ariaLabel?: string\n}\n\nexport interface GrCommandPaletteEmits {\n (e: 'update:modelValue', value: boolean): void\n /** Команда выбрана (клик или Enter). */\n (e: 'select', item: GrCommandItem): void\n /** Поисковый запрос изменился — точка входа для remote-поиска. */\n (e: 'search', query: string): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(\n defineProps<GrCommandPaletteProps>(),\n {\n items: undefined,\n recentIds: undefined,\n placeholder: undefined,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n hotkey: 'mod+k',\n filterable: true,\n filter: undefined,\n loading: false,\n closeOnSelect: true,\n maxHeight: 360,\n virtual: false,\n showHotkeyHint: true,\n emptyText: undefined,\n ariaLabel: undefined,\n },\n)\n\nconst emit = defineEmits<GrCommandPaletteEmits>()\n\nconst { t } = useGranularityTranslations()\n\nconst resolvedPlaceholder = computed(() => props.placeholder ?? t('gr.commandPalette.placeholder', 'Type a command or search…'))\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.commandPalette.empty', 'Nothing found'))\nconst resolvedAriaLabel = computed(() => props.ariaLabel ?? t('gr.commandPalette.label', 'Command palette'))\nconst loadingText = computed(() => t('gr.commandPalette.loading', 'Loading…'))\nconst recentTitle = computed(() => t('gr.commandPalette.recent', 'Recent'))\n\nconst query = ref('')\nconst inputEl = ref<HTMLInputElement | null>(null)\nconst listboxId = useId()\n\nconst itemsResolved = computed<GrCommandItem[]>(() => props.items ?? [])\n\nconst filteredItems = computed<GrCommandItem[]>(() =>\n props.filterable\n ? filterCommandItems(itemsResolved.value, query.value, props.filter ?? matchCommandItem)\n : itemsResolved.value,\n)\n\nconst groups = computed(() => {\n const grouped = groupCommandItems(filteredItems.value)\n\n // С непустым запросом секции «недавние» нет: там правит релевантность, а не\n // история — иначе первая же буква уводила бы взгляд не туда.\n if (query.value.trim())\n return grouped\n\n return withRecentCommands(grouped, filteredItems.value, props.recentIds ?? [], recentTitle.value)\n})\n\n/**\n * Порядок обхода стрелками совпадает с порядком на экране: «недавние» стоят\n * первыми, значит и первая стрелка ведёт туда же.\n */\nconst orderedItems = computed(() => groups.value.flatMap(group => group.items))\n\n/** Плоский список того, что реально выбирается — по нему ходят стрелки. */\nconst navigableItems = computed(() => orderedItems.value.filter(item => !item.disabled))\n\nfunction itemDomId(id: string): string {\n return `${listboxId}-item-${id}`\n}\n\n/**\n * Виртуализация списка.\n *\n * Набор — плоский поток строк экрана: заголовок группы занимает такую же\n * строку, как команда, поэтому входит в него наравне. Вложенную структуру\n * рендер пересобирает уже из окна.\n */\n\n/** Оценки высоты строк. Команда крупнее заголовка; дальше уточняются замером. */\nconst ITEM_SIZE_ESTIMATE = 44\nconst GROUP_LABEL_SIZE_ESTIMATE = 28\n\ntype PaletteRow\n = | { kind: 'label', groupIndex: number }\n | { kind: 'item', groupIndex: number, item: GrCommandItem, posInSet: number, setSize: number }\n\nconst listEl = ref<HTMLElement | null>(null)\n\nconst paletteRows = computed<PaletteRow[]>(() => {\n const rows: PaletteRow[] = []\n\n groups.value.forEach((group, groupIndex) => {\n if (group.name)\n rows.push({ kind: 'label', groupIndex })\n\n group.items.forEach((item, index) => {\n rows.push({\n kind: 'item',\n groupIndex,\n item,\n // Набор — группа, а не весь список: по ARIA позиция отсчитывается от неё.\n posInSet: index + 1,\n setSize: group.items.length,\n })\n })\n })\n\n return rows\n})\n\nconst virtualizer = useVirtualList({\n container: listEl,\n count: () => (props.virtual ? paletteRows.value.length : 0),\n // Запрос пересобирает набор строк — замеры прошлого набора невалидны.\n source: () => paletteRows.value,\n itemSize: index => (paletteRows.value[index]?.kind === 'label' ? GROUP_LABEL_SIZE_ESTIMATE : ITEM_SIZE_ESTIMATE),\n // Список закрытой палитры не смонтирован вовсе: `clientHeight` взять неоткуда.\n // `maxHeight` можно перебить `--gr-command-list-max-height` — тогда точная\n // высота приедет с первым замером, а это останется оценкой первого рендера.\n viewportSize: () => props.maxHeight,\n})\n\n/**\n * Группы к отрисовке. При виртуализации пересобираются из среза `paletteRows`:\n * группа, начатая выше окна, всё равно открывается — иначе её команды остались\n * бы прямыми потомками listbox'а, что роль запрещает.\n */\ntype RenderedGroup = {\n key: string\n groupIndex: number\n name: string | undefined\n labelVisible: boolean\n /** Позиция строки заголовка в `paletteRows` — по ней его замеряет виртуализатор. */\n labelRowIndex?: number\n items: { item: GrCommandItem, rowIndex: number, posInSet: number, setSize: number }[]\n}\n\nconst renderedGroups = computed<RenderedGroup[]>(() => {\n const rows = paletteRows.value\n\n const from = props.virtual ? virtualizer.range.value.start : 0\n const to = props.virtual ? Math.min(rows.length, virtualizer.range.value.end) : rows.length\n\n const result: RenderedGroup[] = []\n let current: RenderedGroup | undefined\n\n for (let rowIndex = from; rowIndex < to; rowIndex++) {\n const row = rows[rowIndex]!\n const group = groups.value[row.groupIndex]\n\n if (!current || current.groupIndex !== row.groupIndex) {\n current = {\n key: group?.name ?? `__ungrouped-${row.groupIndex}`,\n groupIndex: row.groupIndex,\n name: group?.name,\n labelVisible: false,\n items: [],\n }\n result.push(current)\n }\n\n if (row.kind === 'label') {\n current.labelVisible = true\n current.labelRowIndex = rowIndex\n continue\n }\n\n current.items.push({ item: row.item, rowIndex, posInSet: row.posInSet, setSize: row.setSize })\n }\n\n return result\n})\n\n/** ARIA набора: объявляем только при виртуализации — иначе набор виден по DOM. */\nfunction itemSetProps(entry: { posInSet: number, setSize: number }): Record<string, number> | undefined {\n if (!props.virtual)\n return undefined\n return { 'aria-setsize': entry.setSize, 'aria-posinset': entry.posInSet }\n}\n\n/** Сегменты подсветки: совпавшее с запросом рисуется `<mark>`. */\nfunction matchSegments(text: string): ReturnType<typeof splitCommandMatch> {\n return splitCommandMatch(text, props.filterable ? query.value : '')\n}\n\nasync function scrollActiveIntoView(item: GrCommandItem): Promise<void> {\n // Вне окна активной команды в DOM нет: `getElementById` вернул бы `null`,\n // прокрутка не случилась бы, а `aria-activedescendant` указал бы в пустоту.\n if (props.virtual) {\n const rowIndex = paletteRows.value.findIndex(row => row.kind === 'item' && row.item.id === item.id)\n if (rowIndex >= 0)\n virtualizer.scrollToIndex(rowIndex)\n }\n\n await nextTick()\n document.getElementById(itemDomId(item.id))?.scrollIntoView?.({ block: 'nearest' })\n}\n\nconst {\n activeItem,\n activeDescendantId,\n setActive,\n reset: resetActive,\n handleNavigationKeys,\n} = useComboboxNavigation<GrCommandItem>({\n items: () => navigableItems.value,\n open: () => props.modelValue,\n idOf: item => itemDomId(item.id),\n scrollTo: item => scrollActiveIntoView(item),\n})\n\n// Палитра всегда стартует с первой команды — и при монтировании открытой тоже.\nresetActive(0)\n\nfunction isActive(item: GrCommandItem): boolean {\n return activeItem.value?.id === item.id\n}\n\n// Активной становится первая команда, когда список изменился **по содержимому**.\n// Следить за идентичностью массива нельзя: родитель, отдающий `:items` инлайн-\n// выражением, пересоздаёт его на каждый посторонний ререндер — и выбранная\n// стрелками команда прыгала бы в начало.\n// Разделитель — пробел, а не запятая: `id` вправе её содержать, и «a,b» + «c»\n// дало бы тот же ключ, что «a» + «b,c».\nwatch(\n () => orderedItems.value.map(item => item.id).join(' '),\n () => resetActive(0),\n)\n\n// `id` — ключ рендера и цель `aria-activedescendant`: дубли дают одинаковые\n// DOM-id, и фокус уезжает не на ту команду.\nwatch(\n itemsResolved,\n (items) => {\n if (!__GR_DEV__)\n return\n const duplicates = findDuplicateCommandIds(items)\n if (!duplicates.length)\n return\n\n console.warn(\n `[GrCommandPalette] повторяющиеся id команд: ${duplicates.join(', ')}. `\n + 'Из-за одинаковых DOM-id `aria-activedescendant` укажет не на ту команду.',\n )\n },\n { immediate: true },\n)\n\nfunction open(): void {\n emit('update:modelValue', true)\n}\n\nfunction close(): void {\n emit('update:modelValue', false)\n}\n\nfunction toggle(): void {\n emit('update:modelValue', !props.modelValue)\n}\n\nfunction selectItem(item: GrCommandItem): void {\n if (item.disabled)\n return\n emit('select', item)\n if (props.closeOnSelect)\n close()\n}\n\nfunction onItemHover(item: GrCommandItem): void {\n const index = navigableItems.value.indexOf(item)\n if (index >= 0)\n setActive(index)\n}\n\nfunction onInput(event: Event): void {\n query.value = (event.target as HTMLInputElement).value\n emit('search', query.value.trim())\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n // Клавиша во время IME-композиции принадлежит композиции: Enter коммитит её,\n // стрелки ходят по кандидатам.\n if (isComposingEvent(event))\n return\n\n if (handleNavigationKeys(event))\n return\n\n switch (event.key) {\n case 'Enter':\n if (!activeItem.value)\n break\n event.preventDefault()\n selectItem(activeItem.value)\n break\n }\n}\n\n// ————— Открытие: сброс запроса и выбора.\nwatch(\n () => props.modelValue,\n (open) => {\n if (!open)\n return\n\n query.value = ''\n resetActive(0)\n },\n)\n\n// Фокус в поле — отдельным наблюдателем, и по появлению самого поля: содержимое\n// панели рождается вместе с ней, и по одному лишь пропу фокусировать нечего.\n// Ловушка фокуса `GrModal` этот выбор не перебивает — фокус, уже стоящий внутри\n// слоя, она считает осознанным.\nwatch(\n [() => props.modelValue, inputEl],\n ([open]) => {\n if (open)\n inputEl.value?.focus()\n },\n { flush: 'post' },\n)\n\n// ————— Глобальное сочетание открытия.\nconst parsedHotkey = computed(() => (props.hotkey ? parseCommandHotkey(props.hotkey) : null))\n\n// Платформа определяется только после монтирования: на сервере `navigator` нет,\n// и первый рендер обязан совпасть с серверным. Иначе сервер отдаёт `Ctrl`,\n// клиент на macOS рисует `⌘`, и гидрация расходится по тексту подсказки.\nconst isApple = ref(false)\n\nconst hotkeyHint = computed(() =>\n props.showHotkeyHint && parsedHotkey.value ? formatCommandHotkey(parsedHotkey.value, isApple.value) : [],\n)\n\nfunction onWindowKeydown(event: KeyboardEvent): void {\n const hotkey = parsedHotkey.value\n if (!hotkey || !matchesCommandHotkey(event, hotkey, isApple.value))\n return\n event.preventDefault()\n toggle()\n}\n\nonMounted(() => {\n if (typeof window === 'undefined')\n return\n isApple.value = isAppleDevice()\n window.addEventListener('keydown', onWindowKeydown)\n})\n\nonBeforeUnmount(() => {\n if (typeof window !== 'undefined')\n window.removeEventListener('keydown', onWindowKeydown)\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrCommandPalette', 'size', () => props.size, 'lg')\n\nconst modalSize = computed(() => commandPaletteModalSizeBySize[resolvedSize.value])\nconst listStyle = computed(() => ({ maxHeight: `var(--gr-command-list-max-height, ${props.maxHeight}px)` }))\n\nconst listStyleWithSpacers = computed(() => {\n const base = listStyle.value\n if (!props.virtual)\n return base\n\n return {\n ...base,\n ...virtualizer.spacerStyle.value,\n }\n})\n\ndefineExpose({ open, close, toggle })\n\ndefineSlots<{\n /** Строка списка вместо стандартной. */\n item?: (props: { item: GrCommandItem, active: boolean }) => any\n /** Пустое состояние: получает запрос, чтобы предложить действие по нему. */\n empty?: (props: { query: string }) => any\n /** Подвал палитры: подсказки по клавишам, счётчик. */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrModal\n :model-value=\"modelValue\"\n :size=\"modalSize\"\n @update:model-value=\"$emit('update:modelValue', $event)\"\n >\n <div data-gr-command-palette :aria-label=\"resolvedAriaLabel\">\n <div data-gr-command-palette-search :class=\"commandSearchRowClass\">\n <IconSearch class=\"block h-4 w-4 shrink-0 text-[var(--gr-muted-fg)]\" aria-hidden=\"true\" />\n\n <input\n ref=\"inputEl\"\n data-gr-command-palette-input\n data-testid=\"gr-command-palette-input\"\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n :aria-label=\"resolvedAriaLabel\"\n :aria-controls=\"listboxId\"\n :aria-activedescendant=\"activeDescendantId\"\n :value=\"query\"\n :placeholder=\"resolvedPlaceholder\"\n :class=\"commandSearchInputClass\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n >\n\n <span v-if=\"loading\" class=\"shrink-0 text-[var(--gr-muted-fg)]\" aria-hidden=\"true\">\n <IconLoaderCircle class=\"block h-4 w-4 animate-spin\" />\n </span>\n <span v-else-if=\"hotkeyHint.length\" class=\"shrink-0\" aria-hidden=\"true\">\n <GrKbd :keys=\"hotkeyHint\" size=\"sm\" />\n </span>\n </div>\n\n <div\n :id=\"listboxId\"\n ref=\"listEl\"\n data-gr-command-palette-list\n data-testid=\"gr-command-palette-list\"\n :data-gr-virtual=\"virtual ? '' : undefined\"\n class=\"overflow-y-auto p-2\"\n :style=\"listStyleWithSpacers\"\n role=\"listbox\"\n :aria-label=\"resolvedAriaLabel\"\n >\n <!-- Прямыми потомками listbox могут быть только `role=\"group\"`: заголовок\n группы лежит внутри неё и объявлен презентационным (имя группе он\n даёт через `aria-labelledby`), иначе ломается `aria-required-children`.\n\n При виртуализации окно может начаться ниже заголовка — тогда его в\n DOM нет, и имя группы идёт напрямую в `aria-label`. -->\n <div\n v-for=\"group in renderedGroups\"\n :key=\"group.key\"\n role=\"group\"\n :aria-labelledby=\"group.name && group.labelVisible ? `${listboxId}-group-${group.groupIndex}` : undefined\"\n :aria-label=\"group.name && !group.labelVisible ? group.name : undefined\"\n >\n <div\n v-if=\"group.name && group.labelVisible\"\n :id=\"`${listboxId}-group-${group.groupIndex}`\"\n :ref=\"(el) => virtual && group.labelRowIndex !== undefined && virtualizer.measure(group.labelRowIndex, el as Element | null)\"\n data-gr-command-palette-group\n role=\"presentation\"\n :class=\"commandGroupLabelClass\"\n >\n {{ group.name }}\n </div>\n\n <div>\n <div\n v-for=\"entry in group.items\"\n :id=\"itemDomId(entry.item.id)\"\n :key=\"entry.item.id\"\n :ref=\"(el) => virtual && virtualizer.measure(entry.rowIndex, el as Element | null)\"\n data-gr-command-palette-item\n :data-testid=\"`gr-command-palette-item-${entry.item.id}`\"\n role=\"option\"\n v-bind=\"itemSetProps(entry)\"\n :aria-selected=\"isActive(entry.item) ? 'true' : 'false'\"\n :aria-disabled=\"entry.item.disabled ? 'true' : undefined\"\n :class=\"commandItemClass({ active: isActive(entry.item), disabled: Boolean(entry.item.disabled) })\"\n @click=\"selectItem(entry.item)\"\n @mousemove=\"onItemHover(entry.item)\"\n >\n <slot name=\"item\" :item=\"entry.item\" :active=\"isActive(entry.item)\">\n <component\n :is=\"iconTag(entry.item.icon)\"\n v-if=\"entry.item.icon\"\n class=\"block h-4 w-4 shrink-0\"\n :class=\"[iconClass(entry.item.icon), commandItemMutedClass(Boolean(entry.item.disabled))]\"\n aria-hidden=\"true\"\n />\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate\">\n <template v-for=\"(segment, index) in matchSegments(entry.item.label)\" :key=\"index\">\n <mark v-if=\"segment.match\" :class=\"commandMatchClass\">{{ segment.text }}</mark>\n <template v-else>{{ segment.text }}</template>\n </template>\n </span>\n <span\n v-if=\"entry.item.description\"\n :class=\"[commandItemDescriptionClass, commandItemMutedClass(Boolean(entry.item.disabled))]\"\n >\n <template v-for=\"(segment, index) in matchSegments(entry.item.description)\" :key=\"index\">\n <mark v-if=\"segment.match\" :class=\"commandMatchClass\">{{ segment.text }}</mark>\n <template v-else>{{ segment.text }}</template>\n </template>\n </span>\n </span>\n <span v-if=\"entry.item.shortcut?.length\" class=\"shrink-0\">\n <GrKbd :keys=\"entry.item.shortcut\" size=\"sm\" />\n </span>\n </slot>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Состояния объявляются живым регионом: `aria-label` на generic-элементе\n большинство AT игнорируют, и загрузка осталась бы неозвученной. Регион\n один на оба состояния и лежит вне listbox — внутри он стал бы его\n недопустимым потомком. -->\n <div\n v-if=\"loading || !filteredItems.length\"\n data-gr-command-palette-empty\n data-testid=\"gr-command-palette-empty\"\n role=\"status\"\n aria-live=\"polite\"\n :class=\"commandEmptyClass\"\n >\n <template v-if=\"loading\">\n {{ loadingText }}\n </template>\n <slot v-else name=\"empty\" :query=\"query\">\n {{ resolvedEmptyText }}\n </slot>\n </div>\n\n <div v-if=\"$slots.footer\" data-gr-command-palette-footer :class=\"commandFooterClass\">\n <slot name=\"footer\" />\n </div>\n </div>\n </GrModal>\n</template>\n\n<style scoped>\n/*\n * Распорки виртуального списка.\n *\n * Не `padding` контейнера: `max-height` меряет ту же коробку. Не обёртка внутри\n * listbox'а: прямыми потомками роли обязаны быть только группы. Не отступы\n * крайних строк: при прыжке прокрутки строки заменяются целиком, и распорка\n * исчезла бы вместе с ними.\n *\n * `display: block` обязателен: список палитры — блочный поток, а псевдоэлемент\n * по умолчанию строчный, и строчная коробка игнорирует `height` — распорка\n * молча не создалась бы вовсе.\n */\n[data-gr-virtual]::before,\n[data-gr-virtual]::after {\n content: '';\n display: block;\n flex: none;\n}\n\n[data-gr-virtual]::before {\n height: var(--gr-virtual-before, 0px);\n}\n\n[data-gr-virtual]::after {\n height: var(--gr-virtual-after, 0px);\n}\n</style>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrCommandPalette_default } from "./chunks/GrCommandPalette-C5abL2Y7.js";
1
+ import { t as GrCommandPalette_default } from "./chunks/GrCommandPalette-BXbh3q7O.js";
2
2
  import { n as grCommandPaletteSafelist, t as grCommandPaletteConfig } from "../../chunks/config-D0NzGYaE.js";
3
3
  export { GrCommandPalette_default as GrCommandPalette, GrCommandPalette_default as default, grCommandPaletteConfig, grCommandPaletteSafelist };
@@ -1 +1 @@
1
- [data-gr-virtual][data-v-dcf84986]:before,[data-gr-virtual][data-v-dcf84986]:after{content:"";flex:none;display:block}[data-gr-virtual][data-v-dcf84986]:before{height:var(--gr-virtual-before,0px)}[data-gr-virtual][data-v-dcf84986]:after{height:var(--gr-virtual-after,0px)}
1
+ [data-gr-virtual][data-v-041dfab7]:before,[data-gr-virtual][data-v-041dfab7]:after{content:"";flex:none;display:block}[data-gr-virtual][data-v-041dfab7]:before{height:var(--gr-virtual-before,0px)}[data-gr-virtual][data-v-041dfab7]:after{height:var(--gr-virtual-after,0px)}
@@ -1 +1 @@
1
- {"version":3,"file":"GrConfigProvider-BF7R3hgg.js","names":[],"sources":["../../../../src/components/GrConfigProvider/zIndexScale.ts","../../../../src/components/GrConfigProvider/GrConfigProvider.vue","../../../../src/components/GrConfigProvider/GrConfigProvider.vue"],"sourcesContent":["/**\n * Шкала слоёв, задаваемая пропом `zIndexBase` у `GrConfigProvider`.\n *\n * Переменные ставятся на `<html>`, а не на обёртку провайдера: панели\n * телепортируются в `body`, то есть живут вне его DOM-поддерева, и\n * «настройка слоёв поддеревом» была бы ложным обещанием.\n *\n * Отсюда же следует, что владелец шкалы один на документ: два провайдера с\n * разными базами — это гонка, о которой надо сказать вслух, а не тихо\n * применить последнюю.\n */\n\n/**\n * Смещения те же, что в `styles/tokens.css`: шаг 50 оставляет приложению место\n * вклиниться между слоями, а тосты стоят выше модалок.\n */\nexport const GR_Z_INDEX_OFFSETS: Record<string, number> = {\n // Шапка ниже якорных панелей: она перекрывает контент, но не выпадашки.\n '--gr-z-navbar': -100,\n '--gr-z-dropdown': 0,\n '--gr-z-tooltip': 50,\n '--gr-z-modal': 100,\n '--gr-z-toast': 200,\n}\n\nlet owner: symbol | null = null\n\n/**\n * Ставит шкалу от базы и возвращает функцию отката к прежним значениям.\n * `null` — нечего ставить (нет базы или нет документа).\n */\nexport function applyGrZIndexBase(token: symbol, base: number | undefined): (() => void) | null {\n if (typeof document === 'undefined' || base == null) {\n if (owner === token) owner = null\n return null\n }\n\n if (owner && owner !== token && __GR_DEV__) {\n console.warn(\n '[GrConfigProvider] zIndexBase задан больше чем одним провайдером. '\n + 'Шкала слоёв одна на документ (панели телепортируются в body), поэтому применится последняя.',\n )\n }\n owner = token\n\n const root = document.documentElement\n const previous = Object.keys(GR_Z_INDEX_OFFSETS)\n .map(name => [name, root.style.getPropertyValue(name)] as const)\n\n for (const [name, offset] of Object.entries(GR_Z_INDEX_OFFSETS))\n root.style.setProperty(name, String(base + offset))\n\n return () => {\n for (const [name, value] of previous) {\n if (value) root.style.setProperty(name, value)\n else root.style.removeProperty(name)\n }\n if (owner === token) owner = null\n }\n}\n\n/** Тестовая очистка владельца шкалы между кейсами. */\nexport function resetGrZIndexOwner(): void {\n owner = null\n}\n","<script setup lang=\"ts\">\n/**\n * GrConfigProvider — глобальные дефолты для вложенных GR-компонентов.\n *\n * Даёт единое место для:\n * - `size` — дефолтного размера контролов (не нужно повторять `size` в каждом вызове);\n * - `componentDefaults` — per-component дефолтных пропсов;\n * - `i18n` — адаптера переводов (иначе приложение инжектит его вручную);\n * - `theme` — темы поддерева;\n * - `portalTarget` — точки монтирования оверлеев;\n * - `zIndexBase` — базы шкалы слоёв.\n *\n * Провайдеры можно вкладывать: дочерний мержится поверх родительского, поэтому\n * можно задать «глобальную» тему и точечно переопределить её в поддереве.\n *\n * Рендерится прозрачно (`display: contents`), чтобы не влиять на layout.\n */\nimport { computed, onBeforeUnmount, provide, watch } from 'vue'\n\nimport { GRANULARITY_I18N_KEY, type GranularityI18nAdapter } from '../../i18n/adapter'\nimport { resolveGranularityI18n } from '../../internal/granularityI18n'\nimport { applyGrZIndexBase } from './zIndexScale'\nimport {\n GR_CONFIG_KEY,\n useGrConfig,\n type GrComponentDefaults,\n type GrComponentSize,\n type GrConfigContext,\n} from './context'\n\nexport type { GrComponentDefaults, GrComponentSize } from './context'\n\nexport interface GrConfigProviderProps {\n /** Дефолтный размер контролов для вложенных компонентов. */\n size?: GrComponentSize\n /** Дефолтные пропсы по компонентам: `{ GrButton: { variant: 'secondary' } }`. */\n componentDefaults?: GrComponentDefaults\n /** Адаптер переводов (fint-i18n-совместимый). Прокидывается вложенным компонентам. */\n i18n?: GranularityI18nAdapter | null\n /**\n * Просьба к адаптеру переключить язык (`syncLocale`). Источником истины\n * остаётся сам адаптер — провайдер лишь передаёт ему намерение.\n */\n locale?: string\n /**\n * Тема поддерева: значение уезжает в `data-theme`. Тема **документа** —\n * работа `useTheme`/`initThemeEarly`, здесь именно остров.\n */\n theme?: string\n /**\n * Куда монтировать оверлеи поддерева. По умолчанию — общий `#gr-portal` в\n * `body`. Своё значение нужно там, где приложение живёт в контейнере:\n * микрофронтенд, shadow DOM, CSS-скоупинг под конкретным корнем.\n */\n portalTarget?: string | HTMLElement\n /**\n * База шкалы слоёв. Переменные `--gr-z-*` пересчитываются от неё и ставятся\n * на `<html>`: панели телепортируются в `body`, и переменные поддерева до\n * них не доходят.\n */\n zIndexBase?: number\n /** Тег обёртки. По умолчанию прозрачный `<div style=\"display:contents\">`. */\n tag?: string\n}\n\nconst props = withDefaults(\n defineProps<GrConfigProviderProps>(),\n {\n size: undefined,\n componentDefaults: undefined,\n i18n: undefined,\n locale: undefined,\n theme: undefined,\n portalTarget: undefined,\n zIndexBase: undefined,\n tag: 'div',\n },\n)\n\n// Наследуемся от родительского провайдера — вложенные провайдеры мержатся.\nconst parent = useGrConfig()\n\nconst size = computed(() => props.size ?? parent.size.value)\nconst theme = computed(() => props.theme ?? parent.theme?.value)\n// Цель портала наследуется вниз: вложенный провайдер без своего значения\n// оставляет оверлеи там же, где их ждёт родительское приложение.\nconst portalTarget = computed(() => props.portalTarget ?? parent.portalTarget?.value)\nconst componentDefaults = computed<GrComponentDefaults>(() => {\n const inherited = parent.componentDefaults.value as Record<string, Record<string, unknown>>\n const own = (props.componentDefaults ?? {}) as Record<string, Record<string, unknown>>\n\n // Мержим на уровне пропов, а не компонентов: иначе вложенный провайдер,\n // переопределяющий один `variant`, стирал бы у родителя весь блок `GrButton`.\n const merged: Record<string, Record<string, unknown>> = { ...inherited }\n for (const [component, componentProps] of Object.entries(own))\n merged[component] = { ...(inherited[component] ?? {}), ...componentProps }\n\n return merged\n})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, { size, componentDefaults, theme, portalTarget })\n\n// ————— i18n.\n//\n// Адаптер отдаём вниз ВСЕГДА и фасадом, а не значением. Прежнее\n// `if (props.i18n != null) provide(…)` решало судьбу один раз в `setup`:\n// адаптер, созданный асинхронно (обычная загрузка локали), не приезжал уже\n// никогда, а подмена адаптера при смене языка до детей не доходила.\nconst inheritedI18n = resolveGranularityI18n()\nconst activeI18n = computed(() => props.i18n ?? inheritedI18n)\n\nprovide<GranularityI18nAdapter>(GRANULARITY_I18N_KEY, {\n t: (key, params) => activeI18n.value?.t(key, params) ?? key,\n // Геттеры, а не поля: `useGranularityTranslations` спрашивает `if (i18n.te)`,\n // и всегда определённый метод у адаптера без `te` означал бы «перевода нет»\n // для каждого ключа.\n get te() {\n const adapter = activeI18n.value\n return adapter?.te ? (key: string) => adapter.te!(key) : undefined\n },\n get locale() {\n return activeI18n.value?.locale\n },\n get syncLocale() {\n const adapter = activeI18n.value\n return adapter?.syncLocale ? (next: string) => adapter.syncLocale!(next) : undefined\n },\n})\n\nwatch(\n () => [props.locale, activeI18n.value] as const,\n ([locale, adapter]) => {\n if (!locale || adapter?.locale?.value === locale) return\n void adapter?.syncLocale?.(locale)\n },\n { immediate: true },\n)\n\n// ————— Шкала слоёв. Ставится на `<html>` и живёт в отдельном модуле: владелец\n// шкалы один на документ, а `<script setup>` — это уже область инстанса.\nconst zIndexToken = Symbol('gr-config-z-index')\nlet restoreZIndex: (() => void) | null = null\n\nwatch(\n () => props.zIndexBase,\n (base) => {\n restoreZIndex?.()\n restoreZIndex = applyGrZIndexBase(zIndexToken, base)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n restoreZIndex?.()\n restoreZIndex = null\n})\n\nconst wrapperStyle = { display: 'contents' } as const\n\ndefineSlots<{\n /** Поддерево, которому адресованы настройки. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"props.tag\"\n data-gr-config-provider\n :data-theme=\"theme\"\n :style=\"wrapperStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrConfigProvider — глобальные дефолты для вложенных GR-компонентов.\n *\n * Даёт единое место для:\n * - `size` — дефолтного размера контролов (не нужно повторять `size` в каждом вызове);\n * - `componentDefaults` — per-component дефолтных пропсов;\n * - `i18n` — адаптера переводов (иначе приложение инжектит его вручную);\n * - `theme` — темы поддерева;\n * - `portalTarget` — точки монтирования оверлеев;\n * - `zIndexBase` — базы шкалы слоёв.\n *\n * Провайдеры можно вкладывать: дочерний мержится поверх родительского, поэтому\n * можно задать «глобальную» тему и точечно переопределить её в поддереве.\n *\n * Рендерится прозрачно (`display: contents`), чтобы не влиять на layout.\n */\nimport { computed, onBeforeUnmount, provide, watch } from 'vue'\n\nimport { GRANULARITY_I18N_KEY, type GranularityI18nAdapter } from '../../i18n/adapter'\nimport { resolveGranularityI18n } from '../../internal/granularityI18n'\nimport { applyGrZIndexBase } from './zIndexScale'\nimport {\n GR_CONFIG_KEY,\n useGrConfig,\n type GrComponentDefaults,\n type GrComponentSize,\n type GrConfigContext,\n} from './context'\n\nexport type { GrComponentDefaults, GrComponentSize } from './context'\n\nexport interface GrConfigProviderProps {\n /** Дефолтный размер контролов для вложенных компонентов. */\n size?: GrComponentSize\n /** Дефолтные пропсы по компонентам: `{ GrButton: { variant: 'secondary' } }`. */\n componentDefaults?: GrComponentDefaults\n /** Адаптер переводов (fint-i18n-совместимый). Прокидывается вложенным компонентам. */\n i18n?: GranularityI18nAdapter | null\n /**\n * Просьба к адаптеру переключить язык (`syncLocale`). Источником истины\n * остаётся сам адаптер — провайдер лишь передаёт ему намерение.\n */\n locale?: string\n /**\n * Тема поддерева: значение уезжает в `data-theme`. Тема **документа** —\n * работа `useTheme`/`initThemeEarly`, здесь именно остров.\n */\n theme?: string\n /**\n * Куда монтировать оверлеи поддерева. По умолчанию — общий `#gr-portal` в\n * `body`. Своё значение нужно там, где приложение живёт в контейнере:\n * микрофронтенд, shadow DOM, CSS-скоупинг под конкретным корнем.\n */\n portalTarget?: string | HTMLElement\n /**\n * База шкалы слоёв. Переменные `--gr-z-*` пересчитываются от неё и ставятся\n * на `<html>`: панели телепортируются в `body`, и переменные поддерева до\n * них не доходят.\n */\n zIndexBase?: number\n /** Тег обёртки. По умолчанию прозрачный `<div style=\"display:contents\">`. */\n tag?: string\n}\n\nconst props = withDefaults(\n defineProps<GrConfigProviderProps>(),\n {\n size: undefined,\n componentDefaults: undefined,\n i18n: undefined,\n locale: undefined,\n theme: undefined,\n portalTarget: undefined,\n zIndexBase: undefined,\n tag: 'div',\n },\n)\n\n// Наследуемся от родительского провайдера — вложенные провайдеры мержатся.\nconst parent = useGrConfig()\n\nconst size = computed(() => props.size ?? parent.size.value)\nconst theme = computed(() => props.theme ?? parent.theme?.value)\n// Цель портала наследуется вниз: вложенный провайдер без своего значения\n// оставляет оверлеи там же, где их ждёт родительское приложение.\nconst portalTarget = computed(() => props.portalTarget ?? parent.portalTarget?.value)\nconst componentDefaults = computed<GrComponentDefaults>(() => {\n const inherited = parent.componentDefaults.value as Record<string, Record<string, unknown>>\n const own = (props.componentDefaults ?? {}) as Record<string, Record<string, unknown>>\n\n // Мержим на уровне пропов, а не компонентов: иначе вложенный провайдер,\n // переопределяющий один `variant`, стирал бы у родителя весь блок `GrButton`.\n const merged: Record<string, Record<string, unknown>> = { ...inherited }\n for (const [component, componentProps] of Object.entries(own))\n merged[component] = { ...(inherited[component] ?? {}), ...componentProps }\n\n return merged\n})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, { size, componentDefaults, theme, portalTarget })\n\n// ————— i18n.\n//\n// Адаптер отдаём вниз ВСЕГДА и фасадом, а не значением. Прежнее\n// `if (props.i18n != null) provide(…)` решало судьбу один раз в `setup`:\n// адаптер, созданный асинхронно (обычная загрузка локали), не приезжал уже\n// никогда, а подмена адаптера при смене языка до детей не доходила.\nconst inheritedI18n = resolveGranularityI18n()\nconst activeI18n = computed(() => props.i18n ?? inheritedI18n)\n\nprovide<GranularityI18nAdapter>(GRANULARITY_I18N_KEY, {\n t: (key, params) => activeI18n.value?.t(key, params) ?? key,\n // Геттеры, а не поля: `useGranularityTranslations` спрашивает `if (i18n.te)`,\n // и всегда определённый метод у адаптера без `te` означал бы «перевода нет»\n // для каждого ключа.\n get te() {\n const adapter = activeI18n.value\n return adapter?.te ? (key: string) => adapter.te!(key) : undefined\n },\n get locale() {\n return activeI18n.value?.locale\n },\n get syncLocale() {\n const adapter = activeI18n.value\n return adapter?.syncLocale ? (next: string) => adapter.syncLocale!(next) : undefined\n },\n})\n\nwatch(\n () => [props.locale, activeI18n.value] as const,\n ([locale, adapter]) => {\n if (!locale || adapter?.locale?.value === locale) return\n void adapter?.syncLocale?.(locale)\n },\n { immediate: true },\n)\n\n// ————— Шкала слоёв. Ставится на `<html>` и живёт в отдельном модуле: владелец\n// шкалы один на документ, а `<script setup>` — это уже область инстанса.\nconst zIndexToken = Symbol('gr-config-z-index')\nlet restoreZIndex: (() => void) | null = null\n\nwatch(\n () => props.zIndexBase,\n (base) => {\n restoreZIndex?.()\n restoreZIndex = applyGrZIndexBase(zIndexToken, base)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n restoreZIndex?.()\n restoreZIndex = null\n})\n\nconst wrapperStyle = { display: 'contents' } as const\n\ndefineSlots<{\n /** Поддерево, которому адресованы настройки. */\n default?: () => any\n}>()\n\n</script>\n\n<template>\n <component\n :is=\"props.tag\"\n data-gr-config-provider\n :data-theme=\"theme\"\n :style=\"wrapperStyle\"\n >\n <slot />\n </component>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrConfigProvider-BF7R3hgg.js","names":[],"sources":["../../../../src/components/GrConfigProvider/zIndexScale.ts","../../../../src/components/GrConfigProvider/GrConfigProvider.vue","../../../../src/components/GrConfigProvider/GrConfigProvider.vue"],"sourcesContent":["/**\n * Шкала слоёв, задаваемая пропом `zIndexBase` у `GrConfigProvider`.\n *\n * Переменные ставятся на `<html>`, а не на обёртку провайдера: панели\n * телепортируются в `body`, то есть живут вне его DOM-поддерева, и\n * «настройка слоёв поддеревом» была бы ложным обещанием.\n *\n * Отсюда же следует, что владелец шкалы один на документ: два провайдера с\n * разными базами — это гонка, о которой надо сказать вслух, а не тихо\n * применить последнюю.\n */\n\n/**\n * Смещения те же, что в `styles/tokens.css`: шаг 50 оставляет приложению место\n * вклиниться между слоями, а тосты стоят выше модалок.\n */\nexport const GR_Z_INDEX_OFFSETS: Record<string, number> = {\n // Шапка ниже якорных панелей: она перекрывает контент, но не выпадашки.\n '--gr-z-navbar': -100,\n '--gr-z-dropdown': 0,\n '--gr-z-tooltip': 50,\n '--gr-z-modal': 100,\n '--gr-z-toast': 200,\n}\n\nlet owner: symbol | null = null\n\n/**\n * Ставит шкалу от базы и возвращает функцию отката к прежним значениям.\n * `null` — нечего ставить (нет базы или нет документа).\n */\nexport function applyGrZIndexBase(token: symbol, base: number | undefined): (() => void) | null {\n if (typeof document === 'undefined' || base == null) {\n if (owner === token)\n owner = null\n return null\n }\n\n if (owner && owner !== token && __GR_DEV__) {\n console.warn(\n '[GrConfigProvider] zIndexBase задан больше чем одним провайдером. '\n + 'Шкала слоёв одна на документ (панели телепортируются в body), поэтому применится последняя.',\n )\n }\n owner = token\n\n const root = document.documentElement\n const previous = Object.keys(GR_Z_INDEX_OFFSETS)\n .map(name => [name, root.style.getPropertyValue(name)] as const)\n\n for (const [name, offset] of Object.entries(GR_Z_INDEX_OFFSETS))\n root.style.setProperty(name, String(base + offset))\n\n return () => {\n for (const [name, value] of previous) {\n if (value)\n root.style.setProperty(name, value)\n else root.style.removeProperty(name)\n }\n if (owner === token)\n owner = null\n }\n}\n\n/** Тестовая очистка владельца шкалы между кейсами. */\nexport function resetGrZIndexOwner(): void {\n owner = null\n}\n","<script setup lang=\"ts\">\n/**\n * GrConfigProvider — глобальные дефолты для вложенных GR-компонентов.\n *\n * Даёт единое место для:\n * - `size` — дефолтного размера контролов (не нужно повторять `size` в каждом вызове);\n * - `componentDefaults` — per-component дефолтных пропсов;\n * - `i18n` — адаптера переводов (иначе приложение инжектит его вручную);\n * - `theme` — темы поддерева;\n * - `portalTarget` — точки монтирования оверлеев;\n * - `zIndexBase` — базы шкалы слоёв.\n *\n * Провайдеры можно вкладывать: дочерний мержится поверх родительского, поэтому\n * можно задать «глобальную» тему и точечно переопределить её в поддереве.\n *\n * Рендерится прозрачно (`display: contents`), чтобы не влиять на layout.\n */\nimport { computed, onBeforeUnmount, provide, watch } from 'vue'\n\nimport { GRANULARITY_I18N_KEY, type GranularityI18nAdapter } from '../../i18n/adapter'\nimport { resolveGranularityI18n } from '../../internal/granularityI18n'\nimport { applyGrZIndexBase } from './zIndexScale'\nimport {\n GR_CONFIG_KEY,\n useGrConfig,\n type GrComponentDefaults,\n type GrComponentSize,\n type GrConfigContext,\n} from './context'\n\nexport type { GrComponentDefaults, GrComponentSize } from './context'\n\nexport interface GrConfigProviderProps {\n /** Дефолтный размер контролов для вложенных компонентов. */\n size?: GrComponentSize\n /** Дефолтные пропсы по компонентам: `{ GrButton: { variant: 'secondary' } }`. */\n componentDefaults?: GrComponentDefaults\n /** Адаптер переводов (fint-i18n-совместимый). Прокидывается вложенным компонентам. */\n i18n?: GranularityI18nAdapter | null\n /**\n * Просьба к адаптеру переключить язык (`syncLocale`). Источником истины\n * остаётся сам адаптер — провайдер лишь передаёт ему намерение.\n */\n locale?: string\n /**\n * Тема поддерева: значение уезжает в `data-theme`. Тема **документа** —\n * работа `useTheme`/`initThemeEarly`, здесь именно остров.\n */\n theme?: string\n /**\n * Куда монтировать оверлеи поддерева. По умолчанию — общий `#gr-portal` в\n * `body`. Своё значение нужно там, где приложение живёт в контейнере:\n * микрофронтенд, shadow DOM, CSS-скоупинг под конкретным корнем.\n */\n portalTarget?: string | HTMLElement\n /**\n * База шкалы слоёв. Переменные `--gr-z-*` пересчитываются от неё и ставятся\n * на `<html>`: панели телепортируются в `body`, и переменные поддерева до\n * них не доходят.\n */\n zIndexBase?: number\n /** Тег обёртки. По умолчанию прозрачный `<div style=\"display:contents\">`. */\n tag?: string\n}\n\nconst props = withDefaults(\n defineProps<GrConfigProviderProps>(),\n {\n size: undefined,\n componentDefaults: undefined,\n i18n: undefined,\n locale: undefined,\n theme: undefined,\n portalTarget: undefined,\n zIndexBase: undefined,\n tag: 'div',\n },\n)\n\n// Наследуемся от родительского провайдера — вложенные провайдеры мержатся.\nconst parent = useGrConfig()\n\nconst size = computed(() => props.size ?? parent.size.value)\nconst theme = computed(() => props.theme ?? parent.theme?.value)\n// Цель портала наследуется вниз: вложенный провайдер без своего значения\n// оставляет оверлеи там же, где их ждёт родительское приложение.\nconst portalTarget = computed(() => props.portalTarget ?? parent.portalTarget?.value)\nconst componentDefaults = computed<GrComponentDefaults>(() => {\n const inherited = parent.componentDefaults.value as Record<string, Record<string, unknown>>\n const own = (props.componentDefaults ?? {}) as Record<string, Record<string, unknown>>\n\n // Мержим на уровне пропов, а не компонентов: иначе вложенный провайдер,\n // переопределяющий один `variant`, стирал бы у родителя весь блок `GrButton`.\n const merged: Record<string, Record<string, unknown>> = { ...inherited }\n for (const [component, componentProps] of Object.entries(own))\n merged[component] = { ...(inherited[component] ?? {}), ...componentProps }\n\n return merged\n})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, { size, componentDefaults, theme, portalTarget })\n\n// ————— i18n.\n//\n// Адаптер отдаём вниз ВСЕГДА и фасадом, а не значением. Прежнее\n// `if (props.i18n != null) provide(…)` решало судьбу один раз в `setup`:\n// адаптер, созданный асинхронно (обычная загрузка локали), не приезжал уже\n// никогда, а подмена адаптера при смене языка до детей не доходила.\nconst inheritedI18n = resolveGranularityI18n()\nconst activeI18n = computed(() => props.i18n ?? inheritedI18n)\n\nprovide<GranularityI18nAdapter>(GRANULARITY_I18N_KEY, {\n t: (key, params) => activeI18n.value?.t(key, params) ?? key,\n // Геттеры, а не поля: `useGranularityTranslations` спрашивает `if (i18n.te)`,\n // и всегда определённый метод у адаптера без `te` означал бы «перевода нет»\n // для каждого ключа.\n get te() {\n const adapter = activeI18n.value\n return adapter?.te ? (key: string) => adapter.te!(key) : undefined\n },\n get locale() {\n return activeI18n.value?.locale\n },\n get syncLocale() {\n const adapter = activeI18n.value\n return adapter?.syncLocale ? (next: string) => adapter.syncLocale!(next) : undefined\n },\n})\n\nwatch(\n () => [props.locale, activeI18n.value] as const,\n ([locale, adapter]) => {\n if (!locale || adapter?.locale?.value === locale)\n return\n void adapter?.syncLocale?.(locale)\n },\n { immediate: true },\n)\n\n// ————— Шкала слоёв. Ставится на `<html>` и живёт в отдельном модуле: владелец\n// шкалы один на документ, а `<script setup>` — это уже область инстанса.\nconst zIndexToken = Symbol('gr-config-z-index')\nlet restoreZIndex: (() => void) | null = null\n\nwatch(\n () => props.zIndexBase,\n (base) => {\n restoreZIndex?.()\n restoreZIndex = applyGrZIndexBase(zIndexToken, base)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n restoreZIndex?.()\n restoreZIndex = null\n})\n\nconst wrapperStyle = { display: 'contents' } as const\n\ndefineSlots<{\n /** Поддерево, которому адресованы настройки. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <component\n :is=\"props.tag\"\n data-gr-config-provider\n :data-theme=\"theme\"\n :style=\"wrapperStyle\"\n >\n <slot />\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrConfigProvider — глобальные дефолты для вложенных GR-компонентов.\n *\n * Даёт единое место для:\n * - `size` — дефолтного размера контролов (не нужно повторять `size` в каждом вызове);\n * - `componentDefaults` — per-component дефолтных пропсов;\n * - `i18n` — адаптера переводов (иначе приложение инжектит его вручную);\n * - `theme` — темы поддерева;\n * - `portalTarget` — точки монтирования оверлеев;\n * - `zIndexBase` — базы шкалы слоёв.\n *\n * Провайдеры можно вкладывать: дочерний мержится поверх родительского, поэтому\n * можно задать «глобальную» тему и точечно переопределить её в поддереве.\n *\n * Рендерится прозрачно (`display: contents`), чтобы не влиять на layout.\n */\nimport { computed, onBeforeUnmount, provide, watch } from 'vue'\n\nimport { GRANULARITY_I18N_KEY, type GranularityI18nAdapter } from '../../i18n/adapter'\nimport { resolveGranularityI18n } from '../../internal/granularityI18n'\nimport { applyGrZIndexBase } from './zIndexScale'\nimport {\n GR_CONFIG_KEY,\n useGrConfig,\n type GrComponentDefaults,\n type GrComponentSize,\n type GrConfigContext,\n} from './context'\n\nexport type { GrComponentDefaults, GrComponentSize } from './context'\n\nexport interface GrConfigProviderProps {\n /** Дефолтный размер контролов для вложенных компонентов. */\n size?: GrComponentSize\n /** Дефолтные пропсы по компонентам: `{ GrButton: { variant: 'secondary' } }`. */\n componentDefaults?: GrComponentDefaults\n /** Адаптер переводов (fint-i18n-совместимый). Прокидывается вложенным компонентам. */\n i18n?: GranularityI18nAdapter | null\n /**\n * Просьба к адаптеру переключить язык (`syncLocale`). Источником истины\n * остаётся сам адаптер — провайдер лишь передаёт ему намерение.\n */\n locale?: string\n /**\n * Тема поддерева: значение уезжает в `data-theme`. Тема **документа** —\n * работа `useTheme`/`initThemeEarly`, здесь именно остров.\n */\n theme?: string\n /**\n * Куда монтировать оверлеи поддерева. По умолчанию — общий `#gr-portal` в\n * `body`. Своё значение нужно там, где приложение живёт в контейнере:\n * микрофронтенд, shadow DOM, CSS-скоупинг под конкретным корнем.\n */\n portalTarget?: string | HTMLElement\n /**\n * База шкалы слоёв. Переменные `--gr-z-*` пересчитываются от неё и ставятся\n * на `<html>`: панели телепортируются в `body`, и переменные поддерева до\n * них не доходят.\n */\n zIndexBase?: number\n /** Тег обёртки. По умолчанию прозрачный `<div style=\"display:contents\">`. */\n tag?: string\n}\n\nconst props = withDefaults(\n defineProps<GrConfigProviderProps>(),\n {\n size: undefined,\n componentDefaults: undefined,\n i18n: undefined,\n locale: undefined,\n theme: undefined,\n portalTarget: undefined,\n zIndexBase: undefined,\n tag: 'div',\n },\n)\n\n// Наследуемся от родительского провайдера — вложенные провайдеры мержатся.\nconst parent = useGrConfig()\n\nconst size = computed(() => props.size ?? parent.size.value)\nconst theme = computed(() => props.theme ?? parent.theme?.value)\n// Цель портала наследуется вниз: вложенный провайдер без своего значения\n// оставляет оверлеи там же, где их ждёт родительское приложение.\nconst portalTarget = computed(() => props.portalTarget ?? parent.portalTarget?.value)\nconst componentDefaults = computed<GrComponentDefaults>(() => {\n const inherited = parent.componentDefaults.value as Record<string, Record<string, unknown>>\n const own = (props.componentDefaults ?? {}) as Record<string, Record<string, unknown>>\n\n // Мержим на уровне пропов, а не компонентов: иначе вложенный провайдер,\n // переопределяющий один `variant`, стирал бы у родителя весь блок `GrButton`.\n const merged: Record<string, Record<string, unknown>> = { ...inherited }\n for (const [component, componentProps] of Object.entries(own))\n merged[component] = { ...(inherited[component] ?? {}), ...componentProps }\n\n return merged\n})\n\nprovide<GrConfigContext>(GR_CONFIG_KEY, { size, componentDefaults, theme, portalTarget })\n\n// ————— i18n.\n//\n// Адаптер отдаём вниз ВСЕГДА и фасадом, а не значением. Прежнее\n// `if (props.i18n != null) provide(…)` решало судьбу один раз в `setup`:\n// адаптер, созданный асинхронно (обычная загрузка локали), не приезжал уже\n// никогда, а подмена адаптера при смене языка до детей не доходила.\nconst inheritedI18n = resolveGranularityI18n()\nconst activeI18n = computed(() => props.i18n ?? inheritedI18n)\n\nprovide<GranularityI18nAdapter>(GRANULARITY_I18N_KEY, {\n t: (key, params) => activeI18n.value?.t(key, params) ?? key,\n // Геттеры, а не поля: `useGranularityTranslations` спрашивает `if (i18n.te)`,\n // и всегда определённый метод у адаптера без `te` означал бы «перевода нет»\n // для каждого ключа.\n get te() {\n const adapter = activeI18n.value\n return adapter?.te ? (key: string) => adapter.te!(key) : undefined\n },\n get locale() {\n return activeI18n.value?.locale\n },\n get syncLocale() {\n const adapter = activeI18n.value\n return adapter?.syncLocale ? (next: string) => adapter.syncLocale!(next) : undefined\n },\n})\n\nwatch(\n () => [props.locale, activeI18n.value] as const,\n ([locale, adapter]) => {\n if (!locale || adapter?.locale?.value === locale)\n return\n void adapter?.syncLocale?.(locale)\n },\n { immediate: true },\n)\n\n// ————— Шкала слоёв. Ставится на `<html>` и живёт в отдельном модуле: владелец\n// шкалы один на документ, а `<script setup>` — это уже область инстанса.\nconst zIndexToken = Symbol('gr-config-z-index')\nlet restoreZIndex: (() => void) | null = null\n\nwatch(\n () => props.zIndexBase,\n (base) => {\n restoreZIndex?.()\n restoreZIndex = applyGrZIndexBase(zIndexToken, base)\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n restoreZIndex?.()\n restoreZIndex = null\n})\n\nconst wrapperStyle = { display: 'contents' } as const\n\ndefineSlots<{\n /** Поддерево, которому адресованы настройки. */\n default?: () => any\n}>()\n</script>\n\n<template>\n <component\n :is=\"props.tag\"\n data-gr-config-provider\n :data-theme=\"theme\"\n :style=\"wrapperStyle\"\n >\n <slot />\n </component>\n</template>\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
2
2
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
3
- import { t as GrButton_default } from "../../GrButton/chunks/GrButton-Bw2AH4uX.js";
4
- import { t as GrDialog_default } from "../../GrDialog/chunks/GrDialog-bOUDYfmh.js";
5
- import { t as GrResponseErrorBanner_default } from "../../GrResponseErrorBanner/chunks/GrResponseErrorBanner-DudGc9LO.js";
3
+ import { t as GrButton_default } from "../../GrButton/chunks/GrButton-7GP0zObj.js";
4
+ import { t as GrDialog_default } from "../../GrDialog/chunks/GrDialog-BiMJ9_T4.js";
5
+ import { t as GrResponseErrorBanner_default } from "../../GrResponseErrorBanner/chunks/GrResponseErrorBanner-DMeOWlzj.js";
6
6
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, ref, renderSlot, toDisplayString, unref, watch, withCtx } from "vue";
7
7
  //#region src/components/GrConfirmDialog/GrConfirmDialog.vue?vue&type=script&setup=true&lang.ts
8
8
  var _hoisted_1 = { class: "grid gap-4" };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrConfirmDialog-CUP43q__.js","names":[],"sources":["../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue","../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — GR-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrResponseErrorBanner from '../GrResponseErrorBanner/GrResponseErrorBanner.vue'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\n/** Какое действие получает фокус при открытии окна. */\nexport type GrConfirmDialogFocusAction = 'confirm' | 'cancel' | 'none'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n /**\n * Структура ошибки ответа сервера для показа в теле диалога\n * (через `GrResponseErrorBanner`). Используется императивным\n * `useDialogService` для async-`onConfirm`. `null` — блок скрыт.\n */\n error?: ResponseErrorInfo | null\n /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */\n confirmLoading?: boolean\n /** Принудительно дизейблит кнопку Confirm. */\n confirmDisabled?: boolean\n /**\n * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`\n * (историческое поведение). `false` — отдаёт управление закрытием наружу\n * (нужно `useDialogService`, который ждёт результат async-`onConfirm`).\n */\n closeOnConfirm?: boolean\n /**\n * Какое действие получает фокус при открытии. По умолчанию «Отмена»:\n * подтверждение бывает деструктивным, и `Enter` сразу после открытия не\n * должен его запускать. `none` оставляет фокус на панели окна.\n *\n * Имя не `initialFocus` намеренно: у `GrModal`/`GrDrawer` так называется\n * проп с элементом, а здесь выбирается действие.\n */\n focusAction?: GrConfirmDialogFocusAction\n /**\n * Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт\n * подтверждение (`confirmLoading`). Кнопка закрытия и «Отмена» остаются:\n * окно без единого выхода — ловушка.\n */\n persistent?: boolean\n}\n\nexport interface GrConfirmDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: undefined,\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n buttonSize: undefined,\n confirmText: undefined,\n cancelText: undefined,\n confirmVariant: 'primary',\n confirmTone: 'primary',\n error: null,\n confirmLoading: false,\n confirmDisabled: false,\n closeOnConfirm: true,\n focusAction: 'cancel',\n persistent: false,\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrConfirmDialog', 'size', () => props.size, 'md')\n\nconst emit = defineEmits<GrConfirmDialogEmits>()\n\n// Дефолты берём из общего i18n-блока пакета (fallback — англ.), а не хардкодим.\nconst { t } = useGranularityTranslations()\nconst resolvedTitle = computed(() => props.title ?? t('gr.dialog.confirm.title', 'Confirm'))\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\nconst resolvedConfirmText = computed(() => props.confirmText ?? t('gr.common.confirm', 'Confirm'))\nconst resolvedCancelText = computed(() => props.cancelText ?? t('gr.common.cancel', 'Cancel'))\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nconst confirmButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\nconst cancelButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\n\n// Пока подтверждение в полёте, случайное движение не должно оборвать операцию.\nconst softCloseBlocked = computed(() => props.persistent && props.confirmLoading)\nconst resolvedCloseOnBackdrop = computed(() => (softCloseBlocked.value ? false : props.closeOnBackdrop))\nconst resolvedCloseOnEsc = computed(() => (softCloseBlocked.value ? false : props.closeOnEsc))\n\n/**\n * Фокус ставит содержимое после отрисовки, а не проп `initialFocus` у\n * `GrModal`: кнопка рождается внутри поддерева диалога, и возврат её же пропом\n * наверх замыкает рендер в цикл (проверено на `GrPromptDialog`).\n *\n * Молчит, когда фокусировать нечего: со своим слотом `#footer` кнопок с\n * рефами в DOM нет, и фокус остаётся на панели — это корректный исход, а не\n * повод падать.\n */\nfunction focusAction(): void {\n if (props.focusAction === 'confirm')\n confirmButtonRef.value?.focus()\n else if (props.focusAction === 'cancel')\n cancelButtonRef.value?.focus()\n}\n\n// Источник — не только `modelValue`, но и сами кнопки: содержимое панели\n// появляется на такт позже открытия, и фокус по фиксированному `nextTick`\n// приходился на момент, когда фокусировать ещё нечего.\nwatch(\n [() => props.modelValue, cancelButtonRef, confirmButtonRef],\n () => {\n if (!props.modelValue || props.focusAction === 'none')\n return\n focusAction()\n },\n // `immediate`: окно могут смонтировать уже открытым — смены пропа тогда нет.\n { immediate: true, flush: 'post' },\n)\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n if (props.closeOnConfirm)\n emit('update:modelValue', false)\n}\n\ndefineSlots<{\n /** Содержимое диалога вместо пропа `message`. */\n default?: () => any\n /** Разбор ошибки вместо встроенного баннера. */\n error?: (props: { error: ResponseErrorInfo | null }) => any\n /** Кнопки диалога вместо пары «отмена и подтверждение». */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"resolvedTitle\"\n :size=\"resolvedSize\"\n :close-on-backdrop=\"resolvedCloseOnBackdrop\"\n :close-on-esc=\"resolvedCloseOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"resolvedCloseLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] text-[var(--gr-muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <slot name=\"error\" :error=\"error\">\n <GrResponseErrorBanner v-if=\"error\" :error=\"error\" :can-dismiss=\"false\" />\n </slot>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton ref=\"cancelButtonRef\" data-testid=\"gr-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ resolvedCancelText }}\n </GrButton>\n <GrButton\n ref=\"confirmButtonRef\"\n data-testid=\"gr-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :loading=\"confirmLoading\"\n :disabled=\"confirmDisabled\"\n @click=\"onConfirm\"\n >\n {{ resolvedConfirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — GR-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { useGrComponentProp } from '../GrConfigProvider/context'\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrResponseErrorBanner from '../GrResponseErrorBanner/GrResponseErrorBanner.vue'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\nimport type { ResponseErrorInfo } from '../GrResponseErrorBanner'\n\n/** Какое действие получает фокус при открытии окна. */\nexport type GrConfirmDialogFocusAction = 'confirm' | 'cancel' | 'none'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n /**\n * Структура ошибки ответа сервера для показа в теле диалога\n * (через `GrResponseErrorBanner`). Используется императивным\n * `useDialogService` для async-`onConfirm`. `null` — блок скрыт.\n */\n error?: ResponseErrorInfo | null\n /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */\n confirmLoading?: boolean\n /** Принудительно дизейблит кнопку Confirm. */\n confirmDisabled?: boolean\n /**\n * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`\n * (историческое поведение). `false` — отдаёт управление закрытием наружу\n * (нужно `useDialogService`, который ждёт результат async-`onConfirm`).\n */\n closeOnConfirm?: boolean\n /**\n * Какое действие получает фокус при открытии. По умолчанию «Отмена»:\n * подтверждение бывает деструктивным, и `Enter` сразу после открытия не\n * должен его запускать. `none` оставляет фокус на панели окна.\n *\n * Имя не `initialFocus` намеренно: у `GrModal`/`GrDrawer` так называется\n * проп с элементом, а здесь выбирается действие.\n */\n focusAction?: GrConfirmDialogFocusAction\n /**\n * Запрет закрытия «мягкими» способами (Esc, клик по бэкдропу), пока идёт\n * подтверждение (`confirmLoading`). Кнопка закрытия и «Отмена» остаются:\n * окно без единого выхода — ловушка.\n */\n persistent?: boolean\n}\n\nexport interface GrConfirmDialogEmits {\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}\n\nimport './defaults'\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: undefined,\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n // Дефолт `size` живёт в резолвере ниже, а не здесь: Vue подставил бы его\n // до того, как компонент заглянет в `GrConfigProvider`.\n size: undefined,\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: undefined,\n buttonSize: undefined,\n confirmText: undefined,\n cancelText: undefined,\n confirmVariant: 'primary',\n confirmTone: 'primary',\n error: null,\n confirmLoading: false,\n confirmDisabled: false,\n closeOnConfirm: true,\n focusAction: 'cancel',\n persistent: false,\n})\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentProp('GrConfirmDialog', 'size', () => props.size, 'md')\n\nconst emit = defineEmits<GrConfirmDialogEmits>()\n\n// Дефолты берём из общего i18n-блока пакета (fallback — англ.), а не хардкодим.\nconst { t } = useGranularityTranslations()\nconst resolvedTitle = computed(() => props.title ?? t('gr.dialog.confirm.title', 'Confirm'))\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.common.close', 'Close'))\nconst resolvedConfirmText = computed(() => props.confirmText ?? t('gr.common.confirm', 'Confirm'))\nconst resolvedCancelText = computed(() => props.cancelText ?? t('gr.common.cancel', 'Cancel'))\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nconst confirmButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\nconst cancelButtonRef = ref<InstanceType<typeof GrButton> | null>(null)\n\n// Пока подтверждение в полёте, случайное движение не должно оборвать операцию.\nconst softCloseBlocked = computed(() => props.persistent && props.confirmLoading)\nconst resolvedCloseOnBackdrop = computed(() => (softCloseBlocked.value ? false : props.closeOnBackdrop))\nconst resolvedCloseOnEsc = computed(() => (softCloseBlocked.value ? false : props.closeOnEsc))\n\n/**\n * Фокус ставит содержимое после отрисовки, а не проп `initialFocus` у\n * `GrModal`: кнопка рождается внутри поддерева диалога, и возврат её же пропом\n * наверх замыкает рендер в цикл (проверено на `GrPromptDialog`).\n *\n * Молчит, когда фокусировать нечего: со своим слотом `#footer` кнопок с\n * рефами в DOM нет, и фокус остаётся на панели — это корректный исход, а не\n * повод падать.\n */\nfunction focusAction(): void {\n if (props.focusAction === 'confirm')\n confirmButtonRef.value?.focus()\n else if (props.focusAction === 'cancel')\n cancelButtonRef.value?.focus()\n}\n\n// Источник — не только `modelValue`, но и сами кнопки: содержимое панели\n// появляется на такт позже открытия, и фокус по фиксированному `nextTick`\n// приходился на момент, когда фокусировать ещё нечего.\nwatch(\n [() => props.modelValue, cancelButtonRef, confirmButtonRef],\n () => {\n if (!props.modelValue || props.focusAction === 'none')\n return\n focusAction()\n },\n // `immediate`: окно могут смонтировать уже открытым — смены пропа тогда нет.\n { immediate: true, flush: 'post' },\n)\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n if (props.closeOnConfirm)\n emit('update:modelValue', false)\n}\n\ndefineSlots<{\n /** Содержимое диалога вместо пропа `message`. */\n default?: () => any\n /** Разбор ошибки вместо встроенного баннера. */\n error?: (props: { error: ResponseErrorInfo | null }) => any\n /** Кнопки диалога вместо пары «отмена и подтверждение». */\n footer?: () => any\n}>()\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"resolvedTitle\"\n :size=\"resolvedSize\"\n :close-on-backdrop=\"resolvedCloseOnBackdrop\"\n :close-on-esc=\"resolvedCloseOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"resolvedCloseLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[length:var(--gr-control-text-md)] leading-[var(--gr-control-leading-md)] text-[var(--gr-muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <slot name=\"error\" :error=\"error\">\n <GrResponseErrorBanner v-if=\"error\" :error=\"error\" :can-dismiss=\"false\" />\n </slot>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton ref=\"cancelButtonRef\" data-testid=\"gr-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ resolvedCancelText }}\n </GrButton>\n <GrButton\n ref=\"confirmButtonRef\"\n data-testid=\"gr-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :loading=\"confirmLoading\"\n :disabled=\"confirmDisabled\"\n @click=\"onConfirm\"\n >\n {{ resolvedConfirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqFA,MAAM,QAAQ;EA4Bd,MAAM,eAAe,mBAAmB,mBAAmB,cAAc,MAAM,MAAM,IAAI;EAEzF,MAAM,OAAO;EAGb,MAAM,EAAE,MAAM,2BAA2B;EACzC,MAAM,gBAAgB,eAAe,MAAM,SAAS,EAAE,2BAA2B,SAAS,CAAC;EAC3F,MAAM,qBAAqB,eAAe,MAAM,cAAc,EAAE,mBAAmB,OAAO,CAAC;EAC3F,MAAM,sBAAsB,eAAe,MAAM,eAAe,EAAE,qBAAqB,SAAS,CAAC;EACjG,MAAM,qBAAqB,eAAe,MAAM,cAAc,EAAE,oBAAoB,QAAQ,CAAC;EAE7F,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,UAAmB,KAAK,qBAAqB,KAAK;EAC1D,CAAC;EAED,MAAM,mBAAmB,IAA0C,IAAI;EACvE,MAAM,kBAAkB,IAA0C,IAAI;EAGtE,MAAM,mBAAmB,eAAe,MAAM,cAAc,MAAM,cAAc;EAChF,MAAM,0BAA0B,eAAgB,iBAAiB,QAAQ,QAAQ,MAAM,eAAgB;EACvG,MAAM,qBAAqB,eAAgB,iBAAiB,QAAQ,QAAQ,MAAM,UAAW;;;;;;;;;;EAW7F,SAAS,cAAoB;GAC3B,IAAI,MAAM,gBAAgB,WACxB,iBAAiB,OAAO,MAAM;QAC3B,IAAI,MAAM,gBAAgB,UAC7B,gBAAgB,OAAO,MAAM;EACjC;EAKA,MACE;SAAO,MAAM;GAAY;GAAiB;EAAgB,SACpD;GACJ,IAAI,CAAC,MAAM,cAAc,MAAM,gBAAgB,QAC7C;GACF,YAAY;EACd,GAEA;GAAE,WAAW;GAAM,OAAO;EAAO,CACnC;EAEA,SAAS,WAAiB;GACxB,KAAK,QAAQ;GACb,KAAK,qBAAqB,KAAK;EACjC;EAEA,SAAS,YAAkB;GACzB,KAAK,SAAS;GACd,IAAI,MAAM,gBACR,KAAK,qBAAqB,KAAK;EACnC;;uBAaE,YA8CW,kBAAA;gBA7CA,KAAA;sEAAI,QAAA;IACZ,OAAO,cAAA;IACP,MAAM,MAAA,YAAA;IACN,qBAAmB,wBAAA;IACnB,gBAAc,mBAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,mBAAA;;IAcH,QAAM,cAmBR,CAlBP,WAkBO,KAAA,QAAA,UAAA,CAAA,SAAA,CAjBL,mBAgBM,OAhBN,YAgBM,CAfJ,YAEW,kBAAA;cAFG;KAAJ,KAAI;KAAkB,eAAY;KAAoB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACnF,CAAA,gBAAA,gBAArB,mBAAA,KAAkB,GAAA,CAAA,CAAA,CAAA;;qBAEvB,YAWW,kBAAA;cAVL;KAAJ,KAAI;KACJ,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,SAAS,QAAA;KACT,UAAU,QAAA;KACV,SAAO;;4BAEiB,CAAA,gBAAA,gBAAtB,oBAAA,KAAmB,GAAA,CAAA,CAAA,CAAA;;;;;;;;;2BAlBxB,CAVN,mBAUM,OAVN,YAUM,CATJ,WAIO,KAAA,QAAA,WAAA,CAAA,SAAA,CAHM,QAAA,eAAA,UAAA,GAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,GAIlB,WAEO,KAAA,QAAA,SAAA,EAFa,OAAO,QAAA,MAAK,SAEzB,CADwB,QAAA,SAAA,UAAA,GAA7B,YAA0E,+BAAA;;KAArC,OAAO,QAAA;KAAQ,eAAa"}
@@ -1,3 +1,3 @@
1
- import { t as GrConfirmDialog_default } from "./chunks/GrConfirmDialog-B9mIU78E.js";
1
+ import { t as GrConfirmDialog_default } from "./chunks/GrConfirmDialog-CUP43q__.js";
2
2
  import { t as grConfirmDialogConfig } from "../../chunks/config-A-bBiotF.js";
3
3
  export { GrConfirmDialog_default as GrConfirmDialog, GrConfirmDialog_default as default, grConfirmDialogConfig };
@@ -1,7 +1,7 @@
1
1
  import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
2
2
  import { i as isEditableTarget } from "../../../chunks/keyboard-DE2yhz_b.js";
3
3
  import { t as useControlledOpen } from "../../../chunks/useControlledOpen-DV3SqLTP.js";
4
- import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-CofG-Tfe.js";
4
+ import { t as GrPopover_default } from "../../GrPopover/chunks/GrPopover-faJanmGs.js";
5
5
  import { t as useMenuItemsFocus } from "../../../chunks/useMenuItemsFocus-B6TldmGf.js";
6
6
  import { i as isMenuSection, n as GrDropdownMenuEntries_default, r as isMenuAction, t as GrDropdownMenuList_default } from "../../GrDropdownMenu/chunks/GrDropdownMenuList-B33ZzwfB.js";
7
7
  import { computed, createCommentVNode, createElementBlock, createVNode, defineComponent, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderSlot, unref, useSlots, watch, withCtx } from "vue";