@feugene/granularity 0.16.0 → 0.19.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 (425) hide show
  1. package/dist/chunks/chevron-left-D8AUBAM7.js +23 -0
  2. package/dist/chunks/chevron-left-D8AUBAM7.js.map +1 -0
  3. package/dist/chunks/{chevron-right-BfqMVpbB.js → chevron-right-C6Z01h0X.js} +1 -22
  4. package/dist/chunks/chevron-right-C6Z01h0X.js.map +1 -0
  5. package/dist/chunks/config-8Pcutu1j2.js.map +1 -0
  6. package/dist/chunks/{config-K0C2tcLB.js → config-9PYRZlKE.js} +1 -1
  7. package/dist/chunks/{config-K0C2tcLB.js.map → config-9PYRZlKE.js.map} +1 -1
  8. package/dist/chunks/{config-Zc_bUvZY2.js → config-BDfTXHo12.js} +1 -1
  9. package/dist/chunks/{config-Zc_bUvZY2.js.map → config-BDfTXHo12.js.map} +1 -1
  10. package/dist/chunks/config-BE6n20np2.js.map +1 -0
  11. package/dist/chunks/config-BJ7Bv_G2.js +148 -0
  12. package/dist/chunks/config-BJ7Bv_G2.js.map +1 -0
  13. package/dist/chunks/config-BKvX0q102.js.map +1 -0
  14. package/dist/chunks/{config-CpwwkFBO.js → config-Baj7Wvx-.js} +1 -1
  15. package/dist/chunks/{config-CpwwkFBO.js.map → config-Baj7Wvx-.js.map} +1 -1
  16. package/dist/chunks/{config-D8tSR2uS.js → config-Be9k9bOf.js} +2 -8
  17. package/dist/chunks/config-Be9k9bOf.js.map +1 -0
  18. package/dist/chunks/config-BoNR7_PD2.js.map +1 -0
  19. package/dist/chunks/{config-DxCTVBfx.js → config-BsPDQ0dS.js} +2 -2
  20. package/dist/chunks/config-BsPDQ0dS.js.map +1 -0
  21. package/dist/chunks/{config-DpqOnJiz2.js → config-CDat1wXf2.js} +1 -1
  22. package/dist/chunks/config-CDat1wXf2.js.map +1 -0
  23. package/dist/chunks/config-CN2ULSQL.js.map +1 -0
  24. package/dist/chunks/{config-Cw6TDzWv2.js → config-COpuWGr_.js} +1 -1
  25. package/dist/chunks/config-COpuWGr_.js.map +1 -0
  26. package/dist/chunks/config-CY0_6cMi2.js.map +1 -0
  27. package/dist/chunks/{config-B-g6lT19.js → config-DA6SnEoy.js} +5 -2
  28. package/dist/chunks/config-DA6SnEoy.js.map +1 -0
  29. package/dist/chunks/config-DAX8Deh1.js +68 -0
  30. package/dist/chunks/config-DAX8Deh1.js.map +1 -0
  31. package/dist/chunks/config-DKdlqXiY.js.map +1 -1
  32. package/dist/chunks/{config-CvC0sX8p.js → config-MRvhUl-O.js} +1 -1
  33. package/dist/chunks/{config-CvC0sX8p.js.map → config-MRvhUl-O.js.map} +1 -1
  34. package/dist/chunks/config-Rw9OyW702.js.map +1 -0
  35. package/dist/chunks/config-ScuvHw6k2.js +42 -0
  36. package/dist/chunks/config-ScuvHw6k2.js.map +1 -0
  37. package/dist/chunks/config-T3qdQBgU2.js.map +1 -0
  38. package/dist/chunks/config-eXB87DOi.js.map +1 -0
  39. package/dist/chunks/context-BSYR7RZs.js.map +1 -1
  40. package/dist/chunks/{en-B3xMeswz.js → en-COdzxgAX.js} +30 -5
  41. package/dist/chunks/en-COdzxgAX.js.map +1 -0
  42. package/dist/chunks/{es-CA-mkU--.js → es-ClqJ-4hr.js} +30 -5
  43. package/dist/chunks/es-ClqJ-4hr.js.map +1 -0
  44. package/dist/chunks/{es-Bv8vvqdT.js → es-DGMHwknJ.js} +3 -3
  45. package/dist/chunks/{es-Bv8vvqdT.js.map → es-DGMHwknJ.js.map} +1 -1
  46. package/dist/chunks/generated-BRkbhyxk.js +3270 -0
  47. package/dist/chunks/generated-BRkbhyxk.js.map +1 -0
  48. package/dist/chunks/grKbdStyles-CeZhGQHr.js +43 -0
  49. package/dist/chunks/grKbdStyles-CeZhGQHr.js.map +1 -0
  50. package/dist/chunks/{grTextareaStyles-CWI2SqC8.js → grTextareaStyles-iOcHuVMM.js} +2 -2
  51. package/dist/chunks/{grTextareaStyles-CWI2SqC8.js.map → grTextareaStyles-iOcHuVMM.js.map} +1 -1
  52. package/dist/chunks/{granular-provider-CtrXGa7c.js → granular-provider-C6uAujdJ.js} +23 -21
  53. package/dist/chunks/granular-provider-C6uAujdJ.js.map +1 -0
  54. package/dist/chunks/grip-vertical-lRha2S7q.js +16 -0
  55. package/dist/chunks/grip-vertical-lRha2S7q.js.map +1 -0
  56. package/dist/chunks/icon-Dag2tIMs.js +21 -0
  57. package/dist/chunks/icon-Dag2tIMs.js.map +1 -0
  58. package/dist/chunks/{keyboard-zYvvyHd4.js → keyboard-DE2yhz_b.js} +10 -1
  59. package/dist/chunks/keyboard-DE2yhz_b.js.map +1 -0
  60. package/dist/chunks/{optionFilter-BVY988pC.js → optionFilter-DYw9XPPx.js} +1 -71
  61. package/dist/chunks/optionFilter-DYw9XPPx.js.map +1 -0
  62. package/dist/chunks/{useOverlayLayer-BupuP_hs.js → overlayStack-C8cfsqXa.js} +11 -61
  63. package/dist/chunks/overlayStack-C8cfsqXa.js.map +1 -0
  64. package/dist/chunks/{portalRoot-CWD4zHBm.js → portalRoot-CVhCgdG6.js} +10 -1
  65. package/dist/chunks/{portalRoot-CWD4zHBm.js.map → portalRoot-CVhCgdG6.js.map} +1 -1
  66. package/dist/chunks/{ru-COWxgh2A.js → ru-9z8ix45c.js} +30 -5
  67. package/dist/chunks/ru-9z8ix45c.js.map +1 -0
  68. package/dist/chunks/useDragSort-0l47h4yb.js +265 -0
  69. package/dist/chunks/useDragSort-0l47h4yb.js.map +1 -0
  70. package/dist/chunks/{useModalOverlay-DCM4d3yA.js → useModalOverlay-DrQVYwwA.js} +2 -2
  71. package/dist/chunks/{useModalOverlay-DCM4d3yA.js.map → useModalOverlay-DrQVYwwA.js.map} +1 -1
  72. package/dist/chunks/{usePortalTarget-RyzEgNTb.js → usePortalTarget-Cn-Wiz5d.js} +1 -1
  73. package/dist/chunks/{usePortalTarget-RyzEgNTb.js.map → usePortalTarget-Cn-Wiz5d.js.map} +1 -1
  74. package/dist/components/GrAutocomplete/chunks/{GrAutocomplete-CQ9T7Lly.js → GrAutocomplete-gY4Xopza.js} +35 -26
  75. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-gY4Xopza.js.map +1 -0
  76. package/dist/components/GrAutocomplete/index.js +1 -1
  77. package/dist/components/GrAutocomplete/styles.css +1 -1
  78. package/dist/components/GrBreadcrumbs/chunks/{GrBreadcrumbs-BCNGDS6k.js → GrBreadcrumbs-DS_-PBVt.js} +8 -7
  79. package/dist/components/GrBreadcrumbs/chunks/GrBreadcrumbs-DS_-PBVt.js.map +1 -0
  80. package/dist/components/GrBreadcrumbs/index.js +1 -1
  81. package/dist/components/GrCollapse/chunks/{GrCollapse-B2Fc6A9r.js.map → GrCollapse-Kk0DE8tb.js.map} +1 -1
  82. package/dist/components/GrCollapse/index.js +1 -1
  83. package/dist/components/GrColorPicker/chunks/{GrColorPicker-bnYBRGk8.js → GrColorPicker-CkBTzkqn.js} +4 -4
  84. package/dist/components/GrColorPicker/chunks/{GrColorPicker-bnYBRGk8.js.map → GrColorPicker-CkBTzkqn.js.map} +1 -1
  85. package/dist/components/GrColorPicker/index.js +2 -2
  86. package/dist/components/GrCommandPalette/chunks/{GrCommandPalette-MWDYDPNC.js → GrCommandPalette-BugTlGdj.js} +41 -16
  87. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-BugTlGdj.js.map +1 -0
  88. package/dist/components/GrCommandPalette/index.js +2 -2
  89. package/dist/components/GrCommandPalette/styles.css +1 -1
  90. package/dist/components/GrConfigProvider/index.js +2 -2
  91. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-DaQmlp1_.js → GrConfirmDialog-Ds5T0GiR.js} +1 -1
  92. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-DaQmlp1_.js.map → GrConfirmDialog-Ds5T0GiR.js.map} +1 -1
  93. package/dist/components/GrConfirmDialog/index.js +1 -1
  94. package/dist/components/GrDataTable/chunks/{GrDataTable-DVFho9Cj.js → GrDataTable-CYe2A2WA.js} +498 -48
  95. package/dist/components/GrDataTable/chunks/GrDataTable-CYe2A2WA.js.map +1 -0
  96. package/dist/components/GrDataTable/index.js +2 -2
  97. package/dist/components/GrDialog/chunks/{GrDialog-AE1gIZuz.js → GrDialog-C3tYaA8v.js} +1 -1
  98. package/dist/components/GrDialog/chunks/{GrDialog-AE1gIZuz.js.map → GrDialog-C3tYaA8v.js.map} +1 -1
  99. package/dist/components/GrDialog/index.js +1 -1
  100. package/dist/components/GrDialogService/chunks/{GrDialogService-B4DYWDkA.js → GrDialogService-CTBiiJDI.js} +3 -3
  101. package/dist/components/GrDialogService/chunks/{GrDialogService-B4DYWDkA.js.map → GrDialogService-CTBiiJDI.js.map} +1 -1
  102. package/dist/components/GrDialogService/index.js +1 -1
  103. package/dist/components/GrDivider/chunks/{GrDivider-B2Xwc_QO.js → GrDivider-xxq1_fIl.js} +1 -1
  104. package/dist/components/GrDivider/chunks/{GrDivider-B2Xwc_QO.js.map → GrDivider-xxq1_fIl.js.map} +1 -1
  105. package/dist/components/GrDivider/index.js +2 -2
  106. package/dist/components/GrDrawer/chunks/{GrDrawer-DQwi6aRw.js → GrDrawer-BSSuiNHU.js} +1 -1
  107. package/dist/components/GrDrawer/chunks/{GrDrawer-DQwi6aRw.js.map → GrDrawer-BSSuiNHU.js.map} +1 -1
  108. package/dist/components/GrDrawer/index.js +1 -1
  109. package/dist/components/GrDropdown/chunks/{GrDropdown-BLng6V1m.js → GrDropdown-Bh6UK2M5.js} +3 -3
  110. package/dist/components/GrDropdown/chunks/{GrDropdown-BLng6V1m.js.map → GrDropdown-Bh6UK2M5.js.map} +1 -1
  111. package/dist/components/GrDropdown/index.js +1 -1
  112. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-BImk2Vs7.js → GrDropdownMenu-LyfEFUbg.js} +2 -2
  113. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-BImk2Vs7.js.map → GrDropdownMenu-LyfEFUbg.js.map} +1 -1
  114. package/dist/components/GrDropdownMenu/index.js +2 -2
  115. package/dist/components/GrFileUpload/chunks/{GrFileUpload-D0B-BEsd.js → GrFileUpload-DuDzC43S.js} +2 -2
  116. package/dist/components/GrFileUpload/chunks/{GrFileUpload-D0B-BEsd.js.map → GrFileUpload-DuDzC43S.js.map} +1 -1
  117. package/dist/components/GrFileUpload/index.js +1 -1
  118. package/dist/components/GrImageViewer/chunks/{GrImageViewer-BeCnE8XQ.js → GrImageViewer-DfD4euH5.js} +48 -23
  119. package/dist/components/GrImageViewer/chunks/GrImageViewer-DfD4euH5.js.map +1 -0
  120. package/dist/components/GrImageViewer/index.js +1 -1
  121. package/dist/components/GrInput/chunks/{GrInput-DD2gYdqS.js → GrInput-2wd7Crs0.js} +1 -1
  122. package/dist/components/GrInput/chunks/GrInput-2wd7Crs0.js.map +1 -0
  123. package/dist/components/GrInput/index.js +1 -1
  124. package/dist/components/GrInputTag/chunks/{GrInputTag-DmNunixz.js → GrInputTag-CyV2eY7Z.js} +20 -33
  125. package/dist/components/GrInputTag/chunks/GrInputTag-CyV2eY7Z.js.map +1 -0
  126. package/dist/components/GrInputTag/index.js +1 -1
  127. package/dist/components/GrKbd/chunks/{GrKbd-DRFPvW3G.js → GrKbd-DU2lBkRV.js} +218 -52
  128. package/dist/components/GrKbd/chunks/GrKbd-DU2lBkRV.js.map +1 -0
  129. package/dist/components/GrKbd/index.js +3 -3
  130. package/dist/components/GrModal/chunks/{GrModal-B8I78T0N.js → GrModal-CbMMr6W1.js} +1 -1
  131. package/dist/components/GrModal/chunks/{GrModal-B8I78T0N.js.map → GrModal-CbMMr6W1.js.map} +1 -1
  132. package/dist/components/GrModal/index.js +1 -1
  133. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CZOyPz4J.js → GrNumberInput-B5CHZDBj.js} +2 -1
  134. package/dist/components/GrNumberInput/chunks/{GrNumberInput-CZOyPz4J.js.map → GrNumberInput-B5CHZDBj.js.map} +1 -1
  135. package/dist/components/GrNumberInput/index.js +1 -1
  136. package/dist/components/GrPagination/chunks/{GrPagination-B6N0QZBf.js → GrPagination-BM4FrD6Q.js} +4 -4
  137. package/dist/components/GrPagination/chunks/GrPagination-BM4FrD6Q.js.map +1 -0
  138. package/dist/components/GrPagination/index.js +1 -1
  139. package/dist/components/GrPopover/chunks/{GrPopover-B1eRCOoO.js → GrPopover-DMH4Jjst.js} +1 -1
  140. package/dist/components/GrPopover/chunks/{GrPopover-B1eRCOoO.js.map → GrPopover-DMH4Jjst.js.map} +1 -1
  141. package/dist/components/GrPopover/index.js +1 -1
  142. package/dist/components/GrProgressBar/chunks/{GrProgressBar-BiHnaitu.js → GrProgressBar-xwbNM9QB.js} +1 -1
  143. package/dist/components/GrProgressBar/chunks/GrProgressBar-xwbNM9QB.js.map +1 -0
  144. package/dist/components/GrProgressBar/index.js +1 -1
  145. package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-CTogjcHz.js → GrProgressCircle-B8olXRo5.js} +1 -1
  146. package/dist/components/GrProgressCircle/chunks/{GrProgressCircle-CTogjcHz.js.map → GrProgressCircle-B8olXRo5.js.map} +1 -1
  147. package/dist/components/GrProgressCircle/index.js +2 -2
  148. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-Ct174NVD.js → GrPromptDialog-Pwr9NPxK.js} +3 -3
  149. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-Ct174NVD.js.map → GrPromptDialog-Pwr9NPxK.js.map} +1 -1
  150. package/dist/components/GrPromptDialog/index.js +1 -1
  151. package/dist/components/GrRadio/chunks/{GrRadio-DksDro_U.js → GrRadio-DWiRaMzt.js} +8 -32
  152. package/dist/components/GrRadio/chunks/GrRadio-DWiRaMzt.js.map +1 -0
  153. package/dist/components/GrRadio/index.js +1 -1
  154. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-BOIhejE6.js → GrRadioGroup-DIuBw0wk.js} +34 -27
  155. package/dist/components/GrRadioGroup/chunks/GrRadioGroup-DIuBw0wk.js.map +1 -0
  156. package/dist/components/GrRadioGroup/index.js +1 -1
  157. package/dist/components/GrRating/chunks/{GrRating-JrHXz0Rv.js → GrRating-DVFH3lYu.js} +10 -9
  158. package/dist/components/GrRating/chunks/GrRating-DVFH3lYu.js.map +1 -0
  159. package/dist/components/GrRating/index.js +2 -2
  160. package/dist/components/GrSegmented/chunks/{GrSegmented-BQIlH5KI.js → GrSegmented-CQw3ijqa.js} +47 -65
  161. package/dist/components/GrSegmented/chunks/GrSegmented-CQw3ijqa.js.map +1 -0
  162. package/dist/components/GrSegmented/index.js +1 -1
  163. package/dist/components/GrSelect/chunks/{GrSelect-aqkPCqjd.js → GrSelect-B-Voni7D.js} +69 -55
  164. package/dist/components/GrSelect/chunks/GrSelect-B-Voni7D.js.map +1 -0
  165. package/dist/components/GrSelect/index.js +1 -1
  166. package/dist/components/GrSelect/styles.css +1 -1
  167. package/dist/components/GrSidebar/chunks/{GrSidebar-DRGnnViw.js → GrSidebar-i7AxjhY_.js} +3 -2
  168. package/dist/components/GrSidebar/chunks/{GrSidebar-DRGnnViw.js.map → GrSidebar-i7AxjhY_.js.map} +1 -1
  169. package/dist/components/GrSidebar/index.js +2 -2
  170. package/dist/components/GrSkeleton/index.js +1 -1
  171. package/dist/components/GrSlider/chunks/{GrSlider-DkU9IQSX.js → GrSlider-CyhVsNKn.js} +21 -34
  172. package/dist/components/GrSlider/chunks/GrSlider-CyhVsNKn.js.map +1 -0
  173. package/dist/components/GrSlider/index.js +2 -2
  174. package/dist/components/GrSortableList/chunks/GrSortableList-XB7mXM1W.js +277 -0
  175. package/dist/components/GrSortableList/chunks/GrSortableList-XB7mXM1W.js.map +1 -0
  176. package/dist/components/GrSortableList/index.js +3 -0
  177. package/dist/components/GrSplitter/chunks/{GrSplitter-7To8jbJ8.js → GrSplitter-BzxVQwbY.js} +17 -37
  178. package/dist/components/GrSplitter/chunks/GrSplitter-BzxVQwbY.js.map +1 -0
  179. package/dist/components/GrSplitter/index.js +2 -2
  180. package/dist/components/GrStatistic/chunks/{GrStatistic-CttyoYPT.js → GrStatistic-DOsM6s5V.js} +54 -7
  181. package/dist/components/GrStatistic/chunks/GrStatistic-DOsM6s5V.js.map +1 -0
  182. package/dist/components/GrStatistic/index.js +2 -2
  183. package/dist/components/GrSwitch/chunks/{GrSwitch-B9TYbiih.js → GrSwitch-DpyvVrZG.js} +1 -1
  184. package/dist/components/GrSwitch/chunks/{GrSwitch-B9TYbiih.js.map → GrSwitch-DpyvVrZG.js.map} +1 -1
  185. package/dist/components/GrSwitch/index.js +2 -2
  186. package/dist/components/GrTabPanels/index.js +1 -1
  187. package/dist/components/GrTable/chunks/{GrTable-BB-mI_NM.js → GrTable-BfqgwETQ.js} +7 -1
  188. package/dist/components/GrTable/chunks/GrTable-BfqgwETQ.js.map +1 -0
  189. package/dist/components/GrTable/index.js +1 -1
  190. package/dist/components/GrTabs/chunks/{GrTabs-B8CDq2D9.js → GrTabs-f3-oQenu.js} +55 -65
  191. package/dist/components/GrTabs/chunks/GrTabs-f3-oQenu.js.map +1 -0
  192. package/dist/components/GrTabs/index.js +1 -1
  193. package/dist/components/GrTextarea/chunks/{GrTextarea-DUh5Tlo4.js → GrTextarea-DSvd1nSy.js} +1 -1
  194. package/dist/components/GrTextarea/chunks/{GrTextarea-DUh5Tlo4.js.map → GrTextarea-DSvd1nSy.js.map} +1 -1
  195. package/dist/components/GrTextarea/index.js +2 -2
  196. package/dist/components/GrTimeline/chunks/{GrTimeline-CE9b3s18.js → GrTimeline-B-h2Yanw.js} +1 -1
  197. package/dist/components/GrTimeline/chunks/{GrTimeline-CE9b3s18.js.map → GrTimeline-B-h2Yanw.js.map} +1 -1
  198. package/dist/components/GrTimeline/index.js +2 -2
  199. package/dist/components/GrToaster/chunks/{GrToaster-BKQy3Srm.js → GrToaster-Dqja0Lf9.js} +114 -13
  200. package/dist/components/GrToaster/chunks/GrToaster-Dqja0Lf9.js.map +1 -0
  201. package/dist/components/GrToaster/index.js +2 -2
  202. package/dist/components/GrToaster/styles.css +1 -1
  203. package/dist/components/GrTooltip/chunks/{GrTooltip-DEbejfhA.js → GrTooltip-Cn08heWz.js} +2 -2
  204. package/dist/components/GrTooltip/chunks/{GrTooltip-DEbejfhA.js.map → GrTooltip-Cn08heWz.js.map} +1 -1
  205. package/dist/components/GrTooltip/index.js +2 -2
  206. package/dist/components/GrTree/chunks/{GrTree-wfdbvygw.js → GrTree-BR9a2pay.js} +148 -111
  207. package/dist/components/GrTree/chunks/GrTree-BR9a2pay.js.map +1 -0
  208. package/dist/components/GrTree/index.js +2 -2
  209. package/dist/components/GrTree/styles.css +1 -1
  210. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-lLWmAMtI.js → GrTreeSelect--muUeB0v.js} +28 -14
  211. package/dist/components/GrTreeSelect/chunks/GrTreeSelect--muUeB0v.js.map +1 -0
  212. package/dist/components/GrTreeSelect/index.js +1 -1
  213. package/dist/composables/useAnnouncer.js +1 -1
  214. package/dist/composables/useComboboxNavigation.js +71 -0
  215. package/dist/composables/useComboboxNavigation.js.map +1 -0
  216. package/dist/composables/useDismissible.js +1 -1
  217. package/dist/composables/useDragGesture.js +55 -0
  218. package/dist/composables/useDragGesture.js.map +1 -0
  219. package/dist/composables/useDragSort.js +2 -0
  220. package/dist/composables/useFloating.js +22 -1
  221. package/dist/composables/useFloating.js.map +1 -1
  222. package/dist/composables/useGrComponentConfig.js +2 -0
  223. package/dist/composables/useGranularityTranslations.js +2 -0
  224. package/dist/composables/useOverlayLayer.js +64 -1
  225. package/dist/composables/useOverlayLayer.js.map +1 -0
  226. package/dist/composables/usePortalTarget.js +1 -1
  227. package/dist/composables/useRovingFocus.js +150 -0
  228. package/dist/composables/useRovingFocus.js.map +1 -0
  229. package/dist/directives/hotkey.js +13 -7
  230. package/dist/directives/hotkey.js.map +1 -1
  231. package/dist/directives/loading.js +1 -1
  232. package/dist/granular-provider-node.js +1 -1
  233. package/dist/granular-provider.js +1 -1
  234. package/dist/i18n/all.js +1 -1
  235. package/dist/i18n/index.js +1 -1
  236. package/dist/index.js +77 -68
  237. package/dist/styles/themes/dark.css +6 -1
  238. package/dist/testing.js +199 -0
  239. package/dist/testing.js.map +1 -0
  240. package/dist/theme-apply.js +33 -0
  241. package/dist/theme-apply.js.map +1 -0
  242. package/dist/theme.js +501 -0
  243. package/dist/theme.js.map +1 -0
  244. package/dist/tokens.js +1 -3131
  245. package/dist/types/src/components/GrAlert/defaults.d.ts +1 -1
  246. package/dist/types/src/components/GrAutocomplete/defaults.d.ts +1 -1
  247. package/dist/types/src/components/GrAvatar/defaults.d.ts +1 -1
  248. package/dist/types/src/components/GrBadge/defaults.d.ts +1 -1
  249. package/dist/types/src/components/GrBottomNav/defaults.d.ts +1 -1
  250. package/dist/types/src/components/GrBreadcrumbs/defaults.d.ts +1 -1
  251. package/dist/types/src/components/GrBreadcrumbs/grBreadcrumbsStyles.d.ts +5 -2
  252. package/dist/types/src/components/GrButton/defaults.d.ts +1 -1
  253. package/dist/types/src/components/GrCard/defaults.d.ts +1 -1
  254. package/dist/types/src/components/GrCheckbox/defaults.d.ts +1 -1
  255. package/dist/types/src/components/GrCheckboxGroup/defaults.d.ts +1 -1
  256. package/dist/types/src/components/GrCollapse/defaults.d.ts +1 -1
  257. package/dist/types/src/components/GrColorPicker/defaults.d.ts +1 -1
  258. package/dist/types/src/components/GrColorPicker/grColorPickerStyles.d.ts +2 -2
  259. package/dist/types/src/components/GrCommandPalette/GrCommandPalette.vue.d.ts +6 -6
  260. package/dist/types/src/components/GrCommandPalette/defaults.d.ts +1 -1
  261. package/dist/types/src/components/GrCommandPalette/filtering.d.ts +6 -2
  262. package/dist/types/src/components/GrConfigProvider/context.d.ts +6 -22
  263. package/dist/types/src/components/GrConfigProvider/index.d.ts +1 -1
  264. package/dist/types/src/components/GrConfirmDialog/defaults.d.ts +1 -1
  265. package/dist/types/src/components/GrDataTable/GrDataTable.vue.d.ts +53 -0
  266. package/dist/types/src/components/GrDataTable/defaults.d.ts +1 -1
  267. package/dist/types/src/components/GrDataTable/grDataTableStyles.d.ts +38 -0
  268. package/dist/types/src/components/GrDialog/defaults.d.ts +1 -1
  269. package/dist/types/src/components/GrDivider/defaults.d.ts +1 -1
  270. package/dist/types/src/components/GrDrawer/defaults.d.ts +1 -1
  271. package/dist/types/src/components/GrEmptyState/defaults.d.ts +1 -1
  272. package/dist/types/src/components/GrFileUpload/defaults.d.ts +1 -1
  273. package/dist/types/src/components/GrFormField/defaults.d.ts +1 -1
  274. package/dist/types/src/components/GrFormFile/defaults.d.ts +1 -1
  275. package/dist/types/src/components/GrFormSection/defaults.d.ts +1 -1
  276. package/dist/types/src/components/GrIcon/defaults.d.ts +1 -1
  277. package/dist/types/src/components/GrImageViewer/composables/usePointerGestures.d.ts +1 -0
  278. package/dist/types/src/components/GrImageViewer/composables/useZoomPan.d.ts +1 -2
  279. package/dist/types/src/components/GrInput/defaults.d.ts +1 -1
  280. package/dist/types/src/components/GrInputTag/defaults.d.ts +1 -1
  281. package/dist/types/src/components/GrKbd/GrKbd.vue.d.ts +18 -3
  282. package/dist/types/src/components/GrKbd/defaults.d.ts +1 -1
  283. package/dist/types/src/components/GrKbd/grKbdStyles.d.ts +20 -3
  284. package/dist/types/src/components/GrKbd/index.d.ts +6 -0
  285. package/dist/types/src/components/GrLink/defaults.d.ts +1 -1
  286. package/dist/types/src/components/GrModal/defaults.d.ts +1 -1
  287. package/dist/types/src/components/GrNumberInput/defaults.d.ts +1 -1
  288. package/dist/types/src/components/GrPagination/defaults.d.ts +1 -1
  289. package/dist/types/src/components/GrPopover/GrPopover.vue.d.ts +1 -1
  290. package/dist/types/src/components/GrPopover/defaults.d.ts +1 -1
  291. package/dist/types/src/components/GrProgressBar/defaults.d.ts +1 -1
  292. package/dist/types/src/components/GrProgressCircle/defaults.d.ts +1 -1
  293. package/dist/types/src/components/GrProgressCircle/grProgressCircleStyles.d.ts +1 -1
  294. package/dist/types/src/components/GrPromptDialog/defaults.d.ts +1 -1
  295. package/dist/types/src/components/GrRadio/defaults.d.ts +1 -1
  296. package/dist/types/src/components/GrRadio/grRadioGroupContext.d.ts +12 -4
  297. package/dist/types/src/components/GrRadioGroup/defaults.d.ts +1 -1
  298. package/dist/types/src/components/GrRating/GrRating.vue.d.ts +9 -4
  299. package/dist/types/src/components/GrRating/defaults.d.ts +1 -1
  300. package/dist/types/src/components/GrSegmented/defaults.d.ts +1 -1
  301. package/dist/types/src/components/GrSelect/defaults.d.ts +1 -1
  302. package/dist/types/src/components/GrSlider/defaults.d.ts +1 -1
  303. package/dist/types/src/components/GrSortableList/GrSortableList.vue.d.ts +68 -0
  304. package/dist/types/src/components/GrSortableList/config.d.ts +1 -0
  305. package/dist/types/src/components/GrSortableList/grSortableListStyles.d.ts +37 -0
  306. package/dist/types/src/components/GrSortableList/index.d.ts +9 -0
  307. package/dist/types/src/components/GrSortableList/safelist.d.ts +1 -0
  308. package/dist/types/src/components/GrSplitter/defaults.d.ts +1 -1
  309. package/dist/types/src/components/GrStatistic/GrStatistic.vue.d.ts +12 -9
  310. package/dist/types/src/components/GrStatistic/defaults.d.ts +1 -1
  311. package/dist/types/src/components/GrStatistic/grStatisticStyles.d.ts +1 -2
  312. package/dist/types/src/components/GrSwitch/defaults.d.ts +1 -1
  313. package/dist/types/src/components/GrTable/GrTable.vue.d.ts +13 -0
  314. package/dist/types/src/components/GrTable/defaults.d.ts +1 -1
  315. package/dist/types/src/components/GrTabs/GrTabs.vue.d.ts +6 -2
  316. package/dist/types/src/components/GrTabs/defaults.d.ts +1 -1
  317. package/dist/types/src/components/GrTextarea/defaults.d.ts +1 -1
  318. package/dist/types/src/components/GrTextarea/grTextareaStyles.d.ts +2 -2
  319. package/dist/types/src/components/GrTimeline/defaults.d.ts +1 -1
  320. package/dist/types/src/components/GrTimeline/grTimelineStyles.d.ts +1 -1
  321. package/dist/types/src/components/GrToaster/GrToaster.vue.d.ts +8 -0
  322. package/dist/types/src/components/GrToaster/grToasterStyles.d.ts +27 -0
  323. package/dist/types/src/components/GrTooltip/defaults.d.ts +1 -1
  324. package/dist/types/src/components/GrTree/defaults.d.ts +1 -1
  325. package/dist/types/src/components/GrTree/grTreeInteractionContext.d.ts +0 -1
  326. package/dist/types/src/components/GrTree/grTreeProps.d.ts +11 -4
  327. package/dist/types/src/components/GrTree/safelist.d.ts +1 -1
  328. package/dist/types/src/components/GrTreeSelect/defaults.d.ts +1 -1
  329. package/dist/types/src/components/shared/hotkey.d.ts +7 -15
  330. package/dist/types/src/components/shared/hotkeyTokens.d.ts +37 -0
  331. package/dist/types/src/components/shared/icon.d.ts +13 -0
  332. package/dist/types/src/composables/internal/dragSortGeometry.d.ts +59 -0
  333. package/dist/types/src/composables/internal/overlayStack.d.ts +11 -0
  334. package/dist/types/src/composables/useDragGesture.d.ts +63 -0
  335. package/dist/types/src/composables/useDragSort.d.ts +80 -0
  336. package/dist/types/src/composables/useFloating.d.ts +5 -1
  337. package/dist/types/src/composables/useGrComponentConfig.d.ts +41 -0
  338. package/dist/types/src/composables/useGranularityTranslations.d.ts +13 -0
  339. package/dist/types/src/composables/useRovingFocus.d.ts +108 -0
  340. package/dist/types/src/granular-provider/shared.d.ts +1 -0
  341. package/dist/types/src/i18n/messages/en.d.ts +48 -0
  342. package/dist/types/src/i18n/messages/es.d.ts +48 -0
  343. package/dist/types/src/i18n/messages/ru.d.ts +48 -0
  344. package/dist/types/src/index.d.ts +12 -0
  345. package/dist/types/src/internal/keyboard.d.ts +6 -0
  346. package/dist/types/src/testing/announcer.d.ts +10 -0
  347. package/dist/types/src/testing/context.d.ts +36 -0
  348. package/dist/types/src/testing/env.d.ts +25 -0
  349. package/dist/types/src/testing/geometry.d.ts +23 -0
  350. package/dist/types/src/testing/index.d.ts +12 -0
  351. package/dist/types/src/testing/pointer.d.ts +31 -0
  352. package/dist/types/src/theme/apply.d.ts +27 -0
  353. package/dist/types/src/theme/color.d.ts +35 -0
  354. package/dist/types/src/theme/extendTheme.d.ts +63 -0
  355. package/dist/types/src/theme/index.d.ts +22 -0
  356. package/dist/types/src/theme/roles.d.ts +16 -0
  357. package/dist/types/src/theme/tone.d.ts +32 -0
  358. package/dist/types/src/theme/validate.d.ts +16 -0
  359. package/dist/types/src/tokens/types.d.ts +8 -0
  360. package/dist/web-types.json +214 -13
  361. package/package.json +47 -4
  362. package/tokens/themes/dark.json +2 -1
  363. package/dist/chunks/chevron-right-BfqMVpbB.js.map +0 -1
  364. package/dist/chunks/config-8Pcutu1j.js.map +0 -1
  365. package/dist/chunks/config-B-g6lT19.js.map +0 -1
  366. package/dist/chunks/config-BE6n20np.js.map +0 -1
  367. package/dist/chunks/config-BKvX0q10.js.map +0 -1
  368. package/dist/chunks/config-BNfQwyL4.js +0 -97
  369. package/dist/chunks/config-BNfQwyL4.js.map +0 -1
  370. package/dist/chunks/config-BoNR7_PD.js.map +0 -1
  371. package/dist/chunks/config-CN2ULSQL2.js.map +0 -1
  372. package/dist/chunks/config-CY0_6cMi.js.map +0 -1
  373. package/dist/chunks/config-Cw6TDzWv2.js.map +0 -1
  374. package/dist/chunks/config-D8tSR2uS.js.map +0 -1
  375. package/dist/chunks/config-DpqOnJiz2.js.map +0 -1
  376. package/dist/chunks/config-DxCTVBfx.js.map +0 -1
  377. package/dist/chunks/config-LGrZIdaZ.js +0 -21
  378. package/dist/chunks/config-LGrZIdaZ.js.map +0 -1
  379. package/dist/chunks/config-Rw9OyW70.js.map +0 -1
  380. package/dist/chunks/config-T3qdQBgU.js.map +0 -1
  381. package/dist/chunks/config-eXB87DOi2.js.map +0 -1
  382. package/dist/chunks/en-B3xMeswz.js.map +0 -1
  383. package/dist/chunks/es-CA-mkU--.js.map +0 -1
  384. package/dist/chunks/grKbdStyles-DAoxiytu.js +0 -31
  385. package/dist/chunks/grKbdStyles-DAoxiytu.js.map +0 -1
  386. package/dist/chunks/granular-provider-CtrXGa7c.js.map +0 -1
  387. package/dist/chunks/keyboard-zYvvyHd4.js.map +0 -1
  388. package/dist/chunks/optionFilter-BVY988pC.js.map +0 -1
  389. package/dist/chunks/ru-COWxgh2A.js.map +0 -1
  390. package/dist/chunks/useOverlayLayer-BupuP_hs.js.map +0 -1
  391. package/dist/components/GrAutocomplete/chunks/GrAutocomplete-CQ9T7Lly.js.map +0 -1
  392. package/dist/components/GrBreadcrumbs/chunks/GrBreadcrumbs-BCNGDS6k.js.map +0 -1
  393. package/dist/components/GrCommandPalette/chunks/GrCommandPalette-MWDYDPNC.js.map +0 -1
  394. package/dist/components/GrDataTable/chunks/GrDataTable-DVFho9Cj.js.map +0 -1
  395. package/dist/components/GrImageViewer/chunks/GrImageViewer-BeCnE8XQ.js.map +0 -1
  396. package/dist/components/GrInput/chunks/GrInput-DD2gYdqS.js.map +0 -1
  397. package/dist/components/GrInputTag/chunks/GrInputTag-DmNunixz.js.map +0 -1
  398. package/dist/components/GrKbd/chunks/GrKbd-DRFPvW3G.js.map +0 -1
  399. package/dist/components/GrPagination/chunks/GrPagination-B6N0QZBf.js.map +0 -1
  400. package/dist/components/GrProgressBar/chunks/GrProgressBar-BiHnaitu.js.map +0 -1
  401. package/dist/components/GrRadio/chunks/GrRadio-DksDro_U.js.map +0 -1
  402. package/dist/components/GrRadioGroup/chunks/GrRadioGroup-BOIhejE6.js.map +0 -1
  403. package/dist/components/GrRating/chunks/GrRating-JrHXz0Rv.js.map +0 -1
  404. package/dist/components/GrSegmented/chunks/GrSegmented-BQIlH5KI.js.map +0 -1
  405. package/dist/components/GrSelect/chunks/GrSelect-aqkPCqjd.js.map +0 -1
  406. package/dist/components/GrSlider/chunks/GrSlider-DkU9IQSX.js.map +0 -1
  407. package/dist/components/GrSplitter/chunks/GrSplitter-7To8jbJ8.js.map +0 -1
  408. package/dist/components/GrStatistic/chunks/GrStatistic-CttyoYPT.js.map +0 -1
  409. package/dist/components/GrTable/chunks/GrTable-BB-mI_NM.js.map +0 -1
  410. package/dist/components/GrTabs/chunks/GrTabs-B8CDq2D9.js.map +0 -1
  411. package/dist/components/GrToaster/chunks/GrToaster-BKQy3Srm.js.map +0 -1
  412. package/dist/components/GrTree/chunks/GrTree-wfdbvygw.js.map +0 -1
  413. package/dist/components/GrTreeSelect/chunks/GrTreeSelect-lLWmAMtI.js.map +0 -1
  414. package/dist/tokens.js.map +0 -1
  415. package/dist/chunks/{config-8Pcutu1j.js → config-8Pcutu1j2.js} +0 -0
  416. package/dist/chunks/{config-BE6n20np.js → config-BE6n20np2.js} +0 -0
  417. package/dist/chunks/{config-BKvX0q10.js → config-BKvX0q102.js} +0 -0
  418. package/dist/chunks/{config-BoNR7_PD.js → config-BoNR7_PD2.js} +0 -0
  419. package/dist/chunks/{config-CN2ULSQL2.js → config-CN2ULSQL.js} +0 -0
  420. package/dist/chunks/{config-CY0_6cMi.js → config-CY0_6cMi2.js} +0 -0
  421. package/dist/chunks/{config-Rw9OyW70.js → config-Rw9OyW702.js} +0 -0
  422. package/dist/chunks/{config-T3qdQBgU.js → config-T3qdQBgU2.js} +0 -0
  423. package/dist/chunks/{config-eXB87DOi2.js → config-eXB87DOi.js} +0 -0
  424. package/dist/components/GrCollapse/chunks/{GrCollapse-B2Fc6A9r.js → GrCollapse-Kk0DE8tb.js} +1 -1
  425. /package/dist/types/src/composables/{internal/useComboboxNavigation.d.ts → useComboboxNavigation.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"GrSidebar-DRGnnViw.js","names":["$slots"],"sources":["../../../../src/components/GrSidebar/sidebarContext.ts","../../../../src/components/GrSidebar/GrSidebar.vue","../../../../src/components/GrSidebar/GrSidebar.vue","../../../../src/components/GrSidebar/GrSidebarItem.vue","../../../../src/components/GrSidebar/GrSidebarItem.vue","../../../../src/components/GrSidebar/GrSidebarGroup.vue","../../../../src/components/GrSidebar/GrSidebarGroup.vue"],"sourcesContent":["import type { InjectionKey, Ref } from 'vue'\n\n/**\n * Контекст `GrSidebar`, который потребляют `GrSidebarItem`'ы: свёрнута ли панель.\n * В свёрнутом состоянии пункты показывают только иконку (или первую букву метки).\n */\nexport interface GrSidebarContext {\n collapsed: Ref<boolean>\n}\n\nexport const GR_SIDEBAR_KEY: InjectionKey<GrSidebarContext> = Symbol.for('@feugene/granularity/sidebar')\n","<script setup lang=\"ts\">\n/**\n * GrSidebar — боковая панель приложения с опциональным заголовком, кнопкой\n * сворачивания и слотом контента (обычно — список `GrSidebarItem`).\n *\n * - Свёрнутое состояние (`collapsed`, поддерживает `v-model:collapsed`) сужает\n * панель до иконочной ширины; `GrSidebarItem`'ы через inject показывают только\n * иконку (или первую букву метки).\n * - Кнопка тогла (`show-toggle-button`) переключает состояние.\n * - Хедер рендерится только если есть `title`/`subtitle` (или кнопка тогла) —\n * иначе панель начинается сразу с контента.\n * - Слоты `#title` / `#subtitle` имеют приоритет над одноимёнными пропами.\n */\nimport { computed, provide, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport IconChevronLeft from '~icons/lucide/chevron-left'\nimport IconChevronRight from '~icons/lucide/chevron-right'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n contentBase,\n grSidebarCollapseDirection,\n grSidebarRootClass,\n headerBase,\n subtitleClass,\n titleClass,\n type GrSidebarLandmark,\n type GrSidebarPosition,\n} from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport type { GrSidebarLandmark, GrSidebarPosition } from './grSidebarStyles'\n\nexport interface GrSidebarProps {\n title?: string\n subtitle?: string\n /** Свёрнутое состояние. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Показать кнопку сворачивания/разворачивания в хедере. */\n showToggleButton?: boolean\n /** Ширина в развёрнутом состоянии. */\n width?: string\n /** Ширина в свёрнутом состоянии. */\n collapsedWidth?: string\n /** A11y-лейбл кнопки тогла. Не задан — берётся из локали (`gr.sidebar.*`). */\n toggleLabel?: string\n /** Сторона экрана: граница и направление шеврона зеркалятся. */\n position?: GrSidebarPosition\n /**\n * Лендмарк корня. `complementary` (по умолчанию) — `<aside>`; `navigation` —\n * `<nav>` для панели, которая действительно является навигацией. Вложенный\n * `<nav>` внутрь `<aside>` не заводим: два лендмарка на одну панель засоряют\n * обзор, а панель фильтров навигацией не является вовсе.\n */\n landmark?: GrSidebarLandmark\n /** Имя лендмарка: без него две панели на странице неразличимы. */\n ariaLabel?: string\n}\n\nexport interface GrSidebarEmits {\n (e: 'update:collapsed', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrSidebarProps>(), {\n title: undefined,\n subtitle: undefined,\n collapsed: false,\n showToggleButton: false,\n width: '240px',\n collapsedWidth: '64px',\n toggleLabel: undefined,\n position: 'left',\n landmark: 'complementary',\n ariaLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<GrSidebarEmits>()\n\n// Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n// (`v-model:collapsed`), и uncontrolled (панель сама помнит состояние).\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\nfunction toggle(): void {\n collapsedState.value = !collapsedState.value\n emit('update:collapsed', collapsedState.value)\n}\n\n// Даём `GrSidebarItem`'ам знать про свёрнутость.\nprovide(GR_SIDEBAR_KEY, { collapsed: collapsedState })\n\nconst hasTitle = computed(() => Boolean(props.title))\nconst hasSubtitle = computed(() => Boolean(props.subtitle))\nconst showHeader = computed(() => Boolean(hasTitle.value || hasSubtitle.value || props.showToggleButton))\n\nconst asideStyle = computed(() => ({\n width: collapsedState.value ? props.collapsedWidth : props.width,\n}))\n\nconst resolvedToggleLabel = computed(() => props.toggleLabel ?? (collapsedState.value\n ? t('gr.sidebar.expand', 'Expand sidebar')\n : t('gr.sidebar.collapse', 'Collapse sidebar')))\n\nconst rootTag = computed(() => (props.landmark === 'navigation' ? 'nav' : 'aside'))\nconst rootClass = computed(() => grSidebarRootClass(props.position))\n\nconst collapseDirection = computed(() => grSidebarCollapseDirection(props.position, collapsedState.value))\nconst collapseIcon = computed(() => (collapseDirection.value === 'right' ? IconChevronRight : IconChevronLeft))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar\n :data-collapsed=\"collapsedState ? 'true' : undefined\"\n :data-position=\"position\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n :style=\"asideStyle\"\n >\n <div\n v-if=\"showHeader\"\n data-gr-sidebar-header\n :class=\"[headerBase, collapsedState ? 'justify-center' : 'justify-between']\"\n >\n <div\n v-if=\"!collapsedState && (hasTitle || hasSubtitle || $slots.title || $slots.subtitle)\"\n class=\"min-w-0\"\n >\n <div\n v-if=\"$slots.subtitle || hasSubtitle\"\n data-gr-sidebar-subtitle\n :class=\"subtitleClass\"\n >\n <slot name=\"subtitle\">\n {{ subtitle }}\n </slot>\n </div>\n <div\n v-if=\"$slots.title || hasTitle\"\n data-gr-sidebar-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n </div>\n\n <GrButton\n v-if=\"showToggleButton\"\n data-gr-sidebar-toggle\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"resolvedToggleLabel\"\n :aria-expanded=\"collapsedState ? 'false' : 'true'\"\n :data-direction=\"collapseDirection\"\n @click=\"toggle\"\n >\n <GrIcon :size=\"16\">\n <component :is=\"collapseIcon\" />\n </GrIcon>\n </GrButton>\n </div>\n\n <div\n data-gr-sidebar-content\n tabindex=\"0\"\n :class=\"[contentBase, collapsedState ? 'p-2' : 'p-3']\"\n >\n <slot />\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebar — боковая панель приложения с опциональным заголовком, кнопкой\n * сворачивания и слотом контента (обычно — список `GrSidebarItem`).\n *\n * - Свёрнутое состояние (`collapsed`, поддерживает `v-model:collapsed`) сужает\n * панель до иконочной ширины; `GrSidebarItem`'ы через inject показывают только\n * иконку (или первую букву метки).\n * - Кнопка тогла (`show-toggle-button`) переключает состояние.\n * - Хедер рендерится только если есть `title`/`subtitle` (или кнопка тогла) —\n * иначе панель начинается сразу с контента.\n * - Слоты `#title` / `#subtitle` имеют приоритет над одноимёнными пропами.\n */\nimport { computed, provide, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport IconChevronLeft from '~icons/lucide/chevron-left'\nimport IconChevronRight from '~icons/lucide/chevron-right'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n contentBase,\n grSidebarCollapseDirection,\n grSidebarRootClass,\n headerBase,\n subtitleClass,\n titleClass,\n type GrSidebarLandmark,\n type GrSidebarPosition,\n} from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport type { GrSidebarLandmark, GrSidebarPosition } from './grSidebarStyles'\n\nexport interface GrSidebarProps {\n title?: string\n subtitle?: string\n /** Свёрнутое состояние. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Показать кнопку сворачивания/разворачивания в хедере. */\n showToggleButton?: boolean\n /** Ширина в развёрнутом состоянии. */\n width?: string\n /** Ширина в свёрнутом состоянии. */\n collapsedWidth?: string\n /** A11y-лейбл кнопки тогла. Не задан — берётся из локали (`gr.sidebar.*`). */\n toggleLabel?: string\n /** Сторона экрана: граница и направление шеврона зеркалятся. */\n position?: GrSidebarPosition\n /**\n * Лендмарк корня. `complementary` (по умолчанию) — `<aside>`; `navigation` —\n * `<nav>` для панели, которая действительно является навигацией. Вложенный\n * `<nav>` внутрь `<aside>` не заводим: два лендмарка на одну панель засоряют\n * обзор, а панель фильтров навигацией не является вовсе.\n */\n landmark?: GrSidebarLandmark\n /** Имя лендмарка: без него две панели на странице неразличимы. */\n ariaLabel?: string\n}\n\nexport interface GrSidebarEmits {\n (e: 'update:collapsed', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrSidebarProps>(), {\n title: undefined,\n subtitle: undefined,\n collapsed: false,\n showToggleButton: false,\n width: '240px',\n collapsedWidth: '64px',\n toggleLabel: undefined,\n position: 'left',\n landmark: 'complementary',\n ariaLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<GrSidebarEmits>()\n\n// Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n// (`v-model:collapsed`), и uncontrolled (панель сама помнит состояние).\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\nfunction toggle(): void {\n collapsedState.value = !collapsedState.value\n emit('update:collapsed', collapsedState.value)\n}\n\n// Даём `GrSidebarItem`'ам знать про свёрнутость.\nprovide(GR_SIDEBAR_KEY, { collapsed: collapsedState })\n\nconst hasTitle = computed(() => Boolean(props.title))\nconst hasSubtitle = computed(() => Boolean(props.subtitle))\nconst showHeader = computed(() => Boolean(hasTitle.value || hasSubtitle.value || props.showToggleButton))\n\nconst asideStyle = computed(() => ({\n width: collapsedState.value ? props.collapsedWidth : props.width,\n}))\n\nconst resolvedToggleLabel = computed(() => props.toggleLabel ?? (collapsedState.value\n ? t('gr.sidebar.expand', 'Expand sidebar')\n : t('gr.sidebar.collapse', 'Collapse sidebar')))\n\nconst rootTag = computed(() => (props.landmark === 'navigation' ? 'nav' : 'aside'))\nconst rootClass = computed(() => grSidebarRootClass(props.position))\n\nconst collapseDirection = computed(() => grSidebarCollapseDirection(props.position, collapsedState.value))\nconst collapseIcon = computed(() => (collapseDirection.value === 'right' ? IconChevronRight : IconChevronLeft))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar\n :data-collapsed=\"collapsedState ? 'true' : undefined\"\n :data-position=\"position\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n :style=\"asideStyle\"\n >\n <div\n v-if=\"showHeader\"\n data-gr-sidebar-header\n :class=\"[headerBase, collapsedState ? 'justify-center' : 'justify-between']\"\n >\n <div\n v-if=\"!collapsedState && (hasTitle || hasSubtitle || $slots.title || $slots.subtitle)\"\n class=\"min-w-0\"\n >\n <div\n v-if=\"$slots.subtitle || hasSubtitle\"\n data-gr-sidebar-subtitle\n :class=\"subtitleClass\"\n >\n <slot name=\"subtitle\">\n {{ subtitle }}\n </slot>\n </div>\n <div\n v-if=\"$slots.title || hasTitle\"\n data-gr-sidebar-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n </div>\n\n <GrButton\n v-if=\"showToggleButton\"\n data-gr-sidebar-toggle\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"resolvedToggleLabel\"\n :aria-expanded=\"collapsedState ? 'false' : 'true'\"\n :data-direction=\"collapseDirection\"\n @click=\"toggle\"\n >\n <GrIcon :size=\"16\">\n <component :is=\"collapseIcon\" />\n </GrIcon>\n </GrButton>\n </div>\n\n <div\n data-gr-sidebar-content\n tabindex=\"0\"\n :class=\"[contentBase, collapsedState ? 'p-2' : 'p-3']\"\n >\n <slot />\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarItem — пункт навигации боковой панели `GrSidebar`.\n *\n * Контракт:\n * - развёрнутая панель — `[иконка] метка [бейдж]`;\n * - свёрнутая панель — только иконка; если иконки нет, показывается ПЕРВАЯ БУКВА\n * метки (uppercase). В свёрнутом виде метка уходит в `title`/`aria-label` для\n * доступности и tooltip.\n *\n * Корневой тег: `as` → `<a href>` → `<button>` (в этом порядке).\n */\nimport { computed, inject, markRaw, type Component } from 'vue'\n\nimport { grSidebarItemClass, itemBadgeClass, itemLetterClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarItemProps {\n label: string\n /** Иконка: класс UnoCSS-иконки (`'i-lucide-home'`) или Vue-компонент. */\n icon?: string | Component\n href?: string\n as?: string | Component\n active?: boolean\n disabled?: boolean\n badge?: string | number\n}\n\nconst props = withDefaults(defineProps<GrSidebarItemProps>(), {\n icon: undefined,\n href: undefined,\n as: undefined,\n active: false,\n disabled: false,\n badge: undefined,\n})\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst isStringIcon = computed(() => typeof props.icon === 'string')\nconst iconComponent = computed(() => (props.icon && typeof props.icon !== 'string' ? markRaw(props.icon as Component) : null))\nconst firstLetter = computed(() => props.label.trim().charAt(0).toUpperCase() || '•')\n\nconst rootTag = computed<string | Component>(() => {\n if (props.disabled) return 'span'\n if (props.as) return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\nconst rootClass = computed(() => grSidebarItemClass({\n collapsed: collapsed.value,\n disabled: props.disabled,\n active: props.active,\n}))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar-item\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootTag === 'a' ? href : undefined\"\n :aria-current=\"active ? 'page' : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :title=\"collapsed ? label : undefined\"\n :aria-label=\"collapsed ? label : undefined\"\n :class=\"rootClass\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center\">\n <component :is=\"iconComponent\" v-if=\"iconComponent\" class=\"h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"isStringIcon\" :class=\"icon\" class=\"block h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"collapsed\" :class=\"itemLetterClass\" aria-hidden=\"true\">{{ firstLetter }}</span>\n </span>\n\n <template v-if=\"!collapsed\">\n <span class=\"min-w-0 flex-1 truncate text-left\">{{ label }}</span>\n <span v-if=\"badge != null\" :class=\"itemBadgeClass\">{{ badge }}</span>\n </template>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarItem — пункт навигации боковой панели `GrSidebar`.\n *\n * Контракт:\n * - развёрнутая панель — `[иконка] метка [бейдж]`;\n * - свёрнутая панель — только иконка; если иконки нет, показывается ПЕРВАЯ БУКВА\n * метки (uppercase). В свёрнутом виде метка уходит в `title`/`aria-label` для\n * доступности и tooltip.\n *\n * Корневой тег: `as` → `<a href>` → `<button>` (в этом порядке).\n */\nimport { computed, inject, markRaw, type Component } from 'vue'\n\nimport { grSidebarItemClass, itemBadgeClass, itemLetterClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarItemProps {\n label: string\n /** Иконка: класс UnoCSS-иконки (`'i-lucide-home'`) или Vue-компонент. */\n icon?: string | Component\n href?: string\n as?: string | Component\n active?: boolean\n disabled?: boolean\n badge?: string | number\n}\n\nconst props = withDefaults(defineProps<GrSidebarItemProps>(), {\n icon: undefined,\n href: undefined,\n as: undefined,\n active: false,\n disabled: false,\n badge: undefined,\n})\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst isStringIcon = computed(() => typeof props.icon === 'string')\nconst iconComponent = computed(() => (props.icon && typeof props.icon !== 'string' ? markRaw(props.icon as Component) : null))\nconst firstLetter = computed(() => props.label.trim().charAt(0).toUpperCase() || '•')\n\nconst rootTag = computed<string | Component>(() => {\n if (props.disabled) return 'span'\n if (props.as) return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\nconst rootClass = computed(() => grSidebarItemClass({\n collapsed: collapsed.value,\n disabled: props.disabled,\n active: props.active,\n}))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar-item\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootTag === 'a' ? href : undefined\"\n :aria-current=\"active ? 'page' : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :title=\"collapsed ? label : undefined\"\n :aria-label=\"collapsed ? label : undefined\"\n :class=\"rootClass\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center\">\n <component :is=\"iconComponent\" v-if=\"iconComponent\" class=\"h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"isStringIcon\" :class=\"icon\" class=\"block h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"collapsed\" :class=\"itemLetterClass\" aria-hidden=\"true\">{{ firstLetter }}</span>\n </span>\n\n <template v-if=\"!collapsed\">\n <span class=\"min-w-0 flex-1 truncate text-left\">{{ label }}</span>\n <span v-if=\"badge != null\" :class=\"itemBadgeClass\">{{ badge }}</span>\n </template>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarGroup — секция пунктов `GrSidebar` с заголовком.\n *\n * В свёрнутой панели заголовку негде поместиться: он скрывается, а секции\n * разделяет линия — без неё иконки соседних секций сливаются в один столбец.\n */\nimport { computed, inject, useId } from 'vue'\n\nimport { groupCollapsedClass, groupLabelClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarGroupProps {\n /** Заголовок секции. Слот `#label` сильнее. */\n label?: string\n}\n\nconst props = withDefaults(defineProps<GrSidebarGroupProps>(), {\n label: undefined,\n})\n\nconst slots = defineSlots<{\n /** Пункты секции. */\n default?: () => unknown\n /** Заголовок целиком — вместо строки `label`. */\n label?: () => unknown\n}>()\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(props.label || slots.label))\n\n// Имя группе даёт только видимый заголовок: в свёрнутом виде его нет, и\n// `aria-labelledby` указывал бы в пустоту.\nconst showLabel = computed(() => hasLabel.value && !collapsed.value)\n</script>\n\n<template>\n <div\n data-gr-sidebar-group\n role=\"group\"\n :aria-labelledby=\"showLabel ? labelId : undefined\"\n :class=\"collapsed ? groupCollapsedClass : undefined\"\n >\n <div\n v-if=\"showLabel\"\n :id=\"labelId\"\n data-gr-sidebar-group-label\n :class=\"groupLabelClass\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </div>\n\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarGroup — секция пунктов `GrSidebar` с заголовком.\n *\n * В свёрнутой панели заголовку негде поместиться: он скрывается, а секции\n * разделяет линия — без неё иконки соседних секций сливаются в один столбец.\n */\nimport { computed, inject, useId } from 'vue'\n\nimport { groupCollapsedClass, groupLabelClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarGroupProps {\n /** Заголовок секции. Слот `#label` сильнее. */\n label?: string\n}\n\nconst props = withDefaults(defineProps<GrSidebarGroupProps>(), {\n label: undefined,\n})\n\nconst slots = defineSlots<{\n /** Пункты секции. */\n default?: () => unknown\n /** Заголовок целиком — вместо строки `label`. */\n label?: () => unknown\n}>()\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(props.label || slots.label))\n\n// Имя группе даёт только видимый заголовок: в свёрнутом виде его нет, и\n// `aria-labelledby` указывал бы в пустоту.\nconst showLabel = computed(() => hasLabel.value && !collapsed.value)\n</script>\n\n<template>\n <div\n data-gr-sidebar-group\n role=\"group\"\n :aria-labelledby=\"showLabel ? labelId : undefined\"\n :class=\"collapsed ? groupCollapsedClass : undefined\"\n >\n <div\n v-if=\"showLabel\"\n :id=\"labelId\"\n data-gr-sidebar-group-label\n :class=\"groupLabelClass\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </div>\n\n <slot />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"GrSidebar-i7AxjhY_.js","names":["$slots"],"sources":["../../../../src/components/GrSidebar/sidebarContext.ts","../../../../src/components/GrSidebar/GrSidebar.vue","../../../../src/components/GrSidebar/GrSidebar.vue","../../../../src/components/GrSidebar/GrSidebarItem.vue","../../../../src/components/GrSidebar/GrSidebarItem.vue","../../../../src/components/GrSidebar/GrSidebarGroup.vue","../../../../src/components/GrSidebar/GrSidebarGroup.vue"],"sourcesContent":["import type { InjectionKey, Ref } from 'vue'\n\n/**\n * Контекст `GrSidebar`, который потребляют `GrSidebarItem`'ы: свёрнута ли панель.\n * В свёрнутом состоянии пункты показывают только иконку (или первую букву метки).\n */\nexport interface GrSidebarContext {\n collapsed: Ref<boolean>\n}\n\nexport const GR_SIDEBAR_KEY: InjectionKey<GrSidebarContext> = Symbol.for('@feugene/granularity/sidebar')\n","<script setup lang=\"ts\">\n/**\n * GrSidebar — боковая панель приложения с опциональным заголовком, кнопкой\n * сворачивания и слотом контента (обычно — список `GrSidebarItem`).\n *\n * - Свёрнутое состояние (`collapsed`, поддерживает `v-model:collapsed`) сужает\n * панель до иконочной ширины; `GrSidebarItem`'ы через inject показывают только\n * иконку (или первую букву метки).\n * - Кнопка тогла (`show-toggle-button`) переключает состояние.\n * - Хедер рендерится только если есть `title`/`subtitle` (или кнопка тогла) —\n * иначе панель начинается сразу с контента.\n * - Слоты `#title` / `#subtitle` имеют приоритет над одноимёнными пропами.\n */\nimport { computed, provide, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport IconChevronLeft from '~icons/lucide/chevron-left'\nimport IconChevronRight from '~icons/lucide/chevron-right'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n contentBase,\n grSidebarCollapseDirection,\n grSidebarRootClass,\n headerBase,\n subtitleClass,\n titleClass,\n type GrSidebarLandmark,\n type GrSidebarPosition,\n} from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport type { GrSidebarLandmark, GrSidebarPosition } from './grSidebarStyles'\n\nexport interface GrSidebarProps {\n title?: string\n subtitle?: string\n /** Свёрнутое состояние. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Показать кнопку сворачивания/разворачивания в хедере. */\n showToggleButton?: boolean\n /** Ширина в развёрнутом состоянии. */\n width?: string\n /** Ширина в свёрнутом состоянии. */\n collapsedWidth?: string\n /** A11y-лейбл кнопки тогла. Не задан — берётся из локали (`gr.sidebar.*`). */\n toggleLabel?: string\n /** Сторона экрана: граница и направление шеврона зеркалятся. */\n position?: GrSidebarPosition\n /**\n * Лендмарк корня. `complementary` (по умолчанию) — `<aside>`; `navigation` —\n * `<nav>` для панели, которая действительно является навигацией. Вложенный\n * `<nav>` внутрь `<aside>` не заводим: два лендмарка на одну панель засоряют\n * обзор, а панель фильтров навигацией не является вовсе.\n */\n landmark?: GrSidebarLandmark\n /** Имя лендмарка: без него две панели на странице неразличимы. */\n ariaLabel?: string\n}\n\nexport interface GrSidebarEmits {\n (e: 'update:collapsed', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrSidebarProps>(), {\n title: undefined,\n subtitle: undefined,\n collapsed: false,\n showToggleButton: false,\n width: '240px',\n collapsedWidth: '64px',\n toggleLabel: undefined,\n position: 'left',\n landmark: 'complementary',\n ariaLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<GrSidebarEmits>()\n\n// Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n// (`v-model:collapsed`), и uncontrolled (панель сама помнит состояние).\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\nfunction toggle(): void {\n collapsedState.value = !collapsedState.value\n emit('update:collapsed', collapsedState.value)\n}\n\n// Даём `GrSidebarItem`'ам знать про свёрнутость.\nprovide(GR_SIDEBAR_KEY, { collapsed: collapsedState })\n\nconst hasTitle = computed(() => Boolean(props.title))\nconst hasSubtitle = computed(() => Boolean(props.subtitle))\nconst showHeader = computed(() => Boolean(hasTitle.value || hasSubtitle.value || props.showToggleButton))\n\nconst asideStyle = computed(() => ({\n width: collapsedState.value ? props.collapsedWidth : props.width,\n}))\n\nconst resolvedToggleLabel = computed(() => props.toggleLabel ?? (collapsedState.value\n ? t('gr.sidebar.expand', 'Expand sidebar')\n : t('gr.sidebar.collapse', 'Collapse sidebar')))\n\nconst rootTag = computed(() => (props.landmark === 'navigation' ? 'nav' : 'aside'))\nconst rootClass = computed(() => grSidebarRootClass(props.position))\n\nconst collapseDirection = computed(() => grSidebarCollapseDirection(props.position, collapsedState.value))\nconst collapseIcon = computed(() => (collapseDirection.value === 'right' ? IconChevronRight : IconChevronLeft))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar\n :data-collapsed=\"collapsedState ? 'true' : undefined\"\n :data-position=\"position\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n :style=\"asideStyle\"\n >\n <div\n v-if=\"showHeader\"\n data-gr-sidebar-header\n :class=\"[headerBase, collapsedState ? 'justify-center' : 'justify-between']\"\n >\n <div\n v-if=\"!collapsedState && (hasTitle || hasSubtitle || $slots.title || $slots.subtitle)\"\n class=\"min-w-0\"\n >\n <div\n v-if=\"$slots.subtitle || hasSubtitle\"\n data-gr-sidebar-subtitle\n :class=\"subtitleClass\"\n >\n <slot name=\"subtitle\">\n {{ subtitle }}\n </slot>\n </div>\n <div\n v-if=\"$slots.title || hasTitle\"\n data-gr-sidebar-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n </div>\n\n <GrButton\n v-if=\"showToggleButton\"\n data-gr-sidebar-toggle\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"resolvedToggleLabel\"\n :aria-expanded=\"collapsedState ? 'false' : 'true'\"\n :data-direction=\"collapseDirection\"\n @click=\"toggle\"\n >\n <GrIcon :size=\"16\">\n <component :is=\"collapseIcon\" />\n </GrIcon>\n </GrButton>\n </div>\n\n <div\n data-gr-sidebar-content\n tabindex=\"0\"\n :class=\"[contentBase, collapsedState ? 'p-2' : 'p-3']\"\n >\n <slot />\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebar — боковая панель приложения с опциональным заголовком, кнопкой\n * сворачивания и слотом контента (обычно — список `GrSidebarItem`).\n *\n * - Свёрнутое состояние (`collapsed`, поддерживает `v-model:collapsed`) сужает\n * панель до иконочной ширины; `GrSidebarItem`'ы через inject показывают только\n * иконку (или первую букву метки).\n * - Кнопка тогла (`show-toggle-button`) переключает состояние.\n * - Хедер рендерится только если есть `title`/`subtitle` (или кнопка тогла) —\n * иначе панель начинается сразу с контента.\n * - Слоты `#title` / `#subtitle` имеют приоритет над одноимёнными пропами.\n */\nimport { computed, provide, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport IconChevronLeft from '~icons/lucide/chevron-left'\nimport IconChevronRight from '~icons/lucide/chevron-right'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n contentBase,\n grSidebarCollapseDirection,\n grSidebarRootClass,\n headerBase,\n subtitleClass,\n titleClass,\n type GrSidebarLandmark,\n type GrSidebarPosition,\n} from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport type { GrSidebarLandmark, GrSidebarPosition } from './grSidebarStyles'\n\nexport interface GrSidebarProps {\n title?: string\n subtitle?: string\n /** Свёрнутое состояние. Поддерживает `v-model:collapsed`. */\n collapsed?: boolean\n /** Показать кнопку сворачивания/разворачивания в хедере. */\n showToggleButton?: boolean\n /** Ширина в развёрнутом состоянии. */\n width?: string\n /** Ширина в свёрнутом состоянии. */\n collapsedWidth?: string\n /** A11y-лейбл кнопки тогла. Не задан — берётся из локали (`gr.sidebar.*`). */\n toggleLabel?: string\n /** Сторона экрана: граница и направление шеврона зеркалятся. */\n position?: GrSidebarPosition\n /**\n * Лендмарк корня. `complementary` (по умолчанию) — `<aside>`; `navigation` —\n * `<nav>` для панели, которая действительно является навигацией. Вложенный\n * `<nav>` внутрь `<aside>` не заводим: два лендмарка на одну панель засоряют\n * обзор, а панель фильтров навигацией не является вовсе.\n */\n landmark?: GrSidebarLandmark\n /** Имя лендмарка: без него две панели на странице неразличимы. */\n ariaLabel?: string\n}\n\nexport interface GrSidebarEmits {\n (e: 'update:collapsed', value: boolean): void\n}\n\nconst props = withDefaults(defineProps<GrSidebarProps>(), {\n title: undefined,\n subtitle: undefined,\n collapsed: false,\n showToggleButton: false,\n width: '240px',\n collapsedWidth: '64px',\n toggleLabel: undefined,\n position: 'left',\n landmark: 'complementary',\n ariaLabel: undefined,\n})\n\nconst { t } = useGranularityTranslations()\n\nconst emit = defineEmits<GrSidebarEmits>()\n\n// Локальное состояние с синхронизацией из пропа — поддерживает и controlled\n// (`v-model:collapsed`), и uncontrolled (панель сама помнит состояние).\nconst collapsedState = ref(props.collapsed)\nwatch(() => props.collapsed, value => (collapsedState.value = value))\n\nfunction toggle(): void {\n collapsedState.value = !collapsedState.value\n emit('update:collapsed', collapsedState.value)\n}\n\n// Даём `GrSidebarItem`'ам знать про свёрнутость.\nprovide(GR_SIDEBAR_KEY, { collapsed: collapsedState })\n\nconst hasTitle = computed(() => Boolean(props.title))\nconst hasSubtitle = computed(() => Boolean(props.subtitle))\nconst showHeader = computed(() => Boolean(hasTitle.value || hasSubtitle.value || props.showToggleButton))\n\nconst asideStyle = computed(() => ({\n width: collapsedState.value ? props.collapsedWidth : props.width,\n}))\n\nconst resolvedToggleLabel = computed(() => props.toggleLabel ?? (collapsedState.value\n ? t('gr.sidebar.expand', 'Expand sidebar')\n : t('gr.sidebar.collapse', 'Collapse sidebar')))\n\nconst rootTag = computed(() => (props.landmark === 'navigation' ? 'nav' : 'aside'))\nconst rootClass = computed(() => grSidebarRootClass(props.position))\n\nconst collapseDirection = computed(() => grSidebarCollapseDirection(props.position, collapsedState.value))\nconst collapseIcon = computed(() => (collapseDirection.value === 'right' ? IconChevronRight : IconChevronLeft))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar\n :data-collapsed=\"collapsedState ? 'true' : undefined\"\n :data-position=\"position\"\n :aria-label=\"ariaLabel\"\n :class=\"rootClass\"\n :style=\"asideStyle\"\n >\n <div\n v-if=\"showHeader\"\n data-gr-sidebar-header\n :class=\"[headerBase, collapsedState ? 'justify-center' : 'justify-between']\"\n >\n <div\n v-if=\"!collapsedState && (hasTitle || hasSubtitle || $slots.title || $slots.subtitle)\"\n class=\"min-w-0\"\n >\n <div\n v-if=\"$slots.subtitle || hasSubtitle\"\n data-gr-sidebar-subtitle\n :class=\"subtitleClass\"\n >\n <slot name=\"subtitle\">\n {{ subtitle }}\n </slot>\n </div>\n <div\n v-if=\"$slots.title || hasTitle\"\n data-gr-sidebar-title\n :class=\"titleClass\"\n >\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n </div>\n\n <GrButton\n v-if=\"showToggleButton\"\n data-gr-sidebar-toggle\n variant=\"ghost\"\n size=\"sm\"\n square\n :aria-label=\"resolvedToggleLabel\"\n :aria-expanded=\"collapsedState ? 'false' : 'true'\"\n :data-direction=\"collapseDirection\"\n @click=\"toggle\"\n >\n <GrIcon :size=\"16\">\n <component :is=\"collapseIcon\" />\n </GrIcon>\n </GrButton>\n </div>\n\n <div\n data-gr-sidebar-content\n tabindex=\"0\"\n :class=\"[contentBase, collapsedState ? 'p-2' : 'p-3']\"\n >\n <slot />\n </div>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarItem — пункт навигации боковой панели `GrSidebar`.\n *\n * Контракт:\n * - развёрнутая панель — `[иконка] метка [бейдж]`;\n * - свёрнутая панель — только иконка; если иконки нет, показывается ПЕРВАЯ БУКВА\n * метки (uppercase). В свёрнутом виде метка уходит в `title`/`aria-label` для\n * доступности и tooltip.\n *\n * Корневой тег: `as` → `<a href>` → `<button>` (в этом порядке).\n */\nimport { computed, inject, markRaw, type Component } from 'vue'\n\nimport { grSidebarItemClass, itemBadgeClass, itemLetterClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarItemProps {\n label: string\n /** Иконка: класс UnoCSS-иконки (`'i-lucide-home'`) или Vue-компонент. */\n icon?: string | Component\n href?: string\n as?: string | Component\n active?: boolean\n disabled?: boolean\n badge?: string | number\n}\n\nconst props = withDefaults(defineProps<GrSidebarItemProps>(), {\n icon: undefined,\n href: undefined,\n as: undefined,\n active: false,\n disabled: false,\n badge: undefined,\n})\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst isStringIcon = computed(() => typeof props.icon === 'string')\nconst iconComponent = computed(() => (props.icon && typeof props.icon !== 'string' ? markRaw(props.icon as Component) : null))\nconst firstLetter = computed(() => props.label.trim().charAt(0).toUpperCase() || '•')\n\nconst rootTag = computed<string | Component>(() => {\n if (props.disabled) return 'span'\n if (props.as) return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\nconst rootClass = computed(() => grSidebarItemClass({\n collapsed: collapsed.value,\n disabled: props.disabled,\n active: props.active,\n}))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar-item\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootTag === 'a' ? href : undefined\"\n :aria-current=\"active ? 'page' : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :title=\"collapsed ? label : undefined\"\n :aria-label=\"collapsed ? label : undefined\"\n :class=\"rootClass\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center\">\n <component :is=\"iconComponent\" v-if=\"iconComponent\" class=\"h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"isStringIcon\" :class=\"icon\" class=\"block h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"collapsed\" :class=\"itemLetterClass\" aria-hidden=\"true\">{{ firstLetter }}</span>\n </span>\n\n <template v-if=\"!collapsed\">\n <span class=\"min-w-0 flex-1 truncate text-left\">{{ label }}</span>\n <span v-if=\"badge != null\" :class=\"itemBadgeClass\">{{ badge }}</span>\n </template>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarItem — пункт навигации боковой панели `GrSidebar`.\n *\n * Контракт:\n * - развёрнутая панель — `[иконка] метка [бейдж]`;\n * - свёрнутая панель — только иконка; если иконки нет, показывается ПЕРВАЯ БУКВА\n * метки (uppercase). В свёрнутом виде метка уходит в `title`/`aria-label` для\n * доступности и tooltip.\n *\n * Корневой тег: `as` → `<a href>` → `<button>` (в этом порядке).\n */\nimport { computed, inject, markRaw, type Component } from 'vue'\n\nimport { grSidebarItemClass, itemBadgeClass, itemLetterClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarItemProps {\n label: string\n /** Иконка: класс UnoCSS-иконки (`'i-lucide-home'`) или Vue-компонент. */\n icon?: string | Component\n href?: string\n as?: string | Component\n active?: boolean\n disabled?: boolean\n badge?: string | number\n}\n\nconst props = withDefaults(defineProps<GrSidebarItemProps>(), {\n icon: undefined,\n href: undefined,\n as: undefined,\n active: false,\n disabled: false,\n badge: undefined,\n})\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst isStringIcon = computed(() => typeof props.icon === 'string')\nconst iconComponent = computed(() => (props.icon && typeof props.icon !== 'string' ? markRaw(props.icon as Component) : null))\nconst firstLetter = computed(() => props.label.trim().charAt(0).toUpperCase() || '•')\n\nconst rootTag = computed<string | Component>(() => {\n if (props.disabled) return 'span'\n if (props.as) return typeof props.as === 'string' ? props.as : markRaw(props.as)\n return props.href ? 'a' : 'button'\n})\n\nconst rootClass = computed(() => grSidebarItemClass({\n collapsed: collapsed.value,\n disabled: props.disabled,\n active: props.active,\n}))\n</script>\n\n<template>\n <component\n :is=\"rootTag\"\n data-gr-sidebar-item\n :type=\"rootTag === 'button' ? 'button' : undefined\"\n :href=\"rootTag === 'a' ? href : undefined\"\n :aria-current=\"active ? 'page' : undefined\"\n :aria-disabled=\"disabled ? 'true' : undefined\"\n :title=\"collapsed ? label : undefined\"\n :aria-label=\"collapsed ? label : undefined\"\n :class=\"rootClass\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center\">\n <component :is=\"iconComponent\" v-if=\"iconComponent\" class=\"h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"isStringIcon\" :class=\"icon\" class=\"block h-5 w-5\" aria-hidden=\"true\" />\n <span v-else-if=\"collapsed\" :class=\"itemLetterClass\" aria-hidden=\"true\">{{ firstLetter }}</span>\n </span>\n\n <template v-if=\"!collapsed\">\n <span class=\"min-w-0 flex-1 truncate text-left\">{{ label }}</span>\n <span v-if=\"badge != null\" :class=\"itemBadgeClass\">{{ badge }}</span>\n </template>\n </component>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarGroup — секция пунктов `GrSidebar` с заголовком.\n *\n * В свёрнутой панели заголовку негде поместиться: он скрывается, а секции\n * разделяет линия — без неё иконки соседних секций сливаются в один столбец.\n */\nimport { computed, inject, useId } from 'vue'\n\nimport { groupCollapsedClass, groupLabelClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarGroupProps {\n /** Заголовок секции. Слот `#label` сильнее. */\n label?: string\n}\n\nconst props = withDefaults(defineProps<GrSidebarGroupProps>(), {\n label: undefined,\n})\n\nconst slots = defineSlots<{\n /** Пункты секции. */\n default?: () => unknown\n /** Заголовок целиком — вместо строки `label`. */\n label?: () => unknown\n}>()\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(props.label || slots.label))\n\n// Имя группе даёт только видимый заголовок: в свёрнутом виде его нет, и\n// `aria-labelledby` указывал бы в пустоту.\nconst showLabel = computed(() => hasLabel.value && !collapsed.value)\n</script>\n\n<template>\n <div\n data-gr-sidebar-group\n role=\"group\"\n :aria-labelledby=\"showLabel ? labelId : undefined\"\n :class=\"collapsed ? groupCollapsedClass : undefined\"\n >\n <div\n v-if=\"showLabel\"\n :id=\"labelId\"\n data-gr-sidebar-group-label\n :class=\"groupLabelClass\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </div>\n\n <slot />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrSidebarGroup — секция пунктов `GrSidebar` с заголовком.\n *\n * В свёрнутой панели заголовку негде поместиться: он скрывается, а секции\n * разделяет линия — без неё иконки соседних секций сливаются в один столбец.\n */\nimport { computed, inject, useId } from 'vue'\n\nimport { groupCollapsedClass, groupLabelClass } from './grSidebarStyles'\nimport { GR_SIDEBAR_KEY } from './sidebarContext'\n\nexport interface GrSidebarGroupProps {\n /** Заголовок секции. Слот `#label` сильнее. */\n label?: string\n}\n\nconst props = withDefaults(defineProps<GrSidebarGroupProps>(), {\n label: undefined,\n})\n\nconst slots = defineSlots<{\n /** Пункты секции. */\n default?: () => unknown\n /** Заголовок целиком — вместо строки `label`. */\n label?: () => unknown\n}>()\n\nconst sidebar = inject(GR_SIDEBAR_KEY, null)\nconst collapsed = computed(() => sidebar?.collapsed.value ?? false)\n\nconst labelId = useId()\nconst hasLabel = computed(() => Boolean(props.label || slots.label))\n\n// Имя группе даёт только видимый заголовок: в свёрнутом виде его нет, и\n// `aria-labelledby` указывал бы в пустоту.\nconst showLabel = computed(() => hasLabel.value && !collapsed.value)\n</script>\n\n<template>\n <div\n data-gr-sidebar-group\n role=\"group\"\n :aria-labelledby=\"showLabel ? labelId : undefined\"\n :class=\"collapsed ? groupCollapsedClass : undefined\"\n >\n <div\n v-if=\"showLabel\"\n :id=\"labelId\"\n data-gr-sidebar-group-label\n :class=\"groupLabelClass\"\n >\n <slot name=\"label\">\n {{ label }}\n </slot>\n </div>\n\n <slot />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { i as GR_SIDEBAR_POSITIONS, n as grSidebarSafelist, r as GR_SIDEBAR_LANDMARKS, t as grSidebarConfig } from "../../chunks/config-Rw9OyW70.js";
2
- import { n as GrSidebarItem_default, r as GrSidebar_default, t as GrSidebarGroup_default } from "./chunks/GrSidebar-DRGnnViw.js";
1
+ import { i as GR_SIDEBAR_POSITIONS, n as grSidebarSafelist, r as GR_SIDEBAR_LANDMARKS, t as grSidebarConfig } from "../../chunks/config-Rw9OyW702.js";
2
+ import { n as GrSidebarItem_default, r as GrSidebar_default, t as GrSidebarGroup_default } from "./chunks/GrSidebar-i7AxjhY_.js";
3
3
  export { GR_SIDEBAR_LANDMARKS, GR_SIDEBAR_POSITIONS, GrSidebar_default as GrSidebar, GrSidebar_default as default, GrSidebarGroup_default as GrSidebarGroup, GrSidebarItem_default as GrSidebarItem, grSidebarConfig, grSidebarSafelist };
@@ -1,3 +1,3 @@
1
1
  import { n as GR_SKELETON_VARIANTS, t as GrSkeleton_default } from "./chunks/GrSkeleton-DEvNE3bC.js";
2
- import { t as grSkeletonConfig } from "../../chunks/config-8Pcutu1j.js";
2
+ import { t as grSkeletonConfig } from "../../chunks/config-8Pcutu1j2.js";
3
3
  export { GR_SKELETON_VARIANTS, GrSkeleton_default as GrSkeleton, GrSkeleton_default as default, grSkeletonConfig };
@@ -3,8 +3,9 @@ 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 useFocusWithin } from "../../../chunks/useFocusWithin-BwHE0rzm.js";
6
+ import { useDragGesture } from "../../../composables/useDragGesture.js";
6
7
  import { A as sliderTrackVerticalLengthClass, D as sliderTooltipClass, a as sliderFillOrientationClass, f as sliderMarkTickClass, g as sliderRailClass, j as sliderTrackWidthBySize, k as sliderTrackHeightBySize, n as sliderFillClass, s as sliderMarkLabelClassFor, v as sliderRootClass, x as sliderThumbClass } from "../../../chunks/grSliderStyles-B5uNxNJq.js";
7
- import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, toDisplayString, unref } from "vue";
8
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, ref, renderList, toDisplayString, unref } from "vue";
8
9
  //#region src/components/GrSlider/GrSlider.vue?vue&type=script&setup=true&lang.ts
9
10
  var _hoisted_1 = ["data-orientation"];
10
11
  var _hoisted_2 = ["name", "value"];
@@ -207,23 +208,6 @@ var GrSlider_default = /* @__PURE__ */ defineComponent({
207
208
  if (value > hi) return 1;
208
209
  return Math.abs(value - lo) < Math.abs(value - hi) ? 0 : 1;
209
210
  }
210
- function onTrackPointerDown(event) {
211
- if (isDisabled.value || isReadonly.value) return;
212
- if (event.button !== 0) return;
213
- const value = valueFromPointer(event);
214
- const index = nearestThumb(value);
215
- activeThumb.value = index;
216
- thumbEls.value[index]?.focus();
217
- setThumb(index, value, false);
218
- window.addEventListener("pointermove", onPointerMove);
219
- window.addEventListener("pointerup", onPointerUp);
220
- window.addEventListener("pointercancel", onPointerCancel);
221
- }
222
- function onPointerMove(event) {
223
- if (activeThumb.value === null) return;
224
- event.preventDefault();
225
- setThumb(activeThumb.value, valueFromPointer(event), false);
226
- }
227
211
  function endDrag(commit) {
228
212
  if (activeThumb.value !== null && commit) {
229
213
  const next = values.value.slice();
@@ -232,20 +216,23 @@ var GrSlider_default = /* @__PURE__ */ defineComponent({
232
216
  }
233
217
  draftValues.value = null;
234
218
  activeThumb.value = null;
235
- window.removeEventListener("pointermove", onPointerMove);
236
- window.removeEventListener("pointerup", onPointerUp);
237
- window.removeEventListener("pointercancel", onPointerCancel);
238
- }
239
- function onPointerUp() {
240
- endDrag(true);
241
- }
242
- function onPointerCancel() {
243
- endDrag(false);
244
219
  }
245
- onBeforeUnmount(() => {
246
- window.removeEventListener("pointermove", onPointerMove);
247
- window.removeEventListener("pointerup", onPointerUp);
248
- window.removeEventListener("pointercancel", onPointerCancel);
220
+ const drag = useDragGesture({
221
+ disabled: () => isDisabled.value || isReadonly.value,
222
+ onStart: (event) => {
223
+ const value = valueFromPointer(event);
224
+ const index = nearestThumb(value);
225
+ activeThumb.value = index;
226
+ thumbEls.value[index]?.focus();
227
+ setThumb(index, value, false);
228
+ },
229
+ onMove: (event) => {
230
+ if (activeThumb.value === null) return;
231
+ event.preventDefault();
232
+ setThumb(activeThumb.value, valueFromPointer(event), false);
233
+ },
234
+ onEnd: () => endDrag(true),
235
+ onCancel: () => endDrag(false)
249
236
  });
250
237
  function bigStep() {
251
238
  return Math.max(props.step * 10, Math.round(span.value / 10 / props.step) * props.step || props.step);
@@ -306,8 +293,8 @@ var GrSlider_default = /* @__PURE__ */ defineComponent({
306
293
  hasMarks: normalizedMarks.value.length > 0,
307
294
  orientation: __props.orientation
308
295
  })),
309
- onFocusin: _cache[2] || (_cache[2] = (...args) => unref(onFocusIn) && unref(onFocusIn)(...args)),
310
- onFocusout: _cache[3] || (_cache[3] = (...args) => unref(onFocusOut) && unref(onFocusOut)(...args))
296
+ onFocusin: _cache[3] || (_cache[3] = (...args) => unref(onFocusIn) && unref(onFocusIn)(...args)),
297
+ onFocusout: _cache[4] || (_cache[4] = (...args) => unref(onFocusOut) && unref(onFocusOut)(...args))
311
298
  }, [__props.name ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(modelValues.value, (value, index) => {
312
299
  return openBlock(), createElementBlock("input", {
313
300
  key: index,
@@ -320,7 +307,7 @@ var GrSlider_default = /* @__PURE__ */ defineComponent({
320
307
  ref: trackEl,
321
308
  "data-gr-slider-track": "",
322
309
  class: normalizeClass(["relative", trackClass.value]),
323
- onPointerdown: onTrackPointerDown
310
+ onPointerdown: _cache[2] || (_cache[2] = (...args) => unref(drag).start && unref(drag).start(...args))
324
311
  }, [
325
312
  createElementVNode("div", { class: normalizeClass(unref(sliderRailClass)) }, null, 2),
326
313
  createElementVNode("div", {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrSlider-CyhVsNKn.js","names":[],"sources":["../../../../src/components/GrSlider/GrSlider.vue","../../../../src/components/GrSlider/GrSlider.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\n\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useDragGesture } from '../../composables/useDragGesture'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n sliderFillClass,\n sliderMarkLabelClassFor,\n sliderMarkTickClass,\n sliderRailClass,\n sliderRootClass,\n sliderThumbClass,\n sliderTooltipClass,\n sliderTrackHeightBySize,\n sliderTrackVerticalLengthClass,\n sliderTrackWidthBySize,\n sliderFillOrientationClass,\n type GrSliderMarks,\n type GrSliderModelValue,\n type GrSliderOrientation,\n type GrSliderSize,\n} from './grSliderStyles'\n\nexport type {\n GrSliderMarks,\n GrSliderModelValue,\n GrSliderOrientation,\n GrSliderSize,\n} from './grSliderStyles'\n\n/**\n * Публичный GR-примитив «Slider» (WAI-ARIA slider pattern).\n *\n * Поддерживает одиночное значение и диапазон (`range` — два бегунка), шаг, метки\n * делений, всплывающее значение (tooltip), полную клавиатурную навигацию\n * (стрелки / PageUp/Down / Home / End) и `role=\"slider\"` с\n * `aria-valuemin`/`max`/`now` на каждом бегунке.\n */\nexport interface GrSliderProps {\n /** `number` — одиночное значение; `[lo, hi]` — диапазон (при `range=true`). */\n modelValue: GrSliderModelValue\n min?: number\n max?: number\n step?: number\n /** Диапазон с двумя бегунками; модель — кортеж `[lo, hi]`. */\n range?: boolean\n disabled?: boolean\n /** Только для чтения: значение видно, но не меняется. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n size?: GrSliderSize\n /** Метки делений: `{ [value]: label }` или массив значений. */\n marks?: GrSliderMarks\n /** Всплывающее значение над бегунком: `true`/`'hover'` — при hover/drag/focus, `'always'` — всегда. */\n showTooltip?: boolean | 'always' | 'hover'\n /** Форматирование значения в tooltip. Оно же уходит в `aria-valuetext`. */\n formatTooltip?: (value: number) => string\n /** Ориентация дорожки. В вертикальной минимум внизу. */\n orientation?: GrSliderOrientation\n /**\n * Эмитить `update:modelValue` только по завершении жеста: во время\n * перетаскивания значение ведёт сам слайдер. Клавиатура коммитит сразу —\n * нажатие клавиши дискретно, придерживать его нечего.\n */\n lazy?: boolean\n ariaLabel?: string\n /** Имя для нативной формы: hidden input на значение, при `range` — два с одним именем. */\n name?: string\n}\n\nexport interface GrSliderEmits {\n (e: 'update:modelValue', value: GrSliderModelValue): void\n /** Значение зафиксировано (отпущен бегунок / клавиша). */\n (e: 'change', value: GrSliderModelValue): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrSliderProps>(),\n {\n min: 0,\n max: 100,\n step: 1,\n range: false,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n size: undefined,\n marks: undefined,\n showTooltip: false,\n formatTooltip: undefined,\n orientation: 'horizontal',\n lazy: false,\n ariaLabel: undefined,\n name: undefined,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst isVertical = computed(() => props.orientation === 'vertical')\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrSlider',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrSliderEmits>()\n\n// Контекст `GrFormField`: id/aria-describedby/invalid/required как fallback.\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props)\nconst describedBy = computed(() => field?.describedById.value)\n\nconst trackEl = ref<HTMLElement | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\n// У диапазона два бегунка, и фокус ходит между ними: без границы переход с\n// одного на другой давал бы потребителю пару `blur` + `focus`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n})\n\nconst thumbEls = ref<HTMLElement[]>([])\n\nfunction focus(): void {\n thumbEls.value[0]?.focus()\n}\n\nfunction blur(): void {\n thumbEls.value[0]?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Нормализованные границы (гард от max<=min).\nconst span = computed(() => (props.max > props.min ? props.max - props.min : 1))\n\nconst stepDecimals = computed(() => {\n const s = String(props.step)\n const dot = s.indexOf('.')\n return dot >= 0 ? s.length - dot - 1 : 0\n})\n\nfunction clamp(value: number): number {\n return Math.min(props.max, Math.max(props.min, value))\n}\n\nfunction snap(value: number): number {\n const stepped = Math.round((value - props.min) / props.step) * props.step + props.min\n return Number(clamp(stepped).toFixed(stepDecimals.value))\n}\n\nfunction percent(value: number): number {\n return ((clamp(value) - props.min) / span.value) * 100\n}\n\n// Черновик жеста: при `lazy` значение до отпускания живёт здесь, а наружу не\n// уходит — иначе смысл режима теряется.\nconst draftValues = ref<number[] | null>(null)\n\n// ————— Значения бегунков как массив (single = один бегунок).\nconst modelValues = computed<number[]>(() => {\n if (props.range) {\n const v = Array.isArray(props.modelValue) ? props.modelValue : [props.min, props.min]\n return [snap(v[0] ?? props.min), snap(v[1] ?? props.min)]\n }\n const v = Array.isArray(props.modelValue) ? (props.modelValue[0] ?? props.min) : props.modelValue\n return [snap(v)]\n})\n\nconst values = computed<number[]>(() => draftValues.value ?? modelValues.value)\n\n// `[touch-action:none]` обязателен: без него вертикальный свайп по бегунку\n// уходит в скролл страницы, браузер шлёт `pointercancel`, и слайдер пальцем\n// неуправляем. Утилиты `touch-none` нет ни в `presetMini`, ни в extra-rules —\n// поэтому arbitrary-значение.\nconst trackClass = computed(() => (isVertical.value\n ? `[touch-action:none] ${sliderTrackWidthBySize[resolvedSize.value]} ${sliderTrackVerticalLengthClass}`\n : `[touch-action:none] w-full ${sliderTrackHeightBySize[resolvedSize.value]}`))\n\n/** Смещение вдоль дорожки: по горизонтали слева, по вертикали снизу. */\nfunction offsetStyle(value: number): Record<string, string> {\n return isVertical.value ? { bottom: `${percent(value)}%` } : { left: `${percent(value)}%` }\n}\n\nconst fillStyle = computed(() => {\n const start = props.range\n ? Math.min(percent(values.value[0]), percent(values.value[1]))\n : 0\n const end = props.range\n ? Math.max(percent(values.value[0]), percent(values.value[1]))\n : percent(values.value[0])\n\n return isVertical.value\n ? { bottom: `${start}%`, top: `${100 - end}%` }\n : { left: `${start}%`, right: `${100 - end}%` }\n})\n\n// ————— Метки делений.\ntype SliderMark = { value: number, label: string }\nconst normalizedMarks = computed<SliderMark[]>(() => {\n if (!props.marks) return []\n if (Array.isArray(props.marks)) return props.marks.map(v => ({ value: v, label: String(v) }))\n return Object.entries(props.marks).map(([value, label]) => ({ value: Number(value), label }))\n})\n\nfunction tooltipText(value: number): string {\n return props.formatTooltip ? props.formatTooltip(value) : String(value)\n}\n\n// ————— Обновление значения конкретного бегунка.\nfunction emitValue(next: number[], commit: boolean): void {\n const payload: GrSliderModelValue = props.range ? [next[0], next[1]] : next[0]\n emit('update:modelValue', payload)\n if (commit) emit('change', payload)\n}\n\nfunction setThumb(index: number, value: number, commit: boolean): void {\n const next = values.value.slice()\n next[index] = snap(value)\n\n // range: не даём бегункам «перепрыгнуть» друг друга.\n if (props.range) {\n if (index === 0) next[0] = Math.min(next[0], next[1])\n else next[1] = Math.max(next[1], next[0])\n }\n\n // `lazy` придерживает только непрерывный жест: `commit` приходит от клавиатуры\n // и от отпускания, и там значение уходит наружу как обычно.\n if (props.lazy && !commit) {\n draftValues.value = next\n return\n }\n\n draftValues.value = null\n emitValue(next, commit)\n}\n\n// ————— Pointer-драг.\nconst activeThumb = ref<number | null>(null)\nconst hoveredThumb = ref<number | null>(null)\n\nfunction valueFromPointer(event: { clientX: number, clientY: number }): number {\n const rect = trackEl.value?.getBoundingClientRect()\n if (!rect) return props.min\n\n // В вертикали минимум внизу, поэтому доля отсчитывается от нижнего края.\n const ratio = isVertical.value\n ? (rect.height === 0 ? 0 : 1 - (event.clientY - rect.top) / rect.height)\n : (rect.width === 0 ? 0 : (event.clientX - rect.left) / rect.width)\n\n return props.min + Math.min(1, Math.max(0, ratio)) * span.value\n}\n\n/**\n * Какой бегунок повезёт клик. При равенстве расстояний берём верхний: иначе\n * схлопнувшийся в точку диапазон не развести мышью — нижний бегунок упирается\n * в верхний и оба стоят на месте.\n */\nfunction nearestThumb(value: number): number {\n if (!props.range) return 0\n\n const [lo, hi] = values.value\n if (value < lo) return 0\n if (value > hi) return 1\n\n return Math.abs(value - lo) < Math.abs(value - hi) ? 0 : 1\n}\n\nfunction endDrag(commit: boolean): void {\n if (activeThumb.value !== null && commit) {\n // Финальный commit значения: у `lazy` он же и единственный `update:modelValue`.\n const next = values.value.slice()\n draftValues.value = null\n emitValue(next, true)\n }\n // Оборванный жест (`pointercancel`: браузер забрал указатель) значения не\n // коммитит — черновик просто отбрасывается, бегунок возвращается к модели.\n draftValues.value = null\n activeThumb.value = null\n}\n\nconst drag = useDragGesture({\n disabled: () => isDisabled.value || isReadonly.value,\n onStart: (event) => {\n const value = valueFromPointer(event)\n const index = nearestThumb(value)\n activeThumb.value = index\n // Фокусируем активный бегунок сразу — чтобы клавиатура работала после клика по\n // дорожке (div не получает фокус по клику автоматически, только через `.focus()`).\n thumbEls.value[index]?.focus()\n setThumb(index, value, false)\n },\n onMove: (event) => {\n if (activeThumb.value === null) return\n event.preventDefault()\n setThumb(activeThumb.value, valueFromPointer(event), false)\n },\n onEnd: () => endDrag(true),\n onCancel: () => endDrag(false),\n})\n\n// ————— Клавиатура.\nfunction bigStep(): number {\n // PageUp/Down: 10 шагов либо 10% диапазона (что крупнее).\n return Math.max(props.step * 10, Math.round((span.value / 10) / props.step) * props.step || props.step)\n}\n\nfunction onThumbKeydown(event: KeyboardEvent, index: number): void {\n if (isDisabled.value || isReadonly.value) return\n const current = values.value[index]\n let next: number | null = null\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + props.step\n break\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - props.step\n break\n case 'PageUp':\n next = current + bigStep()\n break\n case 'PageDown':\n next = current - bigStep()\n break\n case 'Home':\n next = props.min\n break\n case 'End':\n next = props.max\n break\n default:\n return\n }\n\n event.preventDefault()\n setThumb(index, next, true)\n}\n\nconst showTooltipFor = (index: number): boolean => {\n if (props.showTooltip === 'always') return true\n if (!props.showTooltip) return false\n return activeThumb.value === index || hoveredThumb.value === index\n}\n\nfunction thumbAriaLabel(index: number): string | undefined {\n if (!props.ariaLabel) return undefined\n if (!props.range) return props.ariaLabel\n\n const bound = index === 0 ? t('gr.slider.min', 'min') : t('gr.slider.max', 'max')\n return `${props.ariaLabel} (${bound})`\n}\n\n// `aria-valuetext` нужен, только когда число само по себе не читается: «1200»\n// против «$1 200». Без своего формата атрибут не добавляем.\nfunction thumbValueText(value: number): string | undefined {\n return props.formatTooltip ? props.formatTooltip(value) : undefined\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-slider\n :data-orientation=\"orientation\"\n :class=\"sliderRootClass({ size: resolvedSize, disabled: isDisabled, hasMarks: normalizedMarks.length > 0, orientation })\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <!-- Нативная форма: роль-виджет не labelable и в submit не попадает.\n Сериализуется модель (snapped), а не черновик жеста. -->\n <template v-if=\"name\">\n <input\n v-for=\"(value, index) in modelValues\"\n :key=\"index\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(value)\"\n >\n </template>\n <div\n ref=\"trackEl\"\n data-gr-slider-track\n class=\"relative\"\n :class=\"trackClass\"\n @pointerdown=\"drag.start\"\n >\n <div :class=\"sliderRailClass\" />\n <div\n data-gr-slider-fill\n :class=\"[sliderFillClass(isDisabled), sliderFillOrientationClass[orientation]]\"\n :style=\"fillStyle\"\n />\n\n <!-- Метки делений. -->\n <template v-for=\"mark in normalizedMarks\" :key=\"mark.value\">\n <span\n data-gr-slider-mark\n :class=\"sliderMarkTickClass(orientation)\"\n :style=\"offsetStyle(mark.value)\"\n aria-hidden=\"true\"\n />\n <!-- Подпись метки дублирует значение, которое диктор читает с бегунка:\n как отдельный текст внутри слайдера она только мешает. -->\n <span\n data-gr-slider-mark-label\n :class=\"sliderMarkLabelClassFor(percent(mark.value), { orientation, disabled: isDisabled })\"\n :style=\"offsetStyle(mark.value)\"\n aria-hidden=\"true\"\n >\n {{ mark.label }}\n </span>\n </template>\n\n <!-- Бегунки. -->\n <div\n v-for=\"(value, index) in values\"\n :id=\"index === 0 ? resolvedId : undefined\"\n :key=\"index\"\n :ref=\"(el) => { if (el) thumbEls[index] = el as HTMLElement }\"\n data-gr-slider-thumb\n :data-testid=\"`gr-slider-thumb-${index}`\"\n :class=\"sliderThumbClass({ size: resolvedSize, disabled: isDisabled, orientation })\"\n :style=\"offsetStyle(value)\"\n role=\"slider\"\n :tabindex=\"isDisabled ? -1 : 0\"\n :aria-valuemin=\"range && index === 1 ? values[0] : min\"\n :aria-valuemax=\"range && index === 0 ? values[1] : max\"\n :aria-valuenow=\"value\"\n :aria-valuetext=\"thumbValueText(value)\"\n :aria-orientation=\"orientation\"\n :aria-label=\"thumbAriaLabel(index)\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-describedby=\"index === 0 ? describedBy : undefined\"\n :aria-required=\"isRequired && index === 0 ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n @keydown=\"onThumbKeydown($event, index)\"\n @mouseenter=\"hoveredThumb = index\"\n @mouseleave=\"hoveredThumb = null\"\n @focus=\"hoveredThumb = index\"\n @blur=\"hoveredThumb = null\"\n >\n <span\n v-if=\"showTooltipFor(index)\"\n data-gr-slider-tooltip\n :class=\"sliderTooltipClass(orientation)\"\n >\n {{ tooltipText(value) }}\n </span>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\nimport { useGrComponentSize } from '../GrConfigProvider/context'\n\nimport { useGrFormFieldContext } from '../GrFormField/context'\nimport { useDragGesture } from '../../composables/useDragGesture'\nimport { useGrFormControl } from '../../composables/useGrFormControl'\nimport { useFocusWithin } from '../../composables/internal/useFocusWithin'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\nimport {\n sliderFillClass,\n sliderMarkLabelClassFor,\n sliderMarkTickClass,\n sliderRailClass,\n sliderRootClass,\n sliderThumbClass,\n sliderTooltipClass,\n sliderTrackHeightBySize,\n sliderTrackVerticalLengthClass,\n sliderTrackWidthBySize,\n sliderFillOrientationClass,\n type GrSliderMarks,\n type GrSliderModelValue,\n type GrSliderOrientation,\n type GrSliderSize,\n} from './grSliderStyles'\n\nexport type {\n GrSliderMarks,\n GrSliderModelValue,\n GrSliderOrientation,\n GrSliderSize,\n} from './grSliderStyles'\n\n/**\n * Публичный GR-примитив «Slider» (WAI-ARIA slider pattern).\n *\n * Поддерживает одиночное значение и диапазон (`range` — два бегунка), шаг, метки\n * делений, всплывающее значение (tooltip), полную клавиатурную навигацию\n * (стрелки / PageUp/Down / Home / End) и `role=\"slider\"` с\n * `aria-valuemin`/`max`/`now` на каждом бегунке.\n */\nexport interface GrSliderProps {\n /** `number` — одиночное значение; `[lo, hi]` — диапазон (при `range=true`). */\n modelValue: GrSliderModelValue\n min?: number\n max?: number\n step?: number\n /** Диапазон с двумя бегунками; модель — кортеж `[lo, hi]`. */\n range?: boolean\n disabled?: boolean\n /** Только для чтения: значение видно, но не меняется. */\n readonly?: boolean\n /** Визуальное и ARIA-состояние ошибки. */\n invalid?: boolean\n /** Обязательное поле (`aria-required`). */\n required?: boolean\n size?: GrSliderSize\n /** Метки делений: `{ [value]: label }` или массив значений. */\n marks?: GrSliderMarks\n /** Всплывающее значение над бегунком: `true`/`'hover'` — при hover/drag/focus, `'always'` — всегда. */\n showTooltip?: boolean | 'always' | 'hover'\n /** Форматирование значения в tooltip. Оно же уходит в `aria-valuetext`. */\n formatTooltip?: (value: number) => string\n /** Ориентация дорожки. В вертикальной минимум внизу. */\n orientation?: GrSliderOrientation\n /**\n * Эмитить `update:modelValue` только по завершении жеста: во время\n * перетаскивания значение ведёт сам слайдер. Клавиатура коммитит сразу —\n * нажатие клавиши дискретно, придерживать его нечего.\n */\n lazy?: boolean\n ariaLabel?: string\n /** Имя для нативной формы: hidden input на значение, при `range` — два с одним именем. */\n name?: string\n}\n\nexport interface GrSliderEmits {\n (e: 'update:modelValue', value: GrSliderModelValue): void\n /** Значение зафиксировано (отпущен бегунок / клавиша). */\n (e: 'change', value: GrSliderModelValue): void\n (e: 'focus', event: FocusEvent): void\n (e: 'blur', event: FocusEvent): void\n}\n\nconst props = withDefaults(\n defineProps<GrSliderProps>(),\n {\n min: 0,\n max: 100,\n step: 1,\n range: false,\n disabled: false,\n readonly: false,\n invalid: false,\n required: false,\n size: undefined,\n marks: undefined,\n showTooltip: false,\n formatTooltip: undefined,\n orientation: 'horizontal',\n lazy: false,\n ariaLabel: undefined,\n name: undefined,\n },\n)\n\nconst { t } = useGranularityTranslations()\n\nconst isVertical = computed(() => props.orientation === 'vertical')\n\n// Эффективный размер: локальный проп → `GrConfigProvider` → дефолт компонента.\nconst resolvedSize = useGrComponentSize(() => props.size, {\n component: 'GrSlider',\n supported: ['xs', 'sm', 'md', 'lg'],\n})\n\nconst emit = defineEmits<GrSliderEmits>()\n\n// Контекст `GrFormField`: id/aria-describedby/invalid/required как fallback.\nconst field = useGrFormFieldContext()\nconst resolvedId = computed(() => field?.id.value)\nconst {\n disabled: isDisabled,\n invalid: isInvalid, required: isRequired, readonly: isReadonly } = useGrFormControl(() => props)\nconst describedBy = computed(() => field?.describedById.value)\n\nconst trackEl = ref<HTMLElement | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\n// У диапазона два бегунка, и фокус ходит между ними: без границы переход с\n// одного на другой давал бы потребителю пару `blur` + `focus`.\nconst { onFocusIn, onFocusOut } = useFocusWithin(rootEl, {\n enter: event => emit('focus', event),\n leave: event => emit('blur', event),\n})\n\nconst thumbEls = ref<HTMLElement[]>([])\n\nfunction focus(): void {\n thumbEls.value[0]?.focus()\n}\n\nfunction blur(): void {\n thumbEls.value[0]?.blur()\n}\n\ndefineExpose({ focus, blur })\n\n// Нормализованные границы (гард от max<=min).\nconst span = computed(() => (props.max > props.min ? props.max - props.min : 1))\n\nconst stepDecimals = computed(() => {\n const s = String(props.step)\n const dot = s.indexOf('.')\n return dot >= 0 ? s.length - dot - 1 : 0\n})\n\nfunction clamp(value: number): number {\n return Math.min(props.max, Math.max(props.min, value))\n}\n\nfunction snap(value: number): number {\n const stepped = Math.round((value - props.min) / props.step) * props.step + props.min\n return Number(clamp(stepped).toFixed(stepDecimals.value))\n}\n\nfunction percent(value: number): number {\n return ((clamp(value) - props.min) / span.value) * 100\n}\n\n// Черновик жеста: при `lazy` значение до отпускания живёт здесь, а наружу не\n// уходит — иначе смысл режима теряется.\nconst draftValues = ref<number[] | null>(null)\n\n// ————— Значения бегунков как массив (single = один бегунок).\nconst modelValues = computed<number[]>(() => {\n if (props.range) {\n const v = Array.isArray(props.modelValue) ? props.modelValue : [props.min, props.min]\n return [snap(v[0] ?? props.min), snap(v[1] ?? props.min)]\n }\n const v = Array.isArray(props.modelValue) ? (props.modelValue[0] ?? props.min) : props.modelValue\n return [snap(v)]\n})\n\nconst values = computed<number[]>(() => draftValues.value ?? modelValues.value)\n\n// `[touch-action:none]` обязателен: без него вертикальный свайп по бегунку\n// уходит в скролл страницы, браузер шлёт `pointercancel`, и слайдер пальцем\n// неуправляем. Утилиты `touch-none` нет ни в `presetMini`, ни в extra-rules —\n// поэтому arbitrary-значение.\nconst trackClass = computed(() => (isVertical.value\n ? `[touch-action:none] ${sliderTrackWidthBySize[resolvedSize.value]} ${sliderTrackVerticalLengthClass}`\n : `[touch-action:none] w-full ${sliderTrackHeightBySize[resolvedSize.value]}`))\n\n/** Смещение вдоль дорожки: по горизонтали слева, по вертикали снизу. */\nfunction offsetStyle(value: number): Record<string, string> {\n return isVertical.value ? { bottom: `${percent(value)}%` } : { left: `${percent(value)}%` }\n}\n\nconst fillStyle = computed(() => {\n const start = props.range\n ? Math.min(percent(values.value[0]), percent(values.value[1]))\n : 0\n const end = props.range\n ? Math.max(percent(values.value[0]), percent(values.value[1]))\n : percent(values.value[0])\n\n return isVertical.value\n ? { bottom: `${start}%`, top: `${100 - end}%` }\n : { left: `${start}%`, right: `${100 - end}%` }\n})\n\n// ————— Метки делений.\ntype SliderMark = { value: number, label: string }\nconst normalizedMarks = computed<SliderMark[]>(() => {\n if (!props.marks) return []\n if (Array.isArray(props.marks)) return props.marks.map(v => ({ value: v, label: String(v) }))\n return Object.entries(props.marks).map(([value, label]) => ({ value: Number(value), label }))\n})\n\nfunction tooltipText(value: number): string {\n return props.formatTooltip ? props.formatTooltip(value) : String(value)\n}\n\n// ————— Обновление значения конкретного бегунка.\nfunction emitValue(next: number[], commit: boolean): void {\n const payload: GrSliderModelValue = props.range ? [next[0], next[1]] : next[0]\n emit('update:modelValue', payload)\n if (commit) emit('change', payload)\n}\n\nfunction setThumb(index: number, value: number, commit: boolean): void {\n const next = values.value.slice()\n next[index] = snap(value)\n\n // range: не даём бегункам «перепрыгнуть» друг друга.\n if (props.range) {\n if (index === 0) next[0] = Math.min(next[0], next[1])\n else next[1] = Math.max(next[1], next[0])\n }\n\n // `lazy` придерживает только непрерывный жест: `commit` приходит от клавиатуры\n // и от отпускания, и там значение уходит наружу как обычно.\n if (props.lazy && !commit) {\n draftValues.value = next\n return\n }\n\n draftValues.value = null\n emitValue(next, commit)\n}\n\n// ————— Pointer-драг.\nconst activeThumb = ref<number | null>(null)\nconst hoveredThumb = ref<number | null>(null)\n\nfunction valueFromPointer(event: { clientX: number, clientY: number }): number {\n const rect = trackEl.value?.getBoundingClientRect()\n if (!rect) return props.min\n\n // В вертикали минимум внизу, поэтому доля отсчитывается от нижнего края.\n const ratio = isVertical.value\n ? (rect.height === 0 ? 0 : 1 - (event.clientY - rect.top) / rect.height)\n : (rect.width === 0 ? 0 : (event.clientX - rect.left) / rect.width)\n\n return props.min + Math.min(1, Math.max(0, ratio)) * span.value\n}\n\n/**\n * Какой бегунок повезёт клик. При равенстве расстояний берём верхний: иначе\n * схлопнувшийся в точку диапазон не развести мышью — нижний бегунок упирается\n * в верхний и оба стоят на месте.\n */\nfunction nearestThumb(value: number): number {\n if (!props.range) return 0\n\n const [lo, hi] = values.value\n if (value < lo) return 0\n if (value > hi) return 1\n\n return Math.abs(value - lo) < Math.abs(value - hi) ? 0 : 1\n}\n\nfunction endDrag(commit: boolean): void {\n if (activeThumb.value !== null && commit) {\n // Финальный commit значения: у `lazy` он же и единственный `update:modelValue`.\n const next = values.value.slice()\n draftValues.value = null\n emitValue(next, true)\n }\n // Оборванный жест (`pointercancel`: браузер забрал указатель) значения не\n // коммитит — черновик просто отбрасывается, бегунок возвращается к модели.\n draftValues.value = null\n activeThumb.value = null\n}\n\nconst drag = useDragGesture({\n disabled: () => isDisabled.value || isReadonly.value,\n onStart: (event) => {\n const value = valueFromPointer(event)\n const index = nearestThumb(value)\n activeThumb.value = index\n // Фокусируем активный бегунок сразу — чтобы клавиатура работала после клика по\n // дорожке (div не получает фокус по клику автоматически, только через `.focus()`).\n thumbEls.value[index]?.focus()\n setThumb(index, value, false)\n },\n onMove: (event) => {\n if (activeThumb.value === null) return\n event.preventDefault()\n setThumb(activeThumb.value, valueFromPointer(event), false)\n },\n onEnd: () => endDrag(true),\n onCancel: () => endDrag(false),\n})\n\n// ————— Клавиатура.\nfunction bigStep(): number {\n // PageUp/Down: 10 шагов либо 10% диапазона (что крупнее).\n return Math.max(props.step * 10, Math.round((span.value / 10) / props.step) * props.step || props.step)\n}\n\nfunction onThumbKeydown(event: KeyboardEvent, index: number): void {\n if (isDisabled.value || isReadonly.value) return\n const current = values.value[index]\n let next: number | null = null\n\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + props.step\n break\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - props.step\n break\n case 'PageUp':\n next = current + bigStep()\n break\n case 'PageDown':\n next = current - bigStep()\n break\n case 'Home':\n next = props.min\n break\n case 'End':\n next = props.max\n break\n default:\n return\n }\n\n event.preventDefault()\n setThumb(index, next, true)\n}\n\nconst showTooltipFor = (index: number): boolean => {\n if (props.showTooltip === 'always') return true\n if (!props.showTooltip) return false\n return activeThumb.value === index || hoveredThumb.value === index\n}\n\nfunction thumbAriaLabel(index: number): string | undefined {\n if (!props.ariaLabel) return undefined\n if (!props.range) return props.ariaLabel\n\n const bound = index === 0 ? t('gr.slider.min', 'min') : t('gr.slider.max', 'max')\n return `${props.ariaLabel} (${bound})`\n}\n\n// `aria-valuetext` нужен, только когда число само по себе не читается: «1200»\n// против «$1 200». Без своего формата атрибут не добавляем.\nfunction thumbValueText(value: number): string | undefined {\n return props.formatTooltip ? props.formatTooltip(value) : undefined\n}\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n data-gr-slider\n :data-orientation=\"orientation\"\n :class=\"sliderRootClass({ size: resolvedSize, disabled: isDisabled, hasMarks: normalizedMarks.length > 0, orientation })\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <!-- Нативная форма: роль-виджет не labelable и в submit не попадает.\n Сериализуется модель (snapped), а не черновик жеста. -->\n <template v-if=\"name\">\n <input\n v-for=\"(value, index) in modelValues\"\n :key=\"index\"\n type=\"hidden\"\n :name=\"name\"\n :value=\"String(value)\"\n >\n </template>\n <div\n ref=\"trackEl\"\n data-gr-slider-track\n class=\"relative\"\n :class=\"trackClass\"\n @pointerdown=\"drag.start\"\n >\n <div :class=\"sliderRailClass\" />\n <div\n data-gr-slider-fill\n :class=\"[sliderFillClass(isDisabled), sliderFillOrientationClass[orientation]]\"\n :style=\"fillStyle\"\n />\n\n <!-- Метки делений. -->\n <template v-for=\"mark in normalizedMarks\" :key=\"mark.value\">\n <span\n data-gr-slider-mark\n :class=\"sliderMarkTickClass(orientation)\"\n :style=\"offsetStyle(mark.value)\"\n aria-hidden=\"true\"\n />\n <!-- Подпись метки дублирует значение, которое диктор читает с бегунка:\n как отдельный текст внутри слайдера она только мешает. -->\n <span\n data-gr-slider-mark-label\n :class=\"sliderMarkLabelClassFor(percent(mark.value), { orientation, disabled: isDisabled })\"\n :style=\"offsetStyle(mark.value)\"\n aria-hidden=\"true\"\n >\n {{ mark.label }}\n </span>\n </template>\n\n <!-- Бегунки. -->\n <div\n v-for=\"(value, index) in values\"\n :id=\"index === 0 ? resolvedId : undefined\"\n :key=\"index\"\n :ref=\"(el) => { if (el) thumbEls[index] = el as HTMLElement }\"\n data-gr-slider-thumb\n :data-testid=\"`gr-slider-thumb-${index}`\"\n :class=\"sliderThumbClass({ size: resolvedSize, disabled: isDisabled, orientation })\"\n :style=\"offsetStyle(value)\"\n role=\"slider\"\n :tabindex=\"isDisabled ? -1 : 0\"\n :aria-valuemin=\"range && index === 1 ? values[0] : min\"\n :aria-valuemax=\"range && index === 0 ? values[1] : max\"\n :aria-valuenow=\"value\"\n :aria-valuetext=\"thumbValueText(value)\"\n :aria-orientation=\"orientation\"\n :aria-label=\"thumbAriaLabel(index)\"\n :aria-disabled=\"isDisabled ? 'true' : undefined\"\n :aria-invalid=\"isInvalid ? 'true' : undefined\"\n :aria-describedby=\"index === 0 ? describedBy : undefined\"\n :aria-required=\"isRequired && index === 0 ? 'true' : undefined\"\n :aria-readonly=\"isReadonly ? 'true' : undefined\"\n @keydown=\"onThumbKeydown($event, index)\"\n @mouseenter=\"hoveredThumb = index\"\n @mouseleave=\"hoveredThumb = null\"\n @focus=\"hoveredThumb = index\"\n @blur=\"hoveredThumb = null\"\n >\n <span\n v-if=\"showTooltipFor(index)\"\n data-gr-slider-tooltip\n :class=\"sliderTooltipClass(orientation)\"\n >\n {{ tooltipText(value) }}\n </span>\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrSlider_default } from "./chunks/GrSlider-DkU9IQSX.js";
2
- import { n as grSliderSafelist, t as grSliderConfig } from "../../chunks/config-T3qdQBgU.js";
1
+ import { t as GrSlider_default } from "./chunks/GrSlider-CyhVsNKn.js";
2
+ import { n as grSliderSafelist, t as grSliderConfig } from "../../chunks/config-T3qdQBgU2.js";
3
3
  export { GrSlider_default as GrSlider, GrSlider_default as default, grSliderConfig, grSliderSafelist };