@feugene/granularity 0.5.1 → 0.6.2

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 (187) hide show
  1. package/dist/chunks/{adapter-K6zZTzBi.js.map → adapter-CRyH4YC8.js.map} +1 -1
  2. package/dist/chunks/{config-Cgk5ti-b.js.map → config-3SftO0uG.js.map} +1 -1
  3. package/dist/chunks/{config-BN-B2K4r.js.map → config-B44QVIge.js.map} +1 -1
  4. package/dist/chunks/{config-C-GVBa19.js.map → config-B8rC_K97.js.map} +1 -1
  5. package/dist/chunks/{config-DEv4m-ZP.js.map → config-BXffa3ta.js.map} +1 -1
  6. package/dist/chunks/{config-CUgvsjZx.js.map → config-BhvNm4Pp.js.map} +1 -1
  7. package/dist/chunks/{config-BNOf_qjD.js.map → config-C0b_3LJV.js.map} +1 -1
  8. package/dist/chunks/config-C0rHS1-l.js.map +1 -0
  9. package/dist/chunks/{config-fCcRwjIB.js.map → config-C4qAA0Sb.js.map} +1 -1
  10. package/dist/chunks/{config-XwI6t8cn.js.map → config-C5TN9J2Z.js.map} +1 -1
  11. package/dist/chunks/config-CVnluhKO.js.map +1 -0
  12. package/dist/chunks/{config-DUtUkSzc.js.map → config-CjEplP6D.js.map} +1 -1
  13. package/dist/chunks/{config-D19pyP4D.js.map → config-CtomKf-k.js.map} +1 -1
  14. package/dist/chunks/{config-BvuQUBtZ.js.map → config-CxCAfXZ1.js.map} +1 -1
  15. package/dist/chunks/{config-BDiLiqSk.js.map → config-D1DI3roo.js.map} +1 -1
  16. package/dist/chunks/{config-CgjOJ3aF.js.map → config-D27BL0H9.js.map} +1 -1
  17. package/dist/chunks/config-D32znLtV2.js.map +1 -0
  18. package/dist/chunks/{config-YSOeh6cy.js.map → config-D6Af6WZw.js.map} +1 -1
  19. package/dist/chunks/{config-BulF0Bf-.js.map → config-D98m8iyz.js.map} +1 -1
  20. package/dist/chunks/config-DDLoUczC.js.map +1 -0
  21. package/dist/chunks/{config-CFcv0hjb.js.map → config-DQOSlWvp.js.map} +1 -1
  22. package/dist/chunks/{config-ndXqsz5A.js.map → config-DbqFk-IW.js.map} +1 -1
  23. package/dist/chunks/{config-CdHY0Z7L.js.map → config-DnsISjD8.js.map} +1 -1
  24. package/dist/chunks/{config-BFZN9-vt.js.map → config-DudL02ag.js.map} +1 -1
  25. package/dist/chunks/{config-DgRJlF00.js.map → config-Dusr9jcE.js.map} +1 -1
  26. package/dist/chunks/{config-CWvHiaqr2.js.map → config-DxqMXzNV2.js.map} +1 -1
  27. package/dist/chunks/config-Mp9DJ9Mq2.js.map +1 -0
  28. package/dist/chunks/{config-R0jaXatX.js → config-XoANT5mU.js} +1 -1
  29. package/dist/chunks/{config-R0jaXatX.js.map → config-XoANT5mU.js.map} +1 -1
  30. package/dist/chunks/config-ZJVOVgqR.js +22 -0
  31. package/dist/chunks/config-ZJVOVgqR.js.map +1 -0
  32. package/dist/chunks/{config-CM7nbATU2.js.map → config-rxFL-6yF2.js.map} +1 -1
  33. package/dist/chunks/{config-bpQYM5O-.js.map → config-wo-ncgTH.js.map} +1 -1
  34. package/dist/chunks/{en-BeJa78lP.js.map → en-BMjJZttK.js.map} +1 -1
  35. package/dist/chunks/{es-BPqm7rLm.js → es-Cu_RlgIr.js} +3 -3
  36. package/dist/chunks/{es-BPqm7rLm.js.map → es-Cu_RlgIr.js.map} +1 -1
  37. package/dist/chunks/{es-axYOwwWD.js.map → es-EYCf8G_1.js.map} +1 -1
  38. package/dist/chunks/{grSelectStyles-daEeDlBn.js.map → grSelectStyles-DTAYNzxn.js.map} +1 -1
  39. package/dist/chunks/grStyle-5EMYYctb.js +19 -0
  40. package/dist/chunks/grStyle-5EMYYctb.js.map +1 -0
  41. package/dist/chunks/{granularityI18n-GCqUz_lo.js → granularityI18n-Dm4DuCS9.js} +1 -1
  42. package/dist/chunks/{granularityI18n-GCqUz_lo.js.map → granularityI18n-Dm4DuCS9.js.map} +1 -1
  43. package/dist/chunks/{ru-Dqh-2C00.js.map → ru-DKswMSdd.js.map} +1 -1
  44. package/dist/chunks/{shared-CyCPkimZ.js → shared-DO3Sr5FJ.js} +30 -30
  45. package/dist/chunks/{shared-CyCPkimZ.js.map → shared-DO3Sr5FJ.js.map} +1 -1
  46. package/dist/components/GrFileUpload/chunks/{GrFileUpload-u01j9S0t.js → GrFileUpload-DYRERhI2.js} +258 -37
  47. package/dist/components/GrFileUpload/chunks/GrFileUpload-DYRERhI2.js.map +1 -0
  48. package/dist/components/GrFileUpload/index.js +3 -3
  49. package/dist/components/GrFormField/chunks/{GrFormField-C6PfAs4u.js.map → GrFormField-C1oWTT_0.js.map} +1 -1
  50. package/dist/components/GrFormField/index.js +2 -2
  51. package/dist/components/GrFormFile/chunks/{GrFormFile-DdM8Bc2B.js.map → GrFormFile-deDPicM2.js.map} +1 -1
  52. package/dist/components/GrFormFile/index.js +2 -2
  53. package/dist/components/GrFormSection/chunks/{GrFormSection-5djEaQZQ.js.map → GrFormSection-CWBk2EUm.js.map} +1 -1
  54. package/dist/components/GrFormSection/index.js +2 -2
  55. package/dist/components/GrImageViewer/chunks/{GrImageViewer-CjSnohW7.js.map → GrImageViewer-Cpj5zyZQ.js.map} +1 -1
  56. package/dist/components/GrImageViewer/index.js +2 -2
  57. package/dist/components/GrInput/chunks/{GrInput-ghxaTf6d.js.map → GrInput-CfO2RsM-.js.map} +1 -1
  58. package/dist/components/GrInput/index.js +2 -2
  59. package/dist/components/GrInputTag/chunks/{GrInputTag-B0x4U0Yk.js → GrInputTag-G_VYJPF9.js} +1 -1
  60. package/dist/components/GrInputTag/chunks/{GrInputTag-B0x4U0Yk.js.map → GrInputTag-G_VYJPF9.js.map} +1 -1
  61. package/dist/components/GrInputTag/index.js +2 -2
  62. package/dist/components/GrLink/chunks/{GrLink-DvvNkP0M.js → GrLink-BLPigqij.js} +1 -1
  63. package/dist/components/GrLink/chunks/{GrLink-DvvNkP0M.js.map → GrLink-BLPigqij.js.map} +1 -1
  64. package/dist/components/GrLink/index.js +2 -2
  65. package/dist/components/GrList/chunks/{GrList--Ib4zLNw.js.map → GrList-BPjQf-72.js.map} +1 -1
  66. package/dist/components/GrList/index.js +2 -2
  67. package/dist/components/GrLoading/index.js +1 -1
  68. package/dist/components/GrModal/index.js +1 -1
  69. package/dist/components/GrNavbar/chunks/{GrNavbar-nIyuiVj1.js → GrNavbar-BDIKAYfN.js} +1 -1
  70. package/dist/components/GrNavbar/chunks/{GrNavbar-nIyuiVj1.js.map → GrNavbar-BDIKAYfN.js.map} +1 -1
  71. package/dist/components/GrNavbar/index.js +2 -2
  72. package/dist/components/GrNumberInput/chunks/{GrNumberInput-B0mPLjdv.js → GrNumberInput-ECtFCIKV.js} +1 -1
  73. package/dist/components/GrNumberInput/chunks/{GrNumberInput-B0mPLjdv.js.map → GrNumberInput-ECtFCIKV.js.map} +1 -1
  74. package/dist/components/GrNumberInput/index.js +2 -2
  75. package/dist/components/GrPagination/chunks/{GrPagination-C_rxGwfY.js → GrPagination-BZlH-uEd.js} +2 -2
  76. package/dist/components/GrPagination/chunks/{GrPagination-C_rxGwfY.js.map → GrPagination-BZlH-uEd.js.map} +1 -1
  77. package/dist/components/GrPagination/index.js +2 -2
  78. package/dist/components/GrProgressBar/chunks/{GrProgressBar-MvMnzsJl.js → GrProgressBar-hQQK8cYh.js} +1 -1
  79. package/dist/components/GrProgressBar/chunks/{GrProgressBar-MvMnzsJl.js.map → GrProgressBar-hQQK8cYh.js.map} +1 -1
  80. package/dist/components/GrProgressBar/index.js +2 -2
  81. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DKhbN6ji.js → GrPromptDialog-CUMW6_58.js} +2 -2
  82. package/dist/components/GrPromptDialog/chunks/{GrPromptDialog-DKhbN6ji.js.map → GrPromptDialog-CUMW6_58.js.map} +1 -1
  83. package/dist/components/GrPromptDialog/index.js +2 -2
  84. package/dist/components/GrRadio/chunks/{GrRadio-BxBs3WHq.js → GrRadio-B_t_ZNVl.js} +1 -1
  85. package/dist/components/GrRadio/chunks/{GrRadio-BxBs3WHq.js.map → GrRadio-B_t_ZNVl.js.map} +1 -1
  86. package/dist/components/GrRadio/index.js +2 -2
  87. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CEAfJQ6A.js → GrRadioGroup-CVlgpUBr.js} +1 -1
  88. package/dist/components/GrRadioGroup/chunks/{GrRadioGroup-CEAfJQ6A.js.map → GrRadioGroup-CVlgpUBr.js.map} +1 -1
  89. package/dist/components/GrRadioGroup/index.js +2 -2
  90. package/dist/components/GrSegmented/chunks/{GrSegmented-Bwn2qOY4.js → GrSegmented-BPl1koHc.js} +1 -1
  91. package/dist/components/GrSegmented/chunks/{GrSegmented-Bwn2qOY4.js.map → GrSegmented-BPl1koHc.js.map} +1 -1
  92. package/dist/components/GrSegmented/index.js +2 -2
  93. package/dist/components/GrSelect/chunks/{GrSelect-BMMT5MrT.js → GrSelect-C3NAfTqL.js} +2 -2
  94. package/dist/components/GrSelect/chunks/{GrSelect-BMMT5MrT.js.map → GrSelect-C3NAfTqL.js.map} +1 -1
  95. package/dist/components/GrSelect/index.js +2 -2
  96. package/dist/components/GrSidebar/chunks/{GrSidebar-CSZ3RpFB.js.map → GrSidebar-DVucgcfV.js.map} +1 -1
  97. package/dist/components/GrSidebar/index.js +2 -2
  98. package/dist/components/GrSkeleton/chunks/{GrSkeleton-DKXkqWDa.js.map → GrSkeleton-CDTvCSoH.js.map} +1 -1
  99. package/dist/components/GrSkeleton/index.js +2 -2
  100. package/dist/components/GrSwitch/chunks/{GrSwitch-CdBxwV3k.js → GrSwitch-Bnamgqb2.js} +1 -1
  101. package/dist/components/GrSwitch/chunks/{GrSwitch-CdBxwV3k.js.map → GrSwitch-Bnamgqb2.js.map} +1 -1
  102. package/dist/components/GrSwitch/index.js +2 -2
  103. package/dist/components/GrTable/index.js +1 -1
  104. package/dist/components/GrTabs/chunks/{GrTabs-BpF8AAUz.js.map → GrTabs-CiGmcmvm.js.map} +1 -1
  105. package/dist/components/GrTabs/index.js +2 -2
  106. package/dist/components/GrTextarea/chunks/{GrTextarea-DFS9ZkrA.js → GrTextarea-VBSc6A7D.js} +1 -1
  107. package/dist/components/GrTextarea/chunks/{GrTextarea-DFS9ZkrA.js.map → GrTextarea-VBSc6A7D.js.map} +1 -1
  108. package/dist/components/GrTextarea/index.js +2 -2
  109. package/dist/components/GrToaster/chunks/{GrToaster-3Mf0Moxt.js → GrToaster-I1e-zCpf.js} +1 -1
  110. package/dist/components/GrToaster/chunks/{GrToaster-3Mf0Moxt.js.map → GrToaster-I1e-zCpf.js.map} +1 -1
  111. package/dist/components/GrToaster/index.js +2 -2
  112. package/dist/components/GrTooltip/chunks/{GrTooltip-BvmsukLW.js.map → GrTooltip-CrV1gI_c.js.map} +1 -1
  113. package/dist/components/GrTooltip/index.js +2 -2
  114. package/dist/components/GrTree/chunks/{GrTree-C2kN-O4Q.js.map → GrTree-Dlev9oBd.js.map} +1 -1
  115. package/dist/components/GrTree/index.js +2 -2
  116. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-N-oPAOFj.js → GrTreeSelect-n0CZT4Ic.js} +4 -4
  117. package/dist/components/GrTreeSelect/chunks/{GrTreeSelect-N-oPAOFj.js.map → GrTreeSelect-n0CZT4Ic.js.map} +1 -1
  118. package/dist/components/GrTreeSelect/index.js +2 -2
  119. package/dist/directives/loading.js +15 -0
  120. package/dist/directives/loading.js.map +1 -1
  121. package/dist/granular-provider-node.js +2 -2
  122. package/dist/granular-provider.js +1 -1
  123. package/dist/i18n/all.js +1 -1
  124. package/dist/i18n/index.js +2 -2
  125. package/dist/index.js +59 -58
  126. package/dist/index.js.map +1 -1
  127. package/dist/types/src/components/GrFileUpload/GrFileUpload.vue.d.ts +58 -5
  128. package/dist/types/src/components/GrFileUpload/index.d.ts +4 -0
  129. package/dist/types/src/components/GrFileUpload/uploadState.d.ts +38 -0
  130. package/dist/types/src/components/GrFileUpload/uploadViaXhr.d.ts +33 -0
  131. package/dist/types/src/components/GrImageViewer/GrImageViewer.vue.d.ts +1 -1
  132. package/dist/types/src/components/GrInput/GrInput.vue.d.ts +1 -1
  133. package/dist/types/src/components/GrNumberInput/GrNumberInput.vue.d.ts +1 -1
  134. package/dist/types/src/components/GrTextarea/GrTextarea.vue.d.ts +1 -1
  135. package/package.json +1 -1
  136. package/dist/chunks/config-BGmiXpR82.js.map +0 -1
  137. package/dist/chunks/config-CA9XwYnZ2.js.map +0 -1
  138. package/dist/chunks/config-CsMIhZfM.js.map +0 -1
  139. package/dist/chunks/config-CwLoozAz2.js.map +0 -1
  140. package/dist/chunks/config-DCQO6H6h.js.map +0 -1
  141. package/dist/chunks/config-Da90XGsi.js +0 -38
  142. package/dist/chunks/config-Da90XGsi.js.map +0 -1
  143. package/dist/components/GrFileUpload/chunks/GrFileUpload-u01j9S0t.js.map +0 -1
  144. /package/dist/chunks/{adapter-K6zZTzBi.js → adapter-CRyH4YC8.js} +0 -0
  145. /package/dist/chunks/{config-Cgk5ti-b.js → config-3SftO0uG.js} +0 -0
  146. /package/dist/chunks/{config-BN-B2K4r.js → config-B44QVIge.js} +0 -0
  147. /package/dist/chunks/{config-C-GVBa19.js → config-B8rC_K97.js} +0 -0
  148. /package/dist/chunks/{config-DEv4m-ZP.js → config-BXffa3ta.js} +0 -0
  149. /package/dist/chunks/{config-CUgvsjZx.js → config-BhvNm4Pp.js} +0 -0
  150. /package/dist/chunks/{config-BNOf_qjD.js → config-C0b_3LJV.js} +0 -0
  151. /package/dist/chunks/{config-CA9XwYnZ2.js → config-C0rHS1-l.js} +0 -0
  152. /package/dist/chunks/{config-fCcRwjIB.js → config-C4qAA0Sb.js} +0 -0
  153. /package/dist/chunks/{config-XwI6t8cn.js → config-C5TN9J2Z.js} +0 -0
  154. /package/dist/chunks/{config-BGmiXpR82.js → config-CVnluhKO.js} +0 -0
  155. /package/dist/chunks/{config-DUtUkSzc.js → config-CjEplP6D.js} +0 -0
  156. /package/dist/chunks/{config-D19pyP4D.js → config-CtomKf-k.js} +0 -0
  157. /package/dist/chunks/{config-BvuQUBtZ.js → config-CxCAfXZ1.js} +0 -0
  158. /package/dist/chunks/{config-BDiLiqSk.js → config-D1DI3roo.js} +0 -0
  159. /package/dist/chunks/{config-CgjOJ3aF.js → config-D27BL0H9.js} +0 -0
  160. /package/dist/chunks/{config-DCQO6H6h.js → config-D32znLtV2.js} +0 -0
  161. /package/dist/chunks/{config-YSOeh6cy.js → config-D6Af6WZw.js} +0 -0
  162. /package/dist/chunks/{config-BulF0Bf-.js → config-D98m8iyz.js} +0 -0
  163. /package/dist/chunks/{config-CwLoozAz2.js → config-DDLoUczC.js} +0 -0
  164. /package/dist/chunks/{config-CFcv0hjb.js → config-DQOSlWvp.js} +0 -0
  165. /package/dist/chunks/{config-ndXqsz5A.js → config-DbqFk-IW.js} +0 -0
  166. /package/dist/chunks/{config-CdHY0Z7L.js → config-DnsISjD8.js} +0 -0
  167. /package/dist/chunks/{config-BFZN9-vt.js → config-DudL02ag.js} +0 -0
  168. /package/dist/chunks/{config-DgRJlF00.js → config-Dusr9jcE.js} +0 -0
  169. /package/dist/chunks/{config-CWvHiaqr2.js → config-DxqMXzNV2.js} +0 -0
  170. /package/dist/chunks/{config-CsMIhZfM.js → config-Mp9DJ9Mq2.js} +0 -0
  171. /package/dist/chunks/{config-CM7nbATU2.js → config-rxFL-6yF2.js} +0 -0
  172. /package/dist/chunks/{config-bpQYM5O-.js → config-wo-ncgTH.js} +0 -0
  173. /package/dist/chunks/{en-BeJa78lP.js → en-BMjJZttK.js} +0 -0
  174. /package/dist/chunks/{es-axYOwwWD.js → es-EYCf8G_1.js} +0 -0
  175. /package/dist/chunks/{grSelectStyles-daEeDlBn.js → grSelectStyles-DTAYNzxn.js} +0 -0
  176. /package/dist/chunks/{ru-Dqh-2C00.js → ru-DKswMSdd.js} +0 -0
  177. /package/dist/components/GrFormField/chunks/{GrFormField-C6PfAs4u.js → GrFormField-C1oWTT_0.js} +0 -0
  178. /package/dist/components/GrFormFile/chunks/{GrFormFile-DdM8Bc2B.js → GrFormFile-deDPicM2.js} +0 -0
  179. /package/dist/components/GrFormSection/chunks/{GrFormSection-5djEaQZQ.js → GrFormSection-CWBk2EUm.js} +0 -0
  180. /package/dist/components/GrImageViewer/chunks/{GrImageViewer-CjSnohW7.js → GrImageViewer-Cpj5zyZQ.js} +0 -0
  181. /package/dist/components/GrInput/chunks/{GrInput-ghxaTf6d.js → GrInput-CfO2RsM-.js} +0 -0
  182. /package/dist/components/GrList/chunks/{GrList--Ib4zLNw.js → GrList-BPjQf-72.js} +0 -0
  183. /package/dist/components/GrSidebar/chunks/{GrSidebar-CSZ3RpFB.js → GrSidebar-DVucgcfV.js} +0 -0
  184. /package/dist/components/GrSkeleton/chunks/{GrSkeleton-DKXkqWDa.js → GrSkeleton-CDTvCSoH.js} +0 -0
  185. /package/dist/components/GrTabs/chunks/{GrTabs-BpF8AAUz.js → GrTabs-CiGmcmvm.js} +0 -0
  186. /package/dist/components/GrTooltip/chunks/{GrTooltip-BvmsukLW.js → GrTooltip-CrV1gI_c.js} +0 -0
  187. /package/dist/components/GrTree/chunks/{GrTree-C2kN-O4Q.js → GrTree-Dlev9oBd.js} +0 -0
@@ -1,9 +1,18 @@
1
+ import type { GrProgressBarTone } from '../GrProgressBar/grStyle';
1
2
  import type { FileValidator, FileValidatorSource } from '../../fileValidation';
3
+ import type { GrUploadProgressInfo } from './uploadViaXhr';
4
+ import type { GrUploadState } from './uploadState';
2
5
  export type GrFileUploadExtraDataValue = string | Blob;
3
6
  export type GrFileUploadExtraData = Record<string, GrFileUploadExtraDataValue | GrFileUploadExtraDataValue[]>;
4
7
  export type GrFileUploadRequestCtx = {
5
8
  signal: AbortSignal;
6
9
  extraData?: GrFileUploadExtraData;
10
+ /**
11
+ * Колбэк прогресса аплоада. Пользовательский `request` (например, axios)
12
+ * должен вызывать его из `onUploadProgress`, чтобы `GrFileUpload` отображал
13
+ * прогресс через слот `progress` / дефолтный `GrProgressBar`.
14
+ */
15
+ onProgress?: (info: GrUploadProgressInfo) => void;
7
16
  };
8
17
  export type GrFileUploadRequest = (files: File[], ctx: GrFileUploadRequestCtx) => Promise<any>;
9
18
  /**
@@ -30,6 +39,14 @@ export interface GrFileUploadProps {
30
39
  uploadExtraData?: (files: File[]) => GrFileUploadExtraData | undefined;
31
40
  /** i18n: надпись-подсказка в дефолтном UI. */
32
41
  placeholder?: string;
42
+ /** Показывать дефолтный прогресс-бар (если не используется слот `progress`). */
43
+ showProgress?: boolean;
44
+ /** Цветовой тон полосы прогресса в фазе `uploading`. */
45
+ progressTone?: GrProgressBarTone;
46
+ /** aria-label для прогресс-бара. */
47
+ progressLabel?: string;
48
+ /** Через сколько мс после `success` скрыть прогресс-бар. `0` — не скрывать. */
49
+ hideProgressOnSuccess?: number;
33
50
  }
34
51
  declare function openDialog(): void;
35
52
  declare function abort(): void;
@@ -51,7 +68,26 @@ declare var __VLS_1: {
51
68
  text: () => Promise<string>;
52
69
  }[];
53
70
  isOver: boolean;
54
- }, __VLS_14: {}, __VLS_16: {}, __VLS_18: {};
71
+ state: GrUploadState;
72
+ }, __VLS_14: {}, __VLS_16: {}, __VLS_18: {}, __VLS_20: {
73
+ state: GrUploadState;
74
+ percent: number;
75
+ indeterminate: boolean;
76
+ phase: "success" | "error" | "idle" | "uploading";
77
+ files: {
78
+ readonly lastModified: number;
79
+ readonly name: string;
80
+ readonly webkitRelativePath: string;
81
+ readonly size: number;
82
+ readonly type: string;
83
+ arrayBuffer: () => Promise<ArrayBuffer>;
84
+ bytes: () => Promise<Uint8Array<ArrayBuffer>>;
85
+ slice: (start?: number, end?: number, contentType?: string) => Blob;
86
+ stream: () => ReadableStream<Uint8Array<ArrayBuffer>>;
87
+ text: () => Promise<string>;
88
+ }[];
89
+ abort: typeof abort;
90
+ };
55
91
  type __VLS_Slots = {} & {
56
92
  default?: (props: typeof __VLS_1) => any;
57
93
  } & {
@@ -60,6 +96,8 @@ type __VLS_Slots = {} & {
60
96
  default?: (props: typeof __VLS_16) => any;
61
97
  } & {
62
98
  tip?: (props: typeof __VLS_18) => any;
99
+ } & {
100
+ progress?: (props: typeof __VLS_20) => any;
63
101
  };
64
102
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrFileUploadProps>, {
65
103
  action: undefined;
@@ -76,15 +114,21 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
76
114
  showFileList: boolean;
77
115
  uploadExtraData: undefined;
78
116
  placeholder: string;
117
+ showProgress: boolean;
118
+ progressTone: string;
119
+ progressLabel: string;
120
+ hideProgressOnSuccess: number;
79
121
  }>>, {
80
122
  uploadFiles: typeof handleFiles;
81
123
  abort: typeof abort;
82
124
  openDialog: typeof openDialog;
125
+ state: GrUploadState;
83
126
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
84
127
  success: (payload: any) => void;
85
128
  error: (error: unknown) => void;
86
- progress: (percent: number) => void;
129
+ progress: (percent: number, info?: GrUploadProgressInfo | undefined) => void;
87
130
  change: (files: File[]) => void;
131
+ "state-change": (state: GrUploadState) => void;
88
132
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<GrFileUploadProps>, {
89
133
  action: undefined;
90
134
  request: undefined;
@@ -100,14 +144,21 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
100
144
  showFileList: boolean;
101
145
  uploadExtraData: undefined;
102
146
  placeholder: string;
147
+ showProgress: boolean;
148
+ progressTone: string;
149
+ progressLabel: string;
150
+ hideProgressOnSuccess: number;
103
151
  }>>> & Readonly<{
104
152
  onSuccess?: ((payload: any) => any) | undefined;
105
- onProgress?: ((percent: number) => any) | undefined;
153
+ onProgress?: ((percent: number, info?: GrUploadProgressInfo | undefined) => any) | undefined;
106
154
  onChange?: ((files: File[]) => any) | undefined;
107
155
  onError?: ((error: unknown) => any) | undefined;
156
+ "onState-change"?: ((state: GrUploadState) => any) | undefined;
108
157
  }>, {
109
158
  disabled: boolean;
110
159
  name: string;
160
+ headers: Record<string, string>;
161
+ withCredentials: boolean;
111
162
  action: string;
112
163
  request: GrFileUploadRequest;
113
164
  multiple: boolean;
@@ -115,11 +166,13 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
115
166
  onExceed: (files: File[], limit: number) => void;
116
167
  beforeUpload: (file: File) => boolean | Promise<unknown>;
117
168
  validators: FileValidator[];
118
- headers: Record<string, string>;
119
- withCredentials: boolean;
120
169
  showFileList: boolean;
121
170
  uploadExtraData: (files: File[]) => GrFileUploadExtraData | undefined;
122
171
  placeholder: string;
172
+ showProgress: boolean;
173
+ progressTone: GrProgressBarTone;
174
+ progressLabel: string;
175
+ hideProgressOnSuccess: number;
123
176
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
124
177
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
125
178
  declare const _default: typeof __VLS_export;
@@ -2,4 +2,8 @@ export { default } from './GrFileUpload.vue';
2
2
  export { default as GrFileUpload } from './GrFileUpload.vue';
3
3
  export type { GrFileUploadExtraData, GrFileUploadExtraDataValue, GrFileUploadProps, GrFileUploadRequest, GrFileUploadRequestCtx, } from './GrFileUpload.vue';
4
4
  export { grFileUploadConfig } from './config';
5
+ export type { GrUploadProgressInfo } from './uploadViaXhr';
6
+ export { GrUploadAbortError, GrUploadHttpError } from './uploadViaXhr';
7
+ export type { GrUploadPhase, GrUploadState, GrUploadStateError, GrUploadStateIdle, GrUploadStateSuccess, GrUploadStateUploading, } from './uploadState';
8
+ export { GR_UPLOAD_STATE_IDLE } from './uploadState';
5
9
  export * from '../../fileValidation';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Состояние процесса загрузки в `GrFileUpload`.
3
+ *
4
+ * Используется как для внутреннего управления UI, так и пробрасывается наружу
5
+ * через scoped-слоты (`progress`, `default`) и `defineExpose`.
6
+ */
7
+ export type GrUploadPhase = 'idle' | 'uploading' | 'success' | 'error';
8
+ export interface GrUploadStateIdle {
9
+ phase: 'idle';
10
+ percent: 0;
11
+ indeterminate: false;
12
+ loaded: 0;
13
+ total: 0;
14
+ }
15
+ export interface GrUploadStateUploading {
16
+ phase: 'uploading';
17
+ percent: number;
18
+ indeterminate: boolean;
19
+ loaded: number;
20
+ total: number;
21
+ }
22
+ export interface GrUploadStateSuccess {
23
+ phase: 'success';
24
+ percent: 100;
25
+ indeterminate: false;
26
+ loaded: number;
27
+ total: number;
28
+ }
29
+ export interface GrUploadStateError {
30
+ phase: 'error';
31
+ percent: number;
32
+ indeterminate: false;
33
+ loaded: number;
34
+ total: number;
35
+ error: unknown;
36
+ }
37
+ export type GrUploadState = GrUploadStateIdle | GrUploadStateUploading | GrUploadStateSuccess | GrUploadStateError;
38
+ export declare const GR_UPLOAD_STATE_IDLE: GrUploadStateIdle;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Загрузка файлов через `XMLHttpRequest` с поддержкой прогресса аплоада и
3
+ * отмены по `AbortSignal`. Используется в `GrFileUpload` для ветки `action`,
4
+ * а также может применяться пользователем напрямую в `request`-загрузчике.
5
+ */
6
+ export type GrUploadExtraDataValue = string | Blob;
7
+ export type GrUploadExtraData = Record<string, GrUploadExtraDataValue | GrUploadExtraDataValue[]>;
8
+ export interface GrUploadProgressInfo {
9
+ /** Процент `0..100`. Для запросов без `lengthComputable` значение `0` и `indeterminate = true`. */
10
+ percent: number;
11
+ loaded: number;
12
+ total: number;
13
+ indeterminate: boolean;
14
+ }
15
+ export interface UploadViaXhrOptions {
16
+ url: string;
17
+ files: File[];
18
+ name: string;
19
+ headers?: Record<string, string>;
20
+ withCredentials?: boolean;
21
+ extraData?: GrUploadExtraData;
22
+ signal: AbortSignal;
23
+ onProgress?: (info: GrUploadProgressInfo) => void;
24
+ }
25
+ export declare class GrUploadAbortError extends Error {
26
+ constructor(message?: string);
27
+ }
28
+ export declare class GrUploadHttpError extends Error {
29
+ status: number;
30
+ payload: unknown;
31
+ constructor(status: number, payload: unknown);
32
+ }
33
+ export declare function uploadViaXhr(options: UploadViaXhrOptions): Promise<unknown>;
@@ -121,13 +121,13 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
121
121
  }>, {
122
122
  closeLabel: string;
123
123
  zIndex: number;
124
+ showProgress: boolean;
124
125
  initialIndex: number;
125
126
  zoomRate: number;
126
127
  minScale: number;
127
128
  maxScale: number;
128
129
  hideOnClickModal: boolean;
129
130
  closeOnPressEscape: boolean;
130
- showProgress: boolean;
131
131
  showZoomValue: boolean;
132
132
  prevLabel: string;
133
133
  nextLabel: string;
@@ -72,9 +72,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
72
72
  id: string;
73
73
  invalid: boolean;
74
74
  placeholder: string;
75
+ state: "default" | "success" | "warning" | "danger";
75
76
  inputmode: "text" | "search" | "none" | "email" | "tel" | "url" | "numeric" | "decimal";
76
77
  autocomplete: string;
77
- state: "default" | "success" | "warning" | "danger";
78
78
  textAlign: GrInputTextAlign;
79
79
  prefixMinWidth: string;
80
80
  prefixMaxWidth: string;
@@ -103,9 +103,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
103
103
  invalid: boolean;
104
104
  min: number;
105
105
  placeholder: string;
106
+ state: GrNumberInputState;
106
107
  inputmode: "text" | "search" | "none" | "email" | "tel" | "url" | "numeric" | "decimal";
107
108
  autocomplete: string;
108
- state: GrNumberInputState;
109
109
  textAlign: GrNumberInputTextAlign;
110
110
  prefixMinWidth: string;
111
111
  prefixMaxWidth: string;
@@ -55,8 +55,8 @@ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractP
55
55
  rows: number;
56
56
  invalid: boolean;
57
57
  placeholder: string;
58
- autocomplete: string;
59
58
  state: GrTextareaState;
59
+ autocomplete: string;
60
60
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
61
61
  declare const _default: typeof __VLS_export;
62
62
  export default _default;
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.5.1",
4
+ "version": "0.6.2",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": {
7
7
  "name": "Evgeniy Fureev",
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-BGmiXpR82.js","names":[],"sources":["../../src/components/GrFileUpload/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nexport const grFileUploadConfig = defineGranularComponent(import.meta.url, {\n name: 'GrFileUpload',\n dependencies: ['GrIcon'],\n})\n"],"mappings":";;AAEA,IAAa,qBAAqB,wBAAwB,OAAO,KAAK,KAAK;CACzE,MAAM;CACN,cAAc,CAAC,SAAS;CACzB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-CA9XwYnZ2.js","names":[],"sources":["../../src/components/GrTooltip/config.ts"],"sourcesContent":["import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nexport const grTooltipConfig = defineGranularComponent(import.meta.url, {\n name: 'GrTooltip',\n dependencies: ['GrIcon'],\n})\n"],"mappings":";;AAEA,IAAa,kBAAkB,wBAAwB,OAAO,KAAK,KAAK;CACpE,MAAM;CACN,cAAc,CAAC,SAAS;CAC3B,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-CsMIhZfM.js","names":[],"sources":["../../src/components/GrSkeleton/config.ts"],"sourcesContent":["import { defineGranularComponent } from '@feugene/unocss-preset-granular/contract'\n\nexport const grSkeletonConfig = defineGranularComponent(import.meta.url, {\n name: 'GrSkeleton',\n})\n"],"mappings":";;AAEA,IAAa,mBAAmB,wBAAwB,OAAO,KAAK,KAAK,EACvE,MAAM,cACP,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-CwLoozAz2.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-DCQO6H6h.js","names":[],"sources":["../../src/components/GrTree/safelist.ts","../../src/components/GrTree/config.ts"],"sourcesContent":["// Только динамические значения иконок-пропов (`expandIcon`/`collapseIcon`/`dragHandleIcon`).\n// Литералы шаблона (`py-2`, `px-2`, `ml-6`, ...) не дублируем — UnoCSS находит их сканом.\nexport const grTreeSafelist = [\n 'i-lucide-chevron-right',\n 'i-lucide-grip-vertical',\n] as const","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grTreeSafelist } from './safelist'\n\nexport const grTreeConfig = defineGranularComponent(import.meta.url, {\n name: 'GrTree',\n safelist: grTreeSafelist,\n})"],"mappings":";;AAEA,IAAa,iBAAiB,CAC5B,0BACA,yBACD;;;ACDD,IAAa,eAAe,wBAAwB,OAAO,KAAK,KAAK;CACnE,MAAM;CACN,UAAU;CACX,CAAA"}
@@ -1,38 +0,0 @@
1
- import { t as splitClassTokens } from "./classTokens-BPeBXNzu.js";
2
- import { defineGranularComponent } from "@feugene/unocss-preset-granular/contract";
3
- //#region src/components/GrProgressBar/grStyle.ts
4
- function withVar(token) {
5
- return `[${token}]`;
6
- }
7
- var toneVars = {
8
- primary: "var(--pb-bg,var(--primary))",
9
- neutral: "var(--pb-neutral-bg,var(--secondary))",
10
- success: "var(--pb-success-bg,var(--ds-success))",
11
- warning: "var(--pb-warning-bg,var(--ds-warning))",
12
- danger: "var(--pb-danger-bg,var(--ds-danger))",
13
- info: "var(--pb-info-bg,var(--ds-info))",
14
- slate: "var(--pb-slate-bg,var(--ds-slate))",
15
- azure: "var(--pb-azure-bg,var(--ds-azure))"
16
- };
17
- function grProgressBarFillClass(tone) {
18
- return `bg-${withVar(toneVars[tone])}`;
19
- }
20
- var grProgressBarClassTokens = { fill: [
21
- "primary",
22
- "neutral",
23
- "success",
24
- "warning",
25
- "danger",
26
- "info",
27
- "slate",
28
- "azure"
29
- ].flatMap((tone) => splitClassTokens(grProgressBarFillClass(tone))) };
30
- var grProgressBarSafelist = [...new Set([...grProgressBarClassTokens.fill])];
31
- //#endregion
32
- //#region src/components/GrProgressBar/config.ts
33
- var grProgressBarConfig = defineGranularComponent(import.meta.url, {
34
- name: "GrProgressBar",
35
- safelist: grProgressBarSafelist
36
- });
37
- //#endregion
38
- export { grProgressBarSafelist as n, grProgressBarFillClass as r, grProgressBarConfig as t };
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-Da90XGsi.js","names":[],"sources":["../../src/components/GrProgressBar/grStyle.ts","../../src/components/GrProgressBar/safelist.ts","../../src/components/GrProgressBar/config.ts"],"sourcesContent":["import type { GrTone } from '../shared/tones'\n\nexport type GrProgressBarTone = GrTone\n\nfunction withVar(token: string): string {\n return `[${token}]`\n}\n\nconst toneVars: Record<GrProgressBarTone, string> = {\n primary: 'var(--pb-bg,var(--primary))',\n neutral: 'var(--pb-neutral-bg,var(--secondary))',\n success: 'var(--pb-success-bg,var(--ds-success))',\n warning: 'var(--pb-warning-bg,var(--ds-warning))',\n danger: 'var(--pb-danger-bg,var(--ds-danger))',\n info: 'var(--pb-info-bg,var(--ds-info))',\n slate: 'var(--pb-slate-bg,var(--ds-slate))',\n azure: 'var(--pb-azure-bg,var(--ds-azure))',\n}\n\nexport function grProgressBarFillClass(tone: GrProgressBarTone): string {\n return `bg-${withVar(toneVars[tone])}`\n}\n","import { splitClassTokens } from '../shared/classTokens'\nimport { grProgressBarFillClass, type GrProgressBarTone } from './grStyle'\n\nconst TONES: GrProgressBarTone[] = ['primary', 'neutral', 'success', 'warning', 'danger', 'info', 'slate', 'azure']\n\nconst fillTokens = TONES.flatMap(tone => splitClassTokens(grProgressBarFillClass(tone)))\n\nexport const grProgressBarClassTokens = {\n fill: fillTokens,\n} as const\n\nexport const grProgressBarSafelist = [...new Set([\n ...grProgressBarClassTokens.fill,\n])] as const\n","import {defineGranularComponent} from '@feugene/unocss-preset-granular/contract'\n\nimport { grProgressBarSafelist } from './safelist'\n\nexport const grProgressBarConfig = defineGranularComponent(import.meta.url, {\n name: 'GrProgressBar',\n safelist: grProgressBarSafelist,\n})"],"mappings":";;;AAIA,SAAS,QAAQ,OAAuB;AACtC,QAAO,IAAI,MAAM;;AAGnB,IAAM,WAA8C;CAClD,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CACN,OAAO;CACP,OAAO;CACR;AAED,SAAgB,uBAAuB,MAAiC;AACtE,QAAO,MAAM,QAAQ,SAAS,MAAM;;ACbtC,IAAa,2BAA2B,EACtC,MALiC;CAAC;CAAW;CAAW;CAAW;CAAW;CAAU;CAAQ;CAAS;CAAQ,CAE1F,SAAQ,SAAQ,iBAAiB,uBAAuB,KAAK,CAAC,CAAC,EAIvF;AAED,IAAa,wBAAwB,CAAC,GAAG,IAAI,IAAI,CAC/C,GAAG,yBAAyB,KAC7B,CAAC,CAAC;;;ACTH,IAAa,sBAAsB,wBAAwB,OAAO,KAAK,KAAK;CAC1E,MAAM;CACN,UAAU;CACX,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"GrFileUpload-u01j9S0t.js","names":["$slots"],"sources":["../../../../src/components/GrFileUpload/GrFileUpload.vue","../../../../src/components/GrFileUpload/GrFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { Comment, computed, Fragment, nextTick, ref, Text, useSlots, type VNode } from 'vue'\n\nimport IconArrowUp from '~icons/lucide/arrow-up'\n\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport type { FileValidator, FileValidatorSource } from '../../fileValidation'\n\nimport { FileValidationError, runFileValidators } from '../../fileValidation'\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\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}\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 },\n)\n\nconst emit = defineEmits<{\n (e: 'success', payload: any): void\n (e: 'error', error: unknown): void\n (e: 'progress', percent: number): void\n (e: 'change', files: File[]): 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\nlet activeController: AbortController | null = null\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\nfunction appendExtraFormData(body: FormData, extraData: GrFileUploadExtraData | 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\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 const body = new FormData()\n for (const file of files)\n body.append(props.name, file)\n\n appendExtraFormData(body, extraData)\n\n const response = await fetch(props.action, {\n method: 'POST',\n headers: props.headers,\n body,\n signal,\n credentials: props.withCredentials ? 'include' : 'same-origin',\n })\n\n const contentType = response.headers.get('content-type')\n const payload = contentType?.includes('application/json') ? await response.json() : await response.text()\n\n if (!response.ok) {\n const error = new Error(`Upload failed with status ${response.status}`)\n ;(error as any).payload = payload\n ;(error as any).status = response.status\n throw error\n }\n\n return payload\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\n const controller = new AbortController()\n activeController = controller\n\n emit('progress', 0)\n\n try {\n const payload = props.request\n ? await props.request(valid, { signal: controller.signal, extraData })\n : await uploadViaAction(valid, controller.signal, extraData)\n\n emit('success', payload)\n emit('change', valid)\n emit('progress', 100)\n } catch (error) {\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\ndefineExpose({\n uploadFiles: handleFiles,\n abort,\n openDialog,\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 />\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 </div>\n </div>\n </div>\n</template>","<script setup lang=\"ts\">\nimport { Comment, computed, Fragment, nextTick, ref, Text, useSlots, type VNode } from 'vue'\n\nimport IconArrowUp from '~icons/lucide/arrow-up'\n\nimport GrIcon from '../GrIcon/GrIcon.vue'\nimport type { FileValidator, FileValidatorSource } from '../../fileValidation'\n\nimport { FileValidationError, runFileValidators } from '../../fileValidation'\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\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}\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 },\n)\n\nconst emit = defineEmits<{\n (e: 'success', payload: any): void\n (e: 'error', error: unknown): void\n (e: 'progress', percent: number): void\n (e: 'change', files: File[]): 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\nlet activeController: AbortController | null = null\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\nfunction appendExtraFormData(body: FormData, extraData: GrFileUploadExtraData | 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\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 const body = new FormData()\n for (const file of files)\n body.append(props.name, file)\n\n appendExtraFormData(body, extraData)\n\n const response = await fetch(props.action, {\n method: 'POST',\n headers: props.headers,\n body,\n signal,\n credentials: props.withCredentials ? 'include' : 'same-origin',\n })\n\n const contentType = response.headers.get('content-type')\n const payload = contentType?.includes('application/json') ? await response.json() : await response.text()\n\n if (!response.ok) {\n const error = new Error(`Upload failed with status ${response.status}`)\n ;(error as any).payload = payload\n ;(error as any).status = response.status\n throw error\n }\n\n return payload\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\n const controller = new AbortController()\n activeController = controller\n\n emit('progress', 0)\n\n try {\n const payload = props.request\n ? await props.request(valid, { signal: controller.signal, extraData })\n : await uploadViaAction(valid, controller.signal, extraData)\n\n emit('success', payload)\n emit('change', valid)\n emit('progress', 100)\n } catch (error) {\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\ndefineExpose({\n uploadFiles: handleFiles,\n abort,\n openDialog,\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 />\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 </div>\n </div>\n </div>\n</template>"],"mappings":"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"}
File without changes
File without changes
File without changes