@feugene/granularity 0.10.0 → 0.11.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 (442) hide show
  1. package/README.md +44 -45
  2. package/dist/GrButtonGroup.css +1 -1
  3. package/dist/GrFormFile.css +1 -1
  4. package/dist/GrIcon.css +1 -1
  5. package/dist/GrLoading.css +1 -1
  6. package/dist/GrSkeleton.css +1 -1
  7. package/dist/GrToaster.css +1 -0
  8. package/dist/GrTree.css +1 -1
  9. package/dist/chunks/{adapter-BqqjEZGU.js.map → adapter-CAOxmn2G.js.map} +1 -1
  10. package/dist/chunks/arrow-up-C_G4jg8M.js.map +1 -0
  11. package/dist/chunks/{classTokens-BPeBXNzu.js.map → classTokens-BzazaERD.js.map} +1 -1
  12. package/dist/chunks/{config-A-iei0Ux.js → config-1uSYl98Y.js} +5 -5
  13. package/dist/chunks/{config-A-iei0Ux.js.map → config-1uSYl98Y.js.map} +1 -1
  14. package/dist/chunks/{config-DZrlovR42.js.map → config-8Pcutu1j2.js.map} +1 -1
  15. package/dist/chunks/{config-VJuoznpH.js.map → config-B0qIpo8m.js.map} +1 -1
  16. package/dist/chunks/{config-C8MM2Dg0.js → config-B7IIWGt_2.js} +3 -3
  17. package/dist/chunks/config-B7IIWGt_2.js.map +1 -0
  18. package/dist/chunks/{config-DbghHyY_.js.map → config-BEegFP74.js.map} +1 -1
  19. package/dist/chunks/{config-D_Pafsjq2.js → config-BIRO0vDJ2.js} +6 -6
  20. package/dist/chunks/{config-D_Pafsjq2.js.map → config-BIRO0vDJ2.js.map} +1 -1
  21. package/dist/chunks/{config-BeBsN0c12.js.map → config-BLHqZhy-2.js.map} +1 -1
  22. package/dist/chunks/{config-BV4vBzdm.js.map → config-BNu8lFQB.js.map} +1 -1
  23. package/dist/chunks/config-BOlr7qw7.js +106 -0
  24. package/dist/chunks/config-BOlr7qw7.js.map +1 -0
  25. package/dist/chunks/{config-DhQc1TRY.js.map → config-BUHuGBik.js.map} +1 -1
  26. package/dist/chunks/{config-CPSdAjUi.js.map → config-BWGGp7uV.js.map} +1 -1
  27. package/dist/chunks/config-BX1JTrkV2.js +14 -0
  28. package/dist/chunks/config-BX1JTrkV2.js.map +1 -0
  29. package/dist/chunks/{config-BduXEXjt.js.map → config-BXtAmU3s.js.map} +1 -1
  30. package/dist/chunks/{config-CzgNEHKi.js.map → config-Bah4oHwL.js.map} +1 -1
  31. package/dist/chunks/{config-C_egzT_K.js → config-C49QUoJL.js} +3 -3
  32. package/dist/chunks/{config-C_egzT_K.js.map → config-C49QUoJL.js.map} +1 -1
  33. package/dist/chunks/{config-3I3vqDW4.js → config-C4snOIXg.js} +1 -1
  34. package/dist/chunks/{config-3I3vqDW4.js.map → config-C4snOIXg.js.map} +1 -1
  35. package/dist/chunks/{config-DvDNney3.js → config-C7NpDrfO.js} +5 -5
  36. package/dist/chunks/{config-DvDNney3.js.map → config-C7NpDrfO.js.map} +1 -1
  37. package/dist/chunks/{config-lMDE_8A5.js.map → config-C86UzUYf.js.map} +1 -1
  38. package/dist/chunks/{config-BgBWt9-A.js.map → config-C9AcVDkv.js.map} +1 -1
  39. package/dist/chunks/{config-BuoIngj32.js.map → config-CGHLoBlH2.js.map} +1 -1
  40. package/dist/chunks/{config-ChQxl75m.js.map → config-CThzliFi.js.map} +1 -1
  41. package/dist/chunks/{config-DDwBSoc_.js.map → config-Cb2PAlSD.js.map} +1 -1
  42. package/dist/chunks/{config-XspHtPsU.js → config-ClhKPJvg.js} +5 -5
  43. package/dist/chunks/{config-XspHtPsU.js.map → config-ClhKPJvg.js.map} +1 -1
  44. package/dist/chunks/{config-58Mj2rGH.js → config-Cpi9Mh2J.js} +3 -3
  45. package/dist/chunks/{config-58Mj2rGH.js.map → config-Cpi9Mh2J.js.map} +1 -1
  46. package/dist/chunks/{config-nrOj9p6I.js → config-CrG1XiE7.js} +4 -4
  47. package/dist/chunks/{config-nrOj9p6I.js.map → config-CrG1XiE7.js.map} +1 -1
  48. package/dist/chunks/{config-DRpkoSvq.js → config-CziwTDDL.js} +3 -3
  49. package/dist/chunks/{config-DRpkoSvq.js.map → config-CziwTDDL.js.map} +1 -1
  50. package/dist/chunks/{config-C5-ujXCI.js.map → config-D7GZO-Dx.js.map} +1 -1
  51. package/dist/chunks/{config-CUwF4E4R.js.map → config-DBmdgoVf.js.map} +1 -1
  52. package/dist/chunks/{config-C9MblwGq.js.map → config-DICOd-2X.js.map} +1 -1
  53. package/dist/chunks/{config-C6zT56Jc2.js → config-DUcu1D68.js} +3 -3
  54. package/dist/chunks/config-DUcu1D68.js.map +1 -0
  55. package/dist/chunks/{config-8f8624RN.js → config-D_R56_gT.js} +5 -5
  56. package/dist/chunks/{config-8f8624RN.js.map → config-D_R56_gT.js.map} +1 -1
  57. package/dist/chunks/{config-RjfJFv1Y.js → config-DezDih8_.js} +4 -4
  58. package/dist/chunks/config-DezDih8_.js.map +1 -0
  59. package/dist/chunks/{config-B0uUCaJW.js → config-DnvPqu4g.js} +3 -3
  60. package/dist/chunks/{config-B0uUCaJW.js.map → config-DnvPqu4g.js.map} +1 -1
  61. package/dist/chunks/{config-BLa1TEGm2.js.map → config-DpqOnJiz2.js.map} +1 -1
  62. package/dist/chunks/{config-V3LF-b_F.js.map → config-Dxuwwepq.js.map} +1 -1
  63. package/dist/chunks/{config-Doa_gU40.js.map → config-HZto2PVy.js.map} +1 -1
  64. package/dist/chunks/{config-Dl5aZ5VR.js.map → config-JOtB4mzs.js.map} +1 -1
  65. package/dist/chunks/{config-CWTfyPNI.js.map → config-JpHA4Xx0.js.map} +1 -1
  66. package/dist/chunks/{config-DkeLkzxj2.js → config-LGrZIdaZ2.js} +1 -1
  67. package/dist/chunks/{config-DkeLkzxj2.js.map → config-LGrZIdaZ2.js.map} +1 -1
  68. package/dist/chunks/{config-B3dn-gdC.js.map → config-PFg39mYo.js.map} +1 -1
  69. package/dist/chunks/{config-CU_CBd0k.js → config-QYGvEBu5.js} +2 -2
  70. package/dist/chunks/{config-CU_CBd0k.js.map → config-QYGvEBu5.js.map} +1 -1
  71. package/dist/chunks/{config-Bh4NWWsQ.js.map → config-QaIc_gRa.js.map} +1 -1
  72. package/dist/chunks/{config-vcDVCYXo.js.map → config-U4m9PSql.js.map} +1 -1
  73. package/dist/chunks/{config-C_q_4FrU.js.map → config-ZiXWIRBX.js.map} +1 -1
  74. package/dist/chunks/{config-hSlCXHoG.js → config-eYLZYOUS2.js} +63 -63
  75. package/dist/chunks/config-eYLZYOUS2.js.map +1 -0
  76. package/dist/chunks/{config-DDUPnue12.js.map → config-ipvU0lzP2.js.map} +1 -1
  77. package/dist/chunks/{config-B61cX08u.js → config-jBp9wVv-.js} +4 -4
  78. package/dist/chunks/{config-B61cX08u.js.map → config-jBp9wVv-.js.map} +1 -1
  79. package/dist/chunks/{config-D5ek7VSi.js.map → config-xR4XVmcy.js.map} +1 -1
  80. package/dist/chunks/{dialogShared-BtXUk6Zc.js.map → dialogShared-CxW62PQE.js.map} +1 -1
  81. package/dist/chunks/en-BdtiS2d3.js +138 -0
  82. package/dist/chunks/en-BdtiS2d3.js.map +1 -0
  83. package/dist/chunks/es-BGRMZbe9.js +138 -0
  84. package/dist/chunks/es-BGRMZbe9.js.map +1 -0
  85. package/dist/chunks/{es-CISK11Nv.js → es-DBhctWg-.js} +3 -3
  86. package/dist/chunks/{es-CISK11Nv.js.map → es-DBhctWg-.js.map} +1 -1
  87. package/dist/chunks/{fileValidation-c_iBg74s.js → fileValidation-C3WFaWU2.js} +2 -1
  88. package/dist/chunks/{fileValidation-c_iBg74s.js.map → fileValidation-C3WFaWU2.js.map} +1 -1
  89. package/dist/chunks/{grBadgeStyles-Cq0hH2Ls.js → grBadgeStyles-DrycBuKT.js} +13 -13
  90. package/dist/chunks/grBadgeStyles-DrycBuKT.js.map +1 -0
  91. package/dist/chunks/grButtonStyles-C7Yga_Q1.js +191 -0
  92. package/dist/chunks/grButtonStyles-C7Yga_Q1.js.map +1 -0
  93. package/dist/chunks/{grDropdownStyles-Bqx9hOzU.js → grDropdownStyles-B_-DKytw.js} +2 -2
  94. package/dist/chunks/{grDropdownStyles-Bqx9hOzU.js.map → grDropdownStyles-B_-DKytw.js.map} +1 -1
  95. package/dist/chunks/{grLoadingStyles-DmI-SJ3i.js.map → grLoadingStyles-R5sreH__.js.map} +1 -1
  96. package/dist/chunks/{grModalStyles-FgaKqx50.js → grModalStyles-DWd3i05Q.js} +6 -6
  97. package/dist/chunks/{grModalStyles-FgaKqx50.js.map → grModalStyles-DWd3i05Q.js.map} +1 -1
  98. package/dist/chunks/{grSelectStyles-AjWWl007.js → grSelectStyles-CLK5hRd3.js} +3 -3
  99. package/dist/chunks/grSelectStyles-CLK5hRd3.js.map +1 -0
  100. package/dist/chunks/{grStyle-D-gPHdyW.js → grStyle-Blc9otAx.js} +6 -6
  101. package/dist/chunks/grStyle-Blc9otAx.js.map +1 -0
  102. package/dist/chunks/{granularityI18n-D_7jowK2.js → granularityI18n-DoV7Ca2m.js} +1 -1
  103. package/dist/chunks/{granularityI18n-D_7jowK2.js.map → granularityI18n-DoV7Ca2m.js.map} +1 -1
  104. package/dist/chunks/info-Be2OccTu.js.map +1 -0
  105. package/dist/chunks/loader-circle-CfVLz7lb.js.map +1 -0
  106. package/dist/chunks/ru-BFCnOiML.js +138 -0
  107. package/dist/chunks/ru-BFCnOiML.js.map +1 -0
  108. package/dist/chunks/{safelist-_UVzJrgE2.js → safelist-CkF4v7DC.js} +3 -3
  109. package/dist/chunks/safelist-CkF4v7DC.js.map +1 -0
  110. package/dist/chunks/{safelist-DccvJqCE.js → safelist-Do2RtzLB.js} +3 -3
  111. package/dist/chunks/{safelist-DccvJqCE.js.map → safelist-Do2RtzLB.js.map} +1 -1
  112. package/dist/chunks/shared-ChvcQgDl.js +168 -0
  113. package/dist/chunks/shared-ChvcQgDl.js.map +1 -0
  114. package/dist/chunks/{transition-mJ3PZCHH.js → transition-TLFw4KBn.js} +26 -12
  115. package/dist/chunks/{transition-mJ3PZCHH.js.map → transition-TLFw4KBn.js.map} +1 -1
  116. package/dist/chunks/useAddonMeasurement-DM0akF4C.js +65 -0
  117. package/dist/chunks/useAddonMeasurement-DM0akF4C.js.map +1 -0
  118. package/dist/chunks/useEscapeToClose-C2t_S1gh.js +27 -0
  119. package/dist/chunks/useEscapeToClose-C2t_S1gh.js.map +1 -0
  120. package/dist/chunks/{useFloating-CLtbU7eD.js → useFloating-DtM6TyE4.js} +19 -4
  121. package/dist/chunks/{useFloating-CLtbU7eD.js.map → useFloating-DtM6TyE4.js.map} +1 -1
  122. package/dist/chunks/x-2KXnqxiD.js.map +1 -0
  123. package/dist/chunks/x-circle-BCBURwyX.js.map +1 -0
  124. package/dist/components/GrAlert/chunks/{GrAlert-HyCjYJeL.js → GrAlert-DPJSU_fG.js} +40 -37
  125. package/dist/components/GrAlert/chunks/GrAlert-DPJSU_fG.js.map +1 -0
  126. package/dist/components/GrAlert/index.js +2 -2
  127. package/dist/components/GrAvatar/chunks/{GrAvatar-BjnPKNAL.js → GrAvatar-96CpTCq5.js} +2 -2
  128. package/dist/components/GrAvatar/chunks/{GrAvatar-BjnPKNAL.js.map → GrAvatar-96CpTCq5.js.map} +1 -1
  129. package/dist/components/GrAvatar/index.js +2 -2
  130. package/dist/components/GrBadge/chunks/{GrBadge-Cs_cVfuO.js → GrBadge-B77XlaqE.js} +3 -3
  131. package/dist/components/GrBadge/chunks/{GrBadge-Cs_cVfuO.js.map → GrBadge-B77XlaqE.js.map} +1 -1
  132. package/dist/components/GrBadge/index.js +2 -2
  133. package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-BEnE9DyJ.js → GrBadgeWrap-CcktMOdg.js} +2 -2
  134. package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-BEnE9DyJ.js.map → GrBadgeWrap-CcktMOdg.js.map} +1 -1
  135. package/dist/components/GrBadgeWrap/index.js +2 -2
  136. package/dist/components/GrBottomNav/chunks/{GrBottomNav-XPHwd7UQ.js.map → GrBottomNav-usuMgG8_.js.map} +1 -1
  137. package/dist/components/GrBottomNav/index.js +2 -2
  138. package/dist/components/GrButton/chunks/GrButton-BlffdeJr.js +124 -0
  139. package/dist/components/GrButton/chunks/GrButton-BlffdeJr.js.map +1 -0
  140. package/dist/components/GrButton/index.js +4 -4
  141. package/dist/components/GrButtonGroup/chunks/{GrButtonGroup-CPOH6V-P.js → GrButtonGroup-Bs9dEKfA.js} +1 -1
  142. package/dist/components/GrButtonGroup/chunks/GrButtonGroup-Bs9dEKfA.js.map +1 -0
  143. package/dist/components/GrButtonGroup/index.js +2 -2
  144. package/dist/components/GrCard/chunks/{GrCard-6yk1RRAQ.js → GrCard-DUNMkuHW.js} +3 -3
  145. package/dist/components/GrCard/chunks/GrCard-DUNMkuHW.js.map +1 -0
  146. package/dist/components/GrCard/index.js +2 -2
  147. package/dist/components/GrCheckbox/chunks/{GrCheckbox-Bt3d7ckE.js → GrCheckbox-DJhzZZdO.js} +66 -18
  148. package/dist/components/GrCheckbox/chunks/GrCheckbox-DJhzZZdO.js.map +1 -0
  149. package/dist/components/GrCheckbox/index.js +2 -2
  150. package/dist/components/GrCollapse/chunks/{GrCollapse-CU94BTAR.js → GrCollapse-CPPLh_xU.js} +12 -12
  151. package/dist/components/GrCollapse/chunks/{GrCollapse-CU94BTAR.js.map → GrCollapse-CPPLh_xU.js.map} +1 -1
  152. package/dist/components/GrCollapse/index.js +2 -2
  153. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-Bi2KLumL.js → GrConfirmDialog-BWYKCsHd.js} +20 -14
  154. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-BWYKCsHd.js.map +1 -0
  155. package/dist/components/GrConfirmDialog/index.js +2 -2
  156. package/dist/components/GrDataTable/chunks/{GrDataTable-ClcYiyc8.js → GrDataTable-ptbARmJ3.js} +7 -7
  157. package/dist/components/GrDataTable/chunks/{GrDataTable-ClcYiyc8.js.map → GrDataTable-ptbARmJ3.js.map} +1 -1
  158. package/dist/components/GrDataTable/index.js +2 -2
  159. package/dist/components/GrDialog/chunks/{GrDialog-CxK4Lj4F.js → GrDialog-5DAS-1Lb.js} +14 -12
  160. package/dist/components/GrDialog/chunks/GrDialog-5DAS-1Lb.js.map +1 -0
  161. package/dist/components/GrDialog/index.js +3 -3
  162. package/dist/components/GrDialogService/chunks/GrDialogService-DY_fmaMu.js +425 -0
  163. package/dist/components/GrDialogService/chunks/GrDialogService-DY_fmaMu.js.map +1 -0
  164. package/dist/components/GrDialogService/index.js +3 -0
  165. package/dist/components/GrDrawer/chunks/{GrDrawer-BW3wtI7h.js → GrDrawer-D1kzsjXN.js} +19 -15
  166. package/dist/components/GrDrawer/chunks/GrDrawer-D1kzsjXN.js.map +1 -0
  167. package/dist/components/GrDrawer/index.js +2 -2
  168. package/dist/components/GrDropdown/chunks/{GrDropdown-BGKeEfZ1.js → GrDropdown-BXb5Cxxf.js} +9 -19
  169. package/dist/components/GrDropdown/chunks/GrDropdown-BXb5Cxxf.js.map +1 -0
  170. package/dist/components/GrDropdown/index.js +2 -2
  171. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-CJom_-c2.js → GrDropdownMenu-DFEJLPcV.js} +10 -10
  172. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-CJom_-c2.js.map → GrDropdownMenu-DFEJLPcV.js.map} +1 -1
  173. package/dist/components/GrDropdownMenu/index.js +2 -2
  174. package/dist/components/GrEmptyState/chunks/{GrEmptyState-yOuZW7-t.js → GrEmptyState-CA3BiTV7.js} +3 -3
  175. package/dist/components/GrEmptyState/chunks/{GrEmptyState-yOuZW7-t.js.map → GrEmptyState-CA3BiTV7.js.map} +1 -1
  176. package/dist/components/GrEmptyState/index.js +2 -2
  177. package/dist/components/GrFileUpload/chunks/{GrFileUpload-CBKK3dgC.js → GrFileUpload-DvWPpiJS.js} +26 -23
  178. package/dist/components/GrFileUpload/chunks/GrFileUpload-DvWPpiJS.js.map +1 -0
  179. package/dist/components/GrFileUpload/index.js +3 -3
  180. package/dist/components/GrFormField/chunks/{GrFormField-U7c_aDPJ.js → GrFormField-BujNQrw8.js} +1 -1
  181. package/dist/components/GrFormField/chunks/{GrFormField-U7c_aDPJ.js.map → GrFormField-BujNQrw8.js.map} +1 -1
  182. package/dist/components/GrFormField/index.js +2 -2
  183. package/dist/components/GrFormFile/chunks/{GrFormFile-CkR6cYqf.js → GrFormFile-CXcqqdvV.js} +38 -31
  184. package/dist/components/GrFormFile/chunks/GrFormFile-CXcqqdvV.js.map +1 -0
  185. package/dist/components/GrFormFile/index.js +2 -2
  186. package/dist/components/GrFormSection/chunks/{GrFormSection-dbyzqxYk.js → GrFormSection-Ce21jcgo.js} +1 -1
  187. package/dist/components/GrFormSection/chunks/{GrFormSection-dbyzqxYk.js.map → GrFormSection-Ce21jcgo.js.map} +1 -1
  188. package/dist/components/GrFormSection/index.js +2 -2
  189. package/dist/components/GrIcon/chunks/{GrIcon-BV7RBU_0.js → GrIcon-D9AWQLk2.js} +3 -3
  190. package/dist/components/GrIcon/chunks/{GrIcon-BV7RBU_0.js.map → GrIcon-D9AWQLk2.js.map} +1 -1
  191. package/dist/components/GrIcon/index.js +2 -2
  192. package/dist/components/GrImageViewer/chunks/{GrImageViewer-BG40DsHa.js → GrImageViewer-OCUIrNh2.js} +44 -33
  193. package/dist/components/GrImageViewer/chunks/GrImageViewer-OCUIrNh2.js.map +1 -0
  194. package/dist/components/GrImageViewer/index.js +2 -2
  195. package/dist/components/GrInput/chunks/{GrInput-gwFQ1sk4.js → GrInput-C8pOJgCi.js} +43 -66
  196. package/dist/components/GrInput/chunks/GrInput-C8pOJgCi.js.map +1 -0
  197. package/dist/components/GrInput/index.js +2 -2
  198. package/dist/components/GrInputTag/chunks/{GrInputTag-g-KdUI_Z.js → GrInputTag-zMgFqp2g.js} +27 -24
  199. package/dist/components/GrInputTag/chunks/GrInputTag-zMgFqp2g.js.map +1 -0
  200. package/dist/components/GrInputTag/index.js +2 -2
  201. package/dist/components/GrLink/chunks/{GrLink-KSTmk9Yq.js → GrLink-CYUe-Q8k.js} +14 -7
  202. package/dist/components/GrLink/chunks/GrLink-CYUe-Q8k.js.map +1 -0
  203. package/dist/components/GrLink/index.js +2 -2
  204. package/dist/components/GrList/chunks/{GrList-CUW2sRm_.js → GrList-Dx772Ns4.js} +1 -1
  205. package/dist/components/GrList/chunks/{GrList-CUW2sRm_.js.map → GrList-Dx772Ns4.js.map} +1 -1
  206. package/dist/components/GrList/index.js +2 -2
  207. package/dist/components/GrLoading/chunks/{GrLoading-mfyfghxs.js → GrLoading--X_7rdbb.js} +7 -7
  208. package/dist/components/GrLoading/chunks/{GrLoading-mfyfghxs.js.map → GrLoading--X_7rdbb.js.map} +1 -1
  209. package/dist/components/GrLoading/index.js +2 -2
  210. package/dist/components/GrModal/chunks/{GrModal-CSOL3fHQ.js → GrModal-BkjW9jZS.js} +7 -7
  211. package/dist/components/GrModal/chunks/{GrModal-CSOL3fHQ.js.map → GrModal-BkjW9jZS.js.map} +1 -1
  212. package/dist/components/GrModal/index.js +3 -3
  213. package/dist/components/GrNavbar/chunks/{GrNavbar-CHxwtFIR.js → GrNavbar-DW3MiIIf.js} +6 -6
  214. package/dist/components/GrNavbar/chunks/{GrNavbar-CHxwtFIR.js.map → GrNavbar-DW3MiIIf.js.map} +1 -1
  215. package/dist/components/GrNavbar/index.js +2 -2
  216. package/dist/components/GrNumberInput/chunks/{GrNumberInput-ClPBwkxx.js → GrNumberInput-CldPIWQx.js} +51 -61
  217. package/dist/components/GrNumberInput/chunks/GrNumberInput-CldPIWQx.js.map +1 -0
  218. package/dist/components/GrNumberInput/index.js +2 -2
  219. package/dist/components/GrPagination/chunks/{GrPagination-D2GS0ShQ.js → GrPagination-Bu9wv6it.js} +76 -25
  220. package/dist/components/GrPagination/chunks/GrPagination-Bu9wv6it.js.map +1 -0
  221. package/dist/components/GrPagination/index.js +2 -2
  222. package/dist/components/GrProgressBar/chunks/{GrProgressBar-BBSFpVEq.js → GrProgressBar-CC3z-Zqp.js} +3 -3
  223. package/dist/components/GrProgressBar/chunks/{GrProgressBar-BBSFpVEq.js.map → GrProgressBar-CC3z-Zqp.js.map} +1 -1
  224. package/dist/components/GrProgressBar/index.js +2 -2
  225. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-D_TFqKsF.js → GrPromptDialog-TmWXbpEP.js} +31 -23
  226. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-TmWXbpEP.js.map +1 -0
  227. package/dist/components/GrPromptDialog/index.js +2 -2
  228. package/dist/components/GrRadio/chunks/{GrRadio-CSbTnrom.js → GrRadio-CPTixXaY.js} +6 -6
  229. package/dist/components/GrRadio/chunks/{GrRadio-CSbTnrom.js.map → GrRadio-CPTixXaY.js.map} +1 -1
  230. package/dist/components/GrRadio/index.js +2 -2
  231. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-DsrnTygR.js → GrRadioGroup-vKZCbkCp.js} +3 -3
  232. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-DsrnTygR.js.map → GrRadioGroup-vKZCbkCp.js.map} +1 -1
  233. package/dist/components/GrRadioGroup/index.js +2 -2
  234. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-K1uZ1mYD.js → GrResponseErrorBanner-BWJNe2gr.js} +21 -18
  235. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-BWJNe2gr.js.map +1 -0
  236. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-bM8FC_Bw.js → GrResponseErrorBanner-Cdu9ekK9.js} +5 -5
  237. package/dist/components/GrResponseErrorBanner/chunks/{GrResponseErrorBanner-bM8FC_Bw.js.map → GrResponseErrorBanner-Cdu9ekK9.js.map} +1 -1
  238. package/dist/components/GrResponseErrorBanner/index.js +2 -2
  239. package/dist/components/GrSegmented/chunks/{GrSegmented-DpZGs4VX.js → GrSegmented-C1y0UXpQ.js} +5 -5
  240. package/dist/components/GrSegmented/chunks/{GrSegmented-DpZGs4VX.js.map → GrSegmented-C1y0UXpQ.js.map} +1 -1
  241. package/dist/components/GrSegmented/index.js +2 -2
  242. package/dist/components/GrSelect/chunks/{GrSelect-DSz7jvUb.js → GrSelect-RShK21lK.js} +84 -64
  243. package/dist/components/GrSelect/chunks/GrSelect-RShK21lK.js.map +1 -0
  244. package/dist/components/GrSelect/index.js +2 -2
  245. package/dist/components/GrSidebar/chunks/GrSidebar-DkWozzwA.js +238 -0
  246. package/dist/components/GrSidebar/chunks/GrSidebar-DkWozzwA.js.map +1 -0
  247. package/dist/components/GrSidebar/index.js +3 -3
  248. package/dist/components/GrSkeleton/chunks/{GrSkeleton-B05K0QKh.js → GrSkeleton-DsN-_CDZ.js} +1 -1
  249. package/dist/components/GrSkeleton/chunks/{GrSkeleton-B05K0QKh.js.map → GrSkeleton-DsN-_CDZ.js.map} +1 -1
  250. package/dist/components/GrSkeleton/index.js +2 -2
  251. package/dist/components/GrSwitch/chunks/{GrSwitch-CSRtcN5-.js → GrSwitch-DAioyccZ.js} +10 -10
  252. package/dist/components/GrSwitch/chunks/{GrSwitch-CSRtcN5-.js.map → GrSwitch-DAioyccZ.js.map} +1 -1
  253. package/dist/components/GrSwitch/index.js +2 -2
  254. package/dist/components/GrTable/chunks/{GrTable-dTWUxzRm.js → GrTable-Db3hRnKA.js} +3 -3
  255. package/dist/components/GrTable/chunks/{GrTable-dTWUxzRm.js.map → GrTable-Db3hRnKA.js.map} +1 -1
  256. package/dist/components/GrTable/index.js +2 -2
  257. package/dist/components/GrTabs/chunks/{GrTabs-BfeVNMFJ.js → GrTabs-Z-FDJUr_.js} +3 -3
  258. package/dist/components/GrTabs/chunks/{GrTabs-BfeVNMFJ.js.map → GrTabs-Z-FDJUr_.js.map} +1 -1
  259. package/dist/components/GrTabs/index.js +2 -2
  260. package/dist/components/GrTextarea/chunks/{GrTextarea-CBBzpF2S.js → GrTextarea-D56YxhKq.js} +3 -3
  261. package/dist/components/GrTextarea/chunks/{GrTextarea-CBBzpF2S.js.map → GrTextarea-D56YxhKq.js.map} +1 -1
  262. package/dist/components/GrTextarea/index.js +2 -2
  263. package/dist/components/GrToaster/chunks/GrToaster-eI8YvnIo.js +189 -0
  264. package/dist/components/GrToaster/chunks/GrToaster-eI8YvnIo.js.map +1 -0
  265. package/dist/components/GrToaster/index.js +2 -2
  266. package/dist/components/GrTooltip/chunks/{GrTooltip-BC-40SA5.js → GrTooltip-BeyZ8ssR.js} +10 -10
  267. package/dist/components/GrTooltip/chunks/{GrTooltip-BC-40SA5.js.map → GrTooltip-BeyZ8ssR.js.map} +1 -1
  268. package/dist/components/GrTooltip/index.js +2 -2
  269. package/dist/components/GrTree/chunks/{GrTree-uZr5SyQI.js → GrTree-D3ODe2dB.js} +40 -35
  270. package/dist/components/GrTree/chunks/GrTree-D3ODe2dB.js.map +1 -0
  271. package/dist/components/GrTree/index.js +2 -2
  272. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-CytivcCa.js → GrTreeSelect-B2xBKs5Q.js} +16 -16
  273. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-CytivcCa.js.map → GrTreeSelect-B2xBKs5Q.js.map} +1 -1
  274. package/dist/components/GrTreeSelect/index.js +2 -2
  275. package/dist/composables/useTheme.js +48 -8
  276. package/dist/composables/useTheme.js.map +1 -1
  277. package/dist/composables/useToast.js +88 -26
  278. package/dist/composables/useToast.js.map +1 -1
  279. package/dist/directives/autofocus.js.map +1 -1
  280. package/dist/directives/autosize.js.map +1 -1
  281. package/dist/directives/clickOutside.js.map +1 -1
  282. package/dist/directives/dropzone.js +6 -5
  283. package/dist/directives/dropzone.js.map +1 -1
  284. package/dist/directives/hotkey.js +24 -7
  285. package/dist/directives/hotkey.js.map +1 -1
  286. package/dist/directives/loading.js +2 -2
  287. package/dist/directives/loading.js.map +1 -1
  288. package/dist/fileValidation/index.js +1 -1
  289. package/dist/granular-provider-node.js +7 -7
  290. package/dist/granular-provider-node.js.map +1 -1
  291. package/dist/granular-provider.js +1 -1
  292. package/dist/granular-provider.js.map +1 -1
  293. package/dist/i18n/all.js +1 -1
  294. package/dist/i18n/all.js.map +1 -1
  295. package/dist/i18n/index.js +2 -2
  296. package/dist/index.js +109 -534
  297. package/dist/index.js.map +1 -1
  298. package/dist/styles/base.css +32 -0
  299. package/dist/styles/index.css +15 -0
  300. package/dist/styles/preflight.css +29 -0
  301. package/dist/styles/themes/dark.css +107 -0
  302. package/dist/styles/themes/light.css +98 -0
  303. package/dist/styles/tokens.css +135 -0
  304. package/dist/types/src/components/GrButton/GrButton.vue.d.ts +25 -2
  305. package/dist/types/src/components/GrCheckbox/GrCheckbox.vue.d.ts +7 -2
  306. package/dist/types/src/components/GrConfirmDialog/GrConfirmDialog.vue.d.ts +8 -8
  307. package/dist/types/src/components/GrDataTable/GrDataTable.vue.d.ts +1 -1
  308. package/dist/types/src/components/GrDialog/GrDialog.vue.d.ts +2 -2
  309. package/dist/types/src/components/GrDialog/GrDialogHeader.vue.d.ts +2 -2
  310. package/dist/types/src/components/GrDrawer/GrDrawer.vue.d.ts +2 -2
  311. package/dist/types/src/components/GrFileUpload/GrFileUpload.vue.d.ts +4 -4
  312. package/dist/types/src/components/GrFormFile/GrFormFile.vue.d.ts +11 -11
  313. package/dist/types/src/components/GrImageViewer/GrImageViewer.vue.d.ts +18 -18
  314. package/dist/types/src/components/GrInput/GrInput.vue.d.ts +14 -0
  315. package/dist/types/src/components/GrInput/grInputStyles.d.ts +3 -3
  316. package/dist/types/src/components/GrInputTag/GrInputTag.vue.d.ts +2 -2
  317. package/dist/types/src/components/GrLink/GrLink.vue.d.ts +12 -6
  318. package/dist/types/src/components/GrLink/grLinkStyles.d.ts +31 -3
  319. package/dist/types/src/components/GrLink/index.d.ts +1 -1
  320. package/dist/types/src/components/GrLoading/GrLoading.vue.d.ts +1 -1
  321. package/dist/types/src/components/GrModal/grModalStyles.d.ts +1 -1
  322. package/dist/types/src/components/GrNumberInput/GrNumberInput.vue.d.ts +17 -4
  323. package/dist/types/src/components/GrPagination/GrPagination.vue.d.ts +13 -1
  324. package/dist/types/src/components/GrPromptDialog/GrPromptDialog.vue.d.ts +12 -12
  325. package/dist/types/src/components/GrSegmented/GrSegmented.vue.d.ts +1 -1
  326. package/dist/types/src/components/GrSegmented/grSegmentedStyles.d.ts +5 -5
  327. package/dist/types/src/components/GrSelect/GrSelect.vue.d.ts +1 -1
  328. package/dist/types/src/components/GrSelect/grSelectStyles.d.ts +2 -1
  329. package/dist/types/src/components/GrSidebar/GrSidebar.vue.d.ts +33 -10
  330. package/dist/types/src/components/GrSidebar/GrSidebarItem.vue.d.ts +64 -0
  331. package/dist/types/src/components/GrSidebar/index.d.ts +1 -0
  332. package/dist/types/src/components/GrSidebar/sidebarContext.d.ts +9 -0
  333. package/dist/types/src/components/GrSwitch/GrSwitch.vue.d.ts +1 -1
  334. package/dist/types/src/components/GrSwitch/grSwitchStyles.d.ts +2 -2
  335. package/dist/types/src/components/GrToaster/GrToaster.vue.d.ts +9 -4
  336. package/dist/types/src/components/GrTree/GrTree.vue.d.ts +1 -1
  337. package/dist/types/src/components/GrTreeSelect/GrTreeSelect.vue.d.ts +2 -2
  338. package/dist/types/src/components/GrTreeSelect/grTreeSelectStyles.d.ts +1 -1
  339. package/dist/types/src/components/GrTreeSelect/grTreeSelectTypes.d.ts +1 -1
  340. package/dist/types/src/composables/internal/useAddonMeasurement.d.ts +18 -0
  341. package/dist/types/src/composables/internal/useEscapeToClose.d.ts +11 -0
  342. package/dist/types/src/composables/useTheme.d.ts +5 -2
  343. package/dist/types/src/composables/useToast.d.ts +33 -1
  344. package/dist/types/src/directives/hotkey.d.ts +14 -0
  345. package/dist/types/src/granular-provider/shared.d.ts +1 -3
  346. package/dist/types/src/i18n/messages/en.d.ts +120 -0
  347. package/dist/types/src/i18n/messages/es.d.ts +120 -0
  348. package/dist/types/src/i18n/messages/ru.d.ts +120 -0
  349. package/dist/types/src/index.d.ts +2 -2
  350. package/dist/vue/index.js.map +1 -1
  351. package/dist/web-types.json +4673 -0
  352. package/package.json +26 -20
  353. package/dist/chunks/arrow-up-DZdIrpaF.js.map +0 -1
  354. package/dist/chunks/config-C6zT56Jc2.js.map +0 -1
  355. package/dist/chunks/config-C8MM2Dg0.js.map +0 -1
  356. package/dist/chunks/config-NkbzVFZo.js +0 -59
  357. package/dist/chunks/config-NkbzVFZo.js.map +0 -1
  358. package/dist/chunks/config-RjfJFv1Y.js.map +0 -1
  359. package/dist/chunks/config-hSlCXHoG.js.map +0 -1
  360. package/dist/chunks/en-B_fSdoTi.js +0 -72
  361. package/dist/chunks/en-B_fSdoTi.js.map +0 -1
  362. package/dist/chunks/es-DKP6fLir.js +0 -72
  363. package/dist/chunks/es-DKP6fLir.js.map +0 -1
  364. package/dist/chunks/grBadgeStyles-Cq0hH2Ls.js.map +0 -1
  365. package/dist/chunks/grButtonStyles-DKuXUemw.js +0 -191
  366. package/dist/chunks/grButtonStyles-DKuXUemw.js.map +0 -1
  367. package/dist/chunks/grSelectStyles-AjWWl007.js.map +0 -1
  368. package/dist/chunks/grStyle-D-gPHdyW.js.map +0 -1
  369. package/dist/chunks/info-C0bHmdZq.js.map +0 -1
  370. package/dist/chunks/loader-circle-BUntgosj.js.map +0 -1
  371. package/dist/chunks/ru-S6VlnurJ.js +0 -72
  372. package/dist/chunks/ru-S6VlnurJ.js.map +0 -1
  373. package/dist/chunks/safelist-_UVzJrgE2.js.map +0 -1
  374. package/dist/chunks/shared-DpjTvFno.js +0 -169
  375. package/dist/chunks/shared-DpjTvFno.js.map +0 -1
  376. package/dist/chunks/x-Pa6C2hwi.js.map +0 -1
  377. package/dist/chunks/x-circle-DQSlBLmX.js.map +0 -1
  378. package/dist/components/GrAlert/chunks/GrAlert-HyCjYJeL.js.map +0 -1
  379. package/dist/components/GrButton/chunks/GrButton-CPDKonoB.js +0 -83
  380. package/dist/components/GrButton/chunks/GrButton-CPDKonoB.js.map +0 -1
  381. package/dist/components/GrButtonGroup/chunks/GrButtonGroup-CPOH6V-P.js.map +0 -1
  382. package/dist/components/GrCard/chunks/GrCard-6yk1RRAQ.js.map +0 -1
  383. package/dist/components/GrCheckbox/chunks/GrCheckbox-Bt3d7ckE.js.map +0 -1
  384. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-Bi2KLumL.js.map +0 -1
  385. package/dist/components/GrDialog/chunks/GrDialog-CxK4Lj4F.js.map +0 -1
  386. package/dist/components/GrDrawer/chunks/GrDrawer-BW3wtI7h.js.map +0 -1
  387. package/dist/components/GrDropdown/chunks/GrDropdown-BGKeEfZ1.js.map +0 -1
  388. package/dist/components/GrFileUpload/chunks/GrFileUpload-CBKK3dgC.js.map +0 -1
  389. package/dist/components/GrFormFile/chunks/GrFormFile-CkR6cYqf.js.map +0 -1
  390. package/dist/components/GrImageViewer/chunks/GrImageViewer-BG40DsHa.js.map +0 -1
  391. package/dist/components/GrInput/chunks/GrInput-gwFQ1sk4.js.map +0 -1
  392. package/dist/components/GrInputTag/chunks/GrInputTag-g-KdUI_Z.js.map +0 -1
  393. package/dist/components/GrLink/chunks/GrLink-KSTmk9Yq.js.map +0 -1
  394. package/dist/components/GrNumberInput/chunks/GrNumberInput-ClPBwkxx.js.map +0 -1
  395. package/dist/components/GrPagination/chunks/GrPagination-D2GS0ShQ.js.map +0 -1
  396. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-D_TFqKsF.js.map +0 -1
  397. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-K1uZ1mYD.js.map +0 -1
  398. package/dist/components/GrSelect/chunks/GrSelect-DSz7jvUb.js.map +0 -1
  399. package/dist/components/GrSidebar/chunks/GrSidebar-BW8LRMZ-.js +0 -44
  400. package/dist/components/GrSidebar/chunks/GrSidebar-BW8LRMZ-.js.map +0 -1
  401. package/dist/components/GrToaster/chunks/GrToaster-C6_iHk2J.js +0 -172
  402. package/dist/components/GrToaster/chunks/GrToaster-C6_iHk2J.js.map +0 -1
  403. package/dist/components/GrTree/chunks/GrTree-uZr5SyQI.js.map +0 -1
  404. /package/dist/chunks/{_plugin-vue_export-helper-DQR7Sy7Q.js → _plugin-vue_export-helper-BOaGB7Aw.js} +0 -0
  405. /package/dist/chunks/{adapter-BqqjEZGU.js → adapter-CAOxmn2G.js} +0 -0
  406. /package/dist/chunks/{arrow-up-DZdIrpaF.js → arrow-up-C_G4jg8M.js} +0 -0
  407. /package/dist/chunks/{classTokens-BPeBXNzu.js → classTokens-BzazaERD.js} +0 -0
  408. /package/dist/chunks/{config-DZrlovR42.js → config-8Pcutu1j2.js} +0 -0
  409. /package/dist/chunks/{config-VJuoznpH.js → config-B0qIpo8m.js} +0 -0
  410. /package/dist/chunks/{config-DbghHyY_.js → config-BEegFP74.js} +0 -0
  411. /package/dist/chunks/{config-BeBsN0c12.js → config-BLHqZhy-2.js} +0 -0
  412. /package/dist/chunks/{config-BV4vBzdm.js → config-BNu8lFQB.js} +0 -0
  413. /package/dist/chunks/{config-DhQc1TRY.js → config-BUHuGBik.js} +0 -0
  414. /package/dist/chunks/{config-CPSdAjUi.js → config-BWGGp7uV.js} +0 -0
  415. /package/dist/chunks/{config-BduXEXjt.js → config-BXtAmU3s.js} +0 -0
  416. /package/dist/chunks/{config-CzgNEHKi.js → config-Bah4oHwL.js} +0 -0
  417. /package/dist/chunks/{config-lMDE_8A5.js → config-C86UzUYf.js} +0 -0
  418. /package/dist/chunks/{config-BgBWt9-A.js → config-C9AcVDkv.js} +0 -0
  419. /package/dist/chunks/{config-BuoIngj32.js → config-CGHLoBlH2.js} +0 -0
  420. /package/dist/chunks/{config-ChQxl75m.js → config-CThzliFi.js} +0 -0
  421. /package/dist/chunks/{config-DDwBSoc_.js → config-Cb2PAlSD.js} +0 -0
  422. /package/dist/chunks/{config-C5-ujXCI.js → config-D7GZO-Dx.js} +0 -0
  423. /package/dist/chunks/{config-CUwF4E4R.js → config-DBmdgoVf.js} +0 -0
  424. /package/dist/chunks/{config-C9MblwGq.js → config-DICOd-2X.js} +0 -0
  425. /package/dist/chunks/{config-BLa1TEGm2.js → config-DpqOnJiz2.js} +0 -0
  426. /package/dist/chunks/{config-V3LF-b_F.js → config-Dxuwwepq.js} +0 -0
  427. /package/dist/chunks/{config-Doa_gU40.js → config-HZto2PVy.js} +0 -0
  428. /package/dist/chunks/{config-Dl5aZ5VR.js → config-JOtB4mzs.js} +0 -0
  429. /package/dist/chunks/{config-CWTfyPNI.js → config-JpHA4Xx0.js} +0 -0
  430. /package/dist/chunks/{config-B3dn-gdC.js → config-PFg39mYo.js} +0 -0
  431. /package/dist/chunks/{config-Bh4NWWsQ.js → config-QaIc_gRa.js} +0 -0
  432. /package/dist/chunks/{config-vcDVCYXo.js → config-U4m9PSql.js} +0 -0
  433. /package/dist/chunks/{config-C_q_4FrU.js → config-ZiXWIRBX.js} +0 -0
  434. /package/dist/chunks/{config-DDUPnue12.js → config-ipvU0lzP2.js} +0 -0
  435. /package/dist/chunks/{config-D5ek7VSi.js → config-xR4XVmcy.js} +0 -0
  436. /package/dist/chunks/{dialogShared-BtXUk6Zc.js → dialogShared-CxW62PQE.js} +0 -0
  437. /package/dist/chunks/{grLoadingStyles-DmI-SJ3i.js → grLoadingStyles-R5sreH__.js} +0 -0
  438. /package/dist/chunks/{info-C0bHmdZq.js → info-Be2OccTu.js} +0 -0
  439. /package/dist/chunks/{loader-circle-BUntgosj.js → loader-circle-CfVLz7lb.js} +0 -0
  440. /package/dist/chunks/{x-Pa6C2hwi.js → x-2KXnqxiD.js} +0 -0
  441. /package/dist/chunks/{x-circle-DQSlBLmX.js → x-circle-BCBURwyX.js} +0 -0
  442. /package/dist/components/GrBottomNav/chunks/{GrBottomNav-XPHwd7UQ.js → GrBottomNav-usuMgG8_.js} +0 -0
@@ -1,4 +1,5 @@
1
- import { n as he, o as Ye, r as Ge, t as Se } from "../../../chunks/transition-mJ3PZCHH.js";
1
+ import { t as useGranularityTranslations } from "../../../chunks/granularityI18n-DoV7Ca2m.js";
2
+ import { n as he, o as Ye, r as Ge, t as Se } from "../../../chunks/transition-TLFw4KBn.js";
2
3
  import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, guardReactiveProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onBeforeUnmount, openBlock, ref, renderSlot, toDisplayString, unref, watch, withCtx } from "vue";
3
4
  //#region src/components/GrImageViewer/GrImageViewer.vue?vue&type=script&setup=true&lang.ts
4
5
  var _hoisted_1 = { class: "fixed inset-0 overflow-hidden" };
@@ -7,12 +8,12 @@ var _hoisted_3 = { class: "pointer-events-auto flex items-center justify-between
7
8
  var _hoisted_4 = { class: "flex items-center gap-2" };
8
9
  var _hoisted_5 = {
9
10
  key: 0,
10
- "data-ds-image-viewer-progress": "",
11
+ "data-gr-image-viewer-progress": "",
11
12
  class: "rounded-full bg-black/35 px-3 py-1 text-xs font-600 text-white/95 sm:text-sm"
12
13
  };
13
14
  var _hoisted_6 = {
14
15
  key: 1,
15
- "data-ds-image-viewer-zoom-value": "",
16
+ "data-gr-image-viewer-zoom-value": "",
16
17
  class: "rounded-full bg-black/35 px-3 py-1 text-xs font-700 text-white/95 sm:text-sm"
17
18
  };
18
19
  var _hoisted_7 = ["aria-label"];
@@ -22,7 +23,7 @@ var _hoisted_10 = { class: "h-full w-full flex items-center justify-center" };
22
23
  var _hoisted_11 = ["src"];
23
24
  var _hoisted_12 = {
24
25
  key: 1,
25
- class: "rounded-[var(--ds-radius-xl)] border border-white/20 bg-black/25 px-4 py-3 text-sm text-white/80"
26
+ class: "rounded-[var(--gr-radius-xl)] border border-white/20 bg-black/25 px-4 py-3 text-sm text-white/80"
26
27
  };
27
28
  var _hoisted_13 = { class: "pointer-events-none absolute inset-x-0 bottom-0 z-30 px-3 pb-3 sm:px-6 sm:pb-6" };
28
29
  var _hoisted_14 = { class: "pointer-events-auto mx-auto w-full max-w-max" };
@@ -76,15 +77,15 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
76
77
  default: false
77
78
  },
78
79
  zIndex: { default: void 0 },
79
- closeLabel: { default: "Close image viewer" },
80
- prevLabel: { default: "Previous image" },
81
- nextLabel: { default: "Next image" },
82
- zoomInLabel: { default: "Zoom in" },
83
- zoomOutLabel: { default: "Zoom out" },
84
- resetZoomLabel: { default: "Reset zoom" },
85
- rotateLeftLabel: { default: "Rotate left" },
86
- rotateRightLabel: { default: "Rotate right" },
87
- emptyText: { default: "No image" }
80
+ closeLabel: { default: void 0 },
81
+ prevLabel: { default: void 0 },
82
+ nextLabel: { default: void 0 },
83
+ zoomInLabel: { default: void 0 },
84
+ zoomOutLabel: { default: void 0 },
85
+ resetZoomLabel: { default: void 0 },
86
+ rotateLeftLabel: { default: void 0 },
87
+ rotateRightLabel: { default: void 0 },
88
+ emptyText: { default: void 0 }
88
89
  },
89
90
  emits: [
90
91
  "update:modelValue",
@@ -94,6 +95,16 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
94
95
  ],
95
96
  setup(__props, { emit: __emit }) {
96
97
  const props = __props;
98
+ const { t } = useGranularityTranslations();
99
+ const resolvedCloseLabel = computed(() => props.closeLabel ?? t("gr.imageViewer.close", "Close image viewer"));
100
+ const resolvedPrevLabel = computed(() => props.prevLabel ?? t("gr.imageViewer.prev", "Previous image"));
101
+ const resolvedNextLabel = computed(() => props.nextLabel ?? t("gr.imageViewer.next", "Next image"));
102
+ const resolvedZoomInLabel = computed(() => props.zoomInLabel ?? t("gr.imageViewer.zoomIn", "Zoom in"));
103
+ const resolvedZoomOutLabel = computed(() => props.zoomOutLabel ?? t("gr.imageViewer.zoomOut", "Zoom out"));
104
+ const resolvedResetZoomLabel = computed(() => props.resetZoomLabel ?? t("gr.imageViewer.resetZoom", "Reset zoom"));
105
+ const resolvedRotateLeftLabel = computed(() => props.rotateLeftLabel ?? t("gr.imageViewer.rotateLeft", "Rotate left"));
106
+ const resolvedRotateRightLabel = computed(() => props.rotateRightLabel ?? t("gr.imageViewer.rotateRight", "Rotate right"));
107
+ const resolvedEmptyText = computed(() => props.emptyText ?? t("gr.imageViewer.empty", "No image"));
97
108
  const emit = __emit;
98
109
  const TRAILING_ZERO_DECIMAL_RE = /\.0$/;
99
110
  const open = computed(() => props.modelValue);
@@ -412,7 +423,7 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
412
423
  "leave-to": "opacity-0"
413
424
  }, {
414
425
  default: withCtx(() => [createElementVNode("div", {
415
- "data-ds-image-viewer-overlay": "",
426
+ "data-gr-image-viewer-overlay": "",
416
427
  class: "absolute inset-0 bg-black/60 backdrop-blur-sm",
417
428
  "aria-hidden": "true",
418
429
  onClick: onBackdropClick
@@ -428,15 +439,15 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
428
439
  "leave-to": "opacity-0 scale-98"
429
440
  }, {
430
441
  default: withCtx(() => [createVNode(unref(Ge), {
431
- "data-ds-image-viewer-panel": "",
442
+ "data-gr-image-viewer-panel": "",
432
443
  class: "relative z-10 h-full w-full outline-none",
433
444
  tabindex: "-1"
434
445
  }, {
435
446
  default: withCtx(() => [
436
447
  createElementVNode("div", _hoisted_2, [createElementVNode("div", _hoisted_3, [createElementVNode("div", _hoisted_4, [__props.showProgress ? (openBlock(), createElementBlock("div", _hoisted_5, toDisplayString(displayIndex.value) + " / " + toDisplayString(total.value), 1)) : createCommentVNode("", true), __props.showZoomValue ? (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString(zoomValueText.value) + "% ", 1)) : createCommentVNode("", true)]), createElementVNode("button", {
437
448
  type: "button",
438
- "data-ds-image-viewer-close": "",
439
- "aria-label": __props.closeLabel,
449
+ "data-gr-image-viewer-close": "",
450
+ "aria-label": resolvedCloseLabel.value,
440
451
  class: "h-11 w-11 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80",
441
452
  onClick: closeViewer
442
453
  }, [..._cache[0] || (_cache[0] = [createElementVNode("span", {
@@ -450,8 +461,8 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
450
461
  total.value > 1 ? (openBlock(), createElementBlock("button", {
451
462
  key: 0,
452
463
  type: "button",
453
- "data-ds-image-viewer-prev": "",
454
- "aria-label": __props.prevLabel,
464
+ "data-gr-image-viewer-prev": "",
465
+ "aria-label": resolvedPrevLabel.value,
455
466
  class: "absolute left-3 top-1/2 z-20 h-12 w-12 -translate-y-1/2 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 sm:left-6",
456
467
  onClick: prev
457
468
  }, [..._cache[1] || (_cache[1] = [createElementVNode("span", {
@@ -461,8 +472,8 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
461
472
  total.value > 1 ? (openBlock(), createElementBlock("button", {
462
473
  key: 1,
463
474
  type: "button",
464
- "data-ds-image-viewer-next": "",
465
- "aria-label": __props.nextLabel,
475
+ "data-gr-image-viewer-next": "",
476
+ "aria-label": resolvedNextLabel.value,
466
477
  class: "absolute right-3 top-1/2 z-20 h-12 w-12 -translate-y-1/2 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 sm:right-6",
467
478
  onClick: next
468
479
  }, [..._cache[2] || (_cache[2] = [createElementVNode("span", {
@@ -473,7 +484,7 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
473
484
  key: 0,
474
485
  ref_key: "imageEl",
475
486
  ref: imageEl,
476
- "data-ds-image-viewer-image": "",
487
+ "data-gr-image-viewer-image": "",
477
488
  src: currentUrl.value,
478
489
  alt: "",
479
490
  draggable: "false",
@@ -484,27 +495,27 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
484
495
  onPointermove: onPointerMove,
485
496
  onPointerup: onPointerUp,
486
497
  onPointercancel: onPointerUp
487
- }, null, 46, _hoisted_11)) : (openBlock(), createElementBlock("div", _hoisted_12, toDisplayString(__props.emptyText), 1))])
498
+ }, null, 46, _hoisted_11)) : (openBlock(), createElementBlock("div", _hoisted_12, toDisplayString(resolvedEmptyText.value), 1))])
488
499
  ], 32),
489
500
  createElementVNode("div", _hoisted_13, [createElementVNode("div", _hoisted_14, [renderSlot(_ctx.$slots, "toolbar", normalizeProps(guardReactiveProps(toolbarSlotProps.value)), () => [createElementVNode("div", _hoisted_15, [
490
501
  createElementVNode("button", {
491
502
  type: "button",
492
- "data-ds-image-viewer-zoom-out": "",
493
- "aria-label": __props.zoomOutLabel,
503
+ "data-gr-image-viewer-zoom-out": "",
504
+ "aria-label": resolvedZoomOutLabel.value,
494
505
  class: "h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80",
495
506
  onClick: zoomOut
496
507
  }, " − ", 8, _hoisted_16),
497
508
  createElementVNode("button", {
498
509
  type: "button",
499
- "data-ds-image-viewer-zoom-reset": "",
500
- "aria-label": __props.resetZoomLabel,
510
+ "data-gr-image-viewer-zoom-reset": "",
511
+ "aria-label": resolvedResetZoomLabel.value,
501
512
  class: "h-11 min-w-11 px-3 flex items-center justify-center rounded-full text-xs font-700 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80",
502
513
  onClick: resetTransform
503
514
  }, " 100% ", 8, _hoisted_17),
504
515
  createElementVNode("button", {
505
516
  type: "button",
506
- "data-ds-image-viewer-zoom-in": "",
507
- "aria-label": __props.zoomInLabel,
517
+ "data-gr-image-viewer-zoom-in": "",
518
+ "aria-label": resolvedZoomInLabel.value,
508
519
  class: "h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80",
509
520
  onClick: zoomIn
510
521
  }, " + ", 8, _hoisted_18),
@@ -521,15 +532,15 @@ var GrImageViewer_default = /* @__PURE__ */ defineComponent({
521
532
  ], 64)) : (openBlock(), createElementBlock("div", _hoisted_19)),
522
533
  createElementVNode("button", {
523
534
  type: "button",
524
- "data-ds-image-viewer-rotate-left": "",
525
- "aria-label": __props.rotateLeftLabel,
535
+ "data-gr-image-viewer-rotate-left": "",
536
+ "aria-label": resolvedRotateLeftLabel.value,
526
537
  class: "h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80",
527
538
  onClick: rotateLeft
528
539
  }, " ↺ ", 8, _hoisted_20),
529
540
  createElementVNode("button", {
530
541
  type: "button",
531
- "data-ds-image-viewer-rotate-right": "",
532
- "aria-label": __props.rotateRightLabel,
542
+ "data-gr-image-viewer-rotate-right": "",
543
+ "aria-label": resolvedRotateRightLabel.value,
533
544
  class: "h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80",
534
545
  onClick: rotateRight
535
546
  }, " ↻ ", 8, _hoisted_21)
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrImageViewer-OCUIrNh2.js","names":["$slots"],"sources":["../../../../src/components/GrImageViewer/GrImageViewer.vue","../../../../src/components/GrImageViewer/GrImageViewer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'\nimport { Dialog, DialogPanel, TransitionChild, TransitionRoot } from '@headlessui/vue'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\n/**\n * Usage:\n *\n * <GrImageViewer\n * v-model=\"open\"\n * :url-list=\"images\"\n * :initial-index=\"0\"\n * show-progress\n * hide-on-click-modal\n * />\n */\nconst props = withDefaults(\n defineProps<{\n modelValue: boolean\n urlList: string[]\n initialIndex?: number\n zoomRate?: number\n minScale?: number\n maxScale?: number\n hideOnClickModal?: boolean\n closeOnPressEscape?: boolean\n showProgress?: boolean\n showZoomValue?: boolean\n /** Включает масштабирование колесом мыши / жестом на трекпаде. По умолчанию включено. */\n wheelZoom?: boolean\n /** Включает перетаскивание (pan) картинки мышью. При наведении курсор «рука». По умолчанию выключено. */\n draggable?: boolean\n zIndex?: number\n /** i18n: aria-label кнопки закрытия. */\n closeLabel?: string\n /** i18n: aria-label кнопки «предыдущее изображение». */\n prevLabel?: string\n /** i18n: aria-label кнопки «следующее изображение». */\n nextLabel?: string\n /** i18n: aria-label кнопки «увеличить». */\n zoomInLabel?: string\n /** i18n: aria-label кнопки «уменьшить». */\n zoomOutLabel?: string\n /** i18n: aria-label кнопки «сбросить масштаб». */\n resetZoomLabel?: string\n /** i18n: aria-label кнопки «повернуть влево». */\n rotateLeftLabel?: string\n /** i18n: aria-label кнопки «повернуть вправо». */\n rotateRightLabel?: string\n /** i18n: текст в пустом состоянии (нет изображений). */\n emptyText?: string\n }>(),\n {\n initialIndex: 0,\n zoomRate: 1.2,\n minScale: 0.5,\n maxScale: 5,\n hideOnClickModal: false,\n closeOnPressEscape: true,\n showProgress: false,\n showZoomValue: true,\n wheelZoom: true,\n draggable: false,\n zIndex: undefined,\n closeLabel: undefined,\n prevLabel: undefined,\n nextLabel: undefined,\n zoomInLabel: undefined,\n zoomOutLabel: undefined,\n resetZoomLabel: undefined,\n rotateLeftLabel: undefined,\n rotateRightLabel: undefined,\n emptyText: undefined,\n },\n)\n\nconst { t } = useGranularityTranslations()\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.imageViewer.close', 'Close image viewer'))\nconst resolvedPrevLabel = computed(() => props.prevLabel ?? t('gr.imageViewer.prev', 'Previous image'))\nconst resolvedNextLabel = computed(() => props.nextLabel ?? t('gr.imageViewer.next', 'Next image'))\nconst resolvedZoomInLabel = computed(() => props.zoomInLabel ?? t('gr.imageViewer.zoomIn', 'Zoom in'))\nconst resolvedZoomOutLabel = computed(() => props.zoomOutLabel ?? t('gr.imageViewer.zoomOut', 'Zoom out'))\nconst resolvedResetZoomLabel = computed(() => props.resetZoomLabel ?? t('gr.imageViewer.resetZoom', 'Reset zoom'))\nconst resolvedRotateLeftLabel = computed(() => props.rotateLeftLabel ?? t('gr.imageViewer.rotateLeft', 'Rotate left'))\nconst resolvedRotateRightLabel = computed(() => props.rotateRightLabel ?? t('gr.imageViewer.rotateRight', 'Rotate right'))\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.imageViewer.empty', 'No image'))\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'close'): void\n (e: 'switch', newIndex: number): void\n (e: 'rotate', deg: number): void\n}>()\n\ntype GrImageViewerToolbarActions = {\n close: () => void\n prev: () => void\n next: () => void\n zoomIn: () => void\n zoomOut: () => void\n reset: () => void\n rotateLeft: () => void\n rotateRight: () => void\n}\n\ntype GrImageViewerSlotProps = {\n index: number\n displayIndex: number\n total: number\n scale: number\n rotation: number\n /** Натуральный (исходный) размер картинки, px. 0 пока изображение не загружено. */\n naturalWidth: number\n naturalHeight: number\n /** Фактический размер изображения на экране c учётом scale, px (footprint вдоль осей картинки). */\n renderedWidth: number\n renderedHeight: number\n /** Реальный масштаб относительно натурального размера (доля): renderedWidth / naturalWidth. */\n realScale: number\n /** Реальный масштаб в процентах, отформатированный (например `67`). */\n realScalePercent: string\n actions: GrImageViewerToolbarActions\n}\n\nconst DEFAULT_Z_INDEX = 2000\nconst TRAILING_ZERO_DECIMAL_RE = /\\.0$/\n// Чувствительность масштабирования колесом/трекпадом: чем больше — тем резче реакция.\nconst WHEEL_ZOOM_SENSITIVITY = 0.0015\n// Сколько ms простоя после последнего wheel-события считаем «зум завершён»\n// (после этого возвращаем плавный CSS-переход).\nconst WHEEL_IDLE_MS = 120\n\nconst open = computed(() => props.modelValue)\nconst total = computed(() => props.urlList.length)\nconst hasImages = computed(() => total.value > 0)\n\nconst currentIndex = ref(0)\nconst scale = ref(1)\nconst rotation = ref(0)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\n\nconst imageEl = ref<HTMLImageElement | null>(null)\n\n// Флаг активного зума колесом/трекпадом. Пока true — CSS-переход отключён,\n// чтобы непрерывное масштабирование не «наслаивалось» и не дёргалось.\nconst isWheelZooming = ref(false)\n\n// Накопленный deltaY между кадрами и id запланированного rAF.\nlet pendingWheelDelta = 0\nlet wheelFrameId: number | null = null\nlet wheelIdleTimer: ReturnType<typeof setTimeout> | null = null\n\n// Флаг активного перетаскивания (pan) картинки мышью.\nconst isDragging = ref(false)\n\n// Координаты указателя и offset на момент начала перетаскивания.\nlet dragStartX = 0\nlet dragStartY = 0\nlet dragOffsetStartX = 0\nlet dragOffsetStartY = 0\n\n// Натуральный (исходный) размер картинки, читается из `<img>` при загрузке.\nconst naturalWidth = ref(0)\nconst naturalHeight = ref(0)\n\n// Layout-размер вписанного (`object-contain`) изображения без учёта CSS transform/scale.\nconst fittedWidth = ref(0)\nconst fittedHeight = ref(0)\n\nlet resizeObserver: ResizeObserver | null = null\n\nconst currentUrl = computed(() => {\n if (!hasImages.value) {\n return undefined\n }\n\n return props.urlList[currentIndex.value]\n})\n\nconst displayIndex = computed(() => {\n if (!hasImages.value) {\n return 0\n }\n\n return currentIndex.value + 1\n})\n\nconst viewerStyle = computed(() => ({\n zIndex: String(Number.isFinite(props.zIndex) ? props.zIndex : DEFAULT_Z_INDEX),\n}))\n\nconst imageStyle = computed(() => ({\n transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value}) rotate(${rotation.value}deg)`,\n}))\n\n// Плавный CSS-переход transform только для дискретных зумов (кнопки/клавиши).\n// При непрерывном зуме колесом и при перетаскивании переход отключаем —\n// иначе картинка «дёргается»/наслаивается и тянется за курсором с задержкой.\nconst imageTransitionClass = computed(() =>\n isWheelZooming.value || isDragging.value ? '' : 'transition-transform duration-150 ease-out',\n)\n\n// Курсор «рука» при наведении (grab) и при зажатии (grabbing), только если включён drag.\nconst imageCursorClass = computed(() => {\n if (!props.draggable) {\n return ''\n }\n\n return isDragging.value ? 'cursor-grabbing' : 'cursor-grab'\n})\n\nfunction formatPercent(value: number): string {\n if (Number.isInteger(value)) {\n return String(value)\n }\n\n return value.toFixed(1).replace(TRAILING_ZERO_DECIMAL_RE, '')\n}\n\nconst zoomValueText = computed(() => formatPercent(scale.value * 100))\n\n// Фактический размер изображения на экране вдоль его осей (footprint), c учётом scale.\nconst renderedWidth = computed(() => Math.round(fittedWidth.value * scale.value))\nconst renderedHeight = computed(() => Math.round(fittedHeight.value * scale.value))\n\n// Реальный масштаб относительно натурального размера (доля). Не зависит от rotation,\n// так как scale равномерный по осям картинки.\nconst realScale = computed(() => {\n if (!naturalWidth.value) {\n return 0\n }\n\n return (fittedWidth.value * scale.value) / naturalWidth.value\n})\n\nconst realScalePercent = computed(() => formatPercent(realScale.value * 100))\n\nconst toolbarSlotProps = computed<GrImageViewerSlotProps>(() => ({\n index: currentIndex.value,\n displayIndex: displayIndex.value,\n total: total.value,\n scale: scale.value,\n rotation: rotation.value,\n naturalWidth: naturalWidth.value,\n naturalHeight: naturalHeight.value,\n renderedWidth: renderedWidth.value,\n renderedHeight: renderedHeight.value,\n realScale: realScale.value,\n realScalePercent: realScalePercent.value,\n actions: toolbarActions,\n}))\n\nfunction normalizeIndex(value: number): number {\n if (!hasImages.value) {\n return 0\n }\n\n const normalized = Number.isFinite(value) ? Math.trunc(value) : 0\n\n return ((normalized % total.value) + total.value) % total.value\n}\n\nfunction resetTransform(): void {\n scale.value = 1\n rotation.value = 0\n offsetX.value = 0\n offsetY.value = 0\n isDragging.value = false\n}\n\nfunction resetImageMetrics(): void {\n naturalWidth.value = 0\n naturalHeight.value = 0\n fittedWidth.value = 0\n fittedHeight.value = 0\n}\n\nfunction measureFitted(): void {\n const el = imageEl.value\n\n if (!el) {\n return\n }\n\n // offsetWidth/Height — layout-размер вписанного изображения, без учёта CSS transform.\n fittedWidth.value = el.offsetWidth\n fittedHeight.value = el.offsetHeight\n}\n\nfunction onImageLoad(event: Event): void {\n const el = event.target as HTMLImageElement\n\n naturalWidth.value = el.naturalWidth\n naturalHeight.value = el.naturalHeight\n measureFitted()\n}\n\nfunction startObservingImage(): void {\n const el = imageEl.value\n\n if (!el || typeof ResizeObserver === 'undefined') {\n return\n }\n\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => measureFitted())\n }\n\n resizeObserver.observe(el)\n\n // Если картинка уже в кэше и `load` не сработал — считаем метрики сразу.\n if (el.complete && el.naturalWidth) {\n naturalWidth.value = el.naturalWidth\n naturalHeight.value = el.naturalHeight\n }\n\n measureFitted()\n}\n\nfunction stopObservingImage(): void {\n resizeObserver?.disconnect()\n}\n\nfunction setIndex(nextIndex: number, options?: { emitSwitch?: boolean }): void {\n const normalizedIndex = normalizeIndex(nextIndex)\n\n if (normalizedIndex === currentIndex.value) {\n return\n }\n\n currentIndex.value = normalizedIndex\n resetTransform()\n resetImageMetrics()\n endWheelZoom()\n\n if (options?.emitSwitch !== false) {\n emit('switch', normalizedIndex)\n }\n}\n\nfunction syncIndexFromInitial(): void {\n if (!hasImages.value) {\n currentIndex.value = 0\n return\n }\n\n currentIndex.value = normalizeIndex(props.initialIndex)\n resetTransform()\n resetImageMetrics()\n endWheelZoom()\n}\n\nfunction preloadAt(index: number): void {\n const url = props.urlList[index]\n\n if (!url) {\n return\n }\n\n const image = new Image()\n image.decoding = 'async'\n image.src = url\n}\n\nfunction closeViewer(): void {\n emit('update:modelValue', false)\n emit('close')\n}\n\nfunction prev(): void {\n setIndex(currentIndex.value - 1)\n}\n\nfunction next(): void {\n setIndex(currentIndex.value + 1)\n}\n\nfunction setScale(value: number): void {\n const clamped = Math.min(props.maxScale, Math.max(props.minScale, value))\n\n scale.value = Number(clamped.toFixed(4))\n}\n\nfunction zoomIn(): void {\n setScale(scale.value * props.zoomRate)\n}\n\nfunction zoomOut(): void {\n setScale(scale.value / props.zoomRate)\n}\n\nfunction cancelWheelFrame(): void {\n if (wheelFrameId !== null) {\n cancelAnimationFrame(wheelFrameId)\n wheelFrameId = null\n }\n}\n\nfunction endWheelZoom(): void {\n if (wheelIdleTimer !== null) {\n clearTimeout(wheelIdleTimer)\n wheelIdleTimer = null\n }\n\n isWheelZooming.value = false\n pendingWheelDelta = 0\n cancelWheelFrame()\n}\n\n// Применяем накопленный за кадр deltaY одним обновлением scale — так рендер\n// происходит не чаще одного раза в кадр (без «дёрганья» от частых обновлений).\nfunction flushWheelZoom(): void {\n wheelFrameId = null\n\n const delta = pendingWheelDelta\n pendingWheelDelta = 0\n\n if (!delta) {\n return\n }\n\n // Экспоненциальный шаг — плавно и одинаково ощущается и для колеса, и для трекпада.\n // delta < 0 (от себя / scroll up) — приближение, delta > 0 — отдаление.\n const factor = Math.exp(-delta * WHEEL_ZOOM_SENSITIVITY)\n\n setScale(scale.value * factor)\n}\n\nfunction onWheel(event: WheelEvent): void {\n if (!props.wheelZoom || !hasImages.value) {\n return\n }\n\n // Не даём странице/оверлею проскроллиться — колесо отдаём под зум.\n event.preventDefault()\n\n // Во время непрерывного зума отключаем CSS-переход: плавность даёт само\n // покадровое обновление, а transition на каждом микрошаге вызывает лаг/наслоение.\n isWheelZooming.value = true\n\n pendingWheelDelta += event.deltaY\n\n if (wheelFrameId === null) {\n wheelFrameId = requestAnimationFrame(flushWheelZoom)\n }\n\n if (wheelIdleTimer !== null) {\n clearTimeout(wheelIdleTimer)\n }\n\n // По завершении жеста возвращаем плавный переход для последующих дискретных зумов.\n wheelIdleTimer = setTimeout(() => {\n wheelIdleTimer = null\n isWheelZooming.value = false\n }, WHEEL_IDLE_MS)\n}\n\nfunction onPointerDown(event: PointerEvent): void {\n // Тянем только основной кнопкой и только если drag включён и есть картинка.\n if (!props.draggable || !hasImages.value || event.button !== 0) {\n return\n }\n\n event.preventDefault()\n\n isDragging.value = true\n dragStartX = event.clientX\n dragStartY = event.clientY\n dragOffsetStartX = offsetX.value\n dragOffsetStartY = offsetY.value\n\n // Захватываем указатель, чтобы движение/отпускание ловились даже за пределами картинки.\n ;(event.currentTarget as Element).setPointerCapture?.(event.pointerId)\n}\n\nfunction onPointerMove(event: PointerEvent): void {\n if (!isDragging.value) {\n return\n }\n\n offsetX.value = dragOffsetStartX + (event.clientX - dragStartX)\n offsetY.value = dragOffsetStartY + (event.clientY - dragStartY)\n}\n\nfunction onPointerUp(event: PointerEvent): void {\n if (!isDragging.value) {\n return\n }\n\n isDragging.value = false\n ;(event.currentTarget as Element).releasePointerCapture?.(event.pointerId)\n}\n\nfunction rotateLeft(): void {\n rotation.value -= 90\n emit('rotate', rotation.value)\n}\n\nfunction rotateRight(): void {\n rotation.value += 90\n emit('rotate', rotation.value)\n}\n\nconst toolbarActions: GrImageViewerToolbarActions = {\n close: closeViewer,\n prev,\n next,\n zoomIn,\n zoomOut,\n reset: resetTransform,\n rotateLeft,\n rotateRight,\n}\n\nfunction onBackdropClick(): void {\n if (!props.hideOnClickModal) {\n return\n }\n\n closeViewer()\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Escape':\n if (!props.closeOnPressEscape) {\n return\n }\n\n event.preventDefault()\n closeViewer()\n return\n\n case 'ArrowLeft':\n event.preventDefault()\n prev()\n return\n\n case 'ArrowRight':\n event.preventDefault()\n next()\n return\n\n case '+':\n case '=':\n case 'Add':\n event.preventDefault()\n zoomIn()\n return\n\n case '-':\n case '_':\n case 'Subtract':\n event.preventDefault()\n zoomOut()\n return\n\n case '0':\n event.preventDefault()\n resetTransform()\n break\n\n default:\n }\n}\n\nwatch(\n () => props.modelValue,\n async (isOpen) => {\n if (!isOpen) {\n stopObservingImage()\n endWheelZoom()\n isDragging.value = false\n return\n }\n\n syncIndexFromInitial()\n await nextTick()\n startObservingImage()\n },\n { immediate: true },\n)\n\nwatch(\n () => props.initialIndex,\n () => {\n if (!props.modelValue) {\n return\n }\n\n syncIndexFromInitial()\n },\n)\n\nwatch(\n () => props.urlList,\n () => {\n if (!props.modelValue) {\n return\n }\n\n syncIndexFromInitial()\n },\n { deep: true },\n)\n\nwatch(\n currentIndex,\n (index) => {\n if (!hasImages.value || total.value < 2) {\n return\n }\n\n preloadAt(normalizeIndex(index - 1))\n preloadAt(normalizeIndex(index + 1))\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n stopObservingImage()\n endWheelZoom()\n})\n</script>\n\n<template>\n <teleport to=\"body\">\n <TransitionRoot :show=\"open\" as=\"template\">\n <Dialog\n as=\"div\"\n class=\"fixed inset-0\"\n :style=\"viewerStyle\"\n role=\"dialog\"\n aria-modal=\"true\"\n :static=\"true\"\n @keydown=\"onKeydown\"\n >\n <div class=\"fixed inset-0 overflow-hidden\">\n <TransitionChild\n as=\"template\"\n enter=\"duration-150 ease-out\"\n enter-from=\"opacity-0\"\n enter-to=\"opacity-100\"\n leave=\"duration-120 ease-in\"\n leave-from=\"opacity-100\"\n leave-to=\"opacity-0\"\n >\n <div\n data-gr-image-viewer-overlay\n class=\"absolute inset-0 bg-black/60 backdrop-blur-sm\"\n aria-hidden=\"true\"\n @click=\"onBackdropClick\"\n />\n </TransitionChild>\n\n <TransitionChild\n as=\"template\"\n enter=\"duration-180 ease-out\"\n enter-from=\"opacity-0 scale-98\"\n enter-to=\"opacity-100 scale-100\"\n leave=\"duration-130 ease-in\"\n leave-from=\"opacity-100 scale-100\"\n leave-to=\"opacity-0 scale-98\"\n >\n <DialogPanel\n data-gr-image-viewer-panel\n class=\"relative z-10 h-full w-full outline-none\"\n tabindex=\"-1\"\n >\n <div class=\"pointer-events-none absolute inset-x-0 top-0 z-30 px-3 py-3 sm:px-6\">\n <div class=\"pointer-events-auto flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-2\">\n <div\n v-if=\"showProgress\"\n data-gr-image-viewer-progress\n class=\"rounded-full bg-black/35 px-3 py-1 text-xs font-600 text-white/95 sm:text-sm\"\n >\n {{ displayIndex }} / {{ total }}\n </div>\n\n <div\n v-if=\"showZoomValue\"\n data-gr-image-viewer-zoom-value\n class=\"rounded-full bg-black/35 px-3 py-1 text-xs font-700 text-white/95 sm:text-sm\"\n >\n {{ zoomValueText }}%\n </div>\n </div>\n\n <button\n type=\"button\"\n data-gr-image-viewer-close\n :aria-label=\"resolvedCloseLabel\"\n class=\"h-11 w-11 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"closeViewer\"\n >\n <span aria-hidden=\"true\" class=\"text-lg leading-none\">✕</span>\n </button>\n </div>\n </div>\n\n <div\n class=\"relative z-10 h-full w-full flex items-center justify-center px-16 py-16 sm:px-24 sm:py-20\"\n @wheel=\"onWheel\"\n >\n <button\n v-if=\"total > 1\"\n type=\"button\"\n data-gr-image-viewer-prev\n :aria-label=\"resolvedPrevLabel\"\n class=\"absolute left-3 top-1/2 z-20 h-12 w-12 -translate-y-1/2 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 sm:left-6\"\n @click=\"prev\"\n >\n <span aria-hidden=\"true\" class=\"text-xl leading-none\">‹</span>\n </button>\n\n <button\n v-if=\"total > 1\"\n type=\"button\"\n data-gr-image-viewer-next\n :aria-label=\"resolvedNextLabel\"\n class=\"absolute right-3 top-1/2 z-20 h-12 w-12 -translate-y-1/2 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 sm:right-6\"\n @click=\"next\"\n >\n <span aria-hidden=\"true\" class=\"text-xl leading-none\">›</span>\n </button>\n\n <div class=\"h-full w-full flex items-center justify-center\">\n <img\n v-if=\"currentUrl\"\n ref=\"imageEl\"\n data-gr-image-viewer-image\n :src=\"currentUrl\"\n alt=\"\"\n draggable=\"false\"\n class=\"max-h-full max-w-full select-none object-contain will-change-transform\"\n :class=\"[imageTransitionClass, imageCursorClass]\"\n :style=\"imageStyle\"\n @load=\"onImageLoad\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerUp\"\n >\n\n <div\n v-else\n class=\"rounded-[var(--gr-radius-xl)] border border-white/20 bg-black/25 px-4 py-3 text-sm text-white/80\"\n >\n {{ resolvedEmptyText }}\n </div>\n </div>\n </div>\n\n <div class=\"pointer-events-none absolute inset-x-0 bottom-0 z-30 px-3 pb-3 sm:px-6 sm:pb-6\">\n <div class=\"pointer-events-auto mx-auto w-full max-w-max\">\n <slot\n name=\"toolbar\"\n v-bind=\"toolbarSlotProps\"\n >\n <div class=\"rounded-full border border-white/20 bg-black/35 p-1 backdrop-blur-sm flex items-center gap-1\">\n <button\n type=\"button\"\n data-gr-image-viewer-zoom-out\n :aria-label=\"resolvedZoomOutLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"zoomOut\"\n >\n −\n </button>\n\n <button\n type=\"button\"\n data-gr-image-viewer-zoom-reset\n :aria-label=\"resolvedResetZoomLabel\"\n class=\"h-11 min-w-11 px-3 flex items-center justify-center rounded-full text-xs font-700 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"resetTransform\"\n >\n 100%\n </button>\n\n <button\n type=\"button\"\n data-gr-image-viewer-zoom-in\n :aria-label=\"resolvedZoomInLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"zoomIn\"\n >\n +\n </button>\n\n <template v-if=\"$slots['toolbar-actions']\">\n <div class=\"mx-1 h-6 w-px bg-white/25\" aria-hidden=\"true\" />\n\n <slot\n name=\"toolbar-actions\"\n v-bind=\"toolbarSlotProps\"\n />\n\n <div class=\"mx-1 h-6 w-px bg-white/25\" aria-hidden=\"true\" />\n </template>\n\n <div v-else class=\"mx-1 h-6 w-px bg-white/25\" aria-hidden=\"true\" />\n\n <button\n type=\"button\"\n data-gr-image-viewer-rotate-left\n :aria-label=\"resolvedRotateLeftLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"rotateLeft\"\n >\n ↺\n </button>\n\n <button\n type=\"button\"\n data-gr-image-viewer-rotate-right\n :aria-label=\"resolvedRotateRightLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"rotateRight\"\n >\n ↻\n </button>\n </div>\n </slot>\n </div>\n </div>\n </DialogPanel>\n </TransitionChild>\n </div>\n </Dialog>\n </TransitionRoot>\n </teleport>\n</template>","<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'\nimport { Dialog, DialogPanel, TransitionChild, TransitionRoot } from '@headlessui/vue'\n\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\n\n/**\n * Usage:\n *\n * <GrImageViewer\n * v-model=\"open\"\n * :url-list=\"images\"\n * :initial-index=\"0\"\n * show-progress\n * hide-on-click-modal\n * />\n */\nconst props = withDefaults(\n defineProps<{\n modelValue: boolean\n urlList: string[]\n initialIndex?: number\n zoomRate?: number\n minScale?: number\n maxScale?: number\n hideOnClickModal?: boolean\n closeOnPressEscape?: boolean\n showProgress?: boolean\n showZoomValue?: boolean\n /** Включает масштабирование колесом мыши / жестом на трекпаде. По умолчанию включено. */\n wheelZoom?: boolean\n /** Включает перетаскивание (pan) картинки мышью. При наведении курсор «рука». По умолчанию выключено. */\n draggable?: boolean\n zIndex?: number\n /** i18n: aria-label кнопки закрытия. */\n closeLabel?: string\n /** i18n: aria-label кнопки «предыдущее изображение». */\n prevLabel?: string\n /** i18n: aria-label кнопки «следующее изображение». */\n nextLabel?: string\n /** i18n: aria-label кнопки «увеличить». */\n zoomInLabel?: string\n /** i18n: aria-label кнопки «уменьшить». */\n zoomOutLabel?: string\n /** i18n: aria-label кнопки «сбросить масштаб». */\n resetZoomLabel?: string\n /** i18n: aria-label кнопки «повернуть влево». */\n rotateLeftLabel?: string\n /** i18n: aria-label кнопки «повернуть вправо». */\n rotateRightLabel?: string\n /** i18n: текст в пустом состоянии (нет изображений). */\n emptyText?: string\n }>(),\n {\n initialIndex: 0,\n zoomRate: 1.2,\n minScale: 0.5,\n maxScale: 5,\n hideOnClickModal: false,\n closeOnPressEscape: true,\n showProgress: false,\n showZoomValue: true,\n wheelZoom: true,\n draggable: false,\n zIndex: undefined,\n closeLabel: undefined,\n prevLabel: undefined,\n nextLabel: undefined,\n zoomInLabel: undefined,\n zoomOutLabel: undefined,\n resetZoomLabel: undefined,\n rotateLeftLabel: undefined,\n rotateRightLabel: undefined,\n emptyText: undefined,\n },\n)\n\nconst { t } = useGranularityTranslations()\nconst resolvedCloseLabel = computed(() => props.closeLabel ?? t('gr.imageViewer.close', 'Close image viewer'))\nconst resolvedPrevLabel = computed(() => props.prevLabel ?? t('gr.imageViewer.prev', 'Previous image'))\nconst resolvedNextLabel = computed(() => props.nextLabel ?? t('gr.imageViewer.next', 'Next image'))\nconst resolvedZoomInLabel = computed(() => props.zoomInLabel ?? t('gr.imageViewer.zoomIn', 'Zoom in'))\nconst resolvedZoomOutLabel = computed(() => props.zoomOutLabel ?? t('gr.imageViewer.zoomOut', 'Zoom out'))\nconst resolvedResetZoomLabel = computed(() => props.resetZoomLabel ?? t('gr.imageViewer.resetZoom', 'Reset zoom'))\nconst resolvedRotateLeftLabel = computed(() => props.rotateLeftLabel ?? t('gr.imageViewer.rotateLeft', 'Rotate left'))\nconst resolvedRotateRightLabel = computed(() => props.rotateRightLabel ?? t('gr.imageViewer.rotateRight', 'Rotate right'))\nconst resolvedEmptyText = computed(() => props.emptyText ?? t('gr.imageViewer.empty', 'No image'))\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'close'): void\n (e: 'switch', newIndex: number): void\n (e: 'rotate', deg: number): void\n}>()\n\ntype GrImageViewerToolbarActions = {\n close: () => void\n prev: () => void\n next: () => void\n zoomIn: () => void\n zoomOut: () => void\n reset: () => void\n rotateLeft: () => void\n rotateRight: () => void\n}\n\ntype GrImageViewerSlotProps = {\n index: number\n displayIndex: number\n total: number\n scale: number\n rotation: number\n /** Натуральный (исходный) размер картинки, px. 0 пока изображение не загружено. */\n naturalWidth: number\n naturalHeight: number\n /** Фактический размер изображения на экране c учётом scale, px (footprint вдоль осей картинки). */\n renderedWidth: number\n renderedHeight: number\n /** Реальный масштаб относительно натурального размера (доля): renderedWidth / naturalWidth. */\n realScale: number\n /** Реальный масштаб в процентах, отформатированный (например `67`). */\n realScalePercent: string\n actions: GrImageViewerToolbarActions\n}\n\nconst DEFAULT_Z_INDEX = 2000\nconst TRAILING_ZERO_DECIMAL_RE = /\\.0$/\n// Чувствительность масштабирования колесом/трекпадом: чем больше — тем резче реакция.\nconst WHEEL_ZOOM_SENSITIVITY = 0.0015\n// Сколько ms простоя после последнего wheel-события считаем «зум завершён»\n// (после этого возвращаем плавный CSS-переход).\nconst WHEEL_IDLE_MS = 120\n\nconst open = computed(() => props.modelValue)\nconst total = computed(() => props.urlList.length)\nconst hasImages = computed(() => total.value > 0)\n\nconst currentIndex = ref(0)\nconst scale = ref(1)\nconst rotation = ref(0)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\n\nconst imageEl = ref<HTMLImageElement | null>(null)\n\n// Флаг активного зума колесом/трекпадом. Пока true — CSS-переход отключён,\n// чтобы непрерывное масштабирование не «наслаивалось» и не дёргалось.\nconst isWheelZooming = ref(false)\n\n// Накопленный deltaY между кадрами и id запланированного rAF.\nlet pendingWheelDelta = 0\nlet wheelFrameId: number | null = null\nlet wheelIdleTimer: ReturnType<typeof setTimeout> | null = null\n\n// Флаг активного перетаскивания (pan) картинки мышью.\nconst isDragging = ref(false)\n\n// Координаты указателя и offset на момент начала перетаскивания.\nlet dragStartX = 0\nlet dragStartY = 0\nlet dragOffsetStartX = 0\nlet dragOffsetStartY = 0\n\n// Натуральный (исходный) размер картинки, читается из `<img>` при загрузке.\nconst naturalWidth = ref(0)\nconst naturalHeight = ref(0)\n\n// Layout-размер вписанного (`object-contain`) изображения без учёта CSS transform/scale.\nconst fittedWidth = ref(0)\nconst fittedHeight = ref(0)\n\nlet resizeObserver: ResizeObserver | null = null\n\nconst currentUrl = computed(() => {\n if (!hasImages.value) {\n return undefined\n }\n\n return props.urlList[currentIndex.value]\n})\n\nconst displayIndex = computed(() => {\n if (!hasImages.value) {\n return 0\n }\n\n return currentIndex.value + 1\n})\n\nconst viewerStyle = computed(() => ({\n zIndex: String(Number.isFinite(props.zIndex) ? props.zIndex : DEFAULT_Z_INDEX),\n}))\n\nconst imageStyle = computed(() => ({\n transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value}) rotate(${rotation.value}deg)`,\n}))\n\n// Плавный CSS-переход transform только для дискретных зумов (кнопки/клавиши).\n// При непрерывном зуме колесом и при перетаскивании переход отключаем —\n// иначе картинка «дёргается»/наслаивается и тянется за курсором с задержкой.\nconst imageTransitionClass = computed(() =>\n isWheelZooming.value || isDragging.value ? '' : 'transition-transform duration-150 ease-out',\n)\n\n// Курсор «рука» при наведении (grab) и при зажатии (grabbing), только если включён drag.\nconst imageCursorClass = computed(() => {\n if (!props.draggable) {\n return ''\n }\n\n return isDragging.value ? 'cursor-grabbing' : 'cursor-grab'\n})\n\nfunction formatPercent(value: number): string {\n if (Number.isInteger(value)) {\n return String(value)\n }\n\n return value.toFixed(1).replace(TRAILING_ZERO_DECIMAL_RE, '')\n}\n\nconst zoomValueText = computed(() => formatPercent(scale.value * 100))\n\n// Фактический размер изображения на экране вдоль его осей (footprint), c учётом scale.\nconst renderedWidth = computed(() => Math.round(fittedWidth.value * scale.value))\nconst renderedHeight = computed(() => Math.round(fittedHeight.value * scale.value))\n\n// Реальный масштаб относительно натурального размера (доля). Не зависит от rotation,\n// так как scale равномерный по осям картинки.\nconst realScale = computed(() => {\n if (!naturalWidth.value) {\n return 0\n }\n\n return (fittedWidth.value * scale.value) / naturalWidth.value\n})\n\nconst realScalePercent = computed(() => formatPercent(realScale.value * 100))\n\nconst toolbarSlotProps = computed<GrImageViewerSlotProps>(() => ({\n index: currentIndex.value,\n displayIndex: displayIndex.value,\n total: total.value,\n scale: scale.value,\n rotation: rotation.value,\n naturalWidth: naturalWidth.value,\n naturalHeight: naturalHeight.value,\n renderedWidth: renderedWidth.value,\n renderedHeight: renderedHeight.value,\n realScale: realScale.value,\n realScalePercent: realScalePercent.value,\n actions: toolbarActions,\n}))\n\nfunction normalizeIndex(value: number): number {\n if (!hasImages.value) {\n return 0\n }\n\n const normalized = Number.isFinite(value) ? Math.trunc(value) : 0\n\n return ((normalized % total.value) + total.value) % total.value\n}\n\nfunction resetTransform(): void {\n scale.value = 1\n rotation.value = 0\n offsetX.value = 0\n offsetY.value = 0\n isDragging.value = false\n}\n\nfunction resetImageMetrics(): void {\n naturalWidth.value = 0\n naturalHeight.value = 0\n fittedWidth.value = 0\n fittedHeight.value = 0\n}\n\nfunction measureFitted(): void {\n const el = imageEl.value\n\n if (!el) {\n return\n }\n\n // offsetWidth/Height — layout-размер вписанного изображения, без учёта CSS transform.\n fittedWidth.value = el.offsetWidth\n fittedHeight.value = el.offsetHeight\n}\n\nfunction onImageLoad(event: Event): void {\n const el = event.target as HTMLImageElement\n\n naturalWidth.value = el.naturalWidth\n naturalHeight.value = el.naturalHeight\n measureFitted()\n}\n\nfunction startObservingImage(): void {\n const el = imageEl.value\n\n if (!el || typeof ResizeObserver === 'undefined') {\n return\n }\n\n if (!resizeObserver) {\n resizeObserver = new ResizeObserver(() => measureFitted())\n }\n\n resizeObserver.observe(el)\n\n // Если картинка уже в кэше и `load` не сработал — считаем метрики сразу.\n if (el.complete && el.naturalWidth) {\n naturalWidth.value = el.naturalWidth\n naturalHeight.value = el.naturalHeight\n }\n\n measureFitted()\n}\n\nfunction stopObservingImage(): void {\n resizeObserver?.disconnect()\n}\n\nfunction setIndex(nextIndex: number, options?: { emitSwitch?: boolean }): void {\n const normalizedIndex = normalizeIndex(nextIndex)\n\n if (normalizedIndex === currentIndex.value) {\n return\n }\n\n currentIndex.value = normalizedIndex\n resetTransform()\n resetImageMetrics()\n endWheelZoom()\n\n if (options?.emitSwitch !== false) {\n emit('switch', normalizedIndex)\n }\n}\n\nfunction syncIndexFromInitial(): void {\n if (!hasImages.value) {\n currentIndex.value = 0\n return\n }\n\n currentIndex.value = normalizeIndex(props.initialIndex)\n resetTransform()\n resetImageMetrics()\n endWheelZoom()\n}\n\nfunction preloadAt(index: number): void {\n const url = props.urlList[index]\n\n if (!url) {\n return\n }\n\n const image = new Image()\n image.decoding = 'async'\n image.src = url\n}\n\nfunction closeViewer(): void {\n emit('update:modelValue', false)\n emit('close')\n}\n\nfunction prev(): void {\n setIndex(currentIndex.value - 1)\n}\n\nfunction next(): void {\n setIndex(currentIndex.value + 1)\n}\n\nfunction setScale(value: number): void {\n const clamped = Math.min(props.maxScale, Math.max(props.minScale, value))\n\n scale.value = Number(clamped.toFixed(4))\n}\n\nfunction zoomIn(): void {\n setScale(scale.value * props.zoomRate)\n}\n\nfunction zoomOut(): void {\n setScale(scale.value / props.zoomRate)\n}\n\nfunction cancelWheelFrame(): void {\n if (wheelFrameId !== null) {\n cancelAnimationFrame(wheelFrameId)\n wheelFrameId = null\n }\n}\n\nfunction endWheelZoom(): void {\n if (wheelIdleTimer !== null) {\n clearTimeout(wheelIdleTimer)\n wheelIdleTimer = null\n }\n\n isWheelZooming.value = false\n pendingWheelDelta = 0\n cancelWheelFrame()\n}\n\n// Применяем накопленный за кадр deltaY одним обновлением scale — так рендер\n// происходит не чаще одного раза в кадр (без «дёрганья» от частых обновлений).\nfunction flushWheelZoom(): void {\n wheelFrameId = null\n\n const delta = pendingWheelDelta\n pendingWheelDelta = 0\n\n if (!delta) {\n return\n }\n\n // Экспоненциальный шаг — плавно и одинаково ощущается и для колеса, и для трекпада.\n // delta < 0 (от себя / scroll up) — приближение, delta > 0 — отдаление.\n const factor = Math.exp(-delta * WHEEL_ZOOM_SENSITIVITY)\n\n setScale(scale.value * factor)\n}\n\nfunction onWheel(event: WheelEvent): void {\n if (!props.wheelZoom || !hasImages.value) {\n return\n }\n\n // Не даём странице/оверлею проскроллиться — колесо отдаём под зум.\n event.preventDefault()\n\n // Во время непрерывного зума отключаем CSS-переход: плавность даёт само\n // покадровое обновление, а transition на каждом микрошаге вызывает лаг/наслоение.\n isWheelZooming.value = true\n\n pendingWheelDelta += event.deltaY\n\n if (wheelFrameId === null) {\n wheelFrameId = requestAnimationFrame(flushWheelZoom)\n }\n\n if (wheelIdleTimer !== null) {\n clearTimeout(wheelIdleTimer)\n }\n\n // По завершении жеста возвращаем плавный переход для последующих дискретных зумов.\n wheelIdleTimer = setTimeout(() => {\n wheelIdleTimer = null\n isWheelZooming.value = false\n }, WHEEL_IDLE_MS)\n}\n\nfunction onPointerDown(event: PointerEvent): void {\n // Тянем только основной кнопкой и только если drag включён и есть картинка.\n if (!props.draggable || !hasImages.value || event.button !== 0) {\n return\n }\n\n event.preventDefault()\n\n isDragging.value = true\n dragStartX = event.clientX\n dragStartY = event.clientY\n dragOffsetStartX = offsetX.value\n dragOffsetStartY = offsetY.value\n\n // Захватываем указатель, чтобы движение/отпускание ловились даже за пределами картинки.\n ;(event.currentTarget as Element).setPointerCapture?.(event.pointerId)\n}\n\nfunction onPointerMove(event: PointerEvent): void {\n if (!isDragging.value) {\n return\n }\n\n offsetX.value = dragOffsetStartX + (event.clientX - dragStartX)\n offsetY.value = dragOffsetStartY + (event.clientY - dragStartY)\n}\n\nfunction onPointerUp(event: PointerEvent): void {\n if (!isDragging.value) {\n return\n }\n\n isDragging.value = false\n ;(event.currentTarget as Element).releasePointerCapture?.(event.pointerId)\n}\n\nfunction rotateLeft(): void {\n rotation.value -= 90\n emit('rotate', rotation.value)\n}\n\nfunction rotateRight(): void {\n rotation.value += 90\n emit('rotate', rotation.value)\n}\n\nconst toolbarActions: GrImageViewerToolbarActions = {\n close: closeViewer,\n prev,\n next,\n zoomIn,\n zoomOut,\n reset: resetTransform,\n rotateLeft,\n rotateRight,\n}\n\nfunction onBackdropClick(): void {\n if (!props.hideOnClickModal) {\n return\n }\n\n closeViewer()\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'Escape':\n if (!props.closeOnPressEscape) {\n return\n }\n\n event.preventDefault()\n closeViewer()\n return\n\n case 'ArrowLeft':\n event.preventDefault()\n prev()\n return\n\n case 'ArrowRight':\n event.preventDefault()\n next()\n return\n\n case '+':\n case '=':\n case 'Add':\n event.preventDefault()\n zoomIn()\n return\n\n case '-':\n case '_':\n case 'Subtract':\n event.preventDefault()\n zoomOut()\n return\n\n case '0':\n event.preventDefault()\n resetTransform()\n break\n\n default:\n }\n}\n\nwatch(\n () => props.modelValue,\n async (isOpen) => {\n if (!isOpen) {\n stopObservingImage()\n endWheelZoom()\n isDragging.value = false\n return\n }\n\n syncIndexFromInitial()\n await nextTick()\n startObservingImage()\n },\n { immediate: true },\n)\n\nwatch(\n () => props.initialIndex,\n () => {\n if (!props.modelValue) {\n return\n }\n\n syncIndexFromInitial()\n },\n)\n\nwatch(\n () => props.urlList,\n () => {\n if (!props.modelValue) {\n return\n }\n\n syncIndexFromInitial()\n },\n { deep: true },\n)\n\nwatch(\n currentIndex,\n (index) => {\n if (!hasImages.value || total.value < 2) {\n return\n }\n\n preloadAt(normalizeIndex(index - 1))\n preloadAt(normalizeIndex(index + 1))\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n stopObservingImage()\n endWheelZoom()\n})\n</script>\n\n<template>\n <teleport to=\"body\">\n <TransitionRoot :show=\"open\" as=\"template\">\n <Dialog\n as=\"div\"\n class=\"fixed inset-0\"\n :style=\"viewerStyle\"\n role=\"dialog\"\n aria-modal=\"true\"\n :static=\"true\"\n @keydown=\"onKeydown\"\n >\n <div class=\"fixed inset-0 overflow-hidden\">\n <TransitionChild\n as=\"template\"\n enter=\"duration-150 ease-out\"\n enter-from=\"opacity-0\"\n enter-to=\"opacity-100\"\n leave=\"duration-120 ease-in\"\n leave-from=\"opacity-100\"\n leave-to=\"opacity-0\"\n >\n <div\n data-gr-image-viewer-overlay\n class=\"absolute inset-0 bg-black/60 backdrop-blur-sm\"\n aria-hidden=\"true\"\n @click=\"onBackdropClick\"\n />\n </TransitionChild>\n\n <TransitionChild\n as=\"template\"\n enter=\"duration-180 ease-out\"\n enter-from=\"opacity-0 scale-98\"\n enter-to=\"opacity-100 scale-100\"\n leave=\"duration-130 ease-in\"\n leave-from=\"opacity-100 scale-100\"\n leave-to=\"opacity-0 scale-98\"\n >\n <DialogPanel\n data-gr-image-viewer-panel\n class=\"relative z-10 h-full w-full outline-none\"\n tabindex=\"-1\"\n >\n <div class=\"pointer-events-none absolute inset-x-0 top-0 z-30 px-3 py-3 sm:px-6\">\n <div class=\"pointer-events-auto flex items-center justify-between gap-3\">\n <div class=\"flex items-center gap-2\">\n <div\n v-if=\"showProgress\"\n data-gr-image-viewer-progress\n class=\"rounded-full bg-black/35 px-3 py-1 text-xs font-600 text-white/95 sm:text-sm\"\n >\n {{ displayIndex }} / {{ total }}\n </div>\n\n <div\n v-if=\"showZoomValue\"\n data-gr-image-viewer-zoom-value\n class=\"rounded-full bg-black/35 px-3 py-1 text-xs font-700 text-white/95 sm:text-sm\"\n >\n {{ zoomValueText }}%\n </div>\n </div>\n\n <button\n type=\"button\"\n data-gr-image-viewer-close\n :aria-label=\"resolvedCloseLabel\"\n class=\"h-11 w-11 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"closeViewer\"\n >\n <span aria-hidden=\"true\" class=\"text-lg leading-none\">✕</span>\n </button>\n </div>\n </div>\n\n <div\n class=\"relative z-10 h-full w-full flex items-center justify-center px-16 py-16 sm:px-24 sm:py-20\"\n @wheel=\"onWheel\"\n >\n <button\n v-if=\"total > 1\"\n type=\"button\"\n data-gr-image-viewer-prev\n :aria-label=\"resolvedPrevLabel\"\n class=\"absolute left-3 top-1/2 z-20 h-12 w-12 -translate-y-1/2 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 sm:left-6\"\n @click=\"prev\"\n >\n <span aria-hidden=\"true\" class=\"text-xl leading-none\">‹</span>\n </button>\n\n <button\n v-if=\"total > 1\"\n type=\"button\"\n data-gr-image-viewer-next\n :aria-label=\"resolvedNextLabel\"\n class=\"absolute right-3 top-1/2 z-20 h-12 w-12 -translate-y-1/2 flex items-center justify-center rounded-full border border-white/20 bg-black/35 text-white transition-colors hover:bg-black/55 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 sm:right-6\"\n @click=\"next\"\n >\n <span aria-hidden=\"true\" class=\"text-xl leading-none\">›</span>\n </button>\n\n <div class=\"h-full w-full flex items-center justify-center\">\n <img\n v-if=\"currentUrl\"\n ref=\"imageEl\"\n data-gr-image-viewer-image\n :src=\"currentUrl\"\n alt=\"\"\n draggable=\"false\"\n class=\"max-h-full max-w-full select-none object-contain will-change-transform\"\n :class=\"[imageTransitionClass, imageCursorClass]\"\n :style=\"imageStyle\"\n @load=\"onImageLoad\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerUp\"\n >\n\n <div\n v-else\n class=\"rounded-[var(--gr-radius-xl)] border border-white/20 bg-black/25 px-4 py-3 text-sm text-white/80\"\n >\n {{ resolvedEmptyText }}\n </div>\n </div>\n </div>\n\n <div class=\"pointer-events-none absolute inset-x-0 bottom-0 z-30 px-3 pb-3 sm:px-6 sm:pb-6\">\n <div class=\"pointer-events-auto mx-auto w-full max-w-max\">\n <slot\n name=\"toolbar\"\n v-bind=\"toolbarSlotProps\"\n >\n <div class=\"rounded-full border border-white/20 bg-black/35 p-1 backdrop-blur-sm flex items-center gap-1\">\n <button\n type=\"button\"\n data-gr-image-viewer-zoom-out\n :aria-label=\"resolvedZoomOutLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"zoomOut\"\n >\n −\n </button>\n\n <button\n type=\"button\"\n data-gr-image-viewer-zoom-reset\n :aria-label=\"resolvedResetZoomLabel\"\n class=\"h-11 min-w-11 px-3 flex items-center justify-center rounded-full text-xs font-700 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"resetTransform\"\n >\n 100%\n </button>\n\n <button\n type=\"button\"\n data-gr-image-viewer-zoom-in\n :aria-label=\"resolvedZoomInLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"zoomIn\"\n >\n +\n </button>\n\n <template v-if=\"$slots['toolbar-actions']\">\n <div class=\"mx-1 h-6 w-px bg-white/25\" aria-hidden=\"true\" />\n\n <slot\n name=\"toolbar-actions\"\n v-bind=\"toolbarSlotProps\"\n />\n\n <div class=\"mx-1 h-6 w-px bg-white/25\" aria-hidden=\"true\" />\n </template>\n\n <div v-else class=\"mx-1 h-6 w-px bg-white/25\" aria-hidden=\"true\" />\n\n <button\n type=\"button\"\n data-gr-image-viewer-rotate-left\n :aria-label=\"resolvedRotateLeftLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"rotateLeft\"\n >\n ↺\n </button>\n\n <button\n type=\"button\"\n data-gr-image-viewer-rotate-right\n :aria-label=\"resolvedRotateRightLabel\"\n class=\"h-11 min-w-11 px-2 flex items-center justify-center rounded-full text-sm font-600 text-white transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80\"\n @click=\"rotateRight\"\n >\n ↻\n </button>\n </div>\n </slot>\n </div>\n </div>\n </DialogPanel>\n </TransitionChild>\n </div>\n </Dialog>\n </TransitionRoot>\n </teleport>\n</template>"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrImageViewer_default } from "./chunks/GrImageViewer-BG40DsHa.js";
2
- import { t as grImageViewerConfig } from "../../chunks/config-Doa_gU40.js";
1
+ import { t as GrImageViewer_default } from "./chunks/GrImageViewer-OCUIrNh2.js";
2
+ import { t as grImageViewerConfig } from "../../chunks/config-HZto2PVy.js";
3
3
  export { GrImageViewer_default as GrImageViewer, GrImageViewer_default as default, grImageViewerConfig };
@@ -1,7 +1,7 @@
1
- import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, nextTick, normalizeStyle, onBeforeUnmount, onMounted, onUpdated, openBlock, ref, renderSlot, useSlots } from "vue";
1
+ import { n as useAddonMeasurement, t as addLen } from "../../../chunks/useAddonMeasurement-DM0akF4C.js";
2
+ import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, normalizeClass, normalizeStyle, openBlock, ref, renderSlot, useSlots } from "vue";
2
3
  //#region src/components/GrInput/GrInput.vue?vue&type=script&setup=true&lang.ts
3
- var _hoisted_1 = { class: "relative w-full" };
4
- var _hoisted_2 = [
4
+ var _hoisted_1 = [
5
5
  "id",
6
6
  "name",
7
7
  "type",
@@ -39,7 +39,15 @@ var GrInput_default = /* @__PURE__ */ defineComponent({
39
39
  prefixMinWidth: { default: void 0 },
40
40
  prefixMaxWidth: { default: void 0 },
41
41
  suffixMinWidth: { default: void 0 },
42
- suffixMaxWidth: { default: void 0 }
42
+ suffixMaxWidth: { default: void 0 },
43
+ prefixFixed: {
44
+ type: Boolean,
45
+ default: false
46
+ },
47
+ suffixFixed: {
48
+ type: Boolean,
49
+ default: false
50
+ }
43
51
  },
44
52
  emits: ["update:modelValue"],
45
53
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -63,49 +71,9 @@ var GrInput_default = /* @__PURE__ */ defineComponent({
63
71
  });
64
72
  const prefixMinWidth = computed(() => props.prefixMinWidth ?? defaultAddonMinWidth.value);
65
73
  const suffixMinWidth = computed(() => props.suffixMinWidth ?? defaultAddonMinWidth.value);
66
- const prefixEl = ref(null);
67
- const suffixEl = ref(null);
68
- const measuredPrefixWidth = ref(void 0);
69
- const measuredSuffixWidth = ref(void 0);
70
- let ro = null;
71
- let scheduled = false;
72
- function readWidthPx(el) {
73
- if (!el) return void 0;
74
- const width = Math.ceil(el.getBoundingClientRect().width || 0);
75
- if (width <= 0) return void 0;
76
- return `${width}px`;
77
- }
78
- function measure() {
79
- measuredPrefixWidth.value = hasPrefix.value ? readWidthPx(prefixEl.value) : void 0;
80
- measuredSuffixWidth.value = hasSuffix.value ? readWidthPx(suffixEl.value) : void 0;
81
- }
82
- function refreshObserver() {
83
- if (typeof ResizeObserver === "undefined") return;
84
- if (!ro) ro = new ResizeObserver(() => measure());
85
- ro.disconnect();
86
- if (prefixEl.value) ro.observe(prefixEl.value);
87
- if (suffixEl.value) ro.observe(suffixEl.value);
88
- }
89
- function scheduleMeasure() {
90
- if (scheduled) return;
91
- scheduled = true;
92
- nextTick(() => {
93
- scheduled = false;
94
- measure();
95
- refreshObserver();
96
- });
97
- }
98
- onMounted(() => scheduleMeasure());
99
- onUpdated(() => scheduleMeasure());
100
- onBeforeUnmount(() => ro?.disconnect());
101
- function addLen(a, b) {
102
- if (a === "0px") return b;
103
- if (b === "0px") return a;
104
- const apx = a.endsWith("px") ? Number(a.slice(0, -2)) : null;
105
- const bpx = b.endsWith("px") ? Number(b.slice(0, -2)) : null;
106
- if (apx !== null && Number.isFinite(apx) && bpx !== null && Number.isFinite(bpx)) return `${apx + bpx}px`;
107
- return `calc(${a} + ${b})`;
108
- }
74
+ const prefixFixedWidth = computed(() => props.prefixMaxWidth ?? props.prefixMinWidth ?? defaultAddonMinWidth.value);
75
+ const suffixFixedWidth = computed(() => props.suffixMaxWidth ?? props.suffixMinWidth ?? defaultAddonMinWidth.value);
76
+ const { prefixEl, suffixEl, measuredPrefixWidth, measuredSuffixWidth } = useAddonMeasurement(hasPrefix, hasSuffix);
109
77
  const basePaddingXLen = computed(() => {
110
78
  return {
111
79
  xs: "10px",
@@ -115,20 +83,30 @@ var GrInput_default = /* @__PURE__ */ defineComponent({
115
83
  }[props.size];
116
84
  });
117
85
  const inputStyle = computed(() => {
118
- const leftReserved = hasPrefix.value ? measuredPrefixWidth.value ?? prefixMinWidth.value : "0px";
119
- const rightReserved = hasSuffix.value ? measuredSuffixWidth.value ?? suffixMinWidth.value : "0px";
86
+ const leftReserved = hasPrefix.value ? props.prefixFixed ? prefixFixedWidth.value : measuredPrefixWidth.value ?? prefixMinWidth.value : "0px";
87
+ const rightReserved = hasSuffix.value ? props.suffixFixed ? suffixFixedWidth.value : measuredSuffixWidth.value ?? suffixMinWidth.value : "0px";
120
88
  return {
121
89
  paddingLeft: hasPrefix.value ? addLen(leftReserved, basePaddingXLen.value) : void 0,
122
90
  paddingRight: hasSuffix.value ? addLen(rightReserved, basePaddingXLen.value) : void 0
123
91
  };
124
92
  });
125
93
  const prefixStyle = computed(() => {
94
+ if (props.prefixFixed) return {
95
+ width: prefixFixedWidth.value,
96
+ minWidth: prefixFixedWidth.value,
97
+ maxWidth: prefixFixedWidth.value
98
+ };
126
99
  return {
127
100
  minWidth: prefixMinWidth.value,
128
101
  maxWidth: props.prefixMaxWidth
129
102
  };
130
103
  });
131
104
  const suffixStyle = computed(() => {
105
+ if (props.suffixFixed) return {
106
+ width: suffixFixedWidth.value,
107
+ minWidth: suffixFixedWidth.value,
108
+ maxWidth: suffixFixedWidth.value
109
+ };
132
110
  return {
133
111
  minWidth: suffixMinWidth.value,
134
112
  maxWidth: props.suffixMaxWidth
@@ -149,30 +127,29 @@ var GrInput_default = /* @__PURE__ */ defineComponent({
149
127
  right: "text-right"
150
128
  }[props.textAlign];
151
129
  });
152
- const className = computed(() => {
130
+ const shellClass = computed(() => {
153
131
  const state = props.state;
154
132
  const borderByState = {
155
133
  default: "border-[var(--brd)]",
156
- success: "border-[var(--ds-success)] focus-visible:ring-[var(--ds-success)]",
157
- warning: "border-[var(--ds-warning)] focus-visible:ring-[var(--ds-warning)]",
158
- danger: "border-[var(--ds-danger)] focus-visible:ring-[var(--ds-danger)]"
134
+ success: "border-[var(--gr-success)] focus-within:ring-[var(--gr-success)]",
135
+ warning: "border-[var(--gr-warning)] focus-within:ring-[var(--gr-warning)]",
136
+ danger: "border-[var(--gr-danger)] focus-within:ring-[var(--gr-danger)]"
159
137
  };
160
- return [
161
- sizeClass.value,
162
- textAlignClass.value,
163
- props.invalid ? borderByState.danger : borderByState[state]
164
- ].join(" ");
138
+ return [props.invalid ? borderByState.danger : borderByState[state], props.disabled ? "opacity-50 cursor-not-allowed" : ""].filter(Boolean).join(" ");
139
+ });
140
+ const className = computed(() => {
141
+ return [sizeClass.value, textAlignClass.value].join(" ");
165
142
  });
166
143
  function onInput(e) {
167
144
  emit("update:modelValue", e.target.value);
168
145
  }
169
146
  return (_ctx, _cache) => {
170
- return openBlock(), createElementBlock("div", _hoisted_1, [
147
+ return openBlock(), createElementBlock("div", { class: normalizeClass(["relative w-full overflow-hidden rounded-md border bg-[var(--bg)] transition-colors duration-150 focus-within:ring-2 focus-within:ring-[var(--ring)]", shellClass.value]) }, [
171
148
  _ctx.$slots.prefix ? (openBlock(), createElementBlock("div", {
172
149
  key: 0,
173
150
  ref_key: "prefixEl",
174
151
  ref: prefixEl,
175
- "data-testid": "ds-input-prefix",
152
+ "data-testid": "gr-input-prefix",
176
153
  class: "absolute inset-y-0 left-0 flex items-center justify-center border-r border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate",
177
154
  style: normalizeStyle(prefixStyle.value),
178
155
  "aria-hidden": "true"
@@ -190,20 +167,20 @@ var GrInput_default = /* @__PURE__ */ defineComponent({
190
167
  disabled: props.disabled,
191
168
  value: props.modelValue,
192
169
  "aria-invalid": props.invalid ? "true" : void 0,
193
- class: ["w-full rounded-md border bg-[var(--bg)] text-[var(--fg)] placeholder:text-[var(--muted-fg)] focus:placeholder:text-transparent transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] disabled:opacity-50 disabled:cursor-not-allowed", className.value],
170
+ class: ["w-full bg-transparent text-[var(--fg)] placeholder:text-[var(--muted-fg)] focus:placeholder:text-transparent focus:outline-none disabled:cursor-not-allowed", className.value],
194
171
  style: inputStyle.value,
195
172
  onInput
196
- }), null, 16, _hoisted_2),
173
+ }), null, 16, _hoisted_1),
197
174
  _ctx.$slots.suffix ? (openBlock(), createElementBlock("div", {
198
175
  key: 1,
199
176
  ref_key: "suffixEl",
200
177
  ref: suffixEl,
201
- "data-testid": "ds-input-suffix",
202
- class: "absolute inset-y-0 right-0 flex items-center justify-center border-l border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate",
178
+ "data-testid": "gr-input-suffix",
179
+ class: normalizeClass(["absolute inset-y-0 right-0 flex items-center justify-center border-l border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate", __props.suffixFixed ? "[direction:rtl]" : ""]),
203
180
  style: normalizeStyle(suffixStyle.value),
204
181
  "aria-hidden": "true"
205
- }, [renderSlot(_ctx.$slots, "suffix")], 4)) : createCommentVNode("", true)
206
- ]);
182
+ }, [renderSlot(_ctx.$slots, "suffix")], 6)) : createCommentVNode("", true)
183
+ ], 2);
207
184
  };
208
185
  }
209
186
  });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrInput-C8pOJgCi.js","names":["$slots","$attrs"],"sources":["../../../../src/components/GrInput/GrInput.vue","../../../../src/components/GrInput/GrInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {computed, ref, useSlots} from 'vue'\n\nimport {addLen, useAddonMeasurement} from '../../composables/internal/useAddonMeasurement'\nimport type {InputHTMLAttributes} from 'vue'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nexport type GrInputSize = 'xs' | 'sm' | 'md' | 'lg'\nexport type GrInputTextAlign = 'left' | 'center' | 'right'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string\n type?: 'text' | 'email' | 'password' | 'number' | 'search'\n placeholder?: string\n autocomplete?: string\n inputmode?: InputHTMLAttributes['inputmode']\n disabled?: boolean\n invalid?: boolean\n state?: 'default' | 'success' | 'warning' | 'danger'\n name?: string\n id?: string\n size?: GrInputSize\n\n textAlign?: GrInputTextAlign\n\n prefixMinWidth?: string\n prefixMaxWidth?: string\n suffixMinWidth?: string\n suffixMaxWidth?: string\n /**\n * Фиксированная ширина у prefix/suffix: аддон получает жёсткую ширину\n * (из `*MaxWidth` → `*MinWidth` → дефолт), а контент обрезается по краю\n * (prefix — справа, suffix — слева). По умолчанию аддоны «растягиваются»\n * под контент (в пределах min/max), а излишек клипается оболочкой.\n */\n prefixFixed?: boolean\n suffixFixed?: boolean\n }>(),\n {\n type: 'text',\n placeholder: undefined,\n autocomplete: undefined,\n inputmode: undefined,\n disabled: false,\n invalid: false,\n state: 'default',\n name: undefined,\n id: undefined,\n size: 'md',\n\n textAlign: 'left',\n\n prefixMinWidth: undefined,\n prefixMaxWidth: undefined,\n suffixMinWidth: undefined,\n suffixMaxWidth: undefined,\n prefixFixed: false,\n suffixFixed: false,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst inputEl = ref<HTMLInputElement | null>(null)\n\nfunction focus(): void {\n inputEl.value?.focus()\n}\n\ndefineExpose({\n focus,\n})\n\nconst slots = useSlots()\n\nconst hasPrefix = computed(() => Boolean(slots.prefix))\nconst hasSuffix = computed(() => Boolean(slots.suffix))\n\nconst defaultAddonMinWidth = computed(() => {\n const map: Record<NonNullable<typeof props.size>, string> = {\n xs: '2rem', // w-8\n sm: '2.25rem', // w-9\n md: '2.5rem', // w-10\n lg: '3rem', // w-12\n }\n\n return map[props.size]\n})\n\nconst prefixMinWidth = computed(() => props.prefixMinWidth ?? defaultAddonMinWidth.value)\nconst suffixMinWidth = computed(() => props.suffixMinWidth ?? defaultAddonMinWidth.value)\n\n// Жёсткая ширина для fixed-режима: max → min → дефолт.\nconst prefixFixedWidth = computed(() => props.prefixMaxWidth ?? props.prefixMinWidth ?? defaultAddonMinWidth.value)\nconst suffixFixedWidth = computed(() => props.suffixMaxWidth ?? props.suffixMinWidth ?? defaultAddonMinWidth.value)\n\nconst { prefixEl, suffixEl, measuredPrefixWidth, measuredSuffixWidth } = useAddonMeasurement(hasPrefix, hasSuffix)\n\nconst basePaddingXLen = computed(() => {\n // Must mirror `sizeClass` horizontal padding (px-*) because inline paddings override class paddings.\n const map: Record<NonNullable<typeof props.size>, string> = {\n xs: '10px', // px-2.5\n sm: '12px', // px-3\n md: '12px', // px-3\n lg: '16px', // px-4\n }\n\n return map[props.size]\n})\n\nconst inputStyle = computed(() => {\n const leftReserved = hasPrefix.value\n ? (props.prefixFixed ? prefixFixedWidth.value : measuredPrefixWidth.value ?? prefixMinWidth.value)\n : '0px'\n const rightReserved = hasSuffix.value\n ? (props.suffixFixed ? suffixFixedWidth.value : measuredSuffixWidth.value ?? suffixMinWidth.value)\n : '0px'\n\n // Keep the same visual text padding as without addons (px-*), but add it on top of reserved space.\n const left = hasPrefix.value ? addLen(leftReserved, basePaddingXLen.value) : undefined\n const right = hasSuffix.value ? addLen(rightReserved, basePaddingXLen.value) : undefined\n\n return {\n paddingLeft: left,\n paddingRight: right,\n } as Record<string, string | undefined>\n})\n\nconst prefixStyle = computed(() => {\n if (props.prefixFixed) {\n return {\n width: prefixFixedWidth.value,\n minWidth: prefixFixedWidth.value,\n maxWidth: prefixFixedWidth.value,\n } as Record<string, string | undefined>\n }\n\n return {\n minWidth: prefixMinWidth.value,\n maxWidth: props.prefixMaxWidth,\n } as Record<string, string | undefined>\n})\n\nconst suffixStyle = computed(() => {\n if (props.suffixFixed) {\n return {\n width: suffixFixedWidth.value,\n minWidth: suffixFixedWidth.value,\n maxWidth: suffixFixedWidth.value,\n } as Record<string, string | undefined>\n }\n\n return {\n minWidth: suffixMinWidth.value,\n maxWidth: props.suffixMaxWidth,\n } as Record<string, string | undefined>\n})\n\nconst sizeClass = computed(() => {\n const map: Record<NonNullable<typeof props.size>, string> = {\n xs: 'h-7 px-2.5 text-[12px]',\n sm: 'h-8 px-3 text-[13px]',\n md: 'h-10 px-3 text-[14px]',\n lg: 'h-11 px-4 text-[16px]',\n }\n\n return map[props.size]\n})\n\nconst textAlignClass = computed(() => {\n const map: Record<NonNullable<typeof props.textAlign>, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n }\n\n return map[props.textAlign]\n})\n\n// Border/ring/disabled — на оболочке (`focus-within`), размеры/выравнивание — на инпуте.\nconst shellClass = computed(() => {\n const state = props.state\n\n const borderByState: Record<typeof state, string> = {\n default: 'border-[var(--brd)]',\n success: 'border-[var(--gr-success)] focus-within:ring-[var(--gr-success)]',\n warning: 'border-[var(--gr-warning)] focus-within:ring-[var(--gr-warning)]',\n danger: 'border-[var(--gr-danger)] focus-within:ring-[var(--gr-danger)]',\n }\n\n return [\n props.invalid ? borderByState.danger : borderByState[state],\n props.disabled ? 'opacity-50 cursor-not-allowed' : '',\n ].filter(Boolean).join(' ')\n})\n\nconst className = computed(() => {\n return [\n sizeClass.value,\n textAlignClass.value,\n ].join(' ')\n})\n\nfunction onInput(e: Event): void {\n emit('update:modelValue', (e.target as HTMLInputElement).value)\n}\n</script>\n\n<template>\n <div\n class=\"relative w-full overflow-hidden rounded-md border bg-[var(--bg)] transition-colors duration-150 focus-within:ring-2 focus-within:ring-[var(--ring)]\"\n :class=\"shellClass\"\n >\n <div\n v-if=\"$slots.prefix\"\n ref=\"prefixEl\"\n data-testid=\"gr-input-prefix\"\n class=\"absolute inset-y-0 left-0 flex items-center justify-center border-r border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate\"\n :style=\"prefixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"prefix\" />\n </div>\n\n <input\n :id=\"props.id\"\n ref=\"inputEl\"\n v-bind=\"$attrs\"\n :name=\"props.name\"\n :type=\"props.type\"\n :inputmode=\"props.inputmode\"\n :autocomplete=\"props.autocomplete\"\n :placeholder=\"props.placeholder\"\n :disabled=\"props.disabled\"\n :value=\"props.modelValue\"\n :aria-invalid=\"props.invalid ? 'true' : undefined\"\n class=\"w-full bg-transparent text-[var(--fg)] placeholder:text-[var(--muted-fg)] focus:placeholder:text-transparent focus:outline-none disabled:cursor-not-allowed\"\n :class=\"className\"\n :style=\"inputStyle\"\n @input=\"onInput\"\n >\n\n <div\n v-if=\"$slots.suffix\"\n ref=\"suffixEl\"\n data-testid=\"gr-input-suffix\"\n class=\"absolute inset-y-0 right-0 flex items-center justify-center border-l border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate\"\n :class=\"suffixFixed ? '[direction:rtl]' : ''\"\n :style=\"suffixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"suffix\" />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport {computed, ref, useSlots} from 'vue'\n\nimport {addLen, useAddonMeasurement} from '../../composables/internal/useAddonMeasurement'\nimport type {InputHTMLAttributes} from 'vue'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nexport type GrInputSize = 'xs' | 'sm' | 'md' | 'lg'\nexport type GrInputTextAlign = 'left' | 'center' | 'right'\n\nconst props = withDefaults(\n defineProps<{\n modelValue: string\n type?: 'text' | 'email' | 'password' | 'number' | 'search'\n placeholder?: string\n autocomplete?: string\n inputmode?: InputHTMLAttributes['inputmode']\n disabled?: boolean\n invalid?: boolean\n state?: 'default' | 'success' | 'warning' | 'danger'\n name?: string\n id?: string\n size?: GrInputSize\n\n textAlign?: GrInputTextAlign\n\n prefixMinWidth?: string\n prefixMaxWidth?: string\n suffixMinWidth?: string\n suffixMaxWidth?: string\n /**\n * Фиксированная ширина у prefix/suffix: аддон получает жёсткую ширину\n * (из `*MaxWidth` → `*MinWidth` → дефолт), а контент обрезается по краю\n * (prefix — справа, suffix — слева). По умолчанию аддоны «растягиваются»\n * под контент (в пределах min/max), а излишек клипается оболочкой.\n */\n prefixFixed?: boolean\n suffixFixed?: boolean\n }>(),\n {\n type: 'text',\n placeholder: undefined,\n autocomplete: undefined,\n inputmode: undefined,\n disabled: false,\n invalid: false,\n state: 'default',\n name: undefined,\n id: undefined,\n size: 'md',\n\n textAlign: 'left',\n\n prefixMinWidth: undefined,\n prefixMaxWidth: undefined,\n suffixMinWidth: undefined,\n suffixMaxWidth: undefined,\n prefixFixed: false,\n suffixFixed: false,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n}>()\n\nconst inputEl = ref<HTMLInputElement | null>(null)\n\nfunction focus(): void {\n inputEl.value?.focus()\n}\n\ndefineExpose({\n focus,\n})\n\nconst slots = useSlots()\n\nconst hasPrefix = computed(() => Boolean(slots.prefix))\nconst hasSuffix = computed(() => Boolean(slots.suffix))\n\nconst defaultAddonMinWidth = computed(() => {\n const map: Record<NonNullable<typeof props.size>, string> = {\n xs: '2rem', // w-8\n sm: '2.25rem', // w-9\n md: '2.5rem', // w-10\n lg: '3rem', // w-12\n }\n\n return map[props.size]\n})\n\nconst prefixMinWidth = computed(() => props.prefixMinWidth ?? defaultAddonMinWidth.value)\nconst suffixMinWidth = computed(() => props.suffixMinWidth ?? defaultAddonMinWidth.value)\n\n// Жёсткая ширина для fixed-режима: max → min → дефолт.\nconst prefixFixedWidth = computed(() => props.prefixMaxWidth ?? props.prefixMinWidth ?? defaultAddonMinWidth.value)\nconst suffixFixedWidth = computed(() => props.suffixMaxWidth ?? props.suffixMinWidth ?? defaultAddonMinWidth.value)\n\nconst { prefixEl, suffixEl, measuredPrefixWidth, measuredSuffixWidth } = useAddonMeasurement(hasPrefix, hasSuffix)\n\nconst basePaddingXLen = computed(() => {\n // Must mirror `sizeClass` horizontal padding (px-*) because inline paddings override class paddings.\n const map: Record<NonNullable<typeof props.size>, string> = {\n xs: '10px', // px-2.5\n sm: '12px', // px-3\n md: '12px', // px-3\n lg: '16px', // px-4\n }\n\n return map[props.size]\n})\n\nconst inputStyle = computed(() => {\n const leftReserved = hasPrefix.value\n ? (props.prefixFixed ? prefixFixedWidth.value : measuredPrefixWidth.value ?? prefixMinWidth.value)\n : '0px'\n const rightReserved = hasSuffix.value\n ? (props.suffixFixed ? suffixFixedWidth.value : measuredSuffixWidth.value ?? suffixMinWidth.value)\n : '0px'\n\n // Keep the same visual text padding as without addons (px-*), but add it on top of reserved space.\n const left = hasPrefix.value ? addLen(leftReserved, basePaddingXLen.value) : undefined\n const right = hasSuffix.value ? addLen(rightReserved, basePaddingXLen.value) : undefined\n\n return {\n paddingLeft: left,\n paddingRight: right,\n } as Record<string, string | undefined>\n})\n\nconst prefixStyle = computed(() => {\n if (props.prefixFixed) {\n return {\n width: prefixFixedWidth.value,\n minWidth: prefixFixedWidth.value,\n maxWidth: prefixFixedWidth.value,\n } as Record<string, string | undefined>\n }\n\n return {\n minWidth: prefixMinWidth.value,\n maxWidth: props.prefixMaxWidth,\n } as Record<string, string | undefined>\n})\n\nconst suffixStyle = computed(() => {\n if (props.suffixFixed) {\n return {\n width: suffixFixedWidth.value,\n minWidth: suffixFixedWidth.value,\n maxWidth: suffixFixedWidth.value,\n } as Record<string, string | undefined>\n }\n\n return {\n minWidth: suffixMinWidth.value,\n maxWidth: props.suffixMaxWidth,\n } as Record<string, string | undefined>\n})\n\nconst sizeClass = computed(() => {\n const map: Record<NonNullable<typeof props.size>, string> = {\n xs: 'h-7 px-2.5 text-[12px]',\n sm: 'h-8 px-3 text-[13px]',\n md: 'h-10 px-3 text-[14px]',\n lg: 'h-11 px-4 text-[16px]',\n }\n\n return map[props.size]\n})\n\nconst textAlignClass = computed(() => {\n const map: Record<NonNullable<typeof props.textAlign>, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n }\n\n return map[props.textAlign]\n})\n\n// Border/ring/disabled — на оболочке (`focus-within`), размеры/выравнивание — на инпуте.\nconst shellClass = computed(() => {\n const state = props.state\n\n const borderByState: Record<typeof state, string> = {\n default: 'border-[var(--brd)]',\n success: 'border-[var(--gr-success)] focus-within:ring-[var(--gr-success)]',\n warning: 'border-[var(--gr-warning)] focus-within:ring-[var(--gr-warning)]',\n danger: 'border-[var(--gr-danger)] focus-within:ring-[var(--gr-danger)]',\n }\n\n return [\n props.invalid ? borderByState.danger : borderByState[state],\n props.disabled ? 'opacity-50 cursor-not-allowed' : '',\n ].filter(Boolean).join(' ')\n})\n\nconst className = computed(() => {\n return [\n sizeClass.value,\n textAlignClass.value,\n ].join(' ')\n})\n\nfunction onInput(e: Event): void {\n emit('update:modelValue', (e.target as HTMLInputElement).value)\n}\n</script>\n\n<template>\n <div\n class=\"relative w-full overflow-hidden rounded-md border bg-[var(--bg)] transition-colors duration-150 focus-within:ring-2 focus-within:ring-[var(--ring)]\"\n :class=\"shellClass\"\n >\n <div\n v-if=\"$slots.prefix\"\n ref=\"prefixEl\"\n data-testid=\"gr-input-prefix\"\n class=\"absolute inset-y-0 left-0 flex items-center justify-center border-r border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate\"\n :style=\"prefixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"prefix\" />\n </div>\n\n <input\n :id=\"props.id\"\n ref=\"inputEl\"\n v-bind=\"$attrs\"\n :name=\"props.name\"\n :type=\"props.type\"\n :inputmode=\"props.inputmode\"\n :autocomplete=\"props.autocomplete\"\n :placeholder=\"props.placeholder\"\n :disabled=\"props.disabled\"\n :value=\"props.modelValue\"\n :aria-invalid=\"props.invalid ? 'true' : undefined\"\n class=\"w-full bg-transparent text-[var(--fg)] placeholder:text-[var(--muted-fg)] focus:placeholder:text-transparent focus:outline-none disabled:cursor-not-allowed\"\n :class=\"className\"\n :style=\"inputStyle\"\n @input=\"onInput\"\n >\n\n <div\n v-if=\"$slots.suffix\"\n ref=\"suffixEl\"\n data-testid=\"gr-input-suffix\"\n class=\"absolute inset-y-0 right-0 flex items-center justify-center border-l border-[var(--brd)] px-2 text-[var(--muted-fg)] pointer-events-none select-none truncate\"\n :class=\"suffixFixed ? '[direction:rtl]' : ''\"\n :style=\"suffixStyle\"\n aria-hidden=\"true\"\n >\n <slot name=\"suffix\" />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { t as GrInput_default } from "./chunks/GrInput-gwFQ1sk4.js";
2
- import { n as grInputSafelist, t as grInputConfig } from "../../chunks/config-8f8624RN.js";
1
+ import { t as GrInput_default } from "./chunks/GrInput-C8pOJgCi.js";
2
+ import { n as grInputSafelist, t as grInputConfig } from "../../chunks/config-D_R56_gT.js";
3
3
  export { GrInput_default as GrInput, GrInput_default as default, grInputConfig, grInputSafelist };