@feugene/granularity 0.7.0 → 0.9.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 (306) hide show
  1. package/dist/GrBadge.css +1 -0
  2. package/dist/chunks/{adapter-CRyH4YC8.js.map → adapter-BqqjEZGU.js.map} +1 -1
  3. package/dist/chunks/arrow-up-DZdIrpaF.js.map +1 -0
  4. package/dist/chunks/{config-Dkq0HeLe.js → config-3I3vqDW4.js} +1 -1
  5. package/dist/chunks/{config-Dkq0HeLe.js.map → config-3I3vqDW4.js.map} +1 -1
  6. package/dist/chunks/config-72sW9Bag2.js.map +1 -0
  7. package/dist/chunks/{config-B8rC_K97.js.map → config-B1kFmhpM.js.map} +1 -1
  8. package/dist/chunks/{config-BhvNm4Pp.js.map → config-B2YTEe_h.js.map} +1 -1
  9. package/dist/chunks/{config-BaMO9dQh.js → config-B61cX08u.js} +1 -1
  10. package/dist/chunks/{config-BaMO9dQh.js.map → config-B61cX08u.js.map} +1 -1
  11. package/dist/chunks/{config-C5TN9J2Z.js.map → config-BK6Odc3T.js.map} +1 -1
  12. package/dist/chunks/{config-C0rHS1-l.js.map → config-BOdu-O_B.js.map} +1 -1
  13. package/dist/chunks/{config-D27BL0H9.js.map → config-BU0olrvr.js.map} +1 -1
  14. package/dist/chunks/{config-XoANT5mU.js → config-BY81UKv0.js} +1 -1
  15. package/dist/chunks/{config-XoANT5mU.js.map → config-BY81UKv0.js.map} +1 -1
  16. package/dist/chunks/config-B_nSBc7W.js.map +1 -0
  17. package/dist/chunks/{config-DbqFk-IW.js.map → config-BbKroFtR.js.map} +1 -1
  18. package/dist/chunks/config-Bcf-8XlK2.js.map +1 -0
  19. package/dist/chunks/{config-C_AOYGBr.js.map → config-BduXEXjt.js.map} +1 -1
  20. package/dist/chunks/config-BeQuykDk2.js.map +1 -0
  21. package/dist/chunks/{config-C_-02Pu-.js.map → config-BgBWt9-A.js.map} +1 -1
  22. package/dist/chunks/{config-Dusr9jcE.js.map → config-BnWSHTEU.js.map} +1 -1
  23. package/dist/chunks/{config-C4AlNm912.js → config-Br_qI3Za.js} +1 -1
  24. package/dist/chunks/config-Br_qI3Za.js.map +1 -0
  25. package/dist/chunks/config-C6zT56Jc2.js.map +1 -0
  26. package/dist/chunks/{config-ZJVOVgqR.js → config-CFf7xaG1.js} +1 -1
  27. package/dist/chunks/{config-ZJVOVgqR.js.map → config-CFf7xaG1.js.map} +1 -1
  28. package/dist/chunks/{config-Cn8TG49a.js.map → config-CUwF4E4R.js.map} +1 -1
  29. package/dist/chunks/{config-wo-ncgTH.js.map → config-CdJpnjDj.js.map} +1 -1
  30. package/dist/chunks/config-CetsgpaZ2.js.map +1 -0
  31. package/dist/chunks/{config-D1DI3roo.js.map → config-Ci9nXGUV.js.map} +1 -1
  32. package/dist/chunks/{config-CjEplP6D.js.map → config-CpMYmvVT.js.map} +1 -1
  33. package/dist/chunks/{config-BXffa3ta.js → config-Cp_XHsze.js} +2 -2
  34. package/dist/chunks/{config-BXffa3ta.js.map → config-Cp_XHsze.js.map} +1 -1
  35. package/dist/chunks/{config-D98m8iyz.js.map → config-CvGdaXvH.js.map} +1 -1
  36. package/dist/chunks/{config-CtomKf-k.js.map → config-D4s_QWVP.js.map} +1 -1
  37. package/dist/chunks/{config-D32znLtV2.js.map → config-D6Oe3blW2.js.map} +1 -1
  38. package/dist/chunks/{config-CVnluhKO.js.map → config-DF_RlCIO.js.map} +1 -1
  39. package/dist/chunks/{config-C4qAA0Sb.js.map → config-DSBlHQVa.js.map} +1 -1
  40. package/dist/chunks/{config-Mp9DJ9Mq2.js.map → config-DaHI5bD_2.js.map} +1 -1
  41. package/dist/chunks/{config-3SftO0uG.js.map → config-Dcb7xK-C.js.map} +1 -1
  42. package/dist/chunks/config-DmjwIqx1.js.map +1 -0
  43. package/dist/chunks/{config-D6Af6WZw.js.map → config-DoBk_CzG.js.map} +1 -1
  44. package/dist/chunks/config-Dzd6BzIN2.js.map +1 -0
  45. package/dist/chunks/{config-Db4BEG8Y.js.map → config-O1_FTqD3.js.map} +1 -1
  46. package/dist/chunks/{config-C9AOlKah.js.map → config-V3LF-b_F.js.map} +1 -1
  47. package/dist/chunks/config-_3De4HFf.js.map +1 -0
  48. package/dist/chunks/{config-B44QVIge.js → config-d386uO3O.js} +1 -1
  49. package/dist/chunks/{config-B44QVIge.js.map → config-d386uO3O.js.map} +1 -1
  50. package/dist/chunks/{config-DudL02ag.js.map → config-iuMz79Mg.js.map} +1 -1
  51. package/dist/chunks/{config-DJWf0kWe.js.map → config-vcDVCYXo.js.map} +1 -1
  52. package/dist/chunks/{en-QNZhjmSJ.js.map → en-foQA8imU.js.map} +1 -1
  53. package/dist/chunks/{es-CKLPuE0h.js → es-Bx3Kuy6z.js} +3 -3
  54. package/dist/chunks/{es-CKLPuE0h.js.map → es-Bx3Kuy6z.js.map} +1 -1
  55. package/dist/chunks/{es-C1c5XsIK.js.map → es-DZFSojYL.js.map} +1 -1
  56. package/dist/chunks/{fileValidation-CwJA8Vmn.js.map → fileValidation-c_iBg74s.js.map} +1 -1
  57. package/dist/chunks/{grBadgeStyles-pqqbVgLk.js → grBadgeStyles-Cq0hH2Ls.js} +7 -5
  58. package/dist/chunks/grBadgeStyles-Cq0hH2Ls.js.map +1 -0
  59. package/dist/chunks/{grButtonStyles-BxZW2x0-.js.map → grButtonStyles-DKuXUemw.js.map} +1 -1
  60. package/dist/chunks/{grDropdownStyles-DMp7RrI9.js.map → grDropdownStyles-B41mVR1H.js.map} +1 -1
  61. package/dist/chunks/{grLoadingStyles-CrxZHFL0.js.map → grLoadingStyles-DmI-SJ3i.js.map} +1 -1
  62. package/dist/chunks/{grSelectStyles-DTAYNzxn.js.map → grSelectStyles-pUt19VGy.js.map} +1 -1
  63. package/dist/chunks/{grStyle-5EMYYctb.js.map → grStyle-CUaTmpyW.js.map} +1 -1
  64. package/dist/chunks/{granularityI18n-CXa_uN7f.js → granularityI18n-LcJ88Vce.js} +1 -1
  65. package/dist/chunks/{granularityI18n-CXa_uN7f.js.map → granularityI18n-LcJ88Vce.js.map} +1 -1
  66. package/dist/chunks/loader-circle-BUntgosj.js.map +1 -0
  67. package/dist/chunks/{ru-DcF7ciz0.js.map → ru-LhkPpPIl.js.map} +1 -1
  68. package/dist/chunks/{safelist-BY7z8fOl.js → safelist-DccvJqCE.js} +1 -1
  69. package/dist/chunks/{safelist-BY7z8fOl.js.map → safelist-DccvJqCE.js.map} +1 -1
  70. package/dist/chunks/safelist-_UVzJrgE2.js.map +1 -0
  71. package/dist/chunks/{shared-BkIIEolF.js → shared-D24hqkyM.js} +42 -42
  72. package/dist/chunks/{shared-BkIIEolF.js.map → shared-D24hqkyM.js.map} +1 -1
  73. package/dist/components/GrBadge/chunks/GrBadge-Cs_cVfuO.js +36 -0
  74. package/dist/components/GrBadge/chunks/GrBadge-Cs_cVfuO.js.map +1 -0
  75. package/dist/components/GrBadge/index.js +2 -2
  76. package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-CxtamOZ-.js.map → GrBadgeWrap-BEnE9DyJ.js.map} +1 -1
  77. package/dist/components/GrBadgeWrap/index.js +2 -2
  78. package/dist/components/GrBottomNav/chunks/{GrBottomNav-CsmQ7mTJ.js.map → GrBottomNav-XPHwd7UQ.js.map} +1 -1
  79. package/dist/components/GrBottomNav/index.js +2 -2
  80. package/dist/components/GrButton/chunks/{GrButton-BmGdp8-4.js → GrButton-CPDKonoB.js} +2 -2
  81. package/dist/components/GrButton/chunks/{GrButton-BmGdp8-4.js.map → GrButton-CPDKonoB.js.map} +1 -1
  82. package/dist/components/GrButton/index.js +4 -4
  83. package/dist/components/GrButtonGroup/chunks/{GrButtonGroup-CBj4tpms.js.map → GrButtonGroup-CPOH6V-P.js.map} +1 -1
  84. package/dist/components/GrButtonGroup/index.js +2 -2
  85. package/dist/components/GrCard/chunks/{GrCard-xtDcXBr7.js → GrCard-6yk1RRAQ.js} +1 -1
  86. package/dist/components/GrCard/chunks/{GrCard-xtDcXBr7.js.map → GrCard-6yk1RRAQ.js.map} +1 -1
  87. package/dist/components/GrCard/index.js +1 -1
  88. package/dist/components/GrCollapse/chunks/{GrCollapse-HU20VTVn.js → GrCollapse-CU94BTAR.js} +1 -1
  89. package/dist/components/GrCollapse/chunks/{GrCollapse-HU20VTVn.js.map → GrCollapse-CU94BTAR.js.map} +1 -1
  90. package/dist/components/GrCollapse/index.js +1 -1
  91. package/dist/components/GrConfirmDialog/chunks/{GrConfirmDialog-DjGOX9Hd.js → GrConfirmDialog-BGmyfDd2.js} +32 -9
  92. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-BGmyfDd2.js.map +1 -0
  93. package/dist/components/GrConfirmDialog/index.js +2 -2
  94. package/dist/components/GrDataTable/chunks/{GrDataTable-QDOJWmdY.js → GrDataTable-ClcYiyc8.js} +2 -2
  95. package/dist/components/GrDataTable/chunks/{GrDataTable-QDOJWmdY.js.map → GrDataTable-ClcYiyc8.js.map} +1 -1
  96. package/dist/components/GrDataTable/index.js +2 -2
  97. package/dist/components/GrDialog/chunks/{GrDialog-gObmaVEl.js → GrDialog-Ba3Ojcsq.js} +1 -1
  98. package/dist/components/GrDialog/chunks/{GrDialog-gObmaVEl.js.map → GrDialog-Ba3Ojcsq.js.map} +1 -1
  99. package/dist/components/GrDialog/index.js +2 -2
  100. package/dist/components/GrDrawer/chunks/{GrDrawer-BJL_gTxI.js → GrDrawer-BW3wtI7h.js} +2 -2
  101. package/dist/components/GrDrawer/chunks/{GrDrawer-BJL_gTxI.js.map → GrDrawer-BW3wtI7h.js.map} +1 -1
  102. package/dist/components/GrDrawer/index.js +2 -2
  103. package/dist/components/GrDropdown/chunks/{GrDropdown-BkACCXdp.js → GrDropdown-DOvHKnih.js} +1 -1
  104. package/dist/components/GrDropdown/chunks/{GrDropdown-BkACCXdp.js.map → GrDropdown-DOvHKnih.js.map} +1 -1
  105. package/dist/components/GrDropdown/index.js +2 -2
  106. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-BEenXrJw.js → GrDropdownMenu-CLPwbiyG.js} +1 -1
  107. package/dist/components/GrDropdownMenu/chunks/{GrDropdownMenu-BEenXrJw.js.map → GrDropdownMenu-CLPwbiyG.js.map} +1 -1
  108. package/dist/components/GrDropdownMenu/index.js +2 -2
  109. package/dist/components/GrEmptyState/chunks/{GrEmptyState-BLbMJFW-.js.map → GrEmptyState-Dj2V5GaX.js.map} +1 -1
  110. package/dist/components/GrEmptyState/index.js +2 -2
  111. package/dist/components/GrFileUpload/chunks/{GrFileUpload-DYRERhI2.js → GrFileUpload-BEKNB1RM.js} +5 -5
  112. package/dist/components/GrFileUpload/chunks/GrFileUpload-BEKNB1RM.js.map +1 -0
  113. package/dist/components/GrFileUpload/index.js +3 -3
  114. package/dist/components/GrFormField/chunks/{GrFormField-C1oWTT_0.js.map → GrFormField-U7c_aDPJ.js.map} +1 -1
  115. package/dist/components/GrFormField/index.js +2 -2
  116. package/dist/components/GrFormFile/chunks/{GrFormFile-deDPicM2.js → GrFormFile-CIleXnfr.js} +3 -3
  117. package/dist/components/GrFormFile/chunks/{GrFormFile-deDPicM2.js.map → GrFormFile-CIleXnfr.js.map} +1 -1
  118. package/dist/components/GrFormFile/index.js +2 -2
  119. package/dist/components/GrFormSection/chunks/{GrFormSection-CWBk2EUm.js.map → GrFormSection-DpGhY7MX.js.map} +1 -1
  120. package/dist/components/GrFormSection/index.js +2 -2
  121. package/dist/components/GrImageViewer/chunks/{GrImageViewer-Cpj5zyZQ.js.map → GrImageViewer-Cn1X-sWS.js.map} +1 -1
  122. package/dist/components/GrImageViewer/index.js +2 -2
  123. package/dist/components/GrInput/chunks/{GrInput-CfO2RsM-.js.map → GrInput-gwFQ1sk4.js.map} +1 -1
  124. package/dist/components/GrInput/index.js +2 -2
  125. package/dist/components/GrInputTag/chunks/{GrInputTag-G_VYJPF9.js → GrInputTag-Dcj3F6rQ.js} +2 -2
  126. package/dist/components/GrInputTag/chunks/{GrInputTag-G_VYJPF9.js.map → GrInputTag-Dcj3F6rQ.js.map} +1 -1
  127. package/dist/components/GrInputTag/index.js +2 -2
  128. package/dist/components/GrLink/chunks/{GrLink-BLPigqij.js → GrLink-BMwn2iJ9.js} +1 -1
  129. package/dist/components/GrLink/chunks/{GrLink-BLPigqij.js.map → GrLink-BMwn2iJ9.js.map} +1 -1
  130. package/dist/components/GrLink/index.js +2 -2
  131. package/dist/components/GrList/chunks/{GrList-BPjQf-72.js → GrList-D8nM1FuV.js} +1 -1
  132. package/dist/components/GrList/chunks/{GrList-BPjQf-72.js.map → GrList-D8nM1FuV.js.map} +1 -1
  133. package/dist/components/GrList/index.js +2 -2
  134. package/dist/components/GrLoading/chunks/{GrLoading-C3QZKwE-.js → GrLoading-mfyfghxs.js} +2 -2
  135. package/dist/components/GrLoading/chunks/{GrLoading-C3QZKwE-.js.map → GrLoading-mfyfghxs.js.map} +1 -1
  136. package/dist/components/GrLoading/index.js +2 -2
  137. package/dist/components/GrModal/index.js +1 -1
  138. package/dist/components/GrNavbar/chunks/{GrNavbar-BoVuSZ-V.js → GrNavbar-BH7XiF9q.js} +2 -2
  139. package/dist/components/GrNavbar/chunks/{GrNavbar-BoVuSZ-V.js.map → GrNavbar-BH7XiF9q.js.map} +1 -1
  140. package/dist/components/GrNavbar/index.js +2 -2
  141. package/dist/components/GrNumberInput/chunks/{GrNumberInput-ECtFCIKV.js → GrNumberInput-YIWhV85S.js} +1 -1
  142. package/dist/components/GrNumberInput/chunks/{GrNumberInput-ECtFCIKV.js.map → GrNumberInput-YIWhV85S.js.map} +1 -1
  143. package/dist/components/GrNumberInput/index.js +2 -2
  144. package/dist/components/GrPagination/chunks/{GrPagination-DW44c2-a.js → GrPagination-cD6rFO9W.js} +3 -3
  145. package/dist/components/GrPagination/chunks/{GrPagination-DW44c2-a.js.map → GrPagination-cD6rFO9W.js.map} +1 -1
  146. package/dist/components/GrPagination/index.js +2 -2
  147. package/dist/components/GrProgressBar/chunks/{GrProgressBar-hQQK8cYh.js → GrProgressBar-C2HdYjp4.js} +1 -1
  148. package/dist/components/GrProgressBar/chunks/{GrProgressBar-hQQK8cYh.js.map → GrProgressBar-C2HdYjp4.js.map} +1 -1
  149. package/dist/components/GrProgressBar/index.js +2 -2
  150. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-CUMW6_58.js → GrPromptDialog-Du1aLfcA.js} +55 -29
  151. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-Du1aLfcA.js.map +1 -0
  152. package/dist/components/GrPromptDialog/index.js +2 -2
  153. package/dist/components/GrRadio/chunks/{GrRadio-B_t_ZNVl.js → GrRadio-IFU9Hiu2.js} +1 -1
  154. package/dist/components/GrRadio/chunks/{GrRadio-B_t_ZNVl.js.map → GrRadio-IFU9Hiu2.js.map} +1 -1
  155. package/dist/components/GrRadio/index.js +2 -2
  156. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CVlgpUBr.js → GrRadioGroup-C8IcJuuF.js} +2 -2
  157. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CVlgpUBr.js.map → GrRadioGroup-C8IcJuuF.js.map} +1 -1
  158. package/dist/components/GrRadioGroup/index.js +2 -2
  159. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-BMvXREcv.js +221 -0
  160. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-BMvXREcv.js.map +1 -0
  161. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-CzdTh4gd.js +782 -0
  162. package/dist/components/GrResponseErrorBanner/chunks/GrResponseErrorBanner-CzdTh4gd.js.map +1 -0
  163. package/dist/components/GrResponseErrorBanner/index.js +3 -0
  164. package/dist/components/GrSegmented/chunks/{GrSegmented-BPl1koHc.js → GrSegmented-BRmwBsEG.js} +1 -1
  165. package/dist/components/GrSegmented/chunks/{GrSegmented-BPl1koHc.js.map → GrSegmented-BRmwBsEG.js.map} +1 -1
  166. package/dist/components/GrSegmented/index.js +2 -2
  167. package/dist/components/GrSelect/chunks/{GrSelect-C3NAfTqL.js → GrSelect-W9lbAjRZ.js} +2 -2
  168. package/dist/components/GrSelect/chunks/{GrSelect-C3NAfTqL.js.map → GrSelect-W9lbAjRZ.js.map} +1 -1
  169. package/dist/components/GrSelect/index.js +2 -2
  170. package/dist/components/GrSidebar/chunks/{GrSidebar-DVucgcfV.js.map → GrSidebar-BpBtAGBs.js.map} +1 -1
  171. package/dist/components/GrSidebar/index.js +2 -2
  172. package/dist/components/GrSkeleton/chunks/{GrSkeleton-CDTvCSoH.js.map → GrSkeleton-URyMkBqI.js.map} +1 -1
  173. package/dist/components/GrSkeleton/index.js +2 -2
  174. package/dist/components/GrSwitch/chunks/{GrSwitch-Bnamgqb2.js → GrSwitch-29h0QhMO.js} +1 -1
  175. package/dist/components/GrSwitch/chunks/{GrSwitch-Bnamgqb2.js.map → GrSwitch-29h0QhMO.js.map} +1 -1
  176. package/dist/components/GrSwitch/index.js +2 -2
  177. package/dist/components/GrTable/chunks/{GrTable-CyQ9uw8A.js.map → GrTable-dTWUxzRm.js.map} +1 -1
  178. package/dist/components/GrTable/index.js +2 -2
  179. package/dist/components/GrTabs/chunks/{GrTabs-CiGmcmvm.js.map → GrTabs-D3ntDdtg.js.map} +1 -1
  180. package/dist/components/GrTabs/index.js +2 -2
  181. package/dist/components/GrTextarea/chunks/{GrTextarea-VBSc6A7D.js → GrTextarea-Cv6r2GuC.js} +1 -1
  182. package/dist/components/GrTextarea/chunks/{GrTextarea-VBSc6A7D.js.map → GrTextarea-Cv6r2GuC.js.map} +1 -1
  183. package/dist/components/GrTextarea/index.js +2 -2
  184. package/dist/components/GrToaster/chunks/{GrToaster-I1e-zCpf.js → GrToaster-DluJmR5D.js} +2 -2
  185. package/dist/components/GrToaster/chunks/{GrToaster-I1e-zCpf.js.map → GrToaster-DluJmR5D.js.map} +1 -1
  186. package/dist/components/GrToaster/index.js +2 -2
  187. package/dist/components/GrTooltip/chunks/{GrTooltip-CrV1gI_c.js.map → GrTooltip-B7I1AVIC.js.map} +1 -1
  188. package/dist/components/GrTooltip/index.js +2 -2
  189. package/dist/components/GrTree/chunks/{GrTree-Dlev9oBd.js → GrTree-B2SMU5Py.js} +1 -1
  190. package/dist/components/GrTree/chunks/{GrTree-Dlev9oBd.js.map → GrTree-B2SMU5Py.js.map} +1 -1
  191. package/dist/components/GrTree/index.js +2 -2
  192. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DkAIksRW.js → GrTreeSelect-C1abr5uH.js} +4 -4
  193. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-DkAIksRW.js.map → GrTreeSelect-C1abr5uH.js.map} +1 -1
  194. package/dist/components/GrTreeSelect/index.js +2 -2
  195. package/dist/directives/dropzone.js +1 -1
  196. package/dist/directives/loading.js +1 -1
  197. package/dist/fileValidation/index.js +1 -1
  198. package/dist/granular-provider-node.js +3 -3
  199. package/dist/granular-provider.js +1 -1
  200. package/dist/i18n/all.js +1 -1
  201. package/dist/i18n/index.js +2 -2
  202. package/dist/index.js +486 -1027
  203. package/dist/index.js.map +1 -1
  204. package/dist/types/src/components/GrBadge/grBadgeStyles.d.ts +1 -1
  205. package/dist/types/src/components/GrConfirmDialog/GrConfirmDialog.vue.d.ts +35 -2
  206. package/dist/types/src/components/GrDialogService/GrDialogServiceHost.vue.d.ts +3 -0
  207. package/dist/types/src/components/GrDialogService/config.d.ts +1 -0
  208. package/dist/types/src/components/GrDialogService/index.d.ts +4 -0
  209. package/dist/types/src/components/GrDialogService/store.d.ts +22 -0
  210. package/dist/types/src/components/GrDialogService/types.d.ts +141 -0
  211. package/dist/types/src/components/GrDialogService/useDialogService.d.ts +13 -0
  212. package/dist/types/src/components/GrFileUpload/GrFileUpload.vue.d.ts +3 -3
  213. package/dist/types/src/components/GrFormFile/GrFormFile.vue.d.ts +2 -2
  214. package/dist/types/src/components/GrInput/GrInput.vue.d.ts +3 -3
  215. package/dist/types/src/components/GrInputTag/GrInputTag.vue.d.ts +1 -1
  216. package/dist/types/src/components/GrNumberInput/GrNumberInput.vue.d.ts +4 -4
  217. package/dist/types/src/components/GrPromptDialog/GrPromptDialog.vue.d.ts +41 -2
  218. package/dist/types/src/components/GrResponseErrorBanner/GrUploadErrorBanner.vue.d.ts +1 -1
  219. package/dist/types/src/components/GrResponseErrorBanner/index.d.ts +2 -2
  220. package/dist/types/src/components/GrResponseErrorBanner/parsers/createResponseErrorClassifier.d.ts +27 -0
  221. package/dist/types/src/components/GrResponseErrorBanner/parsers/index.d.ts +2 -2
  222. package/dist/types/src/components/GrSelect/GrSelect.vue.d.ts +1 -1
  223. package/dist/types/src/components/GrTextarea/GrTextarea.vue.d.ts +2 -2
  224. package/dist/types/src/components/GrToaster/GrToaster.vue.d.ts +1 -1
  225. package/dist/types/src/index.d.ts +1 -0
  226. package/package.json +5 -1
  227. package/dist/chunks/arrow-up-DNXrMoAI.js.map +0 -1
  228. package/dist/chunks/config-C0b_3LJV.js.map +0 -1
  229. package/dist/chunks/config-C4AlNm912.js.map +0 -1
  230. package/dist/chunks/config-CxCAfXZ1.js.map +0 -1
  231. package/dist/chunks/config-DDEWvph-2.js.map +0 -1
  232. package/dist/chunks/config-DDLoUczC.js.map +0 -1
  233. package/dist/chunks/config-DQOSlWvp.js.map +0 -1
  234. package/dist/chunks/config-DnsISjD8.js.map +0 -1
  235. package/dist/chunks/config-DxqMXzNV2.js.map +0 -1
  236. package/dist/chunks/config-DxqpV-KM.js.map +0 -1
  237. package/dist/chunks/config-rxFL-6yF2.js.map +0 -1
  238. package/dist/chunks/grBadgeStyles-pqqbVgLk.js.map +0 -1
  239. package/dist/chunks/loader-circle-B2rWDk5u.js.map +0 -1
  240. package/dist/chunks/safelist-BF822K15.js.map +0 -1
  241. package/dist/components/GrBadge/chunks/GrBadge-wuIb4_2K.js +0 -32
  242. package/dist/components/GrBadge/chunks/GrBadge-wuIb4_2K.js.map +0 -1
  243. package/dist/components/GrConfirmDialog/chunks/GrConfirmDialog-DjGOX9Hd.js.map +0 -1
  244. package/dist/components/GrFileUpload/chunks/GrFileUpload-DYRERhI2.js.map +0 -1
  245. package/dist/components/GrPromptDialog/chunks/GrPromptDialog-CUMW6_58.js.map +0 -1
  246. /package/dist/chunks/{_plugin-vue_export-helper-BG_EqiDU.js → _plugin-vue_export-helper-DQR7Sy7Q.js} +0 -0
  247. /package/dist/chunks/{adapter-CRyH4YC8.js → adapter-BqqjEZGU.js} +0 -0
  248. /package/dist/chunks/{arrow-up-DNXrMoAI.js → arrow-up-DZdIrpaF.js} +0 -0
  249. /package/dist/chunks/{config-C0b_3LJV.js → config-72sW9Bag2.js} +0 -0
  250. /package/dist/chunks/{config-B8rC_K97.js → config-B1kFmhpM.js} +0 -0
  251. /package/dist/chunks/{config-BhvNm4Pp.js → config-B2YTEe_h.js} +0 -0
  252. /package/dist/chunks/{config-C5TN9J2Z.js → config-BK6Odc3T.js} +0 -0
  253. /package/dist/chunks/{config-C0rHS1-l.js → config-BOdu-O_B.js} +0 -0
  254. /package/dist/chunks/{config-D27BL0H9.js → config-BU0olrvr.js} +0 -0
  255. /package/dist/chunks/{config-DxqMXzNV2.js → config-B_nSBc7W.js} +0 -0
  256. /package/dist/chunks/{config-DbqFk-IW.js → config-BbKroFtR.js} +0 -0
  257. /package/dist/chunks/{config-DQOSlWvp.js → config-Bcf-8XlK2.js} +0 -0
  258. /package/dist/chunks/{config-C_AOYGBr.js → config-BduXEXjt.js} +0 -0
  259. /package/dist/chunks/{config-DnsISjD8.js → config-BeQuykDk2.js} +0 -0
  260. /package/dist/chunks/{config-C_-02Pu-.js → config-BgBWt9-A.js} +0 -0
  261. /package/dist/chunks/{config-Dusr9jcE.js → config-BnWSHTEU.js} +0 -0
  262. /package/dist/chunks/{config-DxqpV-KM.js → config-C6zT56Jc2.js} +0 -0
  263. /package/dist/chunks/{config-Cn8TG49a.js → config-CUwF4E4R.js} +0 -0
  264. /package/dist/chunks/{config-wo-ncgTH.js → config-CdJpnjDj.js} +0 -0
  265. /package/dist/chunks/{config-CxCAfXZ1.js → config-CetsgpaZ2.js} +0 -0
  266. /package/dist/chunks/{config-D1DI3roo.js → config-Ci9nXGUV.js} +0 -0
  267. /package/dist/chunks/{config-CjEplP6D.js → config-CpMYmvVT.js} +0 -0
  268. /package/dist/chunks/{config-D98m8iyz.js → config-CvGdaXvH.js} +0 -0
  269. /package/dist/chunks/{config-CtomKf-k.js → config-D4s_QWVP.js} +0 -0
  270. /package/dist/chunks/{config-D32znLtV2.js → config-D6Oe3blW2.js} +0 -0
  271. /package/dist/chunks/{config-CVnluhKO.js → config-DF_RlCIO.js} +0 -0
  272. /package/dist/chunks/{config-C4qAA0Sb.js → config-DSBlHQVa.js} +0 -0
  273. /package/dist/chunks/{config-Mp9DJ9Mq2.js → config-DaHI5bD_2.js} +0 -0
  274. /package/dist/chunks/{config-3SftO0uG.js → config-Dcb7xK-C.js} +0 -0
  275. /package/dist/chunks/{config-DDEWvph-2.js → config-DmjwIqx1.js} +0 -0
  276. /package/dist/chunks/{config-D6Af6WZw.js → config-DoBk_CzG.js} +0 -0
  277. /package/dist/chunks/{config-DDLoUczC.js → config-Dzd6BzIN2.js} +0 -0
  278. /package/dist/chunks/{config-Db4BEG8Y.js → config-O1_FTqD3.js} +0 -0
  279. /package/dist/chunks/{config-C9AOlKah.js → config-V3LF-b_F.js} +0 -0
  280. /package/dist/chunks/{config-rxFL-6yF2.js → config-_3De4HFf.js} +0 -0
  281. /package/dist/chunks/{config-DudL02ag.js → config-iuMz79Mg.js} +0 -0
  282. /package/dist/chunks/{config-DJWf0kWe.js → config-vcDVCYXo.js} +0 -0
  283. /package/dist/chunks/{en-QNZhjmSJ.js → en-foQA8imU.js} +0 -0
  284. /package/dist/chunks/{es-C1c5XsIK.js → es-DZFSojYL.js} +0 -0
  285. /package/dist/chunks/{fileValidation-CwJA8Vmn.js → fileValidation-c_iBg74s.js} +0 -0
  286. /package/dist/chunks/{grButtonStyles-BxZW2x0-.js → grButtonStyles-DKuXUemw.js} +0 -0
  287. /package/dist/chunks/{grDropdownStyles-DMp7RrI9.js → grDropdownStyles-B41mVR1H.js} +0 -0
  288. /package/dist/chunks/{grLoadingStyles-CrxZHFL0.js → grLoadingStyles-DmI-SJ3i.js} +0 -0
  289. /package/dist/chunks/{grSelectStyles-DTAYNzxn.js → grSelectStyles-pUt19VGy.js} +0 -0
  290. /package/dist/chunks/{grStyle-5EMYYctb.js → grStyle-CUaTmpyW.js} +0 -0
  291. /package/dist/chunks/{loader-circle-B2rWDk5u.js → loader-circle-BUntgosj.js} +0 -0
  292. /package/dist/chunks/{ru-DcF7ciz0.js → ru-LhkPpPIl.js} +0 -0
  293. /package/dist/chunks/{safelist-BF822K15.js → safelist-_UVzJrgE2.js} +0 -0
  294. /package/dist/components/GrBadgeWrap/chunks/{GrBadgeWrap-CxtamOZ-.js → GrBadgeWrap-BEnE9DyJ.js} +0 -0
  295. /package/dist/components/GrBottomNav/chunks/{GrBottomNav-CsmQ7mTJ.js → GrBottomNav-XPHwd7UQ.js} +0 -0
  296. /package/dist/components/GrButtonGroup/chunks/{GrButtonGroup-CBj4tpms.js → GrButtonGroup-CPOH6V-P.js} +0 -0
  297. /package/dist/components/GrEmptyState/chunks/{GrEmptyState-BLbMJFW-.js → GrEmptyState-Dj2V5GaX.js} +0 -0
  298. /package/dist/components/GrFormField/chunks/{GrFormField-C1oWTT_0.js → GrFormField-U7c_aDPJ.js} +0 -0
  299. /package/dist/components/GrFormSection/chunks/{GrFormSection-CWBk2EUm.js → GrFormSection-DpGhY7MX.js} +0 -0
  300. /package/dist/components/GrImageViewer/chunks/{GrImageViewer-Cpj5zyZQ.js → GrImageViewer-Cn1X-sWS.js} +0 -0
  301. /package/dist/components/GrInput/chunks/{GrInput-CfO2RsM-.js → GrInput-gwFQ1sk4.js} +0 -0
  302. /package/dist/components/GrSidebar/chunks/{GrSidebar-DVucgcfV.js → GrSidebar-BpBtAGBs.js} +0 -0
  303. /package/dist/components/GrSkeleton/chunks/{GrSkeleton-CDTvCSoH.js → GrSkeleton-URyMkBqI.js} +0 -0
  304. /package/dist/components/GrTable/chunks/{GrTable-CyQ9uw8A.js → GrTable-dTWUxzRm.js} +0 -0
  305. /package/dist/components/GrTabs/chunks/{GrTabs-CiGmcmvm.js → GrTabs-D3ntDdtg.js} +0 -0
  306. /package/dist/components/GrTooltip/chunks/{GrTooltip-CrV1gI_c.js → GrTooltip-B7I1AVIC.js} +0 -0
@@ -70,11 +70,11 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
70
70
  disabled: boolean;
71
71
  name: string;
72
72
  id: string;
73
- invalid: boolean;
74
- placeholder: string;
75
- state: "default" | "success" | "warning" | "danger";
76
73
  inputmode: "text" | "search" | "none" | "email" | "tel" | "url" | "numeric" | "decimal";
74
+ placeholder: string;
77
75
  autocomplete: string;
76
+ invalid: boolean;
77
+ state: "default" | "success" | "warning" | "danger";
78
78
  textAlign: GrInputTextAlign;
79
79
  prefixMinWidth: string;
80
80
  prefixMaxWidth: string;
@@ -91,8 +91,8 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
91
91
  size: GrInputTagSize;
92
92
  disabled: boolean;
93
93
  max: number;
94
- invalid: boolean;
95
94
  placeholder: string;
95
+ invalid: boolean;
96
96
  state: GrInputTagState;
97
97
  separators: string[];
98
98
  allowDuplicates: boolean;
@@ -100,17 +100,17 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
100
100
  name: string;
101
101
  id: string;
102
102
  max: number;
103
- invalid: boolean;
104
- min: number;
105
- placeholder: string;
106
- state: GrNumberInputState;
107
103
  inputmode: "text" | "search" | "none" | "email" | "tel" | "url" | "numeric" | "decimal";
104
+ placeholder: string;
108
105
  autocomplete: string;
106
+ invalid: boolean;
107
+ state: GrNumberInputState;
109
108
  textAlign: GrNumberInputTextAlign;
110
109
  prefixMinWidth: string;
111
110
  prefixMaxWidth: string;
112
111
  suffixMinWidth: string;
113
112
  suffixMaxWidth: string;
113
+ min: number;
114
114
  decimalSeparator: string;
115
115
  step: number;
116
116
  precision: number;
@@ -1,5 +1,6 @@
1
1
  import type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton';
2
2
  import type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog';
3
+ import type { ResponseErrorInfo } from '../GrResponseErrorBanner';
3
4
  export interface GrPromptDialogProps {
4
5
  modelValue: boolean;
5
6
  value: string;
@@ -25,12 +26,35 @@ export interface GrPromptDialogProps {
25
26
  confirmVariant?: GrButtonVariant;
26
27
  confirmTone?: GrButtonTone;
27
28
  required?: boolean;
29
+ /**
30
+ * Структура ошибки ответа сервера для показа общим блоком в теле диалога
31
+ * (через `GrResponseErrorBanner`). `null` — блок скрыт.
32
+ */
33
+ error?: ResponseErrorInfo | null;
34
+ /**
35
+ * Внешняя ошибка поля ввода (например, серверная валидация). Имеет приоритет
36
+ * над встроенной проверкой `required`. `null`/`undefined` — нет внешней ошибки.
37
+ */
38
+ fieldError?: string | null;
39
+ /** Состояние загрузки кнопки Confirm (async-`onConfirm` in-flight). */
40
+ confirmLoading?: boolean;
41
+ /** Принудительно дизейблит кнопку Confirm. */
42
+ confirmDisabled?: boolean;
43
+ /**
44
+ * Закрывать ли диалог автоматически по клику Confirm. По умолчанию `true`.
45
+ * `false` — отдаёт управление закрытием наружу (нужно `useDialogService`).
46
+ */
47
+ closeOnConfirm?: boolean;
28
48
  }
29
- declare var __VLS_8: {}, __VLS_26: {};
49
+ declare var __VLS_8: {}, __VLS_25: {
50
+ error: ResponseErrorInfo | null;
51
+ }, __VLS_33: {};
30
52
  type __VLS_Slots = {} & {
31
53
  default?: (props: typeof __VLS_8) => any;
32
54
  } & {
33
- footer?: (props: typeof __VLS_26) => any;
55
+ error?: (props: typeof __VLS_25) => any;
56
+ } & {
57
+ footer?: (props: typeof __VLS_33) => any;
34
58
  };
35
59
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrPromptDialogProps>, {
36
60
  title: string;
@@ -53,6 +77,11 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
53
77
  confirmVariant: string;
54
78
  confirmTone: string;
55
79
  required: boolean;
80
+ error: null;
81
+ fieldError: null;
82
+ confirmLoading: boolean;
83
+ confirmDisabled: boolean;
84
+ closeOnConfirm: boolean;
56
85
  }>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
57
86
  "update:modelValue": (value: boolean) => void;
58
87
  "update:value": (value: string) => void;
@@ -79,6 +108,11 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
79
108
  confirmVariant: string;
80
109
  confirmTone: string;
81
110
  required: boolean;
111
+ error: null;
112
+ fieldError: null;
113
+ confirmLoading: boolean;
114
+ confirmDisabled: boolean;
115
+ closeOnConfirm: boolean;
82
116
  }>>> & Readonly<{
83
117
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
84
118
  onConfirm?: ((value: string) => any) | undefined;
@@ -98,13 +132,18 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
98
132
  headerConfig: GrDialogSectionConfig;
99
133
  footerConfig: GrDialogSectionConfig;
100
134
  bodyConfig: GrDialogSectionConfig;
135
+ error: ResponseErrorInfo | null;
101
136
  buttonSize: GrButtonSize;
102
137
  confirmText: string;
103
138
  cancelText: string;
104
139
  confirmVariant: GrButtonVariant;
105
140
  confirmTone: GrButtonTone;
141
+ confirmLoading: boolean;
142
+ confirmDisabled: boolean;
143
+ closeOnConfirm: boolean;
106
144
  placeholder: string;
107
145
  requiredErrorText: string;
146
+ fieldError: string | null;
108
147
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
109
148
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
110
149
  declare const _default: typeof __VLS_export;
@@ -43,13 +43,13 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
43
43
  onDismiss?: (() => any) | undefined;
44
44
  }>, {
45
45
  tone: ResponseErrorTone;
46
- files: File[];
47
46
  texts: Partial<ResponseErrorTexts>;
48
47
  toneByKind: Partial<Record<ResponseErrorKind, ResponseErrorTone>>;
49
48
  canRetry: boolean;
50
49
  canDismiss: boolean;
51
50
  autoHideKinds: ResponseErrorKind[];
52
51
  testIdPrefix: string;
52
+ files: File[];
53
53
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
54
54
  declare const _default: typeof __VLS_export;
55
55
  export default _default;
@@ -5,6 +5,6 @@ export { default as GrFormErrorBanner } from './GrFormErrorBanner.vue';
5
5
  export { DEFAULT_RESPONSE_ERROR_TEXTS, useResponseError, } from './useResponseError';
6
6
  export type { UseResponseErrorOptions, UseResponseErrorReturn, } from './useResponseError';
7
7
  export { DEFAULT_AUTO_HIDE_KINDS, DEFAULT_TONE_BY_KIND, } from './responseError.defaults';
8
- export { abortErrorParser, createResponseErrorClassifier, defaultResponseErrorParsers, extendDefaultParsers, fileValidationParser, httpStatusParser, jsonApiErrorParser, laravelValidationParser, networkErrorParser, normalizeError, plainMessageParser, problemDetailsParser, resolveResponseErrorTitle, } from './parsers';
9
- export type { CreateResponseErrorClassifierOptions } from './parsers';
8
+ export { abortErrorParser, coreResponseErrorParsers, createResponseErrorClassifier, defaultResponseErrorParsers, extendDefaultParsers, fileValidationParser, httpStatusParser, jsonApiErrorParser, laravelValidationParser, networkErrorParser, normalizeError, plainMessageParser, problemDetailsParser, resolveResponseErrorTitle, responseErrorParserPresets, } from './parsers';
9
+ export type { CreateResponseErrorClassifierOptions, ResponseErrorParserPresets, } from './parsers';
10
10
  export type { NormalizedRawError, ResponseErrorContext, ResponseErrorFieldError, ResponseErrorInfo, ResponseErrorKind, ResponseErrorParser, ResponseErrorParserResult, ResponseErrorTexts, ResponseErrorTone, } from './responseError.types';
@@ -8,6 +8,33 @@ import type { ResponseErrorInfo, ResponseErrorKind, ResponseErrorParser, Respons
8
8
  * - `plainMessage` всегда последний — добывает хоть какое-то сообщение.
9
9
  */
10
10
  export declare const defaultResponseErrorParsers: ResponseErrorParser[];
11
+ /**
12
+ * Универсальное «ядро» парсеров — транспортно-независимый набор, безопасный
13
+ * для любого бэкенда (Laravel / Symfony / Go / …). Не делает формат-специфичных
14
+ * допущений: разбирает только отмену, сетевые ошибки, HTTP-статус и «плоское»
15
+ * сообщение из тела. Используется как дефолт в `useDialogService`.
16
+ *
17
+ * Порядок: `abort → network → httpStatus → plainMessage`.
18
+ */
19
+ export declare const coreResponseErrorParsers: ResponseErrorParser[];
20
+ /**
21
+ * Именованные пресеты-строительные блоки для удобной композиции цепочки
22
+ * парсеров без ручного импорта каждого из них.
23
+ *
24
+ * - `core` — универсальное ядро (см. `coreResponseErrorParsers`).
25
+ * - `all` — полная дефолтная цепочка (`defaultResponseErrorParsers`).
26
+ * - остальные — серверо-специфичные парсеры, подключаемые осознанно.
27
+ */
28
+ export type ResponseErrorParserPresets = {
29
+ core: ResponseErrorParser[];
30
+ all: ResponseErrorParser[];
31
+ laravel: ResponseErrorParser;
32
+ problemDetails: ResponseErrorParser;
33
+ jsonApi: ResponseErrorParser;
34
+ fileValidation: ResponseErrorParser;
35
+ };
36
+ /** Объект пресетов, передаётся builder-функции `errorParsers`. */
37
+ export declare const responseErrorParserPresets: ResponseErrorParserPresets;
11
38
  /** Добавляет пользовательские парсеры в начало дефолтной цепочки. */
12
39
  export declare function extendDefaultParsers(extra: ResponseErrorParser[]): ResponseErrorParser[];
13
40
  export type CreateResponseErrorClassifierOptions = {
@@ -7,5 +7,5 @@ export { networkErrorParser } from './networkErrorParser';
7
7
  export { plainMessageParser } from './plainMessageParser';
8
8
  export { problemDetailsParser } from './problemDetailsParser';
9
9
  export { normalizeError } from './normalizeError';
10
- export { createResponseErrorClassifier, defaultResponseErrorParsers, extendDefaultParsers, resolveResponseErrorTitle, } from './createResponseErrorClassifier';
11
- export type { CreateResponseErrorClassifierOptions } from './createResponseErrorClassifier';
10
+ export { coreResponseErrorParsers, createResponseErrorClassifier, defaultResponseErrorParsers, extendDefaultParsers, resolveResponseErrorTitle, responseErrorParserPresets, } from './createResponseErrorClassifier';
11
+ export type { CreateResponseErrorClassifierOptions, ResponseErrorParserPresets, } from './createResponseErrorClassifier';
@@ -100,9 +100,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
100
100
  size: GrSelectSize;
101
101
  disabled: boolean;
102
102
  ariaLabel: string;
103
+ placeholder: string;
103
104
  options: GrSelectOption[];
104
105
  multiple: boolean;
105
- placeholder: string;
106
106
  underline: GrSelectUnderline;
107
107
  optionsView: GrSelectOptionsView;
108
108
  allowCustomValue: boolean;
@@ -53,10 +53,10 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
53
53
  name: string;
54
54
  id: string;
55
55
  rows: number;
56
- invalid: boolean;
57
56
  placeholder: string;
58
- state: GrTextareaState;
59
57
  autocomplete: string;
58
+ invalid: boolean;
59
+ state: GrTextareaState;
60
60
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
61
61
  declare const _default: typeof __VLS_export;
62
62
  export default _default;
@@ -17,8 +17,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
17
17
  dismissLabel: string;
18
18
  regionLabel: string;
19
19
  }>>> & Readonly<{}>, {
20
- regionLabel: string;
21
20
  dismissLabel: string;
21
+ regionLabel: string;
22
22
  placement: GrToasterPlacement;
23
23
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
24
24
  declare const _default: typeof __VLS_export;
@@ -11,6 +11,7 @@ export * from './components/GrCollapse';
11
11
  export * from './components/GrConfirmDialog';
12
12
  export * from './components/GrDataTable';
13
13
  export * from './components/GrDialog';
14
+ export * from './components/GrDialogService';
14
15
  export * from './components/GrDrawer';
15
16
  export * from './components/GrDropdown';
16
17
  export * from './components/GrDropdownMenu';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@feugene/granularity",
3
3
  "description": "Granularity design system package with Vue 3 components, consumed via the `@feugene/unocss-preset-granular` preset.",
4
- "version": "0.7.0",
4
+ "version": "0.9.0",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": {
7
7
  "name": "Evgeniy Fureev",
@@ -193,6 +193,10 @@
193
193
  "types": "./dist/types/src/components/GrRadioGroup/index.d.ts",
194
194
  "import": "./dist/components/GrRadioGroup/index.js"
195
195
  },
196
+ "./components/GrResponseErrorBanner": {
197
+ "types": "./dist/types/src/components/GrResponseErrorBanner/index.d.ts",
198
+ "import": "./dist/components/GrResponseErrorBanner/index.js"
199
+ },
196
200
  "./components/GrSegmented": {
197
201
  "types": "./dist/types/src/components/GrSegmented/index.d.ts",
198
202
  "import": "./dist/components/GrSegmented/index.js"
@@ -1 +0,0 @@
1
- {"version":3,"file":"arrow-up-DNXrMoAI.js","names":[],"sources":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-C0b_3LJV.js","names":[],"sources":["../../src/components/GrTreeSelect/grTreeSelectStyles.ts","../../src/components/GrTreeSelect/safelist.ts","../../src/components/GrTreeSelect/config.ts"],"sourcesContent":["import type { GrInputSize } from '../GrInput'\n\nexport type GrTreeSelectState = 'default' | 'success' | 'warning' | 'danger'\n\nexport const sizeClassBySize: Record<GrInputSize, 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\nexport const borderClassByState: Record<GrTreeSelectState, string> = {\n default: 'border-[var(--brd)]',\n success: 'border-[var(--ds-success)] focus-visible:ring-[var(--ds-success)]',\n warning: 'border-[var(--ds-warning)] focus-visible:ring-[var(--ds-warning)]',\n danger: 'border-[var(--ds-danger)] focus-visible:ring-[var(--ds-danger)]',\n}\n\nexport function grTreeSelectClass(options: { size: GrInputSize, state: GrTreeSelectState, invalid: boolean }): string {\n return [\n sizeClassBySize[options.size],\n 'pr-9',\n options.invalid ? borderClassByState.danger : borderClassByState[options.state],\n ].join(' ')\n}\n\nexport const grTreeSelectPanelClass = 'rounded-[var(--ds-radius-xl)] border border-[var(--brd)] bg-[var(--card)] text-[var(--card-fg)] shadow-[var(--ds-shadow-2)] overflow-hidden'\n","import { splitClassTokens } from '../shared/classTokens'\nimport { borderClassByState, grTreeSelectPanelClass, sizeClassBySize } from './grTreeSelectStyles'\n\nexport const grTreeSelectSafelist = [...new Set([\n ...Object.values(sizeClassBySize).flatMap(splitClassTokens),\n ...Object.values(borderClassByState).flatMap(splitClassTokens),\n 'pr-9',\n ...splitClassTokens(grTreeSelectPanelClass),\n])]\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grTreeSelectSafelist } from './safelist'\n\nexport const grTreeSelectConfig = defineGranularComponent(import.meta.url, {\n name: 'GrTreeSelect',\n safelist: grTreeSelectSafelist,\n dependencies: ['GrInput', 'GrTree'],\n})"],"mappings":";;;AAIA,IAAa,kBAA+C;CAC1D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,IAAa,qBAAwD;CACnE,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACT;AAED,SAAgB,kBAAkB,SAAoF;AACpH,QAAO;EACL,gBAAgB,QAAQ;EACxB;EACA,QAAQ,UAAU,mBAAmB,SAAS,mBAAmB,QAAQ;EAC1E,CAAC,KAAK,IAAI;;AAGb,IAAa,yBAAyB;;;ACvBtC,IAAa,uBAAuB,CAAC,GAAG,IAAI,IAAI;CAC9C,GAAG,OAAO,OAAO,gBAAgB,CAAC,QAAQ,iBAAiB;CAC3D,GAAG,OAAO,OAAO,mBAAmB,CAAC,QAAQ,iBAAiB;CAC9D;CACA,GAAG,iBAAiB,uBAAuB;CAC5C,CAAC,CAAC;;;ACJH,IAAa,qBAAqB,wBAAwB,OAAO,KAAK,KAAK;CACzE,MAAM;CACN,UAAU;CACV,cAAc,CAAC,WAAW,SAAS;CACpC,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-C4AlNm912.js","names":[],"sources":["../../src/components/GrDropdown/safelist.ts","../../src/components/GrDropdown/config.ts"],"sourcesContent":["import { splitClassTokens } from '../shared/classTokens'\nimport {\n alignmentClassByAlign,\n widthClassByWidth,\n} from './grDropdownStyles'\n\n// В safelist кладём только динамические токены, выбираемые по ключам в рантайме\n// (`width`/`align`). Литералы content-класса (`rounded-*`, `border`, `bg-*` и пр.)\n// прописаны статически в исходнике `grDropdownStyles.ts` и находятся UnoCSS'ом сканом.\nexport const grDropdownSafelist = [...new Set([\n ...Object.values(widthClassByWidth).flatMap(splitClassTokens),\n ...Object.values(alignmentClassByAlign).flatMap(splitClassTokens),\n])]\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grDropdownSafelist } from './safelist'\n\nexport const grDropdownConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDropdown',\n safelist: grDropdownSafelist,\n})"],"mappings":";;;;AASA,IAAa,qBAAqB,CAAC,GAAG,IAAI,IAAI,CAC5C,GAAG,OAAO,OAAO,kBAAkB,CAAC,QAAQ,iBAAiB,EAC7D,GAAG,OAAO,OAAO,sBAAsB,CAAC,QAAQ,iBAAiB,CAClE,CAAC,CAAC;;;ACRH,IAAa,mBAAmB,wBAAwB,OAAO,KAAK,KAAK;CACvE,MAAM;CACN,UAAU;CACX,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-CxCAfXZ1.js","names":[],"sources":["../../src/components/GrToaster/grToasterStyles.ts","../../src/components/GrToaster/safelist.ts","../../src/components/GrToaster/config.ts"],"sourcesContent":["export type GrToasterPlacement = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n\n// Классы позиционирования контейнера по углам экрана.\n// Вынесены в отдельный модуль, чтобы быть единственным источником истины\n// для шаблона `GrToaster.vue` и для safelist.\nexport const PLACEMENT_CLASS: Record<GrToasterPlacement, string> = {\n 'top-right': 'right-4 top-4',\n 'top-left': 'left-4 top-4',\n 'bottom-right': 'right-4 bottom-4',\n 'bottom-left': 'left-4 bottom-4',\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport { PLACEMENT_CLASS } from './grToasterStyles'\n\n// В safelist попадают только те классы, которые приходят в шаблон динамически\n// (через `:class`/`PLACEMENT_CLASS`). Литералы из шаблона (`class=\"...\"`)\n// UnoCSS находит статическим сканом и дублировать их здесь не нужно.\nexport const grToasterSafelist = [...new Set(\n Object.values(PLACEMENT_CLASS).flatMap(splitClassTokens),\n)]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nimport { grToasterSafelist } from './safelist'\n\nexport const grToasterConfig = defineGranularComponent(import.meta.url, {\n name: 'GrToaster',\n dependencies: ['GrButton', 'GrIcon'],\n safelist: grToasterSafelist,\n})\n"],"mappings":";;;AAKA,IAAa,kBAAsD;CACjE,aAAa;CACb,YAAY;CACZ,gBAAgB;CAChB,eAAe;CAChB;;;ACJD,IAAa,oBAAoB,CAAC,GAAG,IAAI,IACvC,OAAO,OAAO,gBAAgB,CAAC,QAAQ,iBAAiB,CACzD,CAAC;;;ACJF,IAAa,kBAAkB,wBAAwB,OAAO,KAAK,KAAK;CACtE,MAAM;CACN,cAAc,CAAC,YAAY,SAAS;CACpC,UAAU;CACX,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DDEWvph-2.js","names":[],"sources":["../../src/components/GrDropdownMenu/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nexport const grDropdownMenuConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDropdownMenu',\n dependencies: ['GrDropdown'],\n})\n"],"mappings":";;AAEA,IAAa,uBAAuB,wBAAwB,OAAO,KAAK,KAAK;CAC3E,MAAM;CACN,cAAc,CAAC,aAAa;CAC7B,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DDLoUczC.js","names":[],"sources":["../../src/components/GrTabs/config.ts"],"sourcesContent":["import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nexport const grTabsConfig = defineGranularComponent(import.meta.url, {\n name: 'GrTabs',\n})\n"],"mappings":";;AAEA,IAAa,eAAe,wBAAwB,OAAO,KAAK,KAAK,EACjE,MAAM,UACT,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DQOSlWvp.js","names":[],"sources":["../../src/components/GrTable/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\n// Все классы GrTable — статические литералы в шаблоне, UnoCSS найдёт их сканом.\nexport const grTableConfig = defineGranularComponent(import.meta.url, {\n name: 'GrTable',\n})\n"],"mappings":";;AAGA,IAAa,gBAAgB,wBAAwB,OAAO,KAAK,KAAK,EACpE,MAAM,WACP,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DnsISjD8.js","names":[],"sources":["../../src/components/GrSidebar/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nexport const grSidebarConfig = defineGranularComponent(import.meta.url, {\n name: 'GrSidebar',\n})\n"],"mappings":";;AAEA,IAAa,kBAAkB,wBAAwB,OAAO,KAAK,KAAK,EACtE,MAAM,aACP,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DxqMXzNV2.js","names":[],"sources":["../../src/components/GrTextarea/grTextareaStyles.ts","../../src/components/GrTextarea/safelist.ts","../../src/components/GrTextarea/config.ts"],"sourcesContent":["export type GrTextareaState = 'default' | 'success' | 'warning' | 'danger'\n\nexport const borderClassByState: Record<GrTextareaState, string> = {\n default: 'border-[var(--brd)]',\n success: 'border-[var(--ds-success)] focus-visible:ring-[var(--ds-success)]',\n warning: 'border-[var(--ds-warning)] focus-visible:ring-[var(--ds-warning)]',\n danger: 'border-[var(--ds-danger)] focus-visible:ring-[var(--ds-danger)]',\n}\n\nexport function grTextareaClass(options: { state: GrTextareaState, invalid: boolean }): string {\n return options.invalid ? borderClassByState.danger : borderClassByState[options.state]\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport { borderClassByState } from './grTextareaStyles'\n\nexport const grTextareaSafelist = [...new Set([\n ...Object.values(borderClassByState).flatMap(splitClassTokens),\n])]\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grTextareaSafelist } from './safelist'\n\nexport const grTextareaConfig = defineGranularComponent(import.meta.url, {\n name: 'GrTextarea',\n safelist: grTextareaSafelist,\n})"],"mappings":";;;AAEA,IAAa,qBAAsD;CACjE,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACT;AAED,SAAgB,gBAAgB,SAA+D;AAC7F,QAAO,QAAQ,UAAU,mBAAmB,SAAS,mBAAmB,QAAQ;;;;ACPlF,IAAa,qBAAqB,CAAC,GAAG,IAAI,IAAI,CAC5C,GAAG,OAAO,OAAO,mBAAmB,CAAC,QAAQ,iBAAiB,CAC/D,CAAC,CAAC;;;ACDH,IAAa,mBAAmB,wBAAwB,OAAO,KAAK,KAAK;CACvE,MAAM;CACN,UAAU;CACX,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-DxqpV-KM.js","names":[],"sources":["../../src/components/GrDrawer/grDrawerStyles.ts","../../src/components/GrDrawer/safelist.ts","../../src/components/GrDrawer/config.ts"],"sourcesContent":["export type GrDrawerSide = 'left' | 'right'\nexport type GrDrawerSize = 'sm' | 'md' | 'lg' | 'full'\n\nexport const panelWidthBySize: Record<GrDrawerSize, string> = {\n sm: 'w-[360px] max-w-[90vw]',\n md: 'w-[420px] max-w-[92vw]',\n lg: 'w-[560px] max-w-[94vw]',\n full: 'w-[100vw]',\n}\n\nexport const panelSideClass: Record<GrDrawerSide, string> = {\n left: 'left-0 border-r',\n right: 'right-0 border-l',\n}\n\nexport const panelTransitionClass: Record<GrDrawerSide, string> = {\n left: '-translate-x-full',\n right: 'translate-x-full',\n}\n\nexport function grDrawerPanelClass(options: { side: GrDrawerSide, size: GrDrawerSize }): string {\n return [\n panelSideClass[options.side],\n panelWidthBySize[options.size],\n 'border-[var(--brd)]',\n 'bg-[var(--card)] text-[var(--card-fg)]',\n 'shadow-[var(--ds-shadow-2)] outline-none',\n ].join(' ')\n}\n\nexport function grDrawerPanelEnterFrom(side: GrDrawerSide): string {\n return panelTransitionClass[side]\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n panelSideClass,\n panelTransitionClass,\n panelWidthBySize,\n} from './grDrawerStyles'\n\n// Safelist содержит только динамические токены, выбираемые в рантайме через\n// ключи (`side`/`size`). Литералы, прописанные статически в шаблоне и в функции\n// `grDrawerPanelClass`, UnoCSS находит сканом и здесь не дублируются.\nexport const grDrawerSafelist = [...new Set([\n ...Object.values(panelSideClass).flatMap(splitClassTokens),\n ...Object.values(panelWidthBySize).flatMap(splitClassTokens),\n ...Object.values(panelTransitionClass).flatMap(splitClassTokens),\n])]\n","import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\nimport { grDrawerSafelist } from './safelist'\n\nexport const grDrawerConfig = defineGranularComponent(import.meta.url, {\n name: 'GrDrawer',\n dependencies: ['GrButton', 'GrIcon'],\n safelist: grDrawerSafelist,\n})\n"],"mappings":";;;AAGA,IAAa,mBAAiD;CAC5D,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACP;AAED,IAAa,iBAA+C;CAC1D,MAAM;CACN,OAAO;CACR;AAED,IAAa,uBAAqD;CAChE,MAAM;CACN,OAAO;CACR;AAED,SAAgB,mBAAmB,SAA6D;AAC9F,QAAO;EACL,eAAe,QAAQ;EACvB,iBAAiB,QAAQ;EACzB;EACA;EACA;EACD,CAAC,KAAK,IAAI;;AAGb,SAAgB,uBAAuB,MAA4B;AACjE,QAAO,qBAAqB;;;;ACrB9B,IAAa,mBAAmB,CAAC,GAAG,IAAI,IAAI;CAC1C,GAAG,OAAO,OAAO,eAAe,CAAC,QAAQ,iBAAiB;CAC1D,GAAG,OAAO,OAAO,iBAAiB,CAAC,QAAQ,iBAAiB;CAC5D,GAAG,OAAO,OAAO,qBAAqB,CAAC,QAAQ,iBAAiB;CACjE,CAAC,CAAC;;;ACXH,IAAa,iBAAiB,wBAAwB,OAAO,KAAK,KAAK;CACrE,MAAM;CACN,cAAc,CAAC,YAAY,SAAS;CACpC,UAAU;CACX,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-rxFL-6yF2.js","names":[],"sources":["../../src/components/GrSwitch/grSwitchStyles.ts","../../src/components/GrSwitch/safelist.ts","../../src/components/GrSwitch/config.ts"],"sourcesContent":["export type GrSwitchSize = 'sm' | 'md' | 'lg'\n\ntype GrSwitchThumbClassOptions = {\n checked: boolean\n size: GrSwitchSize\n}\n\nexport const trackBase =\n 'relative inline-flex items-center rounded-full border border-[var(--ds-switch-track-brd)] transition-colors duration-150'\n\nexport const trackSizes: Record<GrSwitchSize, string> = {\n sm: 'h-5 w-9',\n md: 'h-6 w-11',\n lg: 'h-7 w-14',\n}\n\nexport const thumbBase =\n 'inline-block rounded-full bg-[var(--card)] shadow-[var(--ds-shadow-1)] transition-transform duration-150'\n\nexport const thumbSizes: Record<GrSwitchSize, string> = {\n sm: 'h-4 w-4',\n md: 'h-5 w-5',\n lg: 'h-6 w-6',\n}\n\nexport const thumbTranslations: Record<GrSwitchSize, { checked: string, unchecked: string }> = {\n sm: {\n checked: 'translate-x-[17px]',\n unchecked: 'translate-x-[2px]',\n },\n md: {\n checked: 'translate-x-5',\n unchecked: 'translate-x-[2px]',\n },\n lg: {\n checked: 'translate-x-[28px]',\n unchecked: 'translate-x-[3px]',\n },\n}\n\nexport const labelBase = 'text-[var(--muted-fg)]'\n\nexport const labelSizes: Record<GrSwitchSize, string> = {\n sm: 'text-sm',\n md: 'text-sm',\n lg: 'text-base',\n}\n\nexport function grSwitchTrackClass(size: GrSwitchSize): string {\n return [trackBase, trackSizes[size]].join(' ')\n}\n\nexport function grSwitchThumbClass(options: GrSwitchThumbClassOptions): string {\n return [\n thumbBase,\n thumbSizes[options.size],\n thumbTranslations[options.size][options.checked ? 'checked' : 'unchecked'],\n ].join(' ')\n}\n\nexport function grSwitchLabelClass(size: GrSwitchSize): string {\n return [labelBase, labelSizes[size]].join(' ')\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport {\n labelBase,\n labelSizes,\n thumbBase,\n thumbSizes,\n thumbTranslations,\n trackBase,\n trackSizes,\n} from './grSwitchStyles'\n\nexport const grSwitchClassTokens = {\n trackBase: splitClassTokens(trackBase),\n trackSizes: Object.values(trackSizes).flatMap(splitClassTokens),\n thumbBase: splitClassTokens(thumbBase),\n thumbSizes: Object.values(thumbSizes).flatMap(splitClassTokens),\n thumbTranslations: Object.values(thumbTranslations).flatMap(({checked, unchecked}) => {\n return [...splitClassTokens(checked), ...splitClassTokens(unchecked)]\n }),\n labelBase: splitClassTokens(labelBase),\n labelSizes: Object.values(labelSizes).flatMap(splitClassTokens),\n} as const\n\nexport const grSwitchSafelist = [...new Set([\n ...grSwitchClassTokens.trackBase,\n ...grSwitchClassTokens.trackSizes,\n ...grSwitchClassTokens.thumbBase,\n ...grSwitchClassTokens.thumbSizes,\n ...grSwitchClassTokens.thumbTranslations,\n ...grSwitchClassTokens.labelBase,\n ...grSwitchClassTokens.labelSizes,\n])]\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grSwitchSafelist } from './safelist'\n\nexport const grSwitchConfig = defineGranularComponent(import.meta.url, {\n name: 'GrSwitch',\n safelist: grSwitchSafelist,\n})"],"mappings":";;;AAOA,IAAa,YACT;AAEJ,IAAa,aAA2C;CACpD,IAAI;CACJ,IAAI;CACJ,IAAI;CACP;AAED,IAAa,YACT;AAEJ,IAAa,aAA2C;CACpD,IAAI;CACJ,IAAI;CACJ,IAAI;CACP;AAED,IAAa,oBAAkF;CAC3F,IAAI;EACA,SAAS;EACT,WAAW;EACd;CACD,IAAI;EACA,SAAS;EACT,WAAW;EACd;CACD,IAAI;EACA,SAAS;EACT,WAAW;EACd;CACJ;AAED,IAAa,YAAY;AAEzB,IAAa,aAA2C;CACpD,IAAI;CACJ,IAAI;CACJ,IAAI;CACP;AAED,SAAgB,mBAAmB,MAA4B;AAC3D,QAAO,CAAC,WAAW,WAAW,MAAM,CAAC,KAAK,IAAI;;AAGlD,SAAgB,mBAAmB,SAA4C;AAC3E,QAAO;EACH;EACA,WAAW,QAAQ;EACnB,kBAAkB,QAAQ,MAAM,QAAQ,UAAU,YAAY;EACjE,CAAC,KAAK,IAAI;;AAGf,SAAgB,mBAAmB,MAA4B;AAC3D,QAAO,CAAC,WAAW,WAAW,MAAM,CAAC,KAAK,IAAI;;;;AClDlD,IAAa,sBAAsB;CAC/B,WAAW,iBAAiB,UAAU;CACtC,YAAY,OAAO,OAAO,WAAW,CAAC,QAAQ,iBAAiB;CAC/D,WAAW,iBAAiB,UAAU;CACtC,YAAY,OAAO,OAAO,WAAW,CAAC,QAAQ,iBAAiB;CAC/D,mBAAmB,OAAO,OAAO,kBAAkB,CAAC,SAAS,EAAC,SAAS,gBAAe;AAClF,SAAO,CAAC,GAAG,iBAAiB,QAAQ,EAAE,GAAG,iBAAiB,UAAU,CAAC;GACvE;CACF,WAAW,iBAAiB,UAAU;CACtC,YAAY,OAAO,OAAO,WAAW,CAAC,QAAQ,iBAAiB;CAClE;AAED,IAAa,mBAAmB,CAAC,GAAG,IAAI,IAAI;CACxC,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CACvB,GAAG,oBAAoB;CAC1B,CAAC,CAAC;;;AC3BH,IAAa,iBAAiB,wBAAwB,OAAO,KAAK,KAAK;CACrE,MAAM;CACN,UAAU;CACX,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"grBadgeStyles-pqqbVgLk.js","names":[],"sources":["../../src/components/GrBadge/grBadgeStyles.ts"],"sourcesContent":["import type { GrTone } from '../shared/tones'\n\nexport type GrBadgeTone = GrTone\nexport type GrBadgeSize = 'sm' | 'md' | 'lg'\nexport type GrBadgeRadius = 'square' | 'semi' | 'round'\nexport const sizeClassBySize: Record<GrBadgeSize, string> = {\n sm: 'px-2 py-0.4 text-[11px]',\n md: 'px-2.5 py-0.5 text-[12px]',\n lg: 'px-3 py-1 text-[13px]',\n}\nexport const semiRadiusClassBySize: Record<GrBadgeSize, string> = {\n sm: 'rounded-[3px]',\n md: 'rounded-[3px]',\n lg: 'rounded-[5px]',\n}\nexport const lightToneClassByTone: Record<GrBadgeTone, string> = {\n neutral: 'bg-[var(--muted)] text-[var(--fg)] border-[var(--brd)]',\n primary:\n 'bg-[var(--accent)] text-[var(--accent-fg)] border-[color-mix(in_srgb,var(--primary)_30%,var(--accent))]',\n success: 'bg-[var(--ds-success-light)] text-[var(--ds-success)] border-[color-mix(in_srgb,var(--ds-success)_30%,var(--ds-success-light))]',\n warning: 'bg-[var(--ds-warning-light)] text-[var(--ds-warning)] border-[color-mix(in_srgb,var(--ds-warning)_30%,var(--ds-warning-light))]',\n danger: 'bg-[var(--ds-danger-light)] text-[var(--ds-danger)] border-[color-mix(in_srgb,var(--ds-danger)_30%,var(--ds-danger-light))]',\n info: 'bg-[var(--ds-info-light)] text-[var(--ds-info)] border-[color-mix(in_srgb,var(--ds-info)_30%,var(--ds-info-light))]',\n slate: 'bg-[var(--ds-slate-light)] text-[var(--ds-slate-text)] border-[color-mix(in_srgb,var(--ds-slate)_30%,var(--ds-slate-light))]',\n azure: 'bg-[var(--ds-azure-light)] text-[var(--ds-azure-text)] border-[color-mix(in_srgb,var(--ds-azure)_30%,var(--ds-azure-light))]',\n}\nexport const darkToneClassByTone: Record<GrBadgeTone, string> = {\n neutral: 'bg-[var(--fg)] text-[var(--bg)] border-[color-mix(in_srgb,var(--fg)_35%,var(--brd))]',\n primary: 'bg-[var(--primary)] text-[var(--primary-fg)] border-[var(--primary)]',\n success: 'bg-[var(--ds-success)] text-white border-[var(--ds-success)]',\n warning: 'bg-[var(--ds-warning)] text-white border-[var(--ds-warning)]',\n danger: 'bg-[var(--ds-danger)] text-white border-[var(--ds-danger)]',\n info: 'bg-[var(--ds-info)] text-white border-[var(--ds-info)]',\n slate: 'bg-[var(--ds-slate)] text-[var(--ds-slate-fg)] border-[var(--ds-slate)]',\n azure: 'bg-[var(--ds-azure)] text-[var(--ds-azure-fg)] border-[var(--ds-azure)]',\n}\nfunction radiusClass(radius: GrBadgeRadius, size: GrBadgeSize): string {\n if (radius === 'square') return 'rounded-[var(--ds-radius-none)]'\n if (radius === 'semi') return semiRadiusClassBySize[size]\n return 'rounded-full'\n}\nfunction toneClass(tone: GrBadgeTone, dark: boolean): string {\n return dark ? darkToneClassByTone[tone] : lightToneClassByTone[tone]\n}\nexport function grBadgeClass(options: { tone: GrBadgeTone, dark: boolean, size: GrBadgeSize, radius: GrBadgeRadius }): string {\n return [\n radiusClass(options.radius, options.size),\n sizeClassBySize[options.size],\n toneClass(options.tone, options.dark),\n ].join(' ')\n}\n"],"mappings":";AAKA,IAAa,kBAA+C;CAC1D,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AACD,IAAa,wBAAqD;CAChE,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AACD,IAAa,uBAAoD;CAC/D,SAAS;CACT,SACE;CACF,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CACN,OAAO;CACP,OAAO;CACR;AACD,IAAa,sBAAmD;CAC9D,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CACN,OAAO;CACP,OAAO;CACR;AACD,SAAS,YAAY,QAAuB,MAA2B;AACrE,KAAI,WAAW,SAAU,QAAO;AAChC,KAAI,WAAW,OAAQ,QAAO,sBAAsB;AACpD,QAAO;;AAET,SAAS,UAAU,MAAmB,MAAuB;AAC3D,QAAO,OAAO,oBAAoB,QAAQ,qBAAqB;;AAEjE,SAAgB,aAAa,SAAiG;AAC5H,QAAO;EACL,YAAY,QAAQ,QAAQ,QAAQ,KAAK;EACzC,gBAAgB,QAAQ;EACxB,UAAU,QAAQ,MAAM,QAAQ,KAAK;EACtC,CAAC,KAAK,IAAI"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"loader-circle-B2rWDk5u.js","names":[],"sources":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"safelist-BF822K15.js","names":[],"sources":["../../src/components/GrDialog/safelist.ts"],"sourcesContent":["import { splitClassTokens } from '../shared/classTokens'\nimport {\n DEFAULT_GR_DIALOG_BODY_CONFIG,\n DEFAULT_GR_DIALOG_FOOTER_CONFIG,\n DEFAULT_GR_DIALOG_HEADER_CONFIG,\n} from './dialogShared'\n\n// В safelist попадают ТОЛЬКО токены, которые нельзя обнаружить статическим\n// сканом шаблонов: значения из дефолтных конфигов секций (`paddingX`/`paddingY`),\n// которые используются через `:class` и могут переопределяться консьюмером.\n//\n// Все литералы, прописанные напрямую в шаблонах (`class=\"...\"` или\n// статические строки в `:class=\"[...]\"` внутри .vue), UnoCSS найдёт сам —\n// дублировать их здесь не нужно.\nfunction configTokens(config: { paddingX: string, paddingY: string }): string[] {\n return [\n ...splitClassTokens(config.paddingX),\n ...splitClassTokens(config.paddingY),\n ]\n}\n\nexport const grDialogSafelist = [...new Set([\n ...configTokens(DEFAULT_GR_DIALOG_HEADER_CONFIG),\n ...configTokens(DEFAULT_GR_DIALOG_FOOTER_CONFIG),\n ...configTokens(DEFAULT_GR_DIALOG_BODY_CONFIG),\n])]\n"],"mappings":";;;AAcA,SAAS,aAAa,QAA0D;AAC9E,QAAO,CACL,GAAG,iBAAiB,OAAO,SAAS,EACpC,GAAG,iBAAiB,OAAO,SAAS,CACrC;;AAGH,IAAa,mBAAmB,CAAC,GAAG,IAAI,IAAI;CAC1C,GAAG,aAAa,gCAAgC;CAChD,GAAG,aAAa,gCAAgC;CAChD,GAAG,aAAa,8BAA8B;CAC/C,CAAC,CAAC"}
@@ -1,32 +0,0 @@
1
- import { n as grBadgeClass } from "../../../chunks/grBadgeStyles-pqqbVgLk.js";
2
- import { computed, createElementBlock, defineComponent, normalizeClass, openBlock, renderSlot } from "vue";
3
- //#endregion
4
- //#region src/components/GrBadge/GrBadge.vue
5
- var GrBadge_default = /* @__PURE__ */ defineComponent({
6
- __name: "GrBadge",
7
- props: {
8
- tone: { default: "neutral" },
9
- dark: {
10
- type: Boolean,
11
- default: false
12
- },
13
- size: { default: "md" },
14
- radius: { default: "round" }
15
- },
16
- setup(__props) {
17
- const props = __props;
18
- const className = computed(() => {
19
- return grBadgeClass({
20
- tone: props.tone,
21
- dark: props.dark,
22
- size: props.size,
23
- radius: props.radius
24
- });
25
- });
26
- return (_ctx, _cache) => {
27
- return openBlock(), createElementBlock("span", { class: normalizeClass(["inline-flex items-center border whitespace-nowrap leading-none", className.value]) }, [renderSlot(_ctx.$slots, "default")], 2);
28
- };
29
- }
30
- });
31
- //#endregion
32
- export { GrBadge_default as t };
@@ -1 +0,0 @@
1
- {"version":3,"file":"GrBadge-wuIb4_2K.js","names":[],"sources":["../../../../src/components/GrBadge/GrBadge.vue","../../../../src/components/GrBadge/GrBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport type { GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles'\n\nimport {\n grBadgeClass,\n type GrBadgeRadius,\n type GrBadgeSize,\n type GrBadgeTone,\n} from './grBadgeStyles'\n\nconst props = withDefaults(\n defineProps<{\n tone?: GrBadgeTone\n dark?: boolean\n size?: GrBadgeSize\n radius?: GrBadgeRadius\n }>(),\n {\n tone: 'neutral',\n dark: false,\n size: 'md',\n radius: 'round',\n },\n)\n\nconst className = computed(() => {\n return grBadgeClass({\n tone: props.tone,\n dark: props.dark,\n size: props.size,\n radius: props.radius,\n })\n})\n</script>\n\n<template>\n <span class=\"inline-flex items-center border whitespace-nowrap leading-none\" :class=\"className\">\n <slot />\n </span>\n</template>","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nexport type { GrBadgeRadius, GrBadgeSize, GrBadgeTone } from './grBadgeStyles'\n\nimport {\n grBadgeClass,\n type GrBadgeRadius,\n type GrBadgeSize,\n type GrBadgeTone,\n} from './grBadgeStyles'\n\nconst props = withDefaults(\n defineProps<{\n tone?: GrBadgeTone\n dark?: boolean\n size?: GrBadgeSize\n radius?: GrBadgeRadius\n }>(),\n {\n tone: 'neutral',\n dark: false,\n size: 'md',\n radius: 'round',\n },\n)\n\nconst className = computed(() => {\n return grBadgeClass({\n tone: props.tone,\n dark: props.dark,\n size: props.size,\n radius: props.radius,\n })\n})\n</script>\n\n<template>\n <span class=\"inline-flex items-center border whitespace-nowrap leading-none\" :class=\"className\">\n <slot />\n </span>\n</template>"],"mappings":";;;;;;;;;;;;;;;;EAYA,MAAM,QAAQ;EAed,MAAM,YAAY,eAAe;AAC/B,UAAO,aAAa;IAClB,MAAM,MAAM;IACZ,MAAM,MAAM;IACZ,MAAM,MAAM;IACZ,QAAQ,MAAM;IACf,CAAA;IACF;;uBAIC,mBAEO,QAAA,EAFD,OAAK,eAAA,CAAC,kEAAyE,UAAA,MAAS,CAAA,EAAA,EAAA,CAC5F,WAAQ,KAAA,QAAA,UAAA,CAAA,EAAA,EAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"GrConfirmDialog-DjGOX9Hd.js","names":[],"sources":["../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue","../../../../src/components/GrConfirmDialog/GrConfirmDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — DS-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { computed } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: 'Confirm',\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrConfirmDialog — DS-примитив диалога подтверждения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog`/`GrPromptDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Клик по «Confirm»/«Cancel» эмитит одноимённое событие и закрывает диалог\n * через `update:modelValue`.\n */\nimport { computed } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrConfirmDialogProps {\n modelValue: boolean\n title?: string\n description?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n}\n\nconst props = withDefaults(defineProps<GrConfirmDialogProps>(), {\n title: 'Confirm',\n description: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'confirm'): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (value: boolean) => emit('update:modelValue', value),\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n emit('confirm')\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-confirm-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-confirm-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCA,MAAM,QAAQ;EAmBd,MAAM,OAAO;EAMb,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,UAAmB,KAAK,qBAAqB,MAAM;GAC1D,CAAA;EAED,SAAS,WAAiB;AACxB,QAAK,SAAQ;AACb,QAAK,qBAAqB,MAAK;;EAGjC,SAAS,YAAkB;AACzB,QAAK,UAAS;AACd,QAAK,qBAAqB,MAAK;;;uBAK/B,YAqCW,kBAAA;gBApCA,KAAA;sEAAI,QAAA;IACZ,OAAO,QAAA;IACP,MAAM,QAAA;IACN,qBAAmB,QAAA;IACnB,gBAAc,QAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,QAAA;;IAQH,QAAM,cAgBR,CAfP,WAeO,KAAA,QAAA,UAAA,EAAA,QAAA,CAdL,mBAaM,OAbN,YAaM,CAZJ,YAEW,kBAAA;KAFD,eAAY;KAAoB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACrE,CAAA,gBAAA,gBAAb,QAAA,WAAU,EAAA,EAAA,CAAA,CAAA;;qBAEf,YAQW,kBAAA;KAPT,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,SAAO;;4BAES,CAAA,gBAAA,gBAAd,QAAA,YAAW,EAAA,EAAA,CAAA,CAAA;;;;;;;2BAff,CAJP,WAIO,KAAA,QAAA,WAAA,EAAA,QAAA,CAHM,QAAA,eAAA,WAAA,EAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,YAAW,EAAA,EAAA,IAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,CAAA,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"GrFileUpload-DYRERhI2.js","names":["$slots"],"sources":["../../../../src/components/GrFileUpload/uploadViaXhr.ts","../../../../src/components/GrFileUpload/uploadState.ts","../../../../src/components/GrFileUpload/GrFileUpload.vue","../../../../src/components/GrFileUpload/GrFileUpload.vue"],"sourcesContent":["/**\n * Загрузка файлов через `XMLHttpRequest` с поддержкой прогресса аплоада и\n * отмены по `AbortSignal`. Используется в `GrFileUpload` для ветки `action`,\n * а также может применяться пользователем напрямую в `request`-загрузчике.\n */\n\nexport type GrUploadExtraDataValue = string | Blob\n\nexport type GrUploadExtraData = Record<string, GrUploadExtraDataValue | GrUploadExtraDataValue[]>\n\nexport interface GrUploadProgressInfo {\n /** Процент `0..100`. Для запросов без `lengthComputable` значение `0` и `indeterminate = true`. */\n percent: number\n loaded: number\n total: number\n indeterminate: boolean\n}\n\nexport interface UploadViaXhrOptions {\n url: string\n files: File[]\n name: string\n headers?: Record<string, string>\n withCredentials?: boolean\n extraData?: GrUploadExtraData\n signal: AbortSignal\n onProgress?: (info: GrUploadProgressInfo) => void\n}\n\nexport class GrUploadAbortError extends Error {\n constructor(message = 'Upload aborted') {\n super(message)\n this.name = 'GrUploadAbortError'\n }\n}\n\nexport class GrUploadHttpError extends Error {\n status: number\n payload: unknown\n\n constructor(status: number, payload: unknown) {\n super(`Upload failed with status ${status}`)\n this.name = 'GrUploadHttpError'\n this.status = status\n this.payload = payload\n }\n}\n\nfunction appendExtraFormData(body: FormData, extraData: GrUploadExtraData | undefined) {\n if (!extraData) return\n\n for (const [key, value] of Object.entries(extraData)) {\n if (Array.isArray(value)) {\n for (const entry of value) body.append(key, entry)\n continue\n }\n\n body.append(key, value)\n }\n}\n\nfunction parseResponse(xhr: XMLHttpRequest): unknown {\n const contentType = xhr.getResponseHeader('content-type') ?? ''\n const raw = xhr.responseText\n\n if (contentType.includes('application/json')) {\n try {\n return JSON.parse(raw)\n } catch {\n return raw\n }\n }\n\n return raw\n}\n\nexport function uploadViaXhr(options: UploadViaXhrOptions): Promise<unknown> {\n const { url, files, name, headers, withCredentials, extraData, signal, onProgress } = options\n\n return new Promise<unknown>((resolve, reject) => {\n if (signal.aborted) {\n reject(new GrUploadAbortError())\n return\n }\n\n const body = new FormData()\n for (const file of files) body.append(name, file)\n appendExtraFormData(body, extraData)\n\n const xhr = new XMLHttpRequest()\n xhr.open('POST', url, true)\n xhr.withCredentials = !!withCredentials\n\n if (headers) {\n for (const [key, value] of Object.entries(headers))\n xhr.setRequestHeader(key, value)\n }\n\n const onAbort = () => {\n try {\n xhr.abort()\n } catch {\n /* ignore */\n }\n }\n\n signal.addEventListener('abort', onAbort)\n\n const cleanup = () => {\n signal.removeEventListener('abort', onAbort)\n }\n\n if (onProgress) {\n xhr.upload.addEventListener('progress', (event) => {\n const indeterminate = !event.lengthComputable\n const total = indeterminate ? 0 : event.total\n const loaded = indeterminate ? 0 : event.loaded\n const percent = indeterminate || total === 0 ? 0 : Math.min(100, (loaded / total) * 100)\n onProgress({ percent, loaded, total, indeterminate })\n })\n }\n\n xhr.addEventListener('load', () => {\n cleanup()\n const payload = parseResponse(xhr)\n const status = xhr.status\n\n if (status >= 200 && status < 300) {\n if (onProgress) onProgress({ percent: 100, loaded: 1, total: 1, indeterminate: false })\n resolve(payload)\n return\n }\n\n reject(new GrUploadHttpError(status, payload))\n })\n\n xhr.addEventListener('error', () => {\n cleanup()\n reject(new Error('Network error during upload'))\n })\n\n xhr.addEventListener('abort', () => {\n cleanup()\n reject(new GrUploadAbortError())\n })\n\n xhr.send(body)\n })\n}\n","/**\n * Состояние процесса загрузки в `GrFileUpload`.\n *\n * Используется как для внутреннего управления UI, так и пробрасывается наружу\n * через scoped-слоты (`progress`, `default`) и `defineExpose`.\n */\n\nexport type GrUploadPhase = 'idle' | 'uploading' | 'success' | 'error'\n\nexport interface GrUploadStateIdle {\n phase: 'idle'\n percent: 0\n indeterminate: false\n loaded: 0\n total: 0\n}\n\nexport interface GrUploadStateUploading {\n phase: 'uploading'\n percent: number\n indeterminate: boolean\n loaded: number\n total: number\n}\n\nexport interface GrUploadStateSuccess {\n phase: 'success'\n percent: 100\n indeterminate: false\n loaded: number\n total: number\n}\n\nexport interface GrUploadStateError {\n phase: 'error'\n percent: number\n indeterminate: false\n loaded: number\n total: number\n error: unknown\n}\n\nexport type GrUploadState =\n | GrUploadStateIdle\n | GrUploadStateUploading\n | GrUploadStateSuccess\n | GrUploadStateError\n\nexport const GR_UPLOAD_STATE_IDLE: GrUploadStateIdle = Object.freeze({\n phase: 'idle',\n percent: 0,\n indeterminate: false,\n loaded: 0,\n total: 0,\n})\n","<script setup lang=\"ts\">\nimport { Comment, computed, Fragment, nextTick, reactive, ref, Text, useSlots, type VNode } from 'vue'\n\nimport IconArrowUp from '~icons/lucide/arrow-up'\n\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport GrProgressBar from '../GrProgressBar/GrProgressBar.vue'\nimport type { GrProgressBarTone } from '../GrProgressBar/grStyle'\nimport type { FileValidator, FileValidatorSource } from '../../fileValidation'\nimport type { GrUploadProgressInfo } from './uploadViaXhr'\nimport type { GrUploadState } from './uploadState'\n\nimport { FileValidationError, runFileValidators } from '../../fileValidation'\nimport { GrUploadAbortError, uploadViaXhr } from './uploadViaXhr'\nimport { GR_UPLOAD_STATE_IDLE } from './uploadState'\n\nexport type GrFileUploadExtraDataValue = string | Blob\n\nexport type GrFileUploadExtraData = Record<string, GrFileUploadExtraDataValue | GrFileUploadExtraDataValue[]>\n\nexport type GrFileUploadRequestCtx = {\n signal: AbortSignal\n extraData?: GrFileUploadExtraData\n /**\n * Колбэк прогресса аплоада. Пользовательский `request` (например, axios)\n * должен вызывать его из `onUploadProgress`, чтобы `GrFileUpload` отображал\n * прогресс через слот `progress` / дефолтный `GrProgressBar`.\n */\n onProgress?: (info: GrUploadProgressInfo) => void\n}\n\nexport type GrFileUploadRequest = (files: File[], ctx: GrFileUploadRequestCtx) => Promise<any>\n\n/**\n * Пропы `GrFileUpload`.\n *\n * Либо `action` (URL для POST multipart/form-data), либо `request` — кастомный\n * загрузчик (например, через axios). Если переданы оба — приоритет у `request`.\n *\n * `placeholder` — надпись в дефолтном UI-варианте (без слота default).\n */\nexport interface GrFileUploadProps {\n action?: string\n request?: GrFileUploadRequest\n name?: string\n multiple?: boolean\n limit?: number\n onExceed?: (files: File[], limit: number) => void\n beforeUpload?: (file: File) => boolean | Promise<unknown>\n validators?: FileValidator[]\n disabled?: boolean\n headers?: Record<string, string>\n withCredentials?: boolean\n showFileList?: boolean\n uploadExtraData?: (files: File[]) => GrFileUploadExtraData | undefined\n /** i18n: надпись-подсказка в дефолтном UI. */\n placeholder?: string\n /** Показывать дефолтный прогресс-бар (если не используется слот `progress`). */\n showProgress?: boolean\n /** Цветовой тон полосы прогресса в фазе `uploading`. */\n progressTone?: GrProgressBarTone\n /** aria-label для прогресс-бара. */\n progressLabel?: string\n /** Через сколько мс после `success` скрыть прогресс-бар. `0` — не скрывать. */\n hideProgressOnSuccess?: number\n}\n\nconst props = withDefaults(\n defineProps<GrFileUploadProps>(),\n {\n action: undefined,\n request: undefined,\n name: 'file',\n multiple: false,\n limit: undefined,\n onExceed: undefined,\n beforeUpload: undefined,\n validators: undefined,\n disabled: false,\n headers: undefined,\n withCredentials: false,\n showFileList: false,\n uploadExtraData: undefined,\n placeholder: 'Drag files here or click to select',\n showProgress: true,\n progressTone: 'primary',\n progressLabel: 'Upload progress',\n hideProgressOnSuccess: 800,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'success', payload: any): void\n (e: 'error', error: unknown): void\n (e: 'progress', percent: number, info?: GrUploadProgressInfo): void\n (e: 'change', files: File[]): void\n (e: 'state-change', state: GrUploadState): void\n}>()\n\nconst slots = useSlots()\n\nfunction flattenSlotNodes(nodes: VNode[]): VNode[] {\n const out: VNode[] = []\n\n for (const node of nodes) {\n if (node.type === Fragment && Array.isArray(node.children)) {\n out.push(...flattenSlotNodes(node.children as VNode[]))\n continue\n }\n\n out.push(node)\n }\n\n return out\n}\n\nfunction isWhitespaceTextNode(node: VNode): boolean {\n if (node.type !== Text) return false\n return typeof node.children === 'string' && node.children.trim().length === 0\n}\n\nfunction slotIsTextOnly(nodes: VNode[]): boolean {\n const flat = flattenSlotNodes(nodes)\n const meaningful = flat.filter(node => node.type !== Comment && !isWhitespaceTextNode(node))\n\n if (meaningful.length === 0) return true\n\n for (const node of meaningful) {\n if (node.type !== Text) return false\n }\n\n return true\n}\n\nconst defaultSlotNodes = computed(() => {\n return slots.default ? flattenSlotNodes(slots.default({} as any)) : []\n})\n\nconst hasCustomUi = computed(() => {\n return !!slots.default && !slotIsTextOnly(defaultSlotNodes.value)\n})\n\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst isOver = ref(false)\nlet overCounter = 0\n\nconst lastFiles = ref<File[]>([])\n\nconst state = reactive<GrUploadState>({ ...GR_UPLOAD_STATE_IDLE }) as GrUploadState\n\nlet activeController: AbortController | null = null\nlet hideSuccessTimer: ReturnType<typeof setTimeout> | null = null\n\nfunction clearHideSuccessTimer() {\n if (hideSuccessTimer !== null) {\n clearTimeout(hideSuccessTimer)\n hideSuccessTimer = null\n }\n}\n\nfunction assignState(next: GrUploadState) {\n // мутируем через Object.assign, чтобы сохранить reactive ссылку\n for (const key of Object.keys(state) as (keyof GrUploadState)[])\n delete (state as any)[key]\n Object.assign(state, next)\n emit('state-change', state as GrUploadState)\n}\n\nfunction setStateIdle() {\n assignState({ ...GR_UPLOAD_STATE_IDLE })\n}\n\nfunction setStateUploading(info?: GrUploadProgressInfo) {\n assignState({\n phase: 'uploading',\n percent: info?.percent ?? 0,\n indeterminate: info?.indeterminate ?? true,\n loaded: info?.loaded ?? 0,\n total: info?.total ?? 0,\n })\n}\n\nfunction setStateSuccess(info: { loaded: number, total: number }) {\n assignState({\n phase: 'success',\n percent: 100,\n indeterminate: false,\n loaded: info.loaded,\n total: info.total,\n })\n}\n\nfunction setStateError(error: unknown) {\n const prev = state\n assignState({\n phase: 'error',\n percent: prev.phase === 'uploading' ? prev.percent : 0,\n indeterminate: false,\n loaded: prev.phase === 'uploading' ? prev.loaded : 0,\n total: prev.phase === 'uploading' ? prev.total : 0,\n error,\n })\n}\n\nfunction handleProgress(info: GrUploadProgressInfo) {\n if (state.phase !== 'uploading') return\n assignState({\n phase: 'uploading',\n percent: info.percent,\n indeterminate: info.indeterminate,\n loaded: info.loaded,\n total: info.total,\n })\n emit('progress', info.percent, info)\n}\n\nconst tabIndex = computed(() => (props.disabled ? -1 : 0))\n\nconst hiddenInputStyle = {\n position: 'fixed',\n top: '-9999px',\n left: '-9999px',\n width: '1px',\n height: '1px',\n opacity: '0',\n overflow: 'hidden',\n pointerEvents: 'none',\n} as const satisfies Record<string, string>\n\nfunction setOver(next: boolean) {\n if (isOver.value === next) return\n isOver.value = next\n}\n\nfunction openDialog() {\n if (props.disabled) return\n inputRef.value?.click()\n}\n\nfunction abort() {\n activeController?.abort()\n activeController = null\n}\n\nfunction normalizeLimit(limit: number | undefined): number | undefined {\n if (typeof limit !== 'number') return undefined\n if (!Number.isFinite(limit)) return undefined\n if (limit <= 0) return undefined\n return Math.floor(limit)\n}\n\n\nasync function uploadViaAction(files: File[], signal: AbortSignal, extraData: GrFileUploadExtraData | undefined) {\n if (!props.action) throw new Error('GrFileUpload: either `action` or `request` must be provided')\n\n return uploadViaXhr({\n url: props.action,\n files,\n name: props.name,\n headers: props.headers,\n withCredentials: props.withCredentials,\n extraData,\n signal,\n onProgress: handleProgress,\n })\n}\n\nasync function runBeforeUpload(files: File[]): Promise<'ok' | { aborted: true; reason: unknown }> {\n if (!props.beforeUpload) return 'ok'\n\n for (const file of files) {\n try {\n const result = props.beforeUpload(file)\n\n if (result === false) {\n return { aborted: true, reason: new Error('Upload aborted by beforeUpload') }\n }\n\n if (result && typeof (result as any).then === 'function')\n await result\n } catch (error) {\n return { aborted: true, reason: error }\n }\n }\n\n return 'ok'\n}\n\nasync function handleFiles(files: File[], source: FileValidatorSource = 'input') {\n if (props.disabled) return\n if (!files.length) return\n\n const normalizedLimit = normalizeLimit(props.limit)\n if (props.multiple && normalizedLimit && files.length > normalizedLimit) {\n props.onExceed?.(files, normalizedLimit)\n emit('error', new Error(`Too many files selected, limit=${normalizedLimit}`))\n return\n }\n\n const { files: valid, issues } = await runFileValidators(files, props.validators ?? [], {\n source,\n multiple: props.multiple,\n })\n\n if (issues.length > 0) {\n emit('error', new FileValidationError(issues, valid))\n return\n }\n\n if (!valid.length) return\n\n lastFiles.value = valid\n\n const before = await runBeforeUpload(valid)\n if (before !== 'ok') {\n emit('error', before.reason)\n return\n }\n\n let extraData: GrFileUploadExtraData | undefined\n try {\n extraData = props.uploadExtraData?.(valid)\n } catch (error) {\n emit('error', error)\n return\n }\n\n abort()\n clearHideSuccessTimer()\n\n const controller = new AbortController()\n activeController = controller\n\n setStateUploading()\n emit('progress', 0, { percent: 0, loaded: 0, total: 0, indeterminate: true })\n\n try {\n const payload = props.request\n ? await props.request(valid, { signal: controller.signal, extraData, onProgress: handleProgress })\n : await uploadViaAction(valid, controller.signal, extraData)\n\n const finalLoaded = state.phase === 'uploading' ? state.total || state.loaded : 0\n setStateSuccess({ loaded: finalLoaded, total: finalLoaded })\n emit('success', payload)\n emit('change', valid)\n emit('progress', 100, { percent: 100, loaded: finalLoaded, total: finalLoaded, indeterminate: false })\n\n if (props.hideProgressOnSuccess && props.hideProgressOnSuccess > 0) {\n hideSuccessTimer = setTimeout(() => {\n if (state.phase === 'success') setStateIdle()\n hideSuccessTimer = null\n }, props.hideProgressOnSuccess)\n }\n } catch (error) {\n if (error instanceof GrUploadAbortError) {\n setStateIdle()\n } else {\n setStateError(error)\n }\n emit('error', error)\n } finally {\n if (activeController === controller) activeController = null\n }\n}\n\nfunction onDragEnter(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n overCounter += 1\n setOver(true)\n}\n\nfunction onDragOver(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy'\n}\n\nfunction onDragLeave(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n overCounter = Math.max(0, overCounter - 1)\n if (overCounter === 0) setOver(false)\n}\n\nfunction onDrop(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n overCounter = 0\n setOver(false)\n\n const files = event.dataTransfer?.files ? Array.prototype.slice.call(event.dataTransfer.files) as File[] : []\n void handleFiles(files, 'drop')\n}\n\nasync function onInputChange(event: Event) {\n if (props.disabled) return\n\n const target = event.target as HTMLInputElement | null\n const files = target?.files ? Array.prototype.slice.call(target.files) as File[] : []\n\n if (target) target.value = ''\n\n await nextTick()\n await handleFiles(files, 'input')\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openDialog()\n }\n}\n\nfunction onRootClick() {\n if (hasCustomUi.value) return\n openDialog()\n}\n\nfunction onRootKeydown(event: KeyboardEvent) {\n if (hasCustomUi.value) return\n onKeydown(event)\n}\n\nconst effectiveProgressTone = computed<GrProgressBarTone>(() => {\n if (state.phase === 'error') return 'danger'\n if (state.phase === 'success') return 'success'\n return props.progressTone\n})\n\nconst progressVisible = computed(() => state.phase !== 'idle')\nconst progressPercent = computed(() => (state.phase === 'uploading' && state.indeterminate ? 0 : state.percent))\nconst progressText = computed(() => {\n if (state.phase === 'uploading' && state.indeterminate) return ''\n return `${Math.round(progressPercent.value)}%`\n})\n\ndefineExpose({\n uploadFiles: handleFiles,\n abort,\n openDialog,\n state,\n})\n</script>\n\n<template>\n <div\n data-ds-file-upload\n :role=\"hasCustomUi ? undefined : 'button'\"\n :tabindex=\"hasCustomUi ? undefined : tabIndex\"\n :aria-disabled=\"hasCustomUi ? undefined : disabled ? 'true' : 'false'\"\n :class=\"\n hasCustomUi\n ? 'inline-block'\n : [\n 'relative w-full rounded-[var(--ds-radius-lg)] border border-dashed border-[var(--brd)] bg-[var(--card)] px-5 py-6 outline-none transition',\n disabled\n ? 'opacity-60 cursor-not-allowed'\n : 'cursor-pointer hover:bg-[var(--muted)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg)]',\n isOver && !disabled ? 'border-[var(--ring)] bg-[var(--muted)]' : '',\n ]\n \"\n @click=\"onRootClick\"\n @keydown=\"onRootKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input\n ref=\"inputRef\"\n data-ds-file-upload-input\n :style=\"hiddenInputStyle\"\n type=\"file\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :name=\"name\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n @change=\"onInputChange\"\n >\n\n <slot\n v-if=\"hasCustomUi\"\n :open-dialog=\"openDialog\"\n :abort=\"abort\"\n :disabled=\"disabled\"\n :files=\"lastFiles\"\n :is-over=\"isOver\"\n :state=\"state\"\n />\n\n <div v-else class=\"flex items-start gap-4\">\n <div\n data-ds-file-upload-icon\n class=\"h-12 w-12 shrink-0 rounded-[12px] bg-[var(--muted)] border border-[var(--brd)] flex items-center justify-center\"\n aria-hidden=\"true\"\n >\n <GrIcon class=\"h-6 w-6 text-[var(--muted-fg)]\">\n <IconArrowUp />\n </GrIcon>\n </div>\n\n <div class=\"min-w-0\">\n <div data-ds-file-upload-label class=\"text-[14px] font-700\">\n <slot name=\"label\">\n <slot>\n {{ placeholder }}\n </slot>\n </slot>\n </div>\n\n <div v-if=\"$slots.tip\" data-ds-file-upload-tip class=\"mt-1 text-[13px] text-[var(--muted-fg)]\">\n <slot name=\"tip\" />\n </div>\n <div v-else class=\"mt-1 text-[13px] text-[var(--muted-fg)]\" />\n\n <ul v-if=\"showFileList && lastFiles.length\" data-ds-file-upload-list class=\"mt-3 space-y-1\">\n <li\n v-for=\"file in lastFiles\"\n :key=\"file.name\"\n data-ds-file-upload-item\n class=\"text-[13px]\"\n >\n <span class=\"font-600\">{{ file.name }}</span>\n <span class=\"text-[var(--muted-fg)]\"> · {{ Math.ceil(file.size / 1024) }} KB</span>\n </li>\n </ul>\n\n <slot\n v-if=\"showProgress || $slots.progress\"\n name=\"progress\"\n :state=\"state\"\n :percent=\"state.percent\"\n :indeterminate=\"state.phase === 'uploading' && state.indeterminate\"\n :phase=\"state.phase\"\n :files=\"lastFiles\"\n :abort=\"abort\"\n >\n <div\n v-if=\"showProgress\"\n data-ds-file-upload-progress\n class=\"mt-3 transition-opacity duration-150\"\n :class=\"progressVisible ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n :aria-hidden=\"!progressVisible\"\n >\n <div class=\"flex items-center gap-2\">\n <GrProgressBar\n :value=\"progressPercent\"\n :tone=\"effectiveProgressTone\"\n :aria-label=\"progressLabel\"\n />\n <span\n data-ds-file-upload-progress-text\n class=\"text-[12px] text-[var(--muted-fg)] tabular-nums min-w-[3ch] text-right\"\n >{{ progressText }}</span>\n </div>\n </div>\n </slot>\n </div>\n </div>\n </div>\n</template>","<script setup lang=\"ts\">\nimport { Comment, computed, Fragment, nextTick, reactive, ref, Text, useSlots, type VNode } from 'vue'\n\nimport IconArrowUp from '~icons/lucide/arrow-up'\n\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport GrProgressBar from '../GrProgressBar/GrProgressBar.vue'\nimport type { GrProgressBarTone } from '../GrProgressBar/grStyle'\nimport type { FileValidator, FileValidatorSource } from '../../fileValidation'\nimport type { GrUploadProgressInfo } from './uploadViaXhr'\nimport type { GrUploadState } from './uploadState'\n\nimport { FileValidationError, runFileValidators } from '../../fileValidation'\nimport { GrUploadAbortError, uploadViaXhr } from './uploadViaXhr'\nimport { GR_UPLOAD_STATE_IDLE } from './uploadState'\n\nexport type GrFileUploadExtraDataValue = string | Blob\n\nexport type GrFileUploadExtraData = Record<string, GrFileUploadExtraDataValue | GrFileUploadExtraDataValue[]>\n\nexport type GrFileUploadRequestCtx = {\n signal: AbortSignal\n extraData?: GrFileUploadExtraData\n /**\n * Колбэк прогресса аплоада. Пользовательский `request` (например, axios)\n * должен вызывать его из `onUploadProgress`, чтобы `GrFileUpload` отображал\n * прогресс через слот `progress` / дефолтный `GrProgressBar`.\n */\n onProgress?: (info: GrUploadProgressInfo) => void\n}\n\nexport type GrFileUploadRequest = (files: File[], ctx: GrFileUploadRequestCtx) => Promise<any>\n\n/**\n * Пропы `GrFileUpload`.\n *\n * Либо `action` (URL для POST multipart/form-data), либо `request` — кастомный\n * загрузчик (например, через axios). Если переданы оба — приоритет у `request`.\n *\n * `placeholder` — надпись в дефолтном UI-варианте (без слота default).\n */\nexport interface GrFileUploadProps {\n action?: string\n request?: GrFileUploadRequest\n name?: string\n multiple?: boolean\n limit?: number\n onExceed?: (files: File[], limit: number) => void\n beforeUpload?: (file: File) => boolean | Promise<unknown>\n validators?: FileValidator[]\n disabled?: boolean\n headers?: Record<string, string>\n withCredentials?: boolean\n showFileList?: boolean\n uploadExtraData?: (files: File[]) => GrFileUploadExtraData | undefined\n /** i18n: надпись-подсказка в дефолтном UI. */\n placeholder?: string\n /** Показывать дефолтный прогресс-бар (если не используется слот `progress`). */\n showProgress?: boolean\n /** Цветовой тон полосы прогресса в фазе `uploading`. */\n progressTone?: GrProgressBarTone\n /** aria-label для прогресс-бара. */\n progressLabel?: string\n /** Через сколько мс после `success` скрыть прогресс-бар. `0` — не скрывать. */\n hideProgressOnSuccess?: number\n}\n\nconst props = withDefaults(\n defineProps<GrFileUploadProps>(),\n {\n action: undefined,\n request: undefined,\n name: 'file',\n multiple: false,\n limit: undefined,\n onExceed: undefined,\n beforeUpload: undefined,\n validators: undefined,\n disabled: false,\n headers: undefined,\n withCredentials: false,\n showFileList: false,\n uploadExtraData: undefined,\n placeholder: 'Drag files here or click to select',\n showProgress: true,\n progressTone: 'primary',\n progressLabel: 'Upload progress',\n hideProgressOnSuccess: 800,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'success', payload: any): void\n (e: 'error', error: unknown): void\n (e: 'progress', percent: number, info?: GrUploadProgressInfo): void\n (e: 'change', files: File[]): void\n (e: 'state-change', state: GrUploadState): void\n}>()\n\nconst slots = useSlots()\n\nfunction flattenSlotNodes(nodes: VNode[]): VNode[] {\n const out: VNode[] = []\n\n for (const node of nodes) {\n if (node.type === Fragment && Array.isArray(node.children)) {\n out.push(...flattenSlotNodes(node.children as VNode[]))\n continue\n }\n\n out.push(node)\n }\n\n return out\n}\n\nfunction isWhitespaceTextNode(node: VNode): boolean {\n if (node.type !== Text) return false\n return typeof node.children === 'string' && node.children.trim().length === 0\n}\n\nfunction slotIsTextOnly(nodes: VNode[]): boolean {\n const flat = flattenSlotNodes(nodes)\n const meaningful = flat.filter(node => node.type !== Comment && !isWhitespaceTextNode(node))\n\n if (meaningful.length === 0) return true\n\n for (const node of meaningful) {\n if (node.type !== Text) return false\n }\n\n return true\n}\n\nconst defaultSlotNodes = computed(() => {\n return slots.default ? flattenSlotNodes(slots.default({} as any)) : []\n})\n\nconst hasCustomUi = computed(() => {\n return !!slots.default && !slotIsTextOnly(defaultSlotNodes.value)\n})\n\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst isOver = ref(false)\nlet overCounter = 0\n\nconst lastFiles = ref<File[]>([])\n\nconst state = reactive<GrUploadState>({ ...GR_UPLOAD_STATE_IDLE }) as GrUploadState\n\nlet activeController: AbortController | null = null\nlet hideSuccessTimer: ReturnType<typeof setTimeout> | null = null\n\nfunction clearHideSuccessTimer() {\n if (hideSuccessTimer !== null) {\n clearTimeout(hideSuccessTimer)\n hideSuccessTimer = null\n }\n}\n\nfunction assignState(next: GrUploadState) {\n // мутируем через Object.assign, чтобы сохранить reactive ссылку\n for (const key of Object.keys(state) as (keyof GrUploadState)[])\n delete (state as any)[key]\n Object.assign(state, next)\n emit('state-change', state as GrUploadState)\n}\n\nfunction setStateIdle() {\n assignState({ ...GR_UPLOAD_STATE_IDLE })\n}\n\nfunction setStateUploading(info?: GrUploadProgressInfo) {\n assignState({\n phase: 'uploading',\n percent: info?.percent ?? 0,\n indeterminate: info?.indeterminate ?? true,\n loaded: info?.loaded ?? 0,\n total: info?.total ?? 0,\n })\n}\n\nfunction setStateSuccess(info: { loaded: number, total: number }) {\n assignState({\n phase: 'success',\n percent: 100,\n indeterminate: false,\n loaded: info.loaded,\n total: info.total,\n })\n}\n\nfunction setStateError(error: unknown) {\n const prev = state\n assignState({\n phase: 'error',\n percent: prev.phase === 'uploading' ? prev.percent : 0,\n indeterminate: false,\n loaded: prev.phase === 'uploading' ? prev.loaded : 0,\n total: prev.phase === 'uploading' ? prev.total : 0,\n error,\n })\n}\n\nfunction handleProgress(info: GrUploadProgressInfo) {\n if (state.phase !== 'uploading') return\n assignState({\n phase: 'uploading',\n percent: info.percent,\n indeterminate: info.indeterminate,\n loaded: info.loaded,\n total: info.total,\n })\n emit('progress', info.percent, info)\n}\n\nconst tabIndex = computed(() => (props.disabled ? -1 : 0))\n\nconst hiddenInputStyle = {\n position: 'fixed',\n top: '-9999px',\n left: '-9999px',\n width: '1px',\n height: '1px',\n opacity: '0',\n overflow: 'hidden',\n pointerEvents: 'none',\n} as const satisfies Record<string, string>\n\nfunction setOver(next: boolean) {\n if (isOver.value === next) return\n isOver.value = next\n}\n\nfunction openDialog() {\n if (props.disabled) return\n inputRef.value?.click()\n}\n\nfunction abort() {\n activeController?.abort()\n activeController = null\n}\n\nfunction normalizeLimit(limit: number | undefined): number | undefined {\n if (typeof limit !== 'number') return undefined\n if (!Number.isFinite(limit)) return undefined\n if (limit <= 0) return undefined\n return Math.floor(limit)\n}\n\n\nasync function uploadViaAction(files: File[], signal: AbortSignal, extraData: GrFileUploadExtraData | undefined) {\n if (!props.action) throw new Error('GrFileUpload: either `action` or `request` must be provided')\n\n return uploadViaXhr({\n url: props.action,\n files,\n name: props.name,\n headers: props.headers,\n withCredentials: props.withCredentials,\n extraData,\n signal,\n onProgress: handleProgress,\n })\n}\n\nasync function runBeforeUpload(files: File[]): Promise<'ok' | { aborted: true; reason: unknown }> {\n if (!props.beforeUpload) return 'ok'\n\n for (const file of files) {\n try {\n const result = props.beforeUpload(file)\n\n if (result === false) {\n return { aborted: true, reason: new Error('Upload aborted by beforeUpload') }\n }\n\n if (result && typeof (result as any).then === 'function')\n await result\n } catch (error) {\n return { aborted: true, reason: error }\n }\n }\n\n return 'ok'\n}\n\nasync function handleFiles(files: File[], source: FileValidatorSource = 'input') {\n if (props.disabled) return\n if (!files.length) return\n\n const normalizedLimit = normalizeLimit(props.limit)\n if (props.multiple && normalizedLimit && files.length > normalizedLimit) {\n props.onExceed?.(files, normalizedLimit)\n emit('error', new Error(`Too many files selected, limit=${normalizedLimit}`))\n return\n }\n\n const { files: valid, issues } = await runFileValidators(files, props.validators ?? [], {\n source,\n multiple: props.multiple,\n })\n\n if (issues.length > 0) {\n emit('error', new FileValidationError(issues, valid))\n return\n }\n\n if (!valid.length) return\n\n lastFiles.value = valid\n\n const before = await runBeforeUpload(valid)\n if (before !== 'ok') {\n emit('error', before.reason)\n return\n }\n\n let extraData: GrFileUploadExtraData | undefined\n try {\n extraData = props.uploadExtraData?.(valid)\n } catch (error) {\n emit('error', error)\n return\n }\n\n abort()\n clearHideSuccessTimer()\n\n const controller = new AbortController()\n activeController = controller\n\n setStateUploading()\n emit('progress', 0, { percent: 0, loaded: 0, total: 0, indeterminate: true })\n\n try {\n const payload = props.request\n ? await props.request(valid, { signal: controller.signal, extraData, onProgress: handleProgress })\n : await uploadViaAction(valid, controller.signal, extraData)\n\n const finalLoaded = state.phase === 'uploading' ? state.total || state.loaded : 0\n setStateSuccess({ loaded: finalLoaded, total: finalLoaded })\n emit('success', payload)\n emit('change', valid)\n emit('progress', 100, { percent: 100, loaded: finalLoaded, total: finalLoaded, indeterminate: false })\n\n if (props.hideProgressOnSuccess && props.hideProgressOnSuccess > 0) {\n hideSuccessTimer = setTimeout(() => {\n if (state.phase === 'success') setStateIdle()\n hideSuccessTimer = null\n }, props.hideProgressOnSuccess)\n }\n } catch (error) {\n if (error instanceof GrUploadAbortError) {\n setStateIdle()\n } else {\n setStateError(error)\n }\n emit('error', error)\n } finally {\n if (activeController === controller) activeController = null\n }\n}\n\nfunction onDragEnter(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n overCounter += 1\n setOver(true)\n}\n\nfunction onDragOver(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy'\n}\n\nfunction onDragLeave(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n overCounter = Math.max(0, overCounter - 1)\n if (overCounter === 0) setOver(false)\n}\n\nfunction onDrop(event: DragEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n event.preventDefault()\n overCounter = 0\n setOver(false)\n\n const files = event.dataTransfer?.files ? Array.prototype.slice.call(event.dataTransfer.files) as File[] : []\n void handleFiles(files, 'drop')\n}\n\nasync function onInputChange(event: Event) {\n if (props.disabled) return\n\n const target = event.target as HTMLInputElement | null\n const files = target?.files ? Array.prototype.slice.call(target.files) as File[] : []\n\n if (target) target.value = ''\n\n await nextTick()\n await handleFiles(files, 'input')\n}\n\nfunction onKeydown(event: KeyboardEvent) {\n if (hasCustomUi.value) return\n if (props.disabled) return\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n openDialog()\n }\n}\n\nfunction onRootClick() {\n if (hasCustomUi.value) return\n openDialog()\n}\n\nfunction onRootKeydown(event: KeyboardEvent) {\n if (hasCustomUi.value) return\n onKeydown(event)\n}\n\nconst effectiveProgressTone = computed<GrProgressBarTone>(() => {\n if (state.phase === 'error') return 'danger'\n if (state.phase === 'success') return 'success'\n return props.progressTone\n})\n\nconst progressVisible = computed(() => state.phase !== 'idle')\nconst progressPercent = computed(() => (state.phase === 'uploading' && state.indeterminate ? 0 : state.percent))\nconst progressText = computed(() => {\n if (state.phase === 'uploading' && state.indeterminate) return ''\n return `${Math.round(progressPercent.value)}%`\n})\n\ndefineExpose({\n uploadFiles: handleFiles,\n abort,\n openDialog,\n state,\n})\n</script>\n\n<template>\n <div\n data-ds-file-upload\n :role=\"hasCustomUi ? undefined : 'button'\"\n :tabindex=\"hasCustomUi ? undefined : tabIndex\"\n :aria-disabled=\"hasCustomUi ? undefined : disabled ? 'true' : 'false'\"\n :class=\"\n hasCustomUi\n ? 'inline-block'\n : [\n 'relative w-full rounded-[var(--ds-radius-lg)] border border-dashed border-[var(--brd)] bg-[var(--card)] px-5 py-6 outline-none transition',\n disabled\n ? 'opacity-60 cursor-not-allowed'\n : 'cursor-pointer hover:bg-[var(--muted)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg)]',\n isOver && !disabled ? 'border-[var(--ring)] bg-[var(--muted)]' : '',\n ]\n \"\n @click=\"onRootClick\"\n @keydown=\"onRootKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input\n ref=\"inputRef\"\n data-ds-file-upload-input\n :style=\"hiddenInputStyle\"\n type=\"file\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :name=\"name\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n @change=\"onInputChange\"\n >\n\n <slot\n v-if=\"hasCustomUi\"\n :open-dialog=\"openDialog\"\n :abort=\"abort\"\n :disabled=\"disabled\"\n :files=\"lastFiles\"\n :is-over=\"isOver\"\n :state=\"state\"\n />\n\n <div v-else class=\"flex items-start gap-4\">\n <div\n data-ds-file-upload-icon\n class=\"h-12 w-12 shrink-0 rounded-[12px] bg-[var(--muted)] border border-[var(--brd)] flex items-center justify-center\"\n aria-hidden=\"true\"\n >\n <GrIcon class=\"h-6 w-6 text-[var(--muted-fg)]\">\n <IconArrowUp />\n </GrIcon>\n </div>\n\n <div class=\"min-w-0\">\n <div data-ds-file-upload-label class=\"text-[14px] font-700\">\n <slot name=\"label\">\n <slot>\n {{ placeholder }}\n </slot>\n </slot>\n </div>\n\n <div v-if=\"$slots.tip\" data-ds-file-upload-tip class=\"mt-1 text-[13px] text-[var(--muted-fg)]\">\n <slot name=\"tip\" />\n </div>\n <div v-else class=\"mt-1 text-[13px] text-[var(--muted-fg)]\" />\n\n <ul v-if=\"showFileList && lastFiles.length\" data-ds-file-upload-list class=\"mt-3 space-y-1\">\n <li\n v-for=\"file in lastFiles\"\n :key=\"file.name\"\n data-ds-file-upload-item\n class=\"text-[13px]\"\n >\n <span class=\"font-600\">{{ file.name }}</span>\n <span class=\"text-[var(--muted-fg)]\"> · {{ Math.ceil(file.size / 1024) }} KB</span>\n </li>\n </ul>\n\n <slot\n v-if=\"showProgress || $slots.progress\"\n name=\"progress\"\n :state=\"state\"\n :percent=\"state.percent\"\n :indeterminate=\"state.phase === 'uploading' && state.indeterminate\"\n :phase=\"state.phase\"\n :files=\"lastFiles\"\n :abort=\"abort\"\n >\n <div\n v-if=\"showProgress\"\n data-ds-file-upload-progress\n class=\"mt-3 transition-opacity duration-150\"\n :class=\"progressVisible ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n :aria-hidden=\"!progressVisible\"\n >\n <div class=\"flex items-center gap-2\">\n <GrProgressBar\n :value=\"progressPercent\"\n :tone=\"effectiveProgressTone\"\n :aria-label=\"progressLabel\"\n />\n <span\n data-ds-file-upload-progress-text\n class=\"text-[12px] text-[var(--muted-fg)] tabular-nums min-w-[3ch] text-right\"\n >{{ progressText }}</span>\n </div>\n </div>\n </slot>\n </div>\n </div>\n </div>\n</template>"],"mappings":";;;;;;AA6BA,IAAa,qBAAb,cAAwC,MAAM;CAC5C,YAAY,UAAU,kBAAkB;AACtC,QAAM,QAAQ;AACd,OAAK,OAAO;;;AAIhB,IAAa,oBAAb,cAAuC,MAAM;CAC3C;CACA;CAEA,YAAY,QAAgB,SAAkB;AAC5C,QAAM,6BAA6B,SAAS;AAC5C,OAAK,OAAO;AACZ,OAAK,SAAS;AACd,OAAK,UAAU;;;AAInB,SAAS,oBAAoB,MAAgB,WAA0C;AACrF,KAAI,CAAC,UAAW;AAEhB,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,UAAU,EAAE;AACpD,MAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,QAAK,MAAM,SAAS,MAAO,MAAK,OAAO,KAAK,MAAM;AAClD;;AAGF,OAAK,OAAO,KAAK,MAAM;;;AAI3B,SAAS,cAAc,KAA8B;CACnD,MAAM,cAAc,IAAI,kBAAkB,eAAe,IAAI;CAC7D,MAAM,MAAM,IAAI;AAEhB,KAAI,YAAY,SAAS,mBAAmB,CAC1C,KAAI;AACF,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;;AAIX,QAAO;;AAGT,SAAgB,aAAa,SAAgD;CAC3E,MAAM,EAAE,KAAK,OAAO,MAAM,SAAS,iBAAiB,WAAW,QAAQ,eAAe;AAEtF,QAAO,IAAI,SAAkB,SAAS,WAAW;AAC/C,MAAI,OAAO,SAAS;AAClB,UAAO,IAAI,oBAAoB,CAAC;AAChC;;EAGF,MAAM,OAAO,IAAI,UAAU;AAC3B,OAAK,MAAM,QAAQ,MAAO,MAAK,OAAO,MAAM,KAAK;AACjD,sBAAoB,MAAM,UAAU;EAEpC,MAAM,MAAM,IAAI,gBAAgB;AAChC,MAAI,KAAK,QAAQ,KAAK,KAAK;AAC3B,MAAI,kBAAkB,CAAC,CAAC;AAExB,MAAI,QACF,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,KAAI,iBAAiB,KAAK,MAAM;EAGpC,MAAM,gBAAgB;AACpB,OAAI;AACF,QAAI,OAAO;WACL;;AAKV,SAAO,iBAAiB,SAAS,QAAQ;EAEzC,MAAM,gBAAgB;AACpB,UAAO,oBAAoB,SAAS,QAAQ;;AAG9C,MAAI,WACF,KAAI,OAAO,iBAAiB,aAAa,UAAU;GACjD,MAAM,gBAAgB,CAAC,MAAM;GAC7B,MAAM,QAAQ,gBAAgB,IAAI,MAAM;GACxC,MAAM,SAAS,gBAAgB,IAAI,MAAM;AAEzC,cAAW;IAAE,SADG,iBAAiB,UAAU,IAAI,IAAI,KAAK,IAAI,KAAM,SAAS,QAAS,IAAI;IAClE;IAAQ;IAAO;IAAe,CAAC;IACrD;AAGJ,MAAI,iBAAiB,cAAc;AACjC,YAAS;GACT,MAAM,UAAU,cAAc,IAAI;GAClC,MAAM,SAAS,IAAI;AAEnB,OAAI,UAAU,OAAO,SAAS,KAAK;AACjC,QAAI,WAAY,YAAW;KAAE,SAAS;KAAK,QAAQ;KAAG,OAAO;KAAG,eAAe;KAAO,CAAC;AACvF,YAAQ,QAAQ;AAChB;;AAGF,UAAO,IAAI,kBAAkB,QAAQ,QAAQ,CAAC;IAC9C;AAEF,MAAI,iBAAiB,eAAe;AAClC,YAAS;AACT,0BAAO,IAAI,MAAM,8BAA8B,CAAC;IAChD;AAEF,MAAI,iBAAiB,eAAe;AAClC,YAAS;AACT,UAAO,IAAI,oBAAoB,CAAC;IAChC;AAEF,MAAI,KAAK,KAAK;GACd;;;;ACnGJ,IAAa,uBAA0C,OAAO,OAAO;CACnE,OAAO;CACP,SAAS;CACT,eAAe;CACf,QAAQ;CACR,OAAO;CACR,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECaF,MAAM,QAAQ;EAwBd,MAAM,OAAO;EAQb,MAAM,QAAQ,UAAS;EAEvB,SAAS,iBAAiB,OAAyB;GACjD,MAAM,MAAe,EAAC;AAEtB,QAAK,MAAM,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,YAAY,MAAM,QAAQ,KAAK,SAAS,EAAE;AAC1D,SAAI,KAAK,GAAG,iBAAiB,KAAK,SAAoB,CAAA;AACtD;;AAGF,QAAI,KAAK,KAAI;;AAGf,UAAO;;EAGT,SAAS,qBAAqB,MAAsB;AAClD,OAAI,KAAK,SAAS,KAAM,QAAO;AAC/B,UAAO,OAAO,KAAK,aAAa,YAAY,KAAK,SAAS,MAAM,CAAC,WAAW;;EAG9E,SAAS,eAAe,OAAyB;GAE/C,MAAM,aADO,iBAAiB,MAAK,CACX,QAAO,SAAQ,KAAK,SAAS,WAAW,CAAC,qBAAqB,KAAK,CAAA;AAE3F,OAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAK,MAAM,QAAQ,WACjB,KAAI,KAAK,SAAS,KAAM,QAAO;AAGjC,UAAO;;EAGT,MAAM,mBAAmB,eAAe;AACtC,UAAO,MAAM,UAAU,iBAAiB,MAAM,QAAQ,EAAE,CAAQ,CAAC,GAAG,EAAC;IACtE;EAED,MAAM,cAAc,eAAe;AACjC,UAAO,CAAC,CAAC,MAAM,WAAW,CAAC,eAAe,iBAAiB,MAAK;IACjE;EAED,MAAM,WAAW,IAA6B,KAAI;EAClD,MAAM,SAAS,IAAI,MAAK;EACxB,IAAI,cAAc;EAElB,MAAM,YAAY,IAAY,EAAE,CAAA;EAEhC,MAAM,QAAQ,SAAwB,EAAE,GAAG,sBAAsB,CAAC;EAElE,IAAI,mBAA2C;EAC/C,IAAI,mBAAyD;EAE7D,SAAS,wBAAwB;AAC/B,OAAI,qBAAqB,MAAM;AAC7B,iBAAa,iBAAgB;AAC7B,uBAAmB;;;EAIvB,SAAS,YAAY,MAAqB;AAExC,QAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAClC,QAAQ,MAAc;AACxB,UAAO,OAAO,OAAO,KAAI;AACzB,QAAK,gBAAgB,MAAsB;;EAG7C,SAAS,eAAe;AACtB,eAAY,EAAE,GAAG,sBAAsB,CAAA;;EAGzC,SAAS,kBAAkB,MAA6B;AACtD,eAAY;IACV,OAAO;IACP,SAAS,MAAM,WAAW;IAC1B,eAAe,MAAM,iBAAiB;IACtC,QAAQ,MAAM,UAAU;IACxB,OAAO,MAAM,SAAS;IACvB,CAAA;;EAGH,SAAS,gBAAgB,MAAyC;AAChE,eAAY;IACV,OAAO;IACP,SAAS;IACT,eAAe;IACf,QAAQ,KAAK;IACb,OAAO,KAAK;IACb,CAAA;;EAGH,SAAS,cAAc,OAAgB;GACrC,MAAM,OAAO;AACb,eAAY;IACV,OAAO;IACP,SAAS,KAAK,UAAU,cAAc,KAAK,UAAU;IACrD,eAAe;IACf,QAAQ,KAAK,UAAU,cAAc,KAAK,SAAS;IACnD,OAAO,KAAK,UAAU,cAAc,KAAK,QAAQ;IACjD;IACD,CAAA;;EAGH,SAAS,eAAe,MAA4B;AAClD,OAAI,MAAM,UAAU,YAAa;AACjC,eAAY;IACV,OAAO;IACP,SAAS,KAAK;IACd,eAAe,KAAK;IACpB,QAAQ,KAAK;IACb,OAAO,KAAK;IACb,CAAA;AACD,QAAK,YAAY,KAAK,SAAS,KAAI;;EAGrC,MAAM,WAAW,eAAgB,MAAM,WAAW,KAAK,EAAE;EAEzD,MAAM,mBAAmB;GACvB,UAAU;GACV,KAAK;GACL,MAAM;GACN,OAAO;GACP,QAAQ;GACR,SAAS;GACT,UAAU;GACV,eAAe;GAChB;EAED,SAAS,QAAQ,MAAe;AAC9B,OAAI,OAAO,UAAU,KAAM;AAC3B,UAAO,QAAQ;;EAGjB,SAAS,aAAa;AACpB,OAAI,MAAM,SAAU;AACpB,YAAS,OAAO,OAAM;;EAGxB,SAAS,QAAQ;AACf,qBAAkB,OAAM;AACxB,sBAAmB;;EAGrB,SAAS,eAAe,OAA+C;AACrE,OAAI,OAAO,UAAU,SAAU,QAAO,KAAA;AACtC,OAAI,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO,KAAA;AACpC,OAAI,SAAS,EAAG,QAAO,KAAA;AACvB,UAAO,KAAK,MAAM,MAAK;;EAIzB,eAAe,gBAAgB,OAAe,QAAqB,WAA8C;AAC/G,OAAI,CAAC,MAAM,OAAQ,OAAM,IAAI,MAAM,8DAA6D;AAEhG,UAAO,aAAa;IAClB,KAAK,MAAM;IACX;IACA,MAAM,MAAM;IACZ,SAAS,MAAM;IACf,iBAAiB,MAAM;IACvB;IACA;IACA,YAAY;IACb,CAAA;;EAGH,eAAe,gBAAgB,OAAmE;AAChG,OAAI,CAAC,MAAM,aAAc,QAAO;AAEhC,QAAK,MAAM,QAAQ,MACjB,KAAI;IACF,MAAM,SAAS,MAAM,aAAa,KAAI;AAEtC,QAAI,WAAW,MACb,QAAO;KAAE,SAAS;KAAM,wBAAQ,IAAI,MAAM,iCAAiC;KAAC;AAG9E,QAAI,UAAU,OAAQ,OAAe,SAAS,WAC5C,OAAM;YACD,OAAO;AACd,WAAO;KAAE,SAAS;KAAM,QAAQ;KAAM;;AAI1C,UAAO;;EAGT,eAAe,YAAY,OAAe,SAA8B,SAAS;AAC/E,OAAI,MAAM,SAAU;AACpB,OAAI,CAAC,MAAM,OAAQ;GAEnB,MAAM,kBAAkB,eAAe,MAAM,MAAK;AAClD,OAAI,MAAM,YAAY,mBAAmB,MAAM,SAAS,iBAAiB;AACvE,UAAM,WAAW,OAAO,gBAAe;AACvC,SAAK,yBAAS,IAAI,MAAM,kCAAkC,kBAAkB,CAAA;AAC5E;;GAGF,MAAM,EAAE,OAAO,OAAO,WAAW,MAAM,kBAAkB,OAAO,MAAM,cAAc,EAAE,EAAE;IACtF;IACA,UAAU,MAAM;IACjB,CAAA;AAED,OAAI,OAAO,SAAS,GAAG;AACrB,SAAK,SAAS,IAAI,oBAAoB,QAAQ,MAAM,CAAA;AACpD;;AAGF,OAAI,CAAC,MAAM,OAAQ;AAEnB,aAAU,QAAQ;GAElB,MAAM,SAAS,MAAM,gBAAgB,MAAK;AAC1C,OAAI,WAAW,MAAM;AACnB,SAAK,SAAS,OAAO,OAAM;AAC3B;;GAGF,IAAI;AACJ,OAAI;AACF,gBAAY,MAAM,kBAAkB,MAAK;YAClC,OAAO;AACd,SAAK,SAAS,MAAK;AACnB;;AAGF,UAAM;AACN,0BAAsB;GAEtB,MAAM,aAAa,IAAI,iBAAgB;AACvC,sBAAmB;AAEnB,sBAAkB;AAClB,QAAK,YAAY,GAAG;IAAE,SAAS;IAAG,QAAQ;IAAG,OAAO;IAAG,eAAe;IAAM,CAAA;AAE5E,OAAI;IACF,MAAM,UAAU,MAAM,UAClB,MAAM,MAAM,QAAQ,OAAO;KAAE,QAAQ,WAAW;KAAQ;KAAW,YAAY;KAAgB,CAAA,GAC/F,MAAM,gBAAgB,OAAO,WAAW,QAAQ,UAAS;IAE7D,MAAM,cAAc,MAAM,UAAU,cAAc,MAAM,SAAS,MAAM,SAAS;AAChF,oBAAgB;KAAE,QAAQ;KAAa,OAAO;KAAa,CAAA;AAC3D,SAAK,WAAW,QAAO;AACvB,SAAK,UAAU,MAAK;AACpB,SAAK,YAAY,KAAK;KAAE,SAAS;KAAK,QAAQ;KAAa,OAAO;KAAa,eAAe;KAAO,CAAA;AAErG,QAAI,MAAM,yBAAyB,MAAM,wBAAwB,EAC/D,oBAAmB,iBAAiB;AAClC,SAAI,MAAM,UAAU,UAAW,eAAa;AAC5C,wBAAmB;OAClB,MAAM,sBAAqB;YAEzB,OAAO;AACd,QAAI,iBAAiB,mBACnB,eAAa;QAEb,eAAc,MAAK;AAErB,SAAK,SAAS,MAAK;aACX;AACR,QAAI,qBAAqB,WAAY,oBAAmB;;;EAI5D,SAAS,YAAY,OAAkB;AACrC,OAAI,YAAY,MAAO;AACvB,OAAI,MAAM,SAAU;AACpB,SAAM,gBAAe;AACrB,kBAAe;AACf,WAAQ,KAAI;;EAGd,SAAS,WAAW,OAAkB;AACpC,OAAI,YAAY,MAAO;AACvB,OAAI,MAAM,SAAU;AACpB,SAAM,gBAAe;AACrB,OAAI,MAAM,aAAc,OAAM,aAAa,aAAa;;EAG1D,SAAS,YAAY,OAAkB;AACrC,OAAI,YAAY,MAAO;AACvB,OAAI,MAAM,SAAU;AACpB,SAAM,gBAAe;AACrB,iBAAc,KAAK,IAAI,GAAG,cAAc,EAAC;AACzC,OAAI,gBAAgB,EAAG,SAAQ,MAAK;;EAGtC,SAAS,OAAO,OAAkB;AAChC,OAAI,YAAY,MAAO;AACvB,OAAI,MAAM,SAAU;AACpB,SAAM,gBAAe;AACrB,iBAAc;AACd,WAAQ,MAAK;AAGR,eADS,MAAM,cAAc,QAAQ,MAAM,UAAU,MAAM,KAAK,MAAM,aAAa,MAAM,GAAa,EAAC,EACpF,OAAM;;EAGhC,eAAe,cAAc,OAAc;AACzC,OAAI,MAAM,SAAU;GAEpB,MAAM,SAAS,MAAM;GACrB,MAAM,QAAQ,QAAQ,QAAQ,MAAM,UAAU,MAAM,KAAK,OAAO,MAAM,GAAa,EAAC;AAEpF,OAAI,OAAQ,QAAO,QAAQ;AAE3B,SAAM,UAAS;AACf,SAAM,YAAY,OAAO,QAAO;;EAGlC,SAAS,UAAU,OAAsB;AACvC,OAAI,YAAY,MAAO;AACvB,OAAI,MAAM,SAAU;AAEpB,OAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC9C,UAAM,gBAAe;AACrB,gBAAW;;;EAIf,SAAS,cAAc;AACrB,OAAI,YAAY,MAAO;AACvB,eAAW;;EAGb,SAAS,cAAc,OAAsB;AAC3C,OAAI,YAAY,MAAO;AACvB,aAAU,MAAK;;EAGjB,MAAM,wBAAwB,eAAkC;AAC9D,OAAI,MAAM,UAAU,QAAS,QAAO;AACpC,OAAI,MAAM,UAAU,UAAW,QAAO;AACtC,UAAO,MAAM;IACd;EAED,MAAM,kBAAkB,eAAe,MAAM,UAAU,OAAM;EAC7D,MAAM,kBAAkB,eAAgB,MAAM,UAAU,eAAe,MAAM,gBAAgB,IAAI,MAAM,QAAQ;EAC/G,MAAM,eAAe,eAAe;AAClC,OAAI,MAAM,UAAU,eAAe,MAAM,cAAe,QAAO;AAC/D,UAAO,GAAG,KAAK,MAAM,gBAAgB,MAAM,CAAC;IAC7C;AAED,WAAa;GACX,aAAa;GACb;GACA;GACA;GACD,CAAA;;uBAIC,mBAmHM,OAAA;IAlHJ,uBAAA;IACC,MAAM,YAAA,QAAc,KAAA,IAAS;IAC7B,UAAU,YAAA,QAAc,KAAA,IAAY,SAAA;IACpC,iBAAe,YAAA,QAAc,KAAA,IAAY,QAAA,WAAQ,SAAA;IACjD,OAAK,eAAS,YAAA,QAAA,iBAAA;;KAAsN,QAAA,WAAA,kCAAA;KAAuP,OAAA,SAAM,CAAK,QAAA,WAAQ,2CAAA;;IAW9e,SAAO;IACP,WAAS;IACT,aAAW;IACX,YAAU;IACV,aAAW;IACL;OAEP,mBAWC,SAAA;aAVK;IAAJ,KAAI;IACJ,6BAAA;IACC,OAAO;IACR,MAAK;IACL,UAAS;IACT,eAAY;IACX,MAAM,QAAA;IACN,UAAU,QAAA;IACV,UAAU,QAAA;IACV,UAAQ;6BAIH,YAAA,QADR,WAQE,KAAA,QAAA,WAAA;;IANc;IACN;IACP,UAAU,QAAA;IACV,OAAO,UAAA;IACP,QAAS,OAAA;IACF;sBAGV,mBAoEM,OApEN,YAoEM,CAnEJ,mBAQM,OARN,YAQM,CAHJ,YAES,gBAAA,EAFD,OAAM,kCAAgC,EAAA;2BAC7B,CAAf,YAAe,MAAA,iBAAA,CAAA,CAAA,CAAA;;SAInB,mBAwDM,OAxDN,YAwDM;IAvDJ,mBAMM,OANN,YAMM,CALJ,WAIO,KAAA,QAAA,SAAA,EAAA,QAAA,CAHL,WAEO,KAAA,QAAA,WAAA,EAAA,QAAA,CAAA,gBAAA,gBADF,QAAA,YAAW,EAAA,EAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;IAKTA,KAAAA,OAAO,OAAA,WAAA,EAAlB,mBAEM,OAFN,YAEM,CADJ,WAAmB,KAAA,QAAA,MAAA,CAAA,CAAA,KAAA,WAAA,EAErB,mBAA8D,OAA9D,WAA8D;IAEpD,QAAA,gBAAgB,UAAA,MAAU,UAAA,WAAA,EAApC,mBAUK,MAVL,YAUK,EAAA,UAAA,KAAA,EATH,mBAQK,UAAA,MAAA,WAPY,UAAA,QAAR,SAAI;yBADb,mBAQK,MAAA;MANF,KAAK,KAAK;MACX,4BAAA;MACA,OAAM;SAEN,mBAA6C,QAA7C,aAA6C,gBAAnB,KAAK,KAAI,EAAA,EAAA,EACnC,mBAAmF,QAAnF,aAAqC,QAAG,gBAAG,KAAK,KAAK,KAAK,OAAI,KAAA,CAAA,GAAW,OAAG,EAAA,CAAA,CAAA;;IAKxE,QAAA,gBAAgBA,KAAAA,OAAO,WAD/B,WA6BO,KAAA,QAAA,YAAA;;KA1BG;KACP,SAAS,MAAM;KACf,eAAe,MAAM,UAAK,eAAoB,MAAM;KACpD,OAAO,MAAM;KACb,OAAO,UAAA;KACA;aAqBH,CAlBG,QAAA,gBAAA,WAAA,EADR,mBAkBM,OAAA;;KAhBJ,gCAAA;KACA,OAAK,eAAA,CAAC,wCACE,gBAAA,QAAe,gBAAA,gCAAA,CAAA;KACtB,eAAW,CAAG,gBAAA;QAEf,mBAUM,OAVN,aAUM,CATJ,YAIE,uBAAA;KAHC,OAAO,gBAAA;KACP,MAAM,sBAAA;KACN,cAAY,QAAA;;;;;QAEf,mBAG0B,QAH1B,aAG0B,gBAAtB,aAAA,MAAY,EAAA,EAAA,CAAA,CAAA,CAAA,EAAA,IAAA,YAAA,IAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,GAAA,mBAAA,IAAA,KAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"GrPromptDialog-CUMW6_58.js","names":[],"sources":["../../../../src/components/GrPromptDialog/GrPromptDialog.vue","../../../../src/components/GrPromptDialog/GrPromptDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * GrPromptDialog — DS-примитив диалога ввода значения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Поведение `required=true` (по умолчанию): пустое значение подсвечивается\n * ошибкой только после первого «касания» (blur или попытка confirm),\n * чтобы не шуметь при открытии.\n */\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrFormField from '../GrFormField/GrFormField.vue'\nimport GrInput from '../GrInput/GrInput.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrPromptDialogProps {\n modelValue: boolean\n value: string\n title?: string\n description?: string\n label?: string\n placeholder?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n /** Текст ошибки для пустого значения при `required=true` (i18n). */\n requiredErrorText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n required?: boolean\n}\n\nconst props = withDefaults(defineProps<GrPromptDialogProps>(), {\n title: 'Prompt',\n description: undefined,\n label: 'Value',\n placeholder: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n requiredErrorText: 'Enter a value.',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n required: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'update:value', value: string): void\n (e: 'confirm', value: string): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst valueModel = computed({\n get: () => props.value,\n set: (v: string) => emit('update:value', v),\n})\n\nconst touched = ref(false)\nconst inputRef = ref<InstanceType<typeof GrInput> | null>(null)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (v) touched.value = false\n },\n)\n\nconst canConfirm = computed(() => {\n if (!props.required) return true\n return valueModel.value.trim().length > 0\n})\n\nconst error = computed(() => {\n if (!props.required) return undefined\n if (!touched.value) return undefined\n return valueModel.value.trim().length > 0\n ? undefined\n : props.requiredErrorText\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n if (!canConfirm.value) {\n touched.value = true\n inputRef.value?.focus()\n return\n }\n\n emit('confirm', valueModel.value)\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <GrFormField :label=\"label\" :error=\"error\" for-id=\"ds-prompt-input\">\n <GrInput\n id=\"ds-prompt-input\"\n ref=\"inputRef\"\n v-model=\"valueModel\"\n data-testid=\"ds-prompt-input\"\n :placeholder=\"placeholder\"\n :invalid=\"!!error\"\n @blur=\"touched = true\"\n />\n </GrFormField>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-prompt-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-prompt-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :disabled=\"required && touched && !canConfirm\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n","<script setup lang=\"ts\">\n/**\n * GrPromptDialog — DS-примитив диалога ввода значения поверх `GrDialog`.\n *\n * Синхронизирован с `GrDialog` по набору проп-проксирования:\n * `size`, `closeOnBackdrop`, `closeOnEsc`, `showHeader`, `showCloseButton`,\n * `headerConfig`, `footerConfig`, `bodyConfig`, `closeLabel`.\n *\n * Поведение `required=true` (по умолчанию): пустое значение подсвечивается\n * ошибкой только после первого «касания» (blur или попытка confirm),\n * чтобы не шуметь при открытии.\n */\nimport { computed, ref, watch } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport GrDialog from '../GrDialog/GrDialog.vue'\nimport GrFormField from '../GrFormField/GrFormField.vue'\nimport GrInput from '../GrInput/GrInput.vue'\nimport type { GrButtonSize, GrButtonTone, GrButtonVariant } from '../GrButton'\nimport type { GrDialogSectionConfig, GrDialogSize } from '../GrDialog'\n\nexport interface GrPromptDialogProps {\n modelValue: boolean\n value: string\n title?: string\n description?: string\n label?: string\n placeholder?: string\n closeOnBackdrop?: boolean\n closeOnEsc?: boolean\n showHeader?: boolean\n showCloseButton?: boolean\n size?: GrDialogSize\n headerConfig?: GrDialogSectionConfig\n footerConfig?: GrDialogSectionConfig\n bodyConfig?: GrDialogSectionConfig\n /** A11y-лейбл кнопки закрытия (i18n). */\n closeLabel?: string\n buttonSize?: GrButtonSize\n confirmText?: string\n cancelText?: string\n /** Текст ошибки для пустого значения при `required=true` (i18n). */\n requiredErrorText?: string\n confirmVariant?: GrButtonVariant\n confirmTone?: GrButtonTone\n required?: boolean\n}\n\nconst props = withDefaults(defineProps<GrPromptDialogProps>(), {\n title: 'Prompt',\n description: undefined,\n label: 'Value',\n placeholder: undefined,\n closeOnBackdrop: true,\n closeOnEsc: true,\n showHeader: true,\n showCloseButton: true,\n size: 'md',\n headerConfig: undefined,\n footerConfig: undefined,\n bodyConfig: undefined,\n closeLabel: 'Close',\n buttonSize: undefined,\n confirmText: 'Confirm',\n cancelText: 'Cancel',\n requiredErrorText: 'Enter a value.',\n confirmVariant: 'primary',\n confirmTone: 'primary',\n required: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'update:value', value: string): void\n (e: 'confirm', value: string): void\n (e: 'cancel'): void\n}>()\n\nconst open = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst valueModel = computed({\n get: () => props.value,\n set: (v: string) => emit('update:value', v),\n})\n\nconst touched = ref(false)\nconst inputRef = ref<InstanceType<typeof GrInput> | null>(null)\n\nwatch(\n () => props.modelValue,\n (v) => {\n if (v) touched.value = false\n },\n)\n\nconst canConfirm = computed(() => {\n if (!props.required) return true\n return valueModel.value.trim().length > 0\n})\n\nconst error = computed(() => {\n if (!props.required) return undefined\n if (!touched.value) return undefined\n return valueModel.value.trim().length > 0\n ? undefined\n : props.requiredErrorText\n})\n\nfunction onCancel(): void {\n emit('cancel')\n emit('update:modelValue', false)\n}\n\nfunction onConfirm(): void {\n if (!canConfirm.value) {\n touched.value = true\n inputRef.value?.focus()\n return\n }\n\n emit('confirm', valueModel.value)\n emit('update:modelValue', false)\n}\n</script>\n\n<template>\n <GrDialog\n v-model=\"open\"\n :title=\"title\"\n :size=\"size\"\n :close-on-backdrop=\"closeOnBackdrop\"\n :close-on-esc=\"closeOnEsc\"\n :show-header=\"showHeader\"\n :show-close-button=\"showCloseButton\"\n :header-config=\"headerConfig\"\n :footer-config=\"footerConfig\"\n :body-config=\"bodyConfig\"\n :close-label=\"closeLabel\"\n >\n <div class=\"grid gap-4\">\n <slot>\n <div v-if=\"description\" class=\"text-[14px] text-[var(--muted-fg)]\">\n {{ description }}\n </div>\n </slot>\n\n <GrFormField :label=\"label\" :error=\"error\" for-id=\"ds-prompt-input\">\n <GrInput\n id=\"ds-prompt-input\"\n ref=\"inputRef\"\n v-model=\"valueModel\"\n data-testid=\"ds-prompt-input\"\n :placeholder=\"placeholder\"\n :invalid=\"!!error\"\n @blur=\"touched = true\"\n />\n </GrFormField>\n </div>\n\n <template #footer>\n <slot name=\"footer\">\n <div class=\"flex items-center justify-end gap-3\">\n <GrButton data-testid=\"ds-prompt-cancel\" variant=\"outline\" :size=\"buttonSize\" @click=\"onCancel\">\n {{ cancelText }}\n </GrButton>\n <GrButton\n data-testid=\"ds-prompt-confirm\"\n :variant=\"confirmVariant\"\n :tone=\"confirmTone\"\n :size=\"buttonSize\"\n :disabled=\"required && touched && !canConfirm\"\n @click=\"onConfirm\"\n >\n {{ confirmText }}\n </GrButton>\n </div>\n </slot>\n </template>\n </GrDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDA,MAAM,QAAQ;EAuBd,MAAM,OAAO;EAOb,MAAM,OAAO,SAAS;GACpB,WAAW,MAAM;GACjB,MAAM,MAAe,KAAK,qBAAqB,EAAE;GAClD,CAAA;EAED,MAAM,aAAa,SAAS;GAC1B,WAAW,MAAM;GACjB,MAAM,MAAc,KAAK,gBAAgB,EAAE;GAC5C,CAAA;EAED,MAAM,UAAU,IAAI,MAAK;EACzB,MAAM,WAAW,IAAyC,KAAI;AAE9D,cACQ,MAAM,aACX,MAAM;AACL,OAAI,EAAG,SAAQ,QAAQ;IAE3B;EAEA,MAAM,aAAa,eAAe;AAChC,OAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,UAAO,WAAW,MAAM,MAAM,CAAC,SAAS;IACzC;EAED,MAAM,QAAQ,eAAe;AAC3B,OAAI,CAAC,MAAM,SAAU,QAAO,KAAA;AAC5B,OAAI,CAAC,QAAQ,MAAO,QAAO,KAAA;AAC3B,UAAO,WAAW,MAAM,MAAM,CAAC,SAAS,IACpC,KAAA,IACA,MAAM;IACX;EAED,SAAS,WAAiB;AACxB,QAAK,SAAQ;AACb,QAAK,qBAAqB,MAAK;;EAGjC,SAAS,YAAkB;AACzB,OAAI,CAAC,WAAW,OAAO;AACrB,YAAQ,QAAQ;AAChB,aAAS,OAAO,OAAM;AACtB;;AAGF,QAAK,WAAW,WAAW,MAAK;AAChC,QAAK,qBAAqB,MAAK;;;uBAK/B,YAoDW,kBAAA;gBAnDA,KAAA;sEAAI,QAAA;IACZ,OAAO,QAAA;IACP,MAAM,QAAA;IACN,qBAAmB,QAAA;IACnB,gBAAc,QAAA;IACd,eAAa,QAAA;IACb,qBAAmB,QAAA;IACnB,iBAAe,QAAA;IACf,iBAAe,QAAA;IACf,eAAa,QAAA;IACb,eAAa,QAAA;;IAsBH,QAAM,cAiBR,CAhBP,WAgBO,KAAA,QAAA,UAAA,EAAA,QAAA,CAfL,mBAcM,OAdN,YAcM,CAbJ,YAEW,kBAAA;KAFD,eAAY;KAAmB,SAAQ;KAAW,MAAM,QAAA;KAAa,SAAO;;4BACpE,CAAA,gBAAA,gBAAb,QAAA,WAAU,EAAA,EAAA,CAAA,CAAA;;qBAEf,YASW,kBAAA;KART,eAAY;KACX,SAAS,QAAA;KACT,MAAM,QAAA;KACN,MAAM,QAAA;KACN,UAAU,QAAA,YAAY,QAAA,SAAO,CAAK,WAAA;KAClC,SAAO;;4BAES,CAAA,gBAAA,gBAAd,QAAA,YAAW,EAAA,EAAA,CAAA,CAAA;;;;;;;;2BAhBhB,CAlBN,mBAkBM,OAlBN,YAkBM,CAjBJ,WAIO,KAAA,QAAA,WAAA,EAAA,QAAA,CAHM,QAAA,eAAA,WAAA,EAAX,mBAEM,OAFN,YAEM,gBADD,QAAA,YAAW,EAAA,EAAA,IAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,EAIlB,YAUc,qBAAA;KAVA,OAAO,QAAA;KAAQ,OAAO,MAAA;KAAO,UAAO;;4BAS9C,CARF,YAQE,iBAAA;MAPA,IAAG;eACC;MAAJ,KAAI;kBACK,WAAA;8EAAU,QAAA;MACnB,eAAY;MACX,aAAa,QAAA;MACb,SAAO,CAAA,CAAI,MAAA;MACX,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO"}