vxe-pc-ui 4.14.6 → 4.14.7

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 (611) hide show
  1. package/LICENSE +21 -21
  2. package/README.en.md +72 -72
  3. package/README.ja-JP.md +72 -72
  4. package/README.md +364 -364
  5. package/README.zh-TW.md +73 -73
  6. package/es/checkbox/src/button.js +26 -5
  7. package/es/checkbox/src/checkbox.js +26 -5
  8. package/es/checkbox/src/group.js +23 -3
  9. package/es/checkbox/style.css +6 -3
  10. package/es/checkbox/style.min.css +1 -1
  11. package/es/language/ar-EG.js +4 -0
  12. package/es/language/de-DE.js +4 -0
  13. package/es/language/en-US.js +4 -0
  14. package/es/language/es-ES.js +4 -0
  15. package/es/language/fr-FR.js +4 -0
  16. package/es/language/hu-HU.js +4 -0
  17. package/es/language/hy-AM.js +4 -0
  18. package/es/language/id-ID.js +4 -0
  19. package/es/language/it-IT.js +4 -0
  20. package/es/language/ja-JP.js +4 -0
  21. package/es/language/ko-KR.js +4 -0
  22. package/es/language/ms-MY.js +4 -0
  23. package/es/language/nb-NO.js +4 -0
  24. package/es/language/pt-BR.js +4 -0
  25. package/es/language/ru-RU.js +4 -0
  26. package/es/language/th-TH.js +4 -0
  27. package/es/language/ug-CN.js +4 -0
  28. package/es/language/uk-UA.js +4 -0
  29. package/es/language/uz-UZ.js +4 -0
  30. package/es/language/vi-VN.js +4 -0
  31. package/es/language/zh-CHT.js +4 -0
  32. package/es/language/zh-CN.js +4 -0
  33. package/es/radio/src/button.js +27 -5
  34. package/es/radio/src/group.js +17 -2
  35. package/es/radio/src/radio.js +27 -5
  36. package/es/radio/style.css +5 -3
  37. package/es/radio/style.min.css +1 -1
  38. package/es/style.css +1 -1
  39. package/es/style.min.css +1 -1
  40. package/es/switch/src/switch.js +19 -11
  41. package/es/tree/style.css +11 -6
  42. package/es/tree/style.min.css +1 -1
  43. package/es/ui/index.js +1 -1
  44. package/es/ui/src/log.js +1 -1
  45. package/es/vxe-checkbox/style.css +6 -3
  46. package/es/vxe-checkbox/style.min.css +1 -1
  47. package/es/vxe-radio/style.css +5 -3
  48. package/es/vxe-radio/style.min.css +1 -1
  49. package/es/vxe-tree/style.css +11 -6
  50. package/es/vxe-tree/style.min.css +1 -1
  51. package/lib/checkbox/src/button.js +26 -3
  52. package/lib/checkbox/src/button.min.js +1 -1
  53. package/lib/checkbox/src/checkbox.js +26 -3
  54. package/lib/checkbox/src/checkbox.min.js +1 -1
  55. package/lib/checkbox/src/group.js +25 -3
  56. package/lib/checkbox/src/group.min.js +1 -1
  57. package/lib/checkbox/style/style.css +6 -3
  58. package/lib/checkbox/style/style.min.css +1 -1
  59. package/lib/index.umd.js +2446 -2376
  60. package/lib/index.umd.min.js +1 -1
  61. package/lib/language/ar-EG.js +4 -0
  62. package/lib/language/ar-EG.min.js +1 -1
  63. package/lib/language/ar-EG.umd.js +4 -0
  64. package/lib/language/de-DE.js +4 -0
  65. package/lib/language/de-DE.min.js +1 -1
  66. package/lib/language/de-DE.umd.js +4 -0
  67. package/lib/language/en-US.js +4 -0
  68. package/lib/language/en-US.min.js +1 -1
  69. package/lib/language/en-US.umd.js +4 -0
  70. package/lib/language/es-ES.js +4 -0
  71. package/lib/language/es-ES.min.js +1 -1
  72. package/lib/language/es-ES.umd.js +4 -0
  73. package/lib/language/fr-FR.js +4 -0
  74. package/lib/language/fr-FR.min.js +1 -1
  75. package/lib/language/fr-FR.umd.js +4 -0
  76. package/lib/language/hu-HU.js +4 -0
  77. package/lib/language/hu-HU.min.js +1 -1
  78. package/lib/language/hu-HU.umd.js +4 -0
  79. package/lib/language/hy-AM.js +4 -0
  80. package/lib/language/hy-AM.min.js +1 -1
  81. package/lib/language/hy-AM.umd.js +4 -0
  82. package/lib/language/id-ID.js +4 -0
  83. package/lib/language/id-ID.min.js +1 -1
  84. package/lib/language/id-ID.umd.js +4 -0
  85. package/lib/language/it-IT.js +4 -0
  86. package/lib/language/it-IT.min.js +1 -1
  87. package/lib/language/it-IT.umd.js +4 -0
  88. package/lib/language/ja-JP.js +4 -0
  89. package/lib/language/ja-JP.min.js +1 -1
  90. package/lib/language/ja-JP.umd.js +4 -0
  91. package/lib/language/ko-KR.js +4 -0
  92. package/lib/language/ko-KR.min.js +1 -1
  93. package/lib/language/ko-KR.umd.js +4 -0
  94. package/lib/language/ms-MY.js +4 -0
  95. package/lib/language/ms-MY.min.js +1 -1
  96. package/lib/language/ms-MY.umd.js +4 -0
  97. package/lib/language/nb-NO.js +4 -0
  98. package/lib/language/nb-NO.min.js +1 -1
  99. package/lib/language/nb-NO.umd.js +4 -0
  100. package/lib/language/pt-BR.js +4 -0
  101. package/lib/language/pt-BR.min.js +1 -1
  102. package/lib/language/pt-BR.umd.js +4 -0
  103. package/lib/language/ru-RU.js +4 -0
  104. package/lib/language/ru-RU.min.js +1 -1
  105. package/lib/language/ru-RU.umd.js +4 -0
  106. package/lib/language/th-TH.js +4 -0
  107. package/lib/language/th-TH.min.js +1 -1
  108. package/lib/language/th-TH.umd.js +4 -0
  109. package/lib/language/ug-CN.js +4 -0
  110. package/lib/language/ug-CN.min.js +1 -1
  111. package/lib/language/ug-CN.umd.js +4 -0
  112. package/lib/language/uk-UA.js +4 -0
  113. package/lib/language/uk-UA.min.js +1 -1
  114. package/lib/language/uk-UA.umd.js +4 -0
  115. package/lib/language/uz-UZ.js +4 -0
  116. package/lib/language/uz-UZ.min.js +1 -1
  117. package/lib/language/uz-UZ.umd.js +4 -0
  118. package/lib/language/vi-VN.js +4 -0
  119. package/lib/language/vi-VN.min.js +1 -1
  120. package/lib/language/vi-VN.umd.js +4 -0
  121. package/lib/language/zh-CHT.js +4 -0
  122. package/lib/language/zh-CHT.min.js +1 -1
  123. package/lib/language/zh-CHT.umd.js +4 -0
  124. package/lib/language/zh-CN.js +4 -0
  125. package/lib/language/zh-CN.min.js +1 -1
  126. package/lib/language/zh-CN.umd.js +4 -0
  127. package/lib/radio/src/button.js +27 -3
  128. package/lib/radio/src/button.min.js +1 -1
  129. package/lib/radio/src/group.js +19 -2
  130. package/lib/radio/src/group.min.js +1 -1
  131. package/lib/radio/src/radio.js +27 -3
  132. package/lib/radio/src/radio.min.js +1 -1
  133. package/lib/radio/style/style.css +5 -3
  134. package/lib/radio/style/style.min.css +1 -1
  135. package/lib/style.css +1 -1
  136. package/lib/style.min.css +1 -1
  137. package/lib/switch/src/switch.js +18 -10
  138. package/lib/switch/src/switch.min.js +1 -1
  139. package/lib/tree/style/style.css +11 -6
  140. package/lib/tree/style/style.min.css +1 -1
  141. package/lib/ui/index.js +1 -1
  142. package/lib/ui/index.min.js +1 -1
  143. package/lib/ui/src/log.js +1 -1
  144. package/lib/ui/src/log.min.js +1 -1
  145. package/lib/vxe-checkbox/style/style.css +6 -3
  146. package/lib/vxe-checkbox/style/style.min.css +1 -1
  147. package/lib/vxe-radio/style/style.css +5 -3
  148. package/lib/vxe-radio/style/style.min.css +1 -1
  149. package/lib/vxe-tree/style/style.css +11 -6
  150. package/lib/vxe-tree/style/style.min.css +1 -1
  151. package/package.json +88 -88
  152. package/packages/alert/index.ts +16 -16
  153. package/packages/alert/src/alert.ts +124 -124
  154. package/packages/anchor/index.ts +16 -16
  155. package/packages/anchor/src/anchor-link.ts +121 -121
  156. package/packages/anchor/src/anchor.ts +237 -237
  157. package/packages/anchor/src/util.ts +23 -23
  158. package/packages/anchor-link/index.ts +16 -16
  159. package/packages/avatar/index.ts +16 -16
  160. package/packages/avatar/src/avatar.ts +149 -149
  161. package/packages/backtop/index.ts +16 -16
  162. package/packages/backtop/src/backtop.ts +314 -314
  163. package/packages/badge/index.ts +16 -16
  164. package/packages/badge/src/badge.ts +100 -100
  165. package/packages/breadcrumb/index.ts +16 -16
  166. package/packages/breadcrumb/src/breadcrumb-item.ts +106 -106
  167. package/packages/breadcrumb/src/breadcrumb.ts +92 -92
  168. package/packages/breadcrumb-item/index.ts +16 -16
  169. package/packages/button/index.ts +16 -16
  170. package/packages/button/src/button-group.ts +110 -110
  171. package/packages/button/src/button.ts +841 -841
  172. package/packages/button-group/index.ts +16 -16
  173. package/packages/calendar/index.ts +16 -16
  174. package/packages/calendar/src/calendar.ts +1351 -1351
  175. package/packages/card/index.ts +16 -16
  176. package/packages/card/src/card.ts +175 -175
  177. package/packages/carousel/index.ts +16 -16
  178. package/packages/carousel/src/carousel-item.ts +102 -102
  179. package/packages/carousel/src/carousel.ts +414 -414
  180. package/packages/carousel/src/util.ts +21 -21
  181. package/packages/carousel-item/index.ts +16 -16
  182. package/packages/cascader/index.ts +16 -16
  183. package/packages/cascader/src/cascader.ts +741 -741
  184. package/packages/checkbox/index.ts +16 -16
  185. package/packages/checkbox/src/button.ts +165 -144
  186. package/packages/checkbox/src/checkbox.ts +176 -154
  187. package/packages/checkbox/src/group.ts +243 -222
  188. package/packages/checkbox-button/index.ts +16 -16
  189. package/packages/checkbox-group/index.ts +16 -16
  190. package/packages/col/index.ts +16 -16
  191. package/packages/collapse/index.ts +16 -16
  192. package/packages/collapse/src/collapse-pane.ts +114 -114
  193. package/packages/collapse/src/collapse.ts +284 -284
  194. package/packages/collapse/src/util.ts +21 -21
  195. package/packages/collapse-pane/index.ts +16 -16
  196. package/packages/color-picker/index.ts +16 -16
  197. package/packages/color-picker/src/color-picker.ts +1109 -1109
  198. package/packages/color-picker/src/util.ts +198 -198
  199. package/packages/components.ts +307 -307
  200. package/packages/context-menu/index.ts +54 -54
  201. package/packages/context-menu/src/context-menu.ts +681 -681
  202. package/packages/countdown/index.ts +16 -16
  203. package/packages/countdown/src/countdown.ts +262 -262
  204. package/packages/date-panel/index.ts +16 -16
  205. package/packages/date-panel/src/date-panel.ts +1809 -1809
  206. package/packages/date-panel/src/util.ts +244 -244
  207. package/packages/date-picker/index.ts +16 -16
  208. package/packages/date-picker/src/date-picker.ts +1071 -1071
  209. package/packages/date-range-picker/index.ts +16 -16
  210. package/packages/date-range-picker/src/date-range-picker.ts +1280 -1280
  211. package/packages/drawer/index.ts +77 -77
  212. package/packages/drawer/src/drawer.ts +657 -657
  213. package/packages/dynamics/index.ts +89 -89
  214. package/packages/empty/index.ts +16 -16
  215. package/packages/empty/src/empty.ts +100 -100
  216. package/packages/form/index.ts +16 -16
  217. package/packages/form/render/index.ts +598 -598
  218. package/packages/form/src/form-config-item.ts +72 -72
  219. package/packages/form/src/form-group.ts +86 -86
  220. package/packages/form/src/form-item.ts +174 -174
  221. package/packages/form/src/form.ts +987 -987
  222. package/packages/form/src/itemInfo.ts +80 -80
  223. package/packages/form/src/render.ts +387 -387
  224. package/packages/form/src/util.ts +93 -93
  225. package/packages/form-gather/index.ts +26 -26
  226. package/packages/form-group/index.ts +16 -16
  227. package/packages/form-item/index.ts +16 -16
  228. package/packages/icon/index.ts +16 -16
  229. package/packages/icon/src/icon.ts +75 -75
  230. package/packages/icon-picker/index.ts +16 -16
  231. package/packages/icon-picker/src/icon-picker.ts +626 -626
  232. package/packages/image/index.ts +16 -16
  233. package/packages/image/src/group.ts +153 -153
  234. package/packages/image/src/image.ts +298 -298
  235. package/packages/image/src/preview.ts +672 -672
  236. package/packages/image/src/util.ts +59 -59
  237. package/packages/image-group/index.ts +16 -16
  238. package/packages/image-preview/index.ts +19 -19
  239. package/packages/index.ts +4 -4
  240. package/packages/input/index.ts +16 -16
  241. package/packages/input/src/input.ts +2788 -2788
  242. package/packages/language/ar-EG.ts +844 -840
  243. package/packages/language/de-DE.ts +844 -840
  244. package/packages/language/en-US.ts +844 -840
  245. package/packages/language/es-ES.ts +844 -840
  246. package/packages/language/fr-FR.ts +844 -840
  247. package/packages/language/hu-HU.ts +844 -840
  248. package/packages/language/hy-AM.ts +844 -840
  249. package/packages/language/id-ID.ts +844 -840
  250. package/packages/language/it-IT.ts +844 -840
  251. package/packages/language/ja-JP.ts +844 -840
  252. package/packages/language/ko-KR.ts +844 -840
  253. package/packages/language/ms-MY.ts +844 -840
  254. package/packages/language/nb-NO.ts +844 -840
  255. package/packages/language/pt-BR.ts +844 -840
  256. package/packages/language/ru-RU.ts +844 -840
  257. package/packages/language/th-TH.ts +844 -840
  258. package/packages/language/ug-CN.ts +844 -840
  259. package/packages/language/uk-UA.ts +844 -840
  260. package/packages/language/uz-UZ.ts +844 -840
  261. package/packages/language/vi-VN.ts +844 -840
  262. package/packages/language/zh-CHT.ts +844 -840
  263. package/packages/language/zh-CN.ts +844 -840
  264. package/packages/language/zh-HK.ts +3 -3
  265. package/packages/language/zh-MO.ts +3 -3
  266. package/packages/language/zh-TC.ts +3 -3
  267. package/packages/language/zh-TW.ts +3 -3
  268. package/packages/layout-aside/index.ts +16 -16
  269. package/packages/layout-aside/src/layout-aside.ts +123 -123
  270. package/packages/layout-body/index.ts +16 -16
  271. package/packages/layout-body/src/layout-body.ts +142 -142
  272. package/packages/layout-container/index.ts +16 -16
  273. package/packages/layout-container/src/layout-container.ts +82 -82
  274. package/packages/layout-footer/index.ts +16 -16
  275. package/packages/layout-footer/src/layout-footer.ts +74 -74
  276. package/packages/layout-header/index.ts +16 -16
  277. package/packages/layout-header/src/layout-header.ts +73 -73
  278. package/packages/link/index.ts +16 -16
  279. package/packages/link/src/link.ts +161 -161
  280. package/packages/list/index.ts +16 -16
  281. package/packages/list/src/list.ts +442 -442
  282. package/packages/loading/index.ts +34 -34
  283. package/packages/loading/src/loading.ts +152 -152
  284. package/packages/mention/index.ts +16 -16
  285. package/packages/mention/src/mention.ts +71 -71
  286. package/packages/menu/index.ts +16 -16
  287. package/packages/menu/src/menu.ts +581 -581
  288. package/packages/modal/index.ts +136 -136
  289. package/packages/modal/src/modal.ts +1494 -1494
  290. package/packages/notice-bar/index.ts +16 -16
  291. package/packages/notice-bar/src/notice-bar.ts +181 -181
  292. package/packages/number-input/index.ts +16 -16
  293. package/packages/number-input/src/number-input.ts +1096 -1096
  294. package/packages/number-input/src/util.ts +12 -12
  295. package/packages/optgroup/index.ts +16 -16
  296. package/packages/option/index.ts +16 -16
  297. package/packages/pager/index.ts +16 -16
  298. package/packages/pager/src/pager.ts +769 -769
  299. package/packages/password-input/index.ts +16 -16
  300. package/packages/password-input/src/password-input.ts +378 -378
  301. package/packages/print/index.ts +18 -18
  302. package/packages/print/src/page-break.ts +92 -92
  303. package/packages/print/src/print.ts +272 -272
  304. package/packages/print/src/util.ts +284 -284
  305. package/packages/print-page-break/index.ts +16 -16
  306. package/packages/pulldown/index.ts +16 -16
  307. package/packages/pulldown/src/pulldown.ts +457 -457
  308. package/packages/radio/index.ts +16 -16
  309. package/packages/radio/src/button.ts +195 -173
  310. package/packages/radio/src/group.ts +229 -213
  311. package/packages/radio/src/radio.ts +203 -180
  312. package/packages/radio-button/index.ts +16 -16
  313. package/packages/radio-group/index.ts +16 -16
  314. package/packages/rate/index.ts +16 -16
  315. package/packages/rate/src/rate.ts +192 -192
  316. package/packages/result/index.ts +16 -16
  317. package/packages/result/src/result.ts +112 -112
  318. package/packages/row/index.ts +16 -16
  319. package/packages/row/src/col.ts +136 -136
  320. package/packages/row/src/row.ts +119 -119
  321. package/packages/segmented/index.ts +16 -16
  322. package/packages/segmented/src/segmented.ts +264 -264
  323. package/packages/select/index.ts +16 -16
  324. package/packages/select/src/optgroup.ts +49 -49
  325. package/packages/select/src/option-info.ts +20 -20
  326. package/packages/select/src/option.ts +47 -47
  327. package/packages/select/src/select.ts +1699 -1699
  328. package/packages/select/src/util.ts +47 -47
  329. package/packages/slider/index.ts +16 -16
  330. package/packages/slider/src/slider.ts +304 -304
  331. package/packages/split/index.ts +16 -16
  332. package/packages/split-pane/index.ts +17 -17
  333. package/packages/splitter/index.ts +16 -16
  334. package/packages/splitter/src/splitter-panel.ts +145 -145
  335. package/packages/splitter/src/splitter.ts +1009 -1009
  336. package/packages/splitter/src/util.ts +21 -21
  337. package/packages/splitter-panel/index.ts +16 -16
  338. package/packages/steps/index.ts +16 -16
  339. package/packages/steps/src/steps.ts +68 -68
  340. package/packages/switch/index.ts +16 -16
  341. package/packages/switch/src/switch.ts +245 -237
  342. package/packages/tab-pane/index.ts +16 -16
  343. package/packages/table-select/index.ts +16 -16
  344. package/packages/table-select/src/table-select.ts +800 -800
  345. package/packages/tabs/index.ts +16 -16
  346. package/packages/tabs/src/tab-pane.ts +117 -117
  347. package/packages/tabs/src/tabs.ts +940 -940
  348. package/packages/tabs/src/util.ts +21 -21
  349. package/packages/tag/index.ts +16 -16
  350. package/packages/tag/src/tag.ts +187 -187
  351. package/packages/text/index.ts +16 -16
  352. package/packages/text/src/text.ts +260 -260
  353. package/packages/text-ellipsis/index.ts +16 -16
  354. package/packages/text-ellipsis/src/text-ellipsis.ts +282 -282
  355. package/packages/textarea/index.ts +16 -16
  356. package/packages/textarea/src/textarea.ts +373 -373
  357. package/packages/timeline/index.ts +16 -16
  358. package/packages/timeline/src/timeline-item.ts +67 -67
  359. package/packages/timeline/src/timeline.ts +71 -71
  360. package/packages/timeline-item/index.ts +16 -16
  361. package/packages/tip/index.ts +19 -19
  362. package/packages/tip/src/tip.ts +129 -129
  363. package/packages/tooltip/index.ts +16 -16
  364. package/packages/tooltip/src/tooltip.ts +589 -589
  365. package/packages/tour/index.ts +16 -16
  366. package/packages/tour/src/tour.ts +71 -71
  367. package/packages/tree/index.ts +16 -16
  368. package/packages/tree/src/store.ts +14 -14
  369. package/packages/tree/src/tree.ts +2825 -2825
  370. package/packages/tree/src/util.ts +45 -45
  371. package/packages/tree-select/index.ts +16 -16
  372. package/packages/tree-select/src/tree-select.ts +979 -979
  373. package/packages/ui/index.ts +697 -697
  374. package/packages/ui/src/anime.ts +52 -52
  375. package/packages/ui/src/comp.ts +3 -3
  376. package/packages/ui/src/dom.ts +279 -279
  377. package/packages/ui/src/log.ts +6 -6
  378. package/packages/ui/src/utils.ts +49 -49
  379. package/packages/ui/src/vn.ts +39 -39
  380. package/packages/upload/index.ts +20 -20
  381. package/packages/upload/src/upload.ts +1919 -1919
  382. package/packages/upload/src/util.ts +109 -109
  383. package/packages/watermark/index.ts +31 -31
  384. package/packages/watermark/src/util.ts +176 -176
  385. package/packages/watermark/src/watermark.ts +168 -168
  386. package/styles/all.scss +90 -90
  387. package/styles/base.scss +16 -16
  388. package/styles/components/alert.scss +101 -101
  389. package/styles/components/anchor.scss +44 -44
  390. package/styles/components/avatar.scss +115 -115
  391. package/styles/components/backtop.scss +82 -82
  392. package/styles/components/badge.scss +45 -45
  393. package/styles/components/breadcrumb.scss +29 -29
  394. package/styles/components/button-group.scss +30 -30
  395. package/styles/components/button.scss +415 -415
  396. package/styles/components/calendar.scss +471 -471
  397. package/styles/components/card.scss +121 -121
  398. package/styles/components/carousel.scss +184 -184
  399. package/styles/components/cascader.scss +140 -140
  400. package/styles/components/checkbox-button.scss +57 -57
  401. package/styles/components/checkbox.scss +81 -81
  402. package/styles/components/collapse.scss +56 -56
  403. package/styles/components/color-picker.scss +409 -409
  404. package/styles/components/context-menu.scss +102 -102
  405. package/styles/components/countdown.scss +35 -35
  406. package/styles/components/date-panel.scss +505 -505
  407. package/styles/components/date-picker.scss +247 -247
  408. package/styles/components/date-range-picker.scss +252 -252
  409. package/styles/components/drawer.scss +298 -298
  410. package/styles/components/empty.scss +79 -79
  411. package/styles/components/form.scss +668 -668
  412. package/styles/components/icon-picker.scss +211 -211
  413. package/styles/components/icon.scss +1048 -1048
  414. package/styles/components/image-group.scss +2 -2
  415. package/styles/components/image-preview.scss +215 -215
  416. package/styles/components/image.scss +16 -16
  417. package/styles/components/input.scss +846 -846
  418. package/styles/components/layout-aside.scss +22 -22
  419. package/styles/components/layout-body.scss +14 -14
  420. package/styles/components/layout-container.scss +13 -13
  421. package/styles/components/layout-footer.scss +14 -14
  422. package/styles/components/layout-header.scss +11 -11
  423. package/styles/components/link.scss +115 -115
  424. package/styles/components/list.scss +40 -40
  425. package/styles/components/loading.scss +137 -137
  426. package/styles/components/menu.scss +150 -150
  427. package/styles/components/modal.scss +480 -480
  428. package/styles/components/notice-bar.scss +91 -91
  429. package/styles/components/number-input.scss +283 -283
  430. package/styles/components/old-icon.scss +4 -4
  431. package/styles/components/pager.scss +282 -282
  432. package/styles/components/password-input.scss +374 -374
  433. package/styles/components/print.scss +3 -3
  434. package/styles/components/pulldown.scss +75 -75
  435. package/styles/components/radio-button.scss +57 -57
  436. package/styles/components/radio.scss +79 -79
  437. package/styles/components/rate.scss +76 -76
  438. package/styles/components/result.scss +91 -91
  439. package/styles/components/row.scss +69 -69
  440. package/styles/components/segmented.scss +215 -215
  441. package/styles/components/select.scss +244 -244
  442. package/styles/components/slider.scss +139 -139
  443. package/styles/components/split.scss +1 -1
  444. package/styles/components/splitter.scss +318 -318
  445. package/styles/components/switch.scss +128 -128
  446. package/styles/components/table-select.scss +105 -105
  447. package/styles/components/tabs.scss +745 -745
  448. package/styles/components/tag.scss +184 -184
  449. package/styles/components/text-ellipsis.scss +130 -130
  450. package/styles/components/text.scss +123 -123
  451. package/styles/components/textarea.scss +106 -106
  452. package/styles/components/tip.scss +97 -97
  453. package/styles/components/tooltip.scss +141 -141
  454. package/styles/components/tree-select.scss +166 -166
  455. package/styles/components/tree.scss +294 -294
  456. package/styles/components/upload.scss +497 -497
  457. package/styles/components/watermark.scss +26 -26
  458. package/styles/helpers/baseMixin.scss +104 -95
  459. package/styles/helpers/baseVar.scss +3 -3
  460. package/styles/helpers/placement.scss +38 -38
  461. package/styles/theme/base.scss +214 -214
  462. package/styles/theme/dark.scss +119 -119
  463. package/styles/theme/light.scss +118 -118
  464. package/styles/variable.scss +111 -111
  465. package/types/all.d.ts +327 -327
  466. package/types/components/alert.d.ts +87 -87
  467. package/types/components/anchor-link.d.ts +91 -91
  468. package/types/components/anchor.d.ts +104 -104
  469. package/types/components/avatar.d.ts +88 -88
  470. package/types/components/backtop.d.ts +122 -122
  471. package/types/components/badge.d.ts +76 -76
  472. package/types/components/breadcrumb-item.d.ts +80 -80
  473. package/types/components/breadcrumb.d.ts +87 -87
  474. package/types/components/button-group.d.ts +120 -120
  475. package/types/components/button.d.ts +323 -323
  476. package/types/components/calendar.d.ts +264 -264
  477. package/types/components/card.d.ts +93 -93
  478. package/types/components/carousel-item.d.ts +75 -75
  479. package/types/components/carousel.d.ts +134 -134
  480. package/types/components/cascader.d.ts +263 -263
  481. package/types/components/checkbox-button.d.ts +103 -103
  482. package/types/components/checkbox-group.d.ts +146 -143
  483. package/types/components/checkbox.d.ts +123 -123
  484. package/types/components/col.d.ts +80 -80
  485. package/types/components/colgroup.d.ts +137 -137
  486. package/types/components/collapse-pane.d.ts +89 -89
  487. package/types/components/collapse.d.ts +121 -121
  488. package/types/components/color-picker.d.ts +176 -176
  489. package/types/components/column.d.ts +841 -841
  490. package/types/components/context-menu.d.ts +289 -289
  491. package/types/components/countdown.d.ts +112 -112
  492. package/types/components/date-panel.d.ts +280 -280
  493. package/types/components/date-picker.d.ts +332 -332
  494. package/types/components/date-range-picker.d.ts +352 -352
  495. package/types/components/drawer.d.ts +299 -299
  496. package/types/components/empty.d.ts +78 -78
  497. package/types/components/flow-design.d.ts +85 -85
  498. package/types/components/flow-view.d.ts +85 -85
  499. package/types/components/form-design.d.ts +376 -376
  500. package/types/components/form-gather.d.ts +124 -124
  501. package/types/components/form-group.d.ts +77 -77
  502. package/types/components/form-item.d.ts +411 -411
  503. package/types/components/form-view.d.ts +183 -183
  504. package/types/components/form.d.ts +468 -468
  505. package/types/components/gantt-module/gantt-view.d.ts +177 -177
  506. package/types/components/gantt-module/index.d.ts +1 -1
  507. package/types/components/gantt-plugins/extend-gantt-chart.d.ts +131 -131
  508. package/types/components/gantt-plugins/index.d.ts +1 -1
  509. package/types/components/gantt.d.ts +1194 -1194
  510. package/types/components/grid.d.ts +1040 -1040
  511. package/types/components/icon-picker.d.ts +196 -196
  512. package/types/components/icon.d.ts +87 -87
  513. package/types/components/image-group.d.ts +127 -127
  514. package/types/components/image-preview.d.ts +167 -167
  515. package/types/components/image.d.ts +173 -173
  516. package/types/components/input.d.ts +435 -435
  517. package/types/components/layout-aside.d.ts +80 -80
  518. package/types/components/layout-body.d.ts +91 -91
  519. package/types/components/layout-container.d.ts +73 -73
  520. package/types/components/layout-footer.d.ts +73 -73
  521. package/types/components/layout-header.d.ts +69 -69
  522. package/types/components/link.d.ts +111 -111
  523. package/types/components/list-design.d.ts +190 -190
  524. package/types/components/list-view.d.ts +199 -199
  525. package/types/components/list.d.ts +204 -204
  526. package/types/components/loading.d.ts +103 -103
  527. package/types/components/mention.d.ts +77 -77
  528. package/types/components/menu.d.ts +211 -211
  529. package/types/components/modal.d.ts +542 -542
  530. package/types/components/notice-bar.d.ts +102 -102
  531. package/types/components/number-input.d.ts +309 -309
  532. package/types/components/optgroup.d.ts +88 -88
  533. package/types/components/option.d.ts +103 -103
  534. package/types/components/pager.d.ts +335 -335
  535. package/types/components/password-input.d.ts +142 -142
  536. package/types/components/print-page-break.d.ts +69 -69
  537. package/types/components/print.d.ts +206 -206
  538. package/types/components/pulldown.d.ts +231 -231
  539. package/types/components/radio-button.d.ts +114 -114
  540. package/types/components/radio-group.d.ts +147 -144
  541. package/types/components/radio.d.ts +129 -129
  542. package/types/components/rate.d.ts +88 -88
  543. package/types/components/result.d.ts +84 -84
  544. package/types/components/row.d.ts +79 -79
  545. package/types/components/segmented.d.ts +123 -123
  546. package/types/components/select.d.ts +527 -527
  547. package/types/components/slider.d.ts +126 -126
  548. package/types/components/split-pane.d.ts +133 -133
  549. package/types/components/split.d.ts +312 -312
  550. package/types/components/splitter-panel.d.ts +105 -105
  551. package/types/components/splitter.d.ts +288 -288
  552. package/types/components/steps.d.ts +68 -68
  553. package/types/components/switch.d.ts +133 -133
  554. package/types/components/tab-pane.d.ts +114 -114
  555. package/types/components/table-module/custom.d.ts +123 -123
  556. package/types/components/table-module/edit.d.ts +243 -243
  557. package/types/components/table-module/export.d.ts +96 -96
  558. package/types/components/table-module/filter.d.ts +140 -140
  559. package/types/components/table-module/index.d.ts +7 -7
  560. package/types/components/table-module/keyboard.d.ts +26 -26
  561. package/types/components/table-module/menu.d.ts +28 -28
  562. package/types/components/table-module/validator.d.ts +53 -53
  563. package/types/components/table-plugins/extend-cell-area.d.ts +770 -770
  564. package/types/components/table-plugins/extend-pivot-table.d.ts +58 -58
  565. package/types/components/table-plugins/filters-combination.d.ts +15 -15
  566. package/types/components/table-plugins/filters-complex-input.d.ts +9 -9
  567. package/types/components/table-plugins/index.d.ts +4 -4
  568. package/types/components/table-select.d.ts +219 -219
  569. package/types/components/table.d.ts +7465 -7465
  570. package/types/components/tabs.d.ts +332 -332
  571. package/types/components/tag.d.ts +114 -114
  572. package/types/components/text-ellipsis.d.ts +112 -112
  573. package/types/components/text.d.ts +122 -122
  574. package/types/components/textarea.d.ts +247 -247
  575. package/types/components/timeline-item.d.ts +75 -75
  576. package/types/components/timeline.d.ts +77 -77
  577. package/types/components/tip.d.ts +83 -83
  578. package/types/components/toolbar.d.ts +336 -336
  579. package/types/components/tooltip.d.ts +180 -180
  580. package/types/components/tour.d.ts +77 -77
  581. package/types/components/tree-select.d.ts +310 -310
  582. package/types/components/tree.d.ts +843 -843
  583. package/types/components/upload.d.ts +437 -437
  584. package/types/components/watermark.d.ts +120 -120
  585. package/types/handles/form-design.d.ts +50 -50
  586. package/types/handles/index.d.ts +3 -3
  587. package/types/handles/list-design.d.ts +2 -2
  588. package/types/handles/table.d.ts +15 -15
  589. package/types/index.d.ts +8 -8
  590. package/types/ui/commands.d.ts +57 -57
  591. package/types/ui/formats.d.ts +62 -62
  592. package/types/ui/global-config.d.ts +254 -254
  593. package/types/ui/global-icon.d.ts +292 -292
  594. package/types/ui/hooks.d.ts +13 -13
  595. package/types/ui/index.d.ts +96 -96
  596. package/types/ui/interceptor.d.ts +52 -52
  597. package/types/ui/menus.d.ts +77 -77
  598. package/types/ui/renderer.d.ts +1041 -1041
  599. package/types/ui/validators.d.ts +38 -38
  600. /package/es/icon/{iconfont.1778317220469.ttf → iconfont.1778465063324.ttf} +0 -0
  601. /package/es/icon/{iconfont.1778317220469.woff → iconfont.1778465063324.woff} +0 -0
  602. /package/es/icon/{iconfont.1778317220469.woff2 → iconfont.1778465063324.woff2} +0 -0
  603. /package/es/{iconfont.1778317220469.ttf → iconfont.1778465063324.ttf} +0 -0
  604. /package/es/{iconfont.1778317220469.woff → iconfont.1778465063324.woff} +0 -0
  605. /package/es/{iconfont.1778317220469.woff2 → iconfont.1778465063324.woff2} +0 -0
  606. /package/lib/icon/style/{iconfont.1778317220469.ttf → iconfont.1778465063324.ttf} +0 -0
  607. /package/lib/icon/style/{iconfont.1778317220469.woff → iconfont.1778465063324.woff} +0 -0
  608. /package/lib/icon/style/{iconfont.1778317220469.woff2 → iconfont.1778465063324.woff2} +0 -0
  609. /package/lib/{iconfont.1778317220469.ttf → iconfont.1778465063324.ttf} +0 -0
  610. /package/lib/{iconfont.1778317220469.woff → iconfont.1778465063324.woff} +0 -0
  611. /package/lib/{iconfont.1778317220469.woff2 → iconfont.1778465063324.woff2} +0 -0
@@ -1,1699 +1,1699 @@
1
- import { h, Teleport, PropType, ref, inject, computed, provide, onUnmounted, reactive, nextTick, watch, onMounted } from 'vue'
2
- import { defineVxeComponent } from '../../ui/src/comp'
3
- import XEUtils from 'xe-utils'
4
- import { VxeUI, getConfig, getIcon, getI18n, globalEvents, GLOBAL_EVENT_KEYS, createEvent, useSize, renderEmptyElement } from '../../ui'
5
- import { getEventTargetNode, toCssUnit, updatePanelPlacement } from '../../ui/src/dom'
6
- import { getLastZIndex, nextZIndex, getFuncText, eqEmptyValue } from '../../ui/src/utils'
7
- import { getSlotVNs } from '../../ui/src/vn'
8
- import { errLog } from '../../ui/src/log'
9
- import VxeInputComponent from '../../input/src/input'
10
- import VxeButtonComponent from '../../button/src/button'
11
-
12
- import type { VxeSelectPropTypes, VxeSelectConstructor, SelectInternalData, SelectReactData, VxeSelectDefines, VxeButtonEvents, ValueOf, VxeSelectEmits, VxeComponentSlotType, VxeInputConstructor, SelectMethods, SelectPrivateRef, VxeSelectMethods, VxeOptionProps, VxeDrawerConstructor, VxeDrawerMethods, VxeFormDefines, VxeFormConstructor, VxeFormPrivateMethods, VxeModalConstructor, VxeModalMethods, VxeInputEvents, VxeComponentStyleType } from '../../../types'
13
- import type { VxeTableConstructor, VxeTablePrivateMethods } from '../../../types/components/table'
14
-
15
- function isOptionVisible (option: any) {
16
- return option.visible !== false
17
- }
18
-
19
- function getOptUniqueId () {
20
- return XEUtils.uniqueId('opt_')
21
- }
22
-
23
- function createInternalData (): SelectInternalData {
24
- return {
25
- // isLoaded: false,
26
- synchData: [],
27
- fullData: [],
28
- afterVisibleList: [],
29
- optAddMaps: {},
30
- optGroupKeyMaps: {},
31
- optFullValMaps: {},
32
- remoteValMaps: {},
33
-
34
- lastScrollLeft: 0,
35
- lastScrollTop: 0,
36
- scrollYStore: {
37
- startIndex: 0,
38
- endIndex: 0,
39
- visibleSize: 0,
40
- offsetSize: 0,
41
- rowHeight: 0
42
- },
43
-
44
- lastScrollTime: 0,
45
- hpTimeout: undefined
46
- }
47
- }
48
-
49
- export default defineVxeComponent({
50
- name: 'VxeSelect',
51
- props: {
52
- modelValue: [String, Number, Boolean, Array] as PropType<VxeSelectPropTypes.ModelValue>,
53
- defaultConfig: Object as PropType<VxeSelectPropTypes.DefaultConfig>,
54
- clearable: Boolean as PropType<VxeSelectPropTypes.Clearable>,
55
- placeholder: String as PropType<VxeSelectPropTypes.Placeholder>,
56
- readonly: {
57
- type: Boolean as PropType<VxeSelectPropTypes.Readonly>,
58
- default: null
59
- },
60
- loading: Boolean as PropType<VxeSelectPropTypes.Loading>,
61
- disabled: {
62
- type: Boolean as PropType<VxeSelectPropTypes.Disabled>,
63
- default: null
64
- },
65
- multiple: Boolean as PropType<VxeSelectPropTypes.Multiple>,
66
- multiCharOverflow: {
67
- type: [Number, String] as PropType<VxeSelectPropTypes.MultiCharOverflow>,
68
- default: () => getConfig().select.multiCharOverflow
69
- },
70
- prefixIcon: String as PropType<VxeSelectPropTypes.PrefixIcon>,
71
- allowCreate: {
72
- type: Boolean as PropType<VxeSelectPropTypes.AllowCreate>,
73
- default: () => getConfig().select.allowCreate
74
- },
75
- placement: String as PropType<VxeSelectPropTypes.Placement>,
76
- lazyOptions: Array as PropType<VxeSelectPropTypes.LazyOptions>,
77
- options: Array as PropType<VxeSelectPropTypes.Options>,
78
- optionProps: Object as PropType<VxeSelectPropTypes.OptionProps>,
79
- optionGroups: Array as PropType<VxeSelectPropTypes.OptionGroups>,
80
- optionGroupProps: Object as PropType<VxeSelectPropTypes.OptionGroupProps>,
81
- optionConfig: Object as PropType<VxeSelectPropTypes.OptionConfig>,
82
- className: [String, Function] as PropType<VxeSelectPropTypes.ClassName>,
83
- /**
84
- * 已废弃,请使用 popupConfig.className
85
- * @deprecated
86
- */
87
- popupClassName: [String, Function] as PropType<VxeSelectPropTypes.PopupClassName>,
88
- max: {
89
- type: [String, Number] as PropType<VxeSelectPropTypes.Max>,
90
- default: null
91
- },
92
- /**
93
- * 已废弃,请使用 popupConfig.zIndex
94
- * @deprecated
95
- */
96
- zIndex: Number as PropType<VxeSelectPropTypes.ZIndex>,
97
- size: {
98
- type: String as PropType<VxeSelectPropTypes.Size>,
99
- default: () => getConfig().select.size || getConfig().size
100
- },
101
- filterable: Boolean as PropType<VxeSelectPropTypes.Filterable>,
102
- /**
103
- * 已废弃,被 filter-config.filterMethod 替换
104
- * @deprecated
105
- */
106
- filterMethod: Function as PropType<VxeSelectPropTypes.FilterMethod>,
107
- filterConfig: Object as PropType<VxeSelectPropTypes.FilterConfig>,
108
- remote: Boolean as PropType<VxeSelectPropTypes.Remote>,
109
- remoteConfig: Object as PropType<VxeSelectPropTypes.RemoteConfig>,
110
- emptyText: String as PropType<VxeSelectPropTypes.EmptyText>,
111
- showTotalButoon: {
112
- type: Boolean as PropType<VxeSelectPropTypes.ShowTotalButoon>,
113
- default: () => getConfig().select.showTotalButoon
114
- },
115
- showCheckedButoon: {
116
- type: Boolean as PropType<VxeSelectPropTypes.ShowCheckedButoon>,
117
- default: () => getConfig().select.showCheckedButoon
118
- },
119
- showClearButton: {
120
- type: Boolean as PropType<VxeSelectPropTypes.ShowClearButton>,
121
- default: () => getConfig().select.showClearButton
122
- },
123
- transfer: {
124
- type: Boolean as PropType<VxeSelectPropTypes.Transfer>,
125
- default: null
126
- },
127
- popupConfig: Object as PropType<VxeSelectPropTypes.PopupConfig>,
128
- virtualYConfig: Object as PropType<VxeSelectPropTypes.VirtualYConfig>,
129
- scrollY: Object as PropType<VxeSelectPropTypes.ScrollY>,
130
-
131
- /**
132
- * 已废弃,被 remote-config.queryMethod 替换
133
- * @deprecated
134
- */
135
- remoteMethod: Function as PropType<VxeSelectPropTypes.RemoteMethod>,
136
- /**
137
- * 已废弃,被 option-config.keyField 替换
138
- * @deprecated
139
- */
140
- optionId: {
141
- type: String as PropType<VxeSelectPropTypes.OptionId>,
142
- default: () => getConfig().select.optionId
143
- },
144
- /**
145
- * 已废弃,被 option-config.useKey 替换
146
- * @deprecated
147
- */
148
- optionKey: Boolean as PropType<VxeSelectPropTypes.OptionKey>
149
- },
150
- emits: [
151
- 'update:modelValue',
152
- 'change',
153
- 'default-change',
154
- 'all-change',
155
- 'clear',
156
- 'blur',
157
- 'focus',
158
- 'click',
159
- 'scroll',
160
- 'visible-change'
161
- ] as VxeSelectEmits,
162
- setup (props, context) {
163
- const { slots, emit } = context
164
-
165
- const $xeModal = inject<(VxeModalConstructor & VxeModalMethods)| null>('$xeModal', null)
166
- const $xeDrawer = inject<(VxeDrawerConstructor & VxeDrawerMethods) | null>('$xeDrawer', null)
167
- const $xeTable = inject<(VxeTableConstructor & VxeTablePrivateMethods) | null>('$xeTable', null)
168
- const $xeForm = inject<(VxeFormConstructor & VxeFormPrivateMethods)| null>('$xeForm', null)
169
- const formItemInfo = inject<VxeFormDefines.ProvideItemInfo | null>('xeFormItemInfo', null)
170
-
171
- const xID = XEUtils.uniqueId()
172
-
173
- const refElem = ref<HTMLDivElement>()
174
- const refInput = ref<VxeInputConstructor>()
175
- const refInpSearch = ref<VxeInputConstructor>()
176
- const refVirtualWrapper = ref<HTMLDivElement>()
177
- const refOptionPanel = ref<HTMLDivElement>()
178
- const refVirtualBody = ref<HTMLDivElement>()
179
-
180
- const { computeSize } = useSize(props)
181
-
182
- const reactData = reactive<SelectReactData>({
183
- initialized: false,
184
- scrollYLoad: false,
185
- bodyHeight: 0,
186
- topSpaceHeight: 0,
187
- optList: [],
188
- staticOptions: [],
189
- reactFlag: 0,
190
-
191
- currentOption: null,
192
- searchValue: '',
193
- searchLoading: false,
194
-
195
- panelIndex: 0,
196
- panelStyle: {},
197
- panelPlacement: null,
198
- triggerFocusPanel: false,
199
- visiblePanel: false,
200
- isAniVisible: false,
201
- isActivated: false
202
- })
203
-
204
- const internalData = createInternalData()
205
-
206
- const refMaps: SelectPrivateRef = {
207
- refElem
208
- }
209
-
210
- const $xeSelect = {
211
- xID,
212
- props,
213
- context,
214
- reactData,
215
- internalData,
216
- getRefMaps: () => refMaps
217
- } as unknown as VxeSelectConstructor & VxeSelectMethods
218
-
219
- const computeFormReadonly = computed(() => {
220
- const { readonly } = props
221
- if (readonly === null) {
222
- if ($xeForm) {
223
- return $xeForm.props.readonly
224
- }
225
- return false
226
- }
227
- return readonly
228
- })
229
-
230
- const computeIsDisabled = computed(() => {
231
- const { disabled } = props
232
- if (disabled === null) {
233
- if ($xeForm) {
234
- return $xeForm.props.disabled
235
- }
236
- return false
237
- }
238
- return disabled
239
- })
240
-
241
- const computeBtnTransfer = computed(() => {
242
- const { transfer } = props
243
- const popupOpts = computePopupOpts.value
244
- if (XEUtils.isBoolean(popupOpts.transfer)) {
245
- return popupOpts.transfer
246
- }
247
- if (transfer === null) {
248
- const globalTransfer = getConfig().select.transfer
249
- if (XEUtils.isBoolean(globalTransfer)) {
250
- return globalTransfer
251
- }
252
- if ($xeTable || $xeModal || $xeDrawer || $xeForm) {
253
- return true
254
- }
255
- }
256
- return transfer
257
- })
258
-
259
- const computeInpPlaceholder = computed(() => {
260
- const { placeholder } = props
261
- if (placeholder) {
262
- return getFuncText(placeholder)
263
- }
264
- const globalPlaceholder = getConfig().select.placeholder
265
- if (globalPlaceholder) {
266
- return getFuncText(globalPlaceholder)
267
- }
268
- return getI18n('vxe.base.pleaseSelect')
269
- })
270
-
271
- const computeDefaultOpts = computed(() => {
272
- return Object.assign({}, props.defaultConfig)
273
- })
274
- const computePropsOpts = computed(() => {
275
- return Object.assign({}, props.optionProps)
276
- })
277
-
278
- const computeGroupPropsOpts = computed(() => {
279
- return Object.assign({}, props.optionGroupProps)
280
- })
281
-
282
- const computeLabelField = computed(() => {
283
- const propsOpts = computePropsOpts.value
284
- return propsOpts.label || 'label'
285
- })
286
-
287
- const computeValueField = computed(() => {
288
- const propsOpts = computePropsOpts.value
289
- return propsOpts.value || 'value'
290
- })
291
-
292
- const computeGroupLabelField = computed(() => {
293
- const groupPropsOpts = computeGroupPropsOpts.value
294
- return groupPropsOpts.label || 'label'
295
- })
296
-
297
- const computeGroupOptionsField = computed(() => {
298
- const groupPropsOpts = computeGroupPropsOpts.value
299
- return groupPropsOpts.options || 'options'
300
- })
301
-
302
- const computeIsMaximize = computed(() => {
303
- const selectVals = computeSelectVals.value
304
- return checkMaxLimit(selectVals)
305
- })
306
-
307
- const computePopupOpts = computed(() => {
308
- return Object.assign({}, getConfig().select.popupConfig, props.popupConfig)
309
- })
310
-
311
- const computeVirtualYOpts = computed(() => {
312
- return Object.assign({} as { gt: number }, getConfig().select.virtualYConfig || getConfig().select.scrollY, props.virtualYConfig || props.scrollY)
313
- })
314
-
315
- const computeRemoteOpts = computed(() => {
316
- return Object.assign({}, getConfig().select.remoteConfig, props.remoteConfig)
317
- })
318
-
319
- const computeFilterOpts = computed(() => {
320
- return Object.assign({}, getConfig().select.filterConfig, props.filterConfig)
321
- })
322
-
323
- const computeOptionOpts = computed(() => {
324
- return Object.assign({}, getConfig().select.optionConfig, props.optionConfig)
325
- })
326
-
327
- const computeMultiMaxCharNum = computed(() => {
328
- return XEUtils.toNumber(props.multiCharOverflow)
329
- })
330
-
331
- const computePopupWrapperStyle = computed(() => {
332
- const popupOpts = computePopupOpts.value
333
- const { height, width } = popupOpts
334
- const stys: VxeComponentStyleType = {}
335
- if (width) {
336
- stys.width = toCssUnit(width)
337
- }
338
- if (height) {
339
- stys.height = toCssUnit(height)
340
- stys.maxHeight = toCssUnit(height)
341
- }
342
- return stys
343
- })
344
-
345
- const computeSelectVals = computed(() => {
346
- const { modelValue, multiple } = props
347
- let vals: (string | number | boolean)[] = []
348
- if (XEUtils.isArray(modelValue)) {
349
- vals = modelValue
350
- } else {
351
- if (multiple) {
352
- if (!eqEmptyValue(modelValue)) {
353
- vals = `${modelValue}`.indexOf(',') > -1 ? `${modelValue}`.split(',') : [modelValue] as any[]
354
- }
355
- } else {
356
- vals = modelValue === null || modelValue === undefined ? [] : [modelValue]
357
- }
358
- }
359
- return vals
360
- })
361
-
362
- const computeFullLabel = computed(() => {
363
- const { remote } = props
364
- const { reactFlag } = reactData
365
- const selectVals = computeSelectVals.value
366
- if (remote && reactFlag) {
367
- return selectVals.map(val => getRemoteSelectLabel(val)).join(', ')
368
- }
369
- return selectVals.map((val) => getSelectLabel(val)).join(', ')
370
- })
371
-
372
- const computeSelectLabel = computed(() => {
373
- const { remote, multiple } = props
374
- const { reactFlag } = reactData
375
- const multiMaxCharNum = computeMultiMaxCharNum.value
376
- const selectVals = computeSelectVals.value
377
- if (remote && reactFlag) {
378
- return selectVals.map(val => getRemoteSelectLabel(val)).join(', ')
379
- }
380
- const labels = selectVals.map((val) => getSelectLabel(val))
381
- if (multiple && multiMaxCharNum > 0 && labels.length > multiMaxCharNum) {
382
- return `${labels.slice(0, multiMaxCharNum)}...`
383
- }
384
- return labels.join(', ')
385
- })
386
-
387
- const callSlot = <T>(slotFunc: ((params: T) => VxeComponentSlotType | VxeComponentSlotType[]) | string | null, params: T) => {
388
- if (slotFunc) {
389
- if (XEUtils.isString(slotFunc)) {
390
- slotFunc = slots[slotFunc] || null
391
- }
392
- if (XEUtils.isFunction(slotFunc)) {
393
- return getSlotVNs(slotFunc(params))
394
- }
395
- }
396
- return []
397
- }
398
-
399
- const dispatchEvent = (type: ValueOf<VxeSelectEmits>, params: Record<string, any>, evnt: Event | null) => {
400
- emit(type, createEvent(evnt, { $select: $xeSelect }, params))
401
- }
402
-
403
- const emitModel = (value: any) => {
404
- emit('update:modelValue', value)
405
- }
406
-
407
- const emitDefaultValue = (value: any) => {
408
- emitModel(value)
409
- dispatchEvent('default-change', { value }, null)
410
- }
411
-
412
- const getOptKey = () => {
413
- const optionOpts = computeOptionOpts.value
414
- return optionOpts.keyField || props.optionId || '_X_OPTION_KEY'
415
- }
416
-
417
- const getOptId = (option: any) => {
418
- const optid = option[getOptKey()]
419
- return optid ? encodeURIComponent(optid) : ''
420
- }
421
-
422
- const checkMaxLimit = (selectVals: VxeSelectPropTypes.ModelValue[]) => {
423
- const { multiple, max } = props
424
- if (multiple && max) {
425
- return selectVals.length >= XEUtils.toNumber(max)
426
- }
427
- return false
428
- }
429
-
430
- const getRemoteSelectLabel = (value: any) => {
431
- const { lazyOptions } = props
432
- const { remoteValMaps, optFullValMaps } = internalData
433
- const valueField = computeValueField.value
434
- const labelField = computeLabelField.value
435
- const remoteItem = remoteValMaps[value] || optFullValMaps[value]
436
- const item = remoteItem ? remoteItem.item : null
437
- if (item) {
438
- return XEUtils.toValueString(item[labelField])
439
- }
440
- if (lazyOptions) {
441
- const lazyItem = lazyOptions.find(item => item[valueField] === value)
442
- if (lazyItem) {
443
- return lazyItem[labelField]
444
- }
445
- }
446
- return value
447
- }
448
-
449
- const getSelectLabel = (value: any) => {
450
- const { lazyOptions } = props
451
- const { optFullValMaps } = internalData
452
- const valueField = computeValueField.value
453
- const labelField = computeLabelField.value
454
- const cacheItem = reactData.reactFlag ? optFullValMaps[value] : null
455
- if (cacheItem) {
456
- return cacheItem.item[labelField as 'label']
457
- }
458
- if (lazyOptions) {
459
- const lazyItem = lazyOptions.find(item => item[valueField] === value)
460
- if (lazyItem) {
461
- return lazyItem[labelField]
462
- }
463
- }
464
- return value
465
- }
466
-
467
- const cacheItemMap = (datas: any[]) => {
468
- const groupOptionsField = computeGroupOptionsField.value
469
- const valueField = computeValueField.value
470
- const key = getOptKey()
471
- const groupKeyMaps: Record<string, any> = {}
472
- const fullKeyMaps: Record<string, VxeSelectDefines.OptCacheItem> = {}
473
- const list: any[] = []
474
- const handleOptItem = (item: any) => {
475
- list.push(item)
476
- let optid = getOptId(item)
477
- if (!optid) {
478
- optid = getOptUniqueId()
479
- item[key] = optid
480
- }
481
- fullKeyMaps[item[valueField]] = {
482
- key: optid,
483
- item,
484
- _index: -1
485
- }
486
- }
487
- datas.forEach((group: any) => {
488
- handleOptItem(group)
489
- if (group[groupOptionsField]) {
490
- groupKeyMaps[group[key]] = group
491
- group[groupOptionsField].forEach(handleOptItem)
492
- }
493
- })
494
- internalData.fullData = list
495
- internalData.optGroupKeyMaps = groupKeyMaps
496
- internalData.optFullValMaps = fullKeyMaps
497
- reactData.reactFlag++
498
- handleOption()
499
- }
500
-
501
- /**
502
- * 处理选项,当选项被动态显示/隐藏时可能会用到
503
- */
504
- const handleOption = () => {
505
- const { remote, modelValue, filterable } = props
506
- const { searchValue } = reactData
507
- const { fullData, optFullValMaps } = internalData
508
- const labelField = computeLabelField.value
509
- const valueField = computeValueField.value
510
- const filterOpts = computeFilterOpts.value
511
- const frMethod = filterOpts.filterMethod || props.filterMethod
512
- const searchStr = `${searchValue || ''}`.toLowerCase()
513
- let avList: any[] = []
514
- if (remote) {
515
- avList = fullData.filter(isOptionVisible)
516
- } else {
517
- if (filterable && frMethod) {
518
- avList = fullData.filter(option => isOptionVisible(option) && frMethod({ $select: $xeSelect, group: null, option, searchValue, value: modelValue }))
519
- } else if (filterable) {
520
- avList = fullData.filter(option => isOptionVisible(option) && (!searchStr || `${option[labelField] || option[valueField]}`.toLowerCase().indexOf(searchStr) > -1))
521
- } else {
522
- avList = fullData.filter(isOptionVisible)
523
- }
524
- }
525
- avList.forEach((item, index) => {
526
- const cacheItem = optFullValMaps[item[valueField]]
527
- if (cacheItem) {
528
- cacheItem._index = index
529
- }
530
- })
531
- internalData.afterVisibleList = avList
532
- return nextTick()
533
- }
534
-
535
- const setCurrentOption = (option: any) => {
536
- if (option) {
537
- reactData.currentOption = option
538
- }
539
- }
540
-
541
- const updateZIndex = () => {
542
- const popupOpts = computePopupOpts.value
543
- const customZIndex = popupOpts.zIndex || props.zIndex
544
- if (customZIndex) {
545
- reactData.panelIndex = XEUtils.toNumber(customZIndex)
546
- } else if (reactData.panelIndex < getLastZIndex()) {
547
- reactData.panelIndex = nextZIndex()
548
- }
549
- }
550
-
551
- const updatePlacement = () => {
552
- const { placement } = props
553
- const { panelIndex } = reactData
554
- const targetElem = refElem.value
555
- const panelElem = refOptionPanel.value
556
- const btnTransfer = computeBtnTransfer.value
557
- const popupOpts = computePopupOpts.value
558
- const handleStyle = () => {
559
- const ppObj = updatePanelPlacement(targetElem, panelElem, {
560
- placement: popupOpts.placement || placement,
561
- defaultPlacement: popupOpts.defaultPlacement,
562
- teleportTo: btnTransfer
563
- })
564
- const panelStyle: { [key: string]: string | number } = Object.assign(ppObj.style, {
565
- zIndex: panelIndex
566
- })
567
- reactData.panelStyle = panelStyle
568
- reactData.panelPlacement = ppObj.placement
569
- }
570
- handleStyle()
571
- return nextTick().then(handleStyle)
572
- }
573
-
574
- const handleScrollSelect = () => {
575
- nextTick(() => {
576
- const { isAniVisible, visiblePanel } = reactData
577
- const { optFullValMaps } = internalData
578
- const selectVals = computeSelectVals.value
579
- if (selectVals.length && isAniVisible && visiblePanel) {
580
- const cacheItem = reactData.reactFlag ? optFullValMaps[`${selectVals[0]}`] : null
581
- if (cacheItem) {
582
- handleScrollToOption(cacheItem.item)
583
- }
584
- }
585
- })
586
- }
587
-
588
- const showOptionPanel = () => {
589
- const { loading, filterable, remote } = props
590
- const { fullData, hpTimeout } = internalData
591
- const isDisabled = computeIsDisabled.value
592
- const remoteOpts = computeRemoteOpts.value
593
- if (!loading && !isDisabled) {
594
- if (hpTimeout) {
595
- clearTimeout(hpTimeout)
596
- internalData.hpTimeout = undefined
597
- }
598
- if (!reactData.initialized) {
599
- reactData.initialized = true
600
- }
601
- reactData.isActivated = true
602
- reactData.isAniVisible = true
603
- if (filterable) {
604
- if (remote && remoteOpts.enabled && ((remoteOpts.autoLoad && !fullData.length) || (fullData.length && remoteOpts.clearOnClose))) {
605
- handleSearchEvent()
606
- } else {
607
- handleOption()
608
- updateYData()
609
- }
610
- }
611
- setTimeout(() => {
612
- reactData.visiblePanel = true
613
- handleFocusSearch()
614
- recalculate().then(() => {
615
- handleScrollSelect()
616
- refreshScroll()
617
- })
618
- updatePlacement()
619
- }, 10)
620
- setTimeout(() => {
621
- recalculate().then(() => refreshScroll())
622
- }, 100)
623
- updateZIndex()
624
- updatePlacement()
625
- dispatchEvent('visible-change', { visible: true }, null)
626
- }
627
- }
628
-
629
- const hideOptionPanel = () => {
630
- const { filterable, remote } = props
631
- const filterOpts = computeFilterOpts.value
632
- const remoteOpts = computeRemoteOpts.value
633
- if (remote) {
634
- if (remoteOpts.clearOnClose) {
635
- reactData.searchValue = ''
636
- }
637
- } else if (filterable) {
638
- if (filterOpts.clearOnClose) {
639
- reactData.searchValue = ''
640
- }
641
- } else {
642
- reactData.searchValue = ''
643
- }
644
- reactData.searchLoading = false
645
- reactData.visiblePanel = false
646
- internalData.hpTimeout = setTimeout(() => {
647
- reactData.isAniVisible = false
648
- }, 350)
649
- dispatchEvent('visible-change', { visible: false }, null)
650
- }
651
-
652
- const changeEvent = (evnt: Event, selectValue: any, option: any) => {
653
- emitModel(selectValue)
654
- if (selectValue !== props.modelValue) {
655
- dispatchEvent('change', { value: selectValue, option }, evnt)
656
- // 自动更新校验状态
657
- if ($xeForm && formItemInfo) {
658
- $xeForm.triggerItemEvent(evnt, formItemInfo.itemConfig.field, selectValue)
659
- }
660
- }
661
- }
662
-
663
- const clearValueEvent = (evnt: Event, selectValue: any) => {
664
- internalData.remoteValMaps = {}
665
- changeEvent(evnt, selectValue, null)
666
- dispatchEvent('clear', { value: selectValue }, evnt)
667
- }
668
-
669
- const clearEvent: VxeInputEvents.Clear = (params) => {
670
- const { $event } = params
671
- clearValueEvent($event, null)
672
- hideOptionPanel()
673
- }
674
-
675
- const allCheckedPanelEvent: VxeButtonEvents.Click = (params) => {
676
- const { $event } = params
677
- const { multiple, max } = props
678
- const { optList } = reactData
679
- const valueField = computeValueField.value
680
- if (multiple) {
681
- const selectVals = computeSelectVals.value
682
- const currVlas = selectVals.slice(0)
683
- for (let i = 0; i < optList.length; i++) {
684
- const option = optList[i]
685
- const selectValue = option[valueField]
686
- // 检测是否超过最大可选数量
687
- if (checkMaxLimit(currVlas)) {
688
- if (VxeUI) {
689
- VxeUI.modal.message({
690
- content: getI18n('vxe.select.overSizeErr', [max]),
691
- status: 'warning'
692
- })
693
- }
694
- break
695
- }
696
- if (!currVlas.some(val => val === selectValue)) {
697
- currVlas.push(selectValue)
698
- }
699
- }
700
- changeEvent($event, currVlas, optList[0])
701
- dispatchEvent('all-change', { value: currVlas }, $event)
702
- }
703
- }
704
-
705
- const clearCheckedPanelEvent: VxeButtonEvents.Click = (params) => {
706
- const { $event } = params
707
- clearValueEvent($event, null)
708
- hideOptionPanel()
709
- }
710
-
711
- const changeOptionEvent = (evnt: Event, option: any) => {
712
- const { multiple } = props
713
- const { remoteValMaps } = internalData
714
- const valueField = computeValueField.value
715
- const selectValue = option[valueField]
716
- const remoteItem = remoteValMaps[selectValue]
717
- if (!reactData.visiblePanel) {
718
- return
719
- }
720
- if (remoteItem) {
721
- remoteItem.item = option
722
- } else {
723
- remoteValMaps[selectValue] = {
724
- key: getOptId(option),
725
- item: option,
726
- _index: -1
727
- }
728
- }
729
- if (multiple) {
730
- let multipleValue: any[] = []
731
- const selectVals = computeSelectVals.value
732
- const index = XEUtils.findIndexOf(selectVals, val => val === selectValue)
733
- if (index === -1) {
734
- multipleValue = selectVals.concat([selectValue])
735
- } else {
736
- multipleValue = selectVals.filter((val) => val !== selectValue)
737
- }
738
- changeEvent(evnt, multipleValue, option)
739
- } else {
740
- changeEvent(evnt, selectValue, option)
741
- hideOptionPanel()
742
- }
743
- reactData.reactFlag++
744
- }
745
-
746
- const handleGlobalMousewheelEvent = (evnt: MouseEvent) => {
747
- const { visiblePanel } = reactData
748
- const isDisabled = computeIsDisabled.value
749
- if (!isDisabled) {
750
- if (visiblePanel) {
751
- const panelElem = refOptionPanel.value
752
- if (getEventTargetNode(evnt, panelElem).flag) {
753
- updatePlacement()
754
- } else {
755
- hideOptionPanel()
756
- }
757
- }
758
- }
759
- }
760
-
761
- const handleGlobalMousedownEvent = (evnt: MouseEvent) => {
762
- const { visiblePanel } = reactData
763
- const isDisabled = computeIsDisabled.value
764
- const popupOpts = computePopupOpts.value
765
- const { trigger } = popupOpts
766
- if (!isDisabled) {
767
- const el = refElem.value
768
- const panelElem = refOptionPanel.value
769
- reactData.isActivated = getEventTargetNode(evnt, el).flag || getEventTargetNode(evnt, panelElem).flag
770
- if (visiblePanel && !reactData.isActivated) {
771
- if (trigger !== 'manual') {
772
- hideOptionPanel()
773
- }
774
- }
775
- }
776
- }
777
-
778
- const validOffsetOption = (option: any) => {
779
- const isDisabled = option.disabled
780
- const optid = getOptId(option)
781
- if (!isDisabled && !hasOptGroupById(optid)) {
782
- return true
783
- }
784
- return false
785
- }
786
-
787
- const findOffsetOption = (option: any, isDwArrow: boolean) => {
788
- const { allowCreate } = props
789
- const { optList } = reactData
790
- const { optFullValMaps, optAddMaps, afterVisibleList } = internalData
791
- const valueField = computeValueField.value
792
- let fullList = afterVisibleList
793
- let offsetAddIndex = 0
794
- if (allowCreate && optList.length) {
795
- const firstItem = optList[0]
796
- const optid = getOptId(firstItem)
797
- if (optAddMaps[optid]) {
798
- offsetAddIndex = 1
799
- fullList = [optAddMaps[optid]].concat(fullList)
800
- }
801
- }
802
- if (!option) {
803
- if (isDwArrow) {
804
- for (let i = 0; i < fullList.length; i++) {
805
- const item = fullList[i]
806
- if (validOffsetOption(item)) {
807
- return item
808
- }
809
- }
810
- } else {
811
- for (let len = fullList.length - 1; len >= 0; len--) {
812
- const item = fullList[len]
813
- if (validOffsetOption(item)) {
814
- return item
815
- }
816
- }
817
- }
818
- }
819
- let avIndex = 0
820
- const cacheItem = option ? optFullValMaps[option[valueField]] : null
821
- if (cacheItem) {
822
- avIndex = cacheItem._index + offsetAddIndex
823
- }
824
- if (avIndex > -1) {
825
- if (isDwArrow) {
826
- for (let i = avIndex + 1; i <= fullList.length - 1; i++) {
827
- const item = fullList[i]
828
- if (validOffsetOption(item)) {
829
- return item
830
- }
831
- }
832
- } else {
833
- if (avIndex > 0) {
834
- for (let len = avIndex - 1; len >= 0; len--) {
835
- const item = fullList[len]
836
- if (validOffsetOption(item)) {
837
- return item
838
- }
839
- }
840
- }
841
- }
842
- }
843
- return null
844
- }
845
-
846
- const handleGlobalKeydownEvent = (evnt: KeyboardEvent) => {
847
- const { clearable } = props
848
- const { visiblePanel, currentOption } = reactData
849
- const isDisabled = computeIsDisabled.value
850
- const popupOpts = computePopupOpts.value
851
- const { trigger } = popupOpts
852
- if (!isDisabled) {
853
- const isTab = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.TAB)
854
- const isEnter = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ENTER)
855
- const isEsc = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ESCAPE)
856
- const isUpArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_UP)
857
- const isDwArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_DOWN)
858
- const isDel = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE)
859
- if (isTab) {
860
- reactData.isActivated = false
861
- }
862
- if (visiblePanel) {
863
- if (isEsc || isTab) {
864
- if (trigger !== 'manual') {
865
- hideOptionPanel()
866
- }
867
- } else if (isEnter) {
868
- if (currentOption) {
869
- evnt.preventDefault()
870
- evnt.stopPropagation()
871
- changeOptionEvent(evnt, currentOption)
872
- }
873
- } else if (isUpArrow || isDwArrow) {
874
- evnt.preventDefault()
875
- let offsetOption = findOffsetOption(currentOption, isDwArrow)
876
- // 如果不匹配,默认最接近一个
877
- if (!offsetOption) {
878
- offsetOption = findOffsetOption(null, isDwArrow)
879
- }
880
- if (offsetOption) {
881
- setCurrentOption(offsetOption)
882
- handleScrollToOption(offsetOption, isDwArrow)
883
- }
884
- }
885
- } else if ((isUpArrow || isDwArrow || isEnter) && reactData.isActivated) {
886
- evnt.preventDefault()
887
- showOptionPanel()
888
- }
889
- if (reactData.isActivated) {
890
- if (isDel && clearable) {
891
- clearValueEvent(evnt, null)
892
- }
893
- }
894
- }
895
- }
896
-
897
- const handleGlobalBlurEvent = () => {
898
- const { visiblePanel, isActivated } = reactData
899
- const popupOpts = computePopupOpts.value
900
- const { trigger } = popupOpts
901
- if (visiblePanel) {
902
- if (trigger !== 'manual') {
903
- hideOptionPanel()
904
- }
905
- }
906
- if (isActivated) {
907
- reactData.isActivated = false
908
- }
909
- if (visiblePanel || isActivated) {
910
- const $input = refInput.value
911
- if ($input) {
912
- $input.blur()
913
- }
914
- }
915
- }
916
-
917
- const handleGlobalResizeEvent = () => {
918
- const { visiblePanel } = reactData
919
- if (visiblePanel) {
920
- updatePlacement()
921
- }
922
- }
923
-
924
- const handleFocusSearch = () => {
925
- if (props.filterable) {
926
- nextTick(() => {
927
- const inpSearch = refInpSearch.value
928
- if (inpSearch) {
929
- inpSearch.focus()
930
- }
931
- })
932
- }
933
- }
934
-
935
- const focusEvent = (evnt: FocusEvent) => {
936
- const isDisabled = computeIsDisabled.value
937
- const popupOpts = computePopupOpts.value
938
- const { trigger } = popupOpts
939
- if (!isDisabled) {
940
- if (!reactData.visiblePanel) {
941
- if (!trigger || trigger === 'default') {
942
- reactData.triggerFocusPanel = true
943
- showOptionPanel()
944
- setTimeout(() => {
945
- reactData.triggerFocusPanel = false
946
- }, 500)
947
- }
948
- }
949
- }
950
- dispatchEvent('focus', {}, evnt)
951
- }
952
-
953
- const clickEvent = (evnt: MouseEvent) => {
954
- const popupOpts = computePopupOpts.value
955
- const { trigger } = popupOpts
956
- if (!trigger || trigger === 'default') {
957
- togglePanelEvent(evnt)
958
- }
959
- dispatchEvent('click', { triggerButton: false, visible: reactData.visiblePanel }, evnt)
960
- }
961
-
962
- const blurEvent = (evnt: FocusEvent) => {
963
- reactData.isActivated = false
964
- dispatchEvent('blur', {}, evnt)
965
- }
966
-
967
- const suffixClickEvent = (evnt: MouseEvent) => {
968
- const popupOpts = computePopupOpts.value
969
- const { trigger } = popupOpts
970
- if (!trigger || trigger === 'default' || trigger === 'icon') {
971
- togglePanelEvent(evnt)
972
- }
973
- dispatchEvent('click', { triggerButton: true, visible: reactData.visiblePanel }, evnt)
974
- }
975
-
976
- const modelSearchEvent = (value: string) => {
977
- reactData.searchValue = value
978
- }
979
-
980
- const focusSearchEvent = () => {
981
- reactData.isActivated = true
982
- }
983
-
984
- const handleSearchEvent = () => {
985
- const { modelValue, remote } = props
986
- const { searchValue } = reactData
987
- const remoteOpts = computeRemoteOpts.value
988
- const qyMethod = remoteOpts.queryMethod || props.remoteMethod
989
- if (remote && qyMethod && remoteOpts.enabled) {
990
- reactData.searchLoading = true
991
- Promise.resolve(
992
- qyMethod({ $select: $xeSelect, searchValue, value: modelValue })
993
- ).then(() => nextTick())
994
- .catch(() => nextTick())
995
- .finally(() => {
996
- reactData.searchLoading = false
997
- handleOption()
998
- updateYData()
999
- })
1000
- } else {
1001
- handleOption()
1002
- updateYData()
1003
- }
1004
- }
1005
-
1006
- const triggerSearchEvent = XEUtils.debounce(handleSearchEvent, 350, { trailing: true })
1007
-
1008
- const togglePanelEvent = (params: any) => {
1009
- const { $event } = params
1010
- $event.preventDefault()
1011
- if (reactData.triggerFocusPanel) {
1012
- reactData.triggerFocusPanel = false
1013
- } else {
1014
- if (reactData.visiblePanel) {
1015
- hideOptionPanel()
1016
- } else {
1017
- showOptionPanel()
1018
- }
1019
- }
1020
- }
1021
-
1022
- const checkOptionDisabled = (isSelected: any, option: VxeOptionProps) => {
1023
- if (option.disabled) {
1024
- return true
1025
- }
1026
- const isMaximize = computeIsMaximize.value
1027
- if (isMaximize && !isSelected) {
1028
- return true
1029
- }
1030
- return false
1031
- }
1032
-
1033
- const updateYSpace = () => {
1034
- const { scrollYLoad } = reactData
1035
- const { scrollYStore, afterVisibleList } = internalData
1036
- reactData.bodyHeight = scrollYLoad ? afterVisibleList.length * scrollYStore.rowHeight : 0
1037
- reactData.topSpaceHeight = scrollYLoad ? Math.max(scrollYStore.startIndex * scrollYStore.rowHeight, 0) : 0
1038
- }
1039
-
1040
- const handleData = () => {
1041
- const { filterable, allowCreate } = props
1042
- const { scrollYLoad, searchValue } = reactData
1043
- const { optAddMaps, scrollYStore, afterVisibleList } = internalData
1044
- const labelField = computeLabelField.value
1045
- const valueField = computeValueField.value
1046
- const restList = scrollYLoad ? afterVisibleList.slice(scrollYStore.startIndex, scrollYStore.endIndex) : afterVisibleList.slice(0)
1047
- if (filterable && allowCreate && searchValue) {
1048
- if (!restList.some(option => option[labelField] === searchValue)) {
1049
- const addItem = optAddMaps[searchValue] || reactive({
1050
- [getOptKey()]: searchValue,
1051
- [labelField]: searchValue,
1052
- [valueField]: searchValue
1053
- })
1054
- optAddMaps[searchValue] = addItem
1055
- restList.unshift(addItem)
1056
- }
1057
- }
1058
- reactData.optList = restList
1059
- return nextTick()
1060
- }
1061
-
1062
- const updateYData = () => {
1063
- handleData()
1064
- updateYSpace()
1065
- }
1066
-
1067
- const computeScrollLoad = () => {
1068
- return nextTick().then(() => {
1069
- const { scrollYLoad } = reactData
1070
- const { scrollYStore } = internalData
1071
- const virtualBodyElem = refVirtualBody.value
1072
- const virtualYOpts = computeVirtualYOpts.value
1073
- let rowHeight = 0
1074
- let firstItemElem: HTMLElement | undefined
1075
- if (virtualBodyElem) {
1076
- if (!firstItemElem) {
1077
- firstItemElem = virtualBodyElem.children[0] as HTMLElement
1078
- }
1079
- }
1080
- if (firstItemElem) {
1081
- rowHeight = firstItemElem.offsetHeight
1082
- }
1083
- rowHeight = Math.max(20, rowHeight)
1084
- scrollYStore.rowHeight = rowHeight
1085
- // 计算 Y 逻辑
1086
- if (scrollYLoad) {
1087
- const scrollBodyElem = refVirtualWrapper.value
1088
- const visibleYSize = Math.max(8, scrollBodyElem ? Math.ceil(scrollBodyElem.clientHeight / rowHeight) : 0)
1089
- const offsetYSize = Math.max(0, Math.min(2, XEUtils.toNumber(virtualYOpts.oSize)))
1090
- scrollYStore.offsetSize = offsetYSize
1091
- scrollYStore.visibleSize = visibleYSize
1092
- scrollYStore.endIndex = Math.max(scrollYStore.startIndex, visibleYSize + offsetYSize, scrollYStore.endIndex)
1093
- updateYData()
1094
- } else {
1095
- updateYSpace()
1096
- }
1097
- })
1098
- }
1099
-
1100
- const handleScrollToOption = (option: any, isDwArrow?: boolean) => {
1101
- const { scrollYLoad } = reactData
1102
- const { optFullValMaps, scrollYStore } = internalData
1103
- const valueField = computeValueField.value
1104
- const cacheItem = optFullValMaps[option[valueField]]
1105
- if (cacheItem) {
1106
- const optid = cacheItem.key
1107
- const avIndex = cacheItem._index
1108
- if (avIndex > -1) {
1109
- const optWrapperElem = refVirtualWrapper.value
1110
- const panelElem = refOptionPanel.value
1111
- if (!panelElem) {
1112
- return
1113
- }
1114
- const optElem = panelElem.querySelector(`[optid='${optid}']`) as HTMLElement
1115
- if (optWrapperElem) {
1116
- if (optElem) {
1117
- const wrapperHeight = optWrapperElem.offsetHeight
1118
- const offsetPadding = 1
1119
- if (isDwArrow) {
1120
- if (optElem.offsetTop + optElem.offsetHeight - optWrapperElem.scrollTop > wrapperHeight) {
1121
- optWrapperElem.scrollTop = optElem.offsetTop + optElem.offsetHeight - wrapperHeight
1122
- } else if (optElem.offsetTop + offsetPadding < optWrapperElem.scrollTop || optElem.offsetTop + offsetPadding > optWrapperElem.scrollTop + optWrapperElem.clientHeight) {
1123
- optWrapperElem.scrollTop = optElem.offsetTop - offsetPadding
1124
- }
1125
- } else {
1126
- if (optElem.offsetTop + offsetPadding < optWrapperElem.scrollTop || optElem.offsetTop + offsetPadding > optWrapperElem.scrollTop + optWrapperElem.clientHeight) {
1127
- optWrapperElem.scrollTop = optElem.offsetTop - offsetPadding
1128
- } else if (optElem.offsetTop + optElem.offsetHeight - optWrapperElem.scrollTop > wrapperHeight) {
1129
- optWrapperElem.scrollTop = optElem.offsetTop + optElem.offsetHeight - wrapperHeight
1130
- }
1131
- }
1132
- } else if (scrollYLoad) {
1133
- if (isDwArrow) {
1134
- optWrapperElem.scrollTop = avIndex * scrollYStore.rowHeight - optWrapperElem.clientHeight + scrollYStore.rowHeight
1135
- } else {
1136
- optWrapperElem.scrollTop = avIndex * scrollYStore.rowHeight
1137
- }
1138
- }
1139
- }
1140
- }
1141
- }
1142
- }
1143
-
1144
- /**
1145
- * 如果有滚动条,则滚动到对应的位置
1146
- * @param {Number} scrollLeft 左距离
1147
- * @param {Number} scrollTop 上距离
1148
- */
1149
- const scrollTo = (scrollLeft: number | null, scrollTop?: number | null) => {
1150
- const scrollBodyElem = refVirtualWrapper.value
1151
- if (scrollBodyElem) {
1152
- if (XEUtils.isNumber(scrollLeft)) {
1153
- scrollBodyElem.scrollLeft = scrollLeft
1154
- }
1155
- if (XEUtils.isNumber(scrollTop)) {
1156
- scrollBodyElem.scrollTop = scrollTop
1157
- }
1158
- }
1159
- if (reactData.scrollYLoad) {
1160
- return new Promise<void>(resolve => {
1161
- setTimeout(() => {
1162
- nextTick(() => {
1163
- resolve()
1164
- })
1165
- }, 50)
1166
- })
1167
- }
1168
- return nextTick()
1169
- }
1170
-
1171
- /**
1172
- * 刷新滚动条
1173
- */
1174
- const refreshScroll = () => {
1175
- const { lastScrollLeft, lastScrollTop } = internalData
1176
- return clearScroll().then(() => {
1177
- if (lastScrollLeft || lastScrollTop) {
1178
- internalData.lastScrollLeft = 0
1179
- internalData.lastScrollTop = 0
1180
- return scrollTo(lastScrollLeft, lastScrollTop)
1181
- }
1182
- })
1183
- }
1184
-
1185
- /**
1186
- * 重新计算列表
1187
- */
1188
- const recalculate = () => {
1189
- const el = refElem.value
1190
- if (el && el.clientWidth && el.clientHeight) {
1191
- return computeScrollLoad()
1192
- }
1193
- return Promise.resolve()
1194
- }
1195
-
1196
- const loadYData = (evnt: Event) => {
1197
- const { scrollYStore } = internalData
1198
- const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore
1199
- const scrollBodyElem = evnt.target as HTMLDivElement
1200
- const scrollTop = scrollBodyElem.scrollTop
1201
- const toVisibleIndex = Math.floor(scrollTop / rowHeight)
1202
- const offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize)
1203
- const offsetEndIndex = toVisibleIndex + visibleSize + offsetSize
1204
- if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
1205
- if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
1206
- scrollYStore.startIndex = offsetStartIndex
1207
- scrollYStore.endIndex = offsetEndIndex
1208
- updateYData()
1209
- }
1210
- }
1211
- }
1212
-
1213
- // 滚动、拖动过程中不需要触发
1214
- const isVMScrollProcess = () => {
1215
- const delayHover = 250
1216
- const { lastScrollTime } = internalData
1217
- return !!(lastScrollTime && Date.now() < lastScrollTime + delayHover)
1218
- }
1219
-
1220
- const scrollEvent = (evnt: Event) => {
1221
- const scrollBodyElem = evnt.target as HTMLDivElement
1222
- const scrollTop = scrollBodyElem.scrollTop
1223
- const scrollLeft = scrollBodyElem.scrollLeft
1224
- const isX = scrollLeft !== internalData.lastScrollLeft
1225
- const isY = scrollTop !== internalData.lastScrollTop
1226
- internalData.lastScrollTop = scrollTop
1227
- internalData.lastScrollLeft = scrollLeft
1228
- if (reactData.scrollYLoad) {
1229
- loadYData(evnt)
1230
- }
1231
- internalData.lastScrollTime = Date.now()
1232
- dispatchEvent('scroll', { scrollLeft, scrollTop, isX, isY }, evnt)
1233
- }
1234
-
1235
- /**
1236
- * 加载数据
1237
- * @param {Array} datas 数据
1238
- */
1239
- const loadData = (datas: any[]) => {
1240
- cacheItemMap(datas || [])
1241
- const { multiple } = props
1242
- const { isLoaded, fullData, scrollYStore } = internalData
1243
- const defaultOpts = computeDefaultOpts.value
1244
- const virtualYOpts = computeVirtualYOpts.value
1245
- const valueField = computeValueField.value
1246
- Object.assign(scrollYStore, {
1247
- startIndex: 0,
1248
- endIndex: 1,
1249
- visibleSize: 0
1250
- })
1251
- internalData.synchData = datas || []
1252
- // 如果gt为0,则总是启用
1253
- reactData.scrollYLoad = !!virtualYOpts.enabled && virtualYOpts.gt > -1 && (virtualYOpts.gt === 0 || virtualYOpts.gt <= fullData.length)
1254
- handleData()
1255
- if (!isLoaded) {
1256
- const { selectMode } = defaultOpts
1257
- if (datas.length > 0 && XEUtils.eqNull(props.modelValue)) {
1258
- if (selectMode === 'all') {
1259
- if (multiple) {
1260
- nextTick(() => {
1261
- emitDefaultValue(datas.map(item => item[valueField]))
1262
- })
1263
- } else {
1264
- errLog('vxe.error.notConflictProp', ['default-config.selectMode=all', 'multiple=true'])
1265
- }
1266
- } else if (selectMode === 'first' || selectMode === 'last') {
1267
- const selectItem = XEUtils[selectMode](datas)
1268
- if (selectItem) {
1269
- nextTick(() => {
1270
- if (XEUtils.eqNull(props.modelValue)) {
1271
- emitDefaultValue(selectItem[valueField])
1272
- }
1273
- })
1274
- }
1275
- }
1276
- internalData.isLoaded = true
1277
- }
1278
- }
1279
- return computeScrollLoad().then(() => {
1280
- refreshScroll()
1281
- })
1282
- }
1283
-
1284
- const clearScroll = () => {
1285
- const scrollBodyElem = refVirtualWrapper.value
1286
- if (scrollBodyElem) {
1287
- scrollBodyElem.scrollTop = 0
1288
- scrollBodyElem.scrollLeft = 0
1289
- }
1290
- internalData.lastScrollTop = 0
1291
- internalData.lastScrollLeft = 0
1292
- return nextTick()
1293
- }
1294
-
1295
- const hasOptGroupById = (optid: any) => {
1296
- const { optGroupKeyMaps } = internalData
1297
- return !!optGroupKeyMaps[optid]
1298
- }
1299
-
1300
- const selectMethods: SelectMethods = {
1301
- dispatchEvent,
1302
- loadData,
1303
- reloadData (datas) {
1304
- internalData.isLoaded = false
1305
- clearScroll()
1306
- return loadData(datas)
1307
- },
1308
- isPanelVisible () {
1309
- return reactData.visiblePanel
1310
- },
1311
- togglePanel () {
1312
- if (reactData.visiblePanel) {
1313
- hideOptionPanel()
1314
- } else {
1315
- showOptionPanel()
1316
- }
1317
- return nextTick()
1318
- },
1319
- hidePanel () {
1320
- if (reactData.visiblePanel) {
1321
- hideOptionPanel()
1322
- }
1323
- return nextTick()
1324
- },
1325
- showPanel () {
1326
- if (!reactData.visiblePanel) {
1327
- showOptionPanel()
1328
- }
1329
- return nextTick()
1330
- },
1331
- refreshOption () {
1332
- handleOption()
1333
- updateYData()
1334
- return nextTick()
1335
- },
1336
- focus () {
1337
- const $input = refInput.value
1338
- if ($input) {
1339
- $input.blur()
1340
- }
1341
- reactData.isActivated = true
1342
- return nextTick()
1343
- },
1344
- blur () {
1345
- const $input = refInput.value
1346
- if ($input) {
1347
- $input.blur()
1348
- }
1349
- reactData.isActivated = false
1350
- return nextTick()
1351
- },
1352
- recalculate,
1353
- clearScroll
1354
- }
1355
-
1356
- Object.assign($xeSelect, selectMethods)
1357
-
1358
- const renderOption = (list: VxeOptionProps[]) => {
1359
- const { allowCreate, optionKey } = props
1360
- const { currentOption } = reactData
1361
- const { optAddMaps } = internalData
1362
- const optionOpts = computeOptionOpts.value
1363
- const labelField = computeLabelField.value
1364
- const valueField = computeValueField.value
1365
- const groupLabelField = computeGroupLabelField.value
1366
- const selectVals = computeSelectVals.value
1367
- const { useKey, height } = optionOpts
1368
- const optionSlot = slots.option
1369
- return list.map((option, cIndex) => {
1370
- const { slots, className } = option
1371
- const optid = getOptId(option)
1372
- const optionValue = option[valueField as 'value']
1373
- const isOptGroup = hasOptGroupById(optid)
1374
- const isAdd = !!(allowCreate && optAddMaps[optid])
1375
- const isSelected = !isAdd && selectVals.indexOf(optionValue) > -1
1376
- const isVisible = isAdd || (!isOptGroup || isOptionVisible(option))
1377
- const isDisabled = !isAdd && checkOptionDisabled(isSelected, option)
1378
- const defaultSlot = slots ? slots.default : null
1379
- const optParams = { option, group: isOptGroup ? option : null, $select: $xeSelect }
1380
- let optLabel = ''
1381
- let optVNs: string | VxeComponentSlotType[] = []
1382
- if (optionSlot) {
1383
- optVNs = callSlot(optionSlot, optParams)
1384
- } else if (defaultSlot) {
1385
- optVNs = callSlot(defaultSlot, optParams)
1386
- } else {
1387
- optLabel = getFuncText(option[(isOptGroup ? groupLabelField : labelField) as 'label'] || optionValue)
1388
- optVNs = optLabel
1389
- }
1390
-
1391
- return isVisible
1392
- ? h('div', {
1393
- key: useKey || optionKey ? optid : cIndex,
1394
- class: ['vxe-select-option', className ? (XEUtils.isFunction(className) ? className(optParams) : className) : '', {
1395
- 'vxe-select-optgroup': isOptGroup,
1396
- 'is--disabled': isDisabled,
1397
- 'is--selected': isSelected,
1398
- 'is--add': isAdd,
1399
- 'is--hover': currentOption && getOptId(currentOption) === optid
1400
- }],
1401
- optid: optid,
1402
- title: optLabel || null,
1403
- style: height
1404
- ? {
1405
- height: toCssUnit(height)
1406
- }
1407
- : undefined,
1408
- onMousedown: (evnt: MouseEvent) => {
1409
- const isLeftBtn = evnt.button === 0
1410
- if (isLeftBtn) {
1411
- evnt.stopPropagation()
1412
- }
1413
- },
1414
- onClick: (evnt: MouseEvent) => {
1415
- if (!isDisabled && !isOptGroup) {
1416
- changeOptionEvent(evnt, option)
1417
- }
1418
- },
1419
- onMouseenter: () => {
1420
- if (!isDisabled && !isOptGroup && !isVMScrollProcess()) {
1421
- setCurrentOption(option)
1422
- }
1423
- }
1424
- }, allowCreate
1425
- ? [
1426
- h('span', {
1427
- key: 1,
1428
- class: 'vxe-select-option--label'
1429
- }, optVNs),
1430
- isAdd
1431
- ? h('span', {
1432
- key: 2,
1433
- class: 'vxe-select-option--add-icon'
1434
- }, [
1435
- h('i', {
1436
- class: getIcon().SELECT_ADD_OPTION
1437
- })
1438
- ])
1439
- : renderEmptyElement($xeSelect)
1440
- ]
1441
- : optVNs)
1442
- : renderEmptyElement($xeSelect)
1443
- })
1444
- }
1445
-
1446
- const renderOpts = () => {
1447
- const { optList, searchLoading } = reactData
1448
- if (searchLoading) {
1449
- return [
1450
- h('div', {
1451
- class: 'vxe-select--search-loading'
1452
- }, [
1453
- h('i', {
1454
- class: ['vxe-select--search-icon', getIcon().SELECT_LOADED]
1455
- }),
1456
- h('span', {
1457
- class: 'vxe-select--search-text'
1458
- }, getI18n('vxe.select.loadingText'))
1459
- ])
1460
- ]
1461
- }
1462
- if (optList.length) {
1463
- return renderOption(optList)
1464
- }
1465
- return [
1466
- h('div', {
1467
- class: 'vxe-select--empty-placeholder'
1468
- }, props.emptyText || getI18n('vxe.select.emptyText'))
1469
- ]
1470
- }
1471
-
1472
- const renderVN = () => {
1473
- const { className, multiple, loading, filterable, showTotalButoon, showCheckedButoon, showClearButton } = props
1474
- const { initialized, isActivated, isAniVisible, optList, visiblePanel, bodyHeight, topSpaceHeight } = reactData
1475
- const vSize = computeSize.value
1476
- const isDisabled = computeIsDisabled.value
1477
- const selectLabel = computeSelectLabel.value
1478
- const fullLabel = computeFullLabel.value
1479
- const btnTransfer = computeBtnTransfer.value
1480
- const formReadonly = computeFormReadonly.value
1481
- const inpPlaceholder = computeInpPlaceholder.value
1482
- const popupWrapperStyle = computePopupWrapperStyle.value
1483
- const popupOpts = computePopupOpts.value
1484
- const defaultSlot = slots.default
1485
- const headerSlot = slots.header
1486
- const footerSlot = slots.footer
1487
- const prefixSlot = slots.prefix
1488
- const ppClassName = popupOpts.className || props.popupClassName
1489
- if (formReadonly) {
1490
- return h('div', {
1491
- ref: refElem,
1492
- class: ['vxe-select--readonly', className]
1493
- }, [
1494
- h('div', {
1495
- class: 'vxe-select-slots',
1496
- ref: 'hideOption'
1497
- }, defaultSlot ? defaultSlot({}) : []),
1498
- h('span', {
1499
- class: 'vxe-select-label',
1500
- title: fullLabel
1501
- }, selectLabel)
1502
- ])
1503
- }
1504
- const selectVals = computeSelectVals.value
1505
- return h('div', {
1506
- ref: refElem,
1507
- class: ['vxe-select', className ? (XEUtils.isFunction(className) ? className({ $select: $xeSelect }) : className) : '', {
1508
- [`size--${vSize}`]: vSize,
1509
- 'is--visible': visiblePanel,
1510
- 'is--disabled': isDisabled,
1511
- 'is--filter': filterable,
1512
- 'is--loading': loading,
1513
- 'is--active': isActivated
1514
- }]
1515
- }, [
1516
- h('div', {
1517
- class: 'vxe-select-slots',
1518
- ref: 'hideOption'
1519
- }, defaultSlot ? defaultSlot({}) : []),
1520
- h(VxeInputComponent, {
1521
- ref: refInput,
1522
- clearable: props.clearable,
1523
- placeholder: inpPlaceholder,
1524
- editable: false,
1525
- disabled: isDisabled,
1526
- type: 'text',
1527
- prefixIcon: props.prefixIcon,
1528
- suffixIcon: loading ? getIcon().SELECT_LOADED : (visiblePanel ? getIcon().SELECT_OPEN : getIcon().SELECT_CLOSE),
1529
- autoFocus: false,
1530
- title: fullLabel,
1531
- modelValue: selectLabel,
1532
- onClear: clearEvent,
1533
- onClick: clickEvent,
1534
- onFocus: focusEvent,
1535
- onBlur: blurEvent,
1536
- onSuffixClick: suffixClickEvent
1537
- }, prefixSlot
1538
- ? {
1539
- prefix: () => prefixSlot({})
1540
- }
1541
- : {}),
1542
- h(Teleport, {
1543
- to: 'body',
1544
- disabled: btnTransfer ? !initialized : true
1545
- }, [
1546
- h('div', {
1547
- ref: refOptionPanel,
1548
- class: ['vxe-table--ignore-clear vxe-select--panel', ppClassName ? (XEUtils.isFunction(ppClassName) ? ppClassName({ $select: $xeSelect }) : ppClassName) : '', {
1549
- [`size--${vSize}`]: vSize,
1550
- 'is--transfer': btnTransfer,
1551
- 'ani--leave': !loading && isAniVisible,
1552
- 'ani--enter': !loading && visiblePanel
1553
- }],
1554
- placement: reactData.panelPlacement,
1555
- style: reactData.panelStyle
1556
- }, initialized && (visiblePanel || isAniVisible)
1557
- ? [
1558
- h('div', {
1559
- class: 'vxe-select--panel-wrapper',
1560
- style: popupWrapperStyle
1561
- }, [
1562
- filterable
1563
- ? h('div', {
1564
- class: 'vxe-select--panel-search'
1565
- }, [
1566
- h(VxeInputComponent, {
1567
- ref: refInpSearch,
1568
- class: 'vxe-select-search--input',
1569
- modelValue: reactData.searchValue,
1570
- type: 'text',
1571
- clearable: true,
1572
- disabled: false,
1573
- readonly: false,
1574
- placeholder: getI18n('vxe.select.search'),
1575
- prefixIcon: getIcon().INPUT_SEARCH,
1576
- 'onUpdate:modelValue': modelSearchEvent,
1577
- onFocus: focusSearchEvent,
1578
- onChange: triggerSearchEvent,
1579
- onSearch: triggerSearchEvent
1580
- })
1581
- ])
1582
- : renderEmptyElement($xeSelect),
1583
- showTotalButoon || (showCheckedButoon && multiple) || showClearButton || headerSlot
1584
- ? h('div', {
1585
- class: 'vxe-select--panel-header'
1586
- }, headerSlot
1587
- ? callSlot(headerSlot, {})
1588
- : [
1589
- h('div', {
1590
- class: 'vxe-select--header-button'
1591
- }, [
1592
- showTotalButoon
1593
- ? h('div', {
1594
- class: 'vxe-select--header-total'
1595
- }, getI18n('vxe.select.total', [selectVals.length, optList.length]))
1596
- : renderEmptyElement($xeSelect),
1597
- h('div', {
1598
- class: 'vxe-select--header-btns'
1599
- }, [
1600
- (showCheckedButoon && multiple)
1601
- ? h(VxeButtonComponent, {
1602
- content: getI18n('vxe.select.allChecked'),
1603
- mode: 'text',
1604
- onClick: allCheckedPanelEvent
1605
- })
1606
- : renderEmptyElement($xeSelect),
1607
- showClearButton
1608
- ? h(VxeButtonComponent, {
1609
- content: getI18n('vxe.select.clear'),
1610
- mode: 'text',
1611
- onClick: clearCheckedPanelEvent
1612
- })
1613
- : renderEmptyElement($xeSelect)
1614
- ])
1615
- ])
1616
- ])
1617
- : renderEmptyElement($xeSelect),
1618
- h('div', {
1619
- class: 'vxe-select--panel-body'
1620
- }, [
1621
- h('div', {
1622
- ref: refVirtualWrapper,
1623
- class: 'vxe-select-option--wrapper',
1624
- onScroll: scrollEvent
1625
- }, [
1626
- h('div', {
1627
- class: 'vxe-select--y-space',
1628
- style: {
1629
- height: bodyHeight ? `${bodyHeight}px` : ''
1630
- }
1631
- }),
1632
- h('div', {
1633
- ref: refVirtualBody,
1634
- class: 'vxe-select--body',
1635
- style: {
1636
- transform: `translateY(${topSpaceHeight}px)`
1637
- }
1638
- }, renderOpts())
1639
- ])
1640
- ]),
1641
- footerSlot
1642
- ? h('div', {
1643
- class: 'vxe-select--panel-footer'
1644
- }, callSlot(footerSlot, {}))
1645
- : renderEmptyElement($xeSelect)
1646
- ])
1647
- ]
1648
- : [])
1649
- ])
1650
- ])
1651
- }
1652
-
1653
- watch(() => reactData.staticOptions, (val) => {
1654
- loadData(val)
1655
- })
1656
-
1657
- watch(() => props.options, (val) => {
1658
- loadData(val || [])
1659
- })
1660
-
1661
- watch(() => props.optionGroups, (val) => {
1662
- loadData(val || [])
1663
- })
1664
-
1665
- onMounted(() => {
1666
- nextTick(() => {
1667
- const { options, optionGroups } = props
1668
- if (optionGroups) {
1669
- loadData(optionGroups)
1670
- } else if (options) {
1671
- loadData(options)
1672
- }
1673
- })
1674
- globalEvents.on($xeSelect, 'mousewheel', handleGlobalMousewheelEvent)
1675
- globalEvents.on($xeSelect, 'mousedown', handleGlobalMousedownEvent)
1676
- globalEvents.on($xeSelect, 'keydown', handleGlobalKeydownEvent)
1677
- globalEvents.on($xeSelect, 'blur', handleGlobalBlurEvent)
1678
- globalEvents.on($xeSelect, 'resize', handleGlobalResizeEvent)
1679
- })
1680
-
1681
- onUnmounted(() => {
1682
- globalEvents.off($xeSelect, 'mousewheel')
1683
- globalEvents.off($xeSelect, 'mousedown')
1684
- globalEvents.off($xeSelect, 'keydown')
1685
- globalEvents.off($xeSelect, 'blur')
1686
- globalEvents.off($xeSelect, 'resize')
1687
- XEUtils.assign(internalData, createInternalData())
1688
- })
1689
-
1690
- provide('$xeSelect', $xeSelect)
1691
-
1692
- $xeSelect.renderVN = renderVN
1693
-
1694
- return $xeSelect
1695
- },
1696
- render () {
1697
- return this.renderVN()
1698
- }
1699
- })
1
+ import { h, Teleport, PropType, ref, inject, computed, provide, onUnmounted, reactive, nextTick, watch, onMounted } from 'vue'
2
+ import { defineVxeComponent } from '../../ui/src/comp'
3
+ import XEUtils from 'xe-utils'
4
+ import { VxeUI, getConfig, getIcon, getI18n, globalEvents, GLOBAL_EVENT_KEYS, createEvent, useSize, renderEmptyElement } from '../../ui'
5
+ import { getEventTargetNode, toCssUnit, updatePanelPlacement } from '../../ui/src/dom'
6
+ import { getLastZIndex, nextZIndex, getFuncText, eqEmptyValue } from '../../ui/src/utils'
7
+ import { getSlotVNs } from '../../ui/src/vn'
8
+ import { errLog } from '../../ui/src/log'
9
+ import VxeInputComponent from '../../input/src/input'
10
+ import VxeButtonComponent from '../../button/src/button'
11
+
12
+ import type { VxeSelectPropTypes, VxeSelectConstructor, SelectInternalData, SelectReactData, VxeSelectDefines, VxeButtonEvents, ValueOf, VxeSelectEmits, VxeComponentSlotType, VxeInputConstructor, SelectMethods, SelectPrivateRef, VxeSelectMethods, VxeOptionProps, VxeDrawerConstructor, VxeDrawerMethods, VxeFormDefines, VxeFormConstructor, VxeFormPrivateMethods, VxeModalConstructor, VxeModalMethods, VxeInputEvents, VxeComponentStyleType } from '../../../types'
13
+ import type { VxeTableConstructor, VxeTablePrivateMethods } from '../../../types/components/table'
14
+
15
+ function isOptionVisible (option: any) {
16
+ return option.visible !== false
17
+ }
18
+
19
+ function getOptUniqueId () {
20
+ return XEUtils.uniqueId('opt_')
21
+ }
22
+
23
+ function createInternalData (): SelectInternalData {
24
+ return {
25
+ // isLoaded: false,
26
+ synchData: [],
27
+ fullData: [],
28
+ afterVisibleList: [],
29
+ optAddMaps: {},
30
+ optGroupKeyMaps: {},
31
+ optFullValMaps: {},
32
+ remoteValMaps: {},
33
+
34
+ lastScrollLeft: 0,
35
+ lastScrollTop: 0,
36
+ scrollYStore: {
37
+ startIndex: 0,
38
+ endIndex: 0,
39
+ visibleSize: 0,
40
+ offsetSize: 0,
41
+ rowHeight: 0
42
+ },
43
+
44
+ lastScrollTime: 0,
45
+ hpTimeout: undefined
46
+ }
47
+ }
48
+
49
+ export default defineVxeComponent({
50
+ name: 'VxeSelect',
51
+ props: {
52
+ modelValue: [String, Number, Boolean, Array] as PropType<VxeSelectPropTypes.ModelValue>,
53
+ defaultConfig: Object as PropType<VxeSelectPropTypes.DefaultConfig>,
54
+ clearable: Boolean as PropType<VxeSelectPropTypes.Clearable>,
55
+ placeholder: String as PropType<VxeSelectPropTypes.Placeholder>,
56
+ readonly: {
57
+ type: Boolean as PropType<VxeSelectPropTypes.Readonly>,
58
+ default: null
59
+ },
60
+ loading: Boolean as PropType<VxeSelectPropTypes.Loading>,
61
+ disabled: {
62
+ type: Boolean as PropType<VxeSelectPropTypes.Disabled>,
63
+ default: null
64
+ },
65
+ multiple: Boolean as PropType<VxeSelectPropTypes.Multiple>,
66
+ multiCharOverflow: {
67
+ type: [Number, String] as PropType<VxeSelectPropTypes.MultiCharOverflow>,
68
+ default: () => getConfig().select.multiCharOverflow
69
+ },
70
+ prefixIcon: String as PropType<VxeSelectPropTypes.PrefixIcon>,
71
+ allowCreate: {
72
+ type: Boolean as PropType<VxeSelectPropTypes.AllowCreate>,
73
+ default: () => getConfig().select.allowCreate
74
+ },
75
+ placement: String as PropType<VxeSelectPropTypes.Placement>,
76
+ lazyOptions: Array as PropType<VxeSelectPropTypes.LazyOptions>,
77
+ options: Array as PropType<VxeSelectPropTypes.Options>,
78
+ optionProps: Object as PropType<VxeSelectPropTypes.OptionProps>,
79
+ optionGroups: Array as PropType<VxeSelectPropTypes.OptionGroups>,
80
+ optionGroupProps: Object as PropType<VxeSelectPropTypes.OptionGroupProps>,
81
+ optionConfig: Object as PropType<VxeSelectPropTypes.OptionConfig>,
82
+ className: [String, Function] as PropType<VxeSelectPropTypes.ClassName>,
83
+ /**
84
+ * 已废弃,请使用 popupConfig.className
85
+ * @deprecated
86
+ */
87
+ popupClassName: [String, Function] as PropType<VxeSelectPropTypes.PopupClassName>,
88
+ max: {
89
+ type: [String, Number] as PropType<VxeSelectPropTypes.Max>,
90
+ default: null
91
+ },
92
+ /**
93
+ * 已废弃,请使用 popupConfig.zIndex
94
+ * @deprecated
95
+ */
96
+ zIndex: Number as PropType<VxeSelectPropTypes.ZIndex>,
97
+ size: {
98
+ type: String as PropType<VxeSelectPropTypes.Size>,
99
+ default: () => getConfig().select.size || getConfig().size
100
+ },
101
+ filterable: Boolean as PropType<VxeSelectPropTypes.Filterable>,
102
+ /**
103
+ * 已废弃,被 filter-config.filterMethod 替换
104
+ * @deprecated
105
+ */
106
+ filterMethod: Function as PropType<VxeSelectPropTypes.FilterMethod>,
107
+ filterConfig: Object as PropType<VxeSelectPropTypes.FilterConfig>,
108
+ remote: Boolean as PropType<VxeSelectPropTypes.Remote>,
109
+ remoteConfig: Object as PropType<VxeSelectPropTypes.RemoteConfig>,
110
+ emptyText: String as PropType<VxeSelectPropTypes.EmptyText>,
111
+ showTotalButoon: {
112
+ type: Boolean as PropType<VxeSelectPropTypes.ShowTotalButoon>,
113
+ default: () => getConfig().select.showTotalButoon
114
+ },
115
+ showCheckedButoon: {
116
+ type: Boolean as PropType<VxeSelectPropTypes.ShowCheckedButoon>,
117
+ default: () => getConfig().select.showCheckedButoon
118
+ },
119
+ showClearButton: {
120
+ type: Boolean as PropType<VxeSelectPropTypes.ShowClearButton>,
121
+ default: () => getConfig().select.showClearButton
122
+ },
123
+ transfer: {
124
+ type: Boolean as PropType<VxeSelectPropTypes.Transfer>,
125
+ default: null
126
+ },
127
+ popupConfig: Object as PropType<VxeSelectPropTypes.PopupConfig>,
128
+ virtualYConfig: Object as PropType<VxeSelectPropTypes.VirtualYConfig>,
129
+ scrollY: Object as PropType<VxeSelectPropTypes.ScrollY>,
130
+
131
+ /**
132
+ * 已废弃,被 remote-config.queryMethod 替换
133
+ * @deprecated
134
+ */
135
+ remoteMethod: Function as PropType<VxeSelectPropTypes.RemoteMethod>,
136
+ /**
137
+ * 已废弃,被 option-config.keyField 替换
138
+ * @deprecated
139
+ */
140
+ optionId: {
141
+ type: String as PropType<VxeSelectPropTypes.OptionId>,
142
+ default: () => getConfig().select.optionId
143
+ },
144
+ /**
145
+ * 已废弃,被 option-config.useKey 替换
146
+ * @deprecated
147
+ */
148
+ optionKey: Boolean as PropType<VxeSelectPropTypes.OptionKey>
149
+ },
150
+ emits: [
151
+ 'update:modelValue',
152
+ 'change',
153
+ 'default-change',
154
+ 'all-change',
155
+ 'clear',
156
+ 'blur',
157
+ 'focus',
158
+ 'click',
159
+ 'scroll',
160
+ 'visible-change'
161
+ ] as VxeSelectEmits,
162
+ setup (props, context) {
163
+ const { slots, emit } = context
164
+
165
+ const $xeModal = inject<(VxeModalConstructor & VxeModalMethods)| null>('$xeModal', null)
166
+ const $xeDrawer = inject<(VxeDrawerConstructor & VxeDrawerMethods) | null>('$xeDrawer', null)
167
+ const $xeTable = inject<(VxeTableConstructor & VxeTablePrivateMethods) | null>('$xeTable', null)
168
+ const $xeForm = inject<(VxeFormConstructor & VxeFormPrivateMethods)| null>('$xeForm', null)
169
+ const formItemInfo = inject<VxeFormDefines.ProvideItemInfo | null>('xeFormItemInfo', null)
170
+
171
+ const xID = XEUtils.uniqueId()
172
+
173
+ const refElem = ref<HTMLDivElement>()
174
+ const refInput = ref<VxeInputConstructor>()
175
+ const refInpSearch = ref<VxeInputConstructor>()
176
+ const refVirtualWrapper = ref<HTMLDivElement>()
177
+ const refOptionPanel = ref<HTMLDivElement>()
178
+ const refVirtualBody = ref<HTMLDivElement>()
179
+
180
+ const { computeSize } = useSize(props)
181
+
182
+ const reactData = reactive<SelectReactData>({
183
+ initialized: false,
184
+ scrollYLoad: false,
185
+ bodyHeight: 0,
186
+ topSpaceHeight: 0,
187
+ optList: [],
188
+ staticOptions: [],
189
+ reactFlag: 0,
190
+
191
+ currentOption: null,
192
+ searchValue: '',
193
+ searchLoading: false,
194
+
195
+ panelIndex: 0,
196
+ panelStyle: {},
197
+ panelPlacement: null,
198
+ triggerFocusPanel: false,
199
+ visiblePanel: false,
200
+ isAniVisible: false,
201
+ isActivated: false
202
+ })
203
+
204
+ const internalData = createInternalData()
205
+
206
+ const refMaps: SelectPrivateRef = {
207
+ refElem
208
+ }
209
+
210
+ const $xeSelect = {
211
+ xID,
212
+ props,
213
+ context,
214
+ reactData,
215
+ internalData,
216
+ getRefMaps: () => refMaps
217
+ } as unknown as VxeSelectConstructor & VxeSelectMethods
218
+
219
+ const computeFormReadonly = computed(() => {
220
+ const { readonly } = props
221
+ if (readonly === null) {
222
+ if ($xeForm) {
223
+ return $xeForm.props.readonly
224
+ }
225
+ return false
226
+ }
227
+ return readonly
228
+ })
229
+
230
+ const computeIsDisabled = computed(() => {
231
+ const { disabled } = props
232
+ if (disabled === null) {
233
+ if ($xeForm) {
234
+ return $xeForm.props.disabled
235
+ }
236
+ return false
237
+ }
238
+ return disabled
239
+ })
240
+
241
+ const computeBtnTransfer = computed(() => {
242
+ const { transfer } = props
243
+ const popupOpts = computePopupOpts.value
244
+ if (XEUtils.isBoolean(popupOpts.transfer)) {
245
+ return popupOpts.transfer
246
+ }
247
+ if (transfer === null) {
248
+ const globalTransfer = getConfig().select.transfer
249
+ if (XEUtils.isBoolean(globalTransfer)) {
250
+ return globalTransfer
251
+ }
252
+ if ($xeTable || $xeModal || $xeDrawer || $xeForm) {
253
+ return true
254
+ }
255
+ }
256
+ return transfer
257
+ })
258
+
259
+ const computeInpPlaceholder = computed(() => {
260
+ const { placeholder } = props
261
+ if (placeholder) {
262
+ return getFuncText(placeholder)
263
+ }
264
+ const globalPlaceholder = getConfig().select.placeholder
265
+ if (globalPlaceholder) {
266
+ return getFuncText(globalPlaceholder)
267
+ }
268
+ return getI18n('vxe.base.pleaseSelect')
269
+ })
270
+
271
+ const computeDefaultOpts = computed(() => {
272
+ return Object.assign({}, props.defaultConfig)
273
+ })
274
+ const computePropsOpts = computed(() => {
275
+ return Object.assign({}, props.optionProps)
276
+ })
277
+
278
+ const computeGroupPropsOpts = computed(() => {
279
+ return Object.assign({}, props.optionGroupProps)
280
+ })
281
+
282
+ const computeLabelField = computed(() => {
283
+ const propsOpts = computePropsOpts.value
284
+ return propsOpts.label || 'label'
285
+ })
286
+
287
+ const computeValueField = computed(() => {
288
+ const propsOpts = computePropsOpts.value
289
+ return propsOpts.value || 'value'
290
+ })
291
+
292
+ const computeGroupLabelField = computed(() => {
293
+ const groupPropsOpts = computeGroupPropsOpts.value
294
+ return groupPropsOpts.label || 'label'
295
+ })
296
+
297
+ const computeGroupOptionsField = computed(() => {
298
+ const groupPropsOpts = computeGroupPropsOpts.value
299
+ return groupPropsOpts.options || 'options'
300
+ })
301
+
302
+ const computeIsMaximize = computed(() => {
303
+ const selectVals = computeSelectVals.value
304
+ return checkMaxLimit(selectVals)
305
+ })
306
+
307
+ const computePopupOpts = computed(() => {
308
+ return Object.assign({}, getConfig().select.popupConfig, props.popupConfig)
309
+ })
310
+
311
+ const computeVirtualYOpts = computed(() => {
312
+ return Object.assign({} as { gt: number }, getConfig().select.virtualYConfig || getConfig().select.scrollY, props.virtualYConfig || props.scrollY)
313
+ })
314
+
315
+ const computeRemoteOpts = computed(() => {
316
+ return Object.assign({}, getConfig().select.remoteConfig, props.remoteConfig)
317
+ })
318
+
319
+ const computeFilterOpts = computed(() => {
320
+ return Object.assign({}, getConfig().select.filterConfig, props.filterConfig)
321
+ })
322
+
323
+ const computeOptionOpts = computed(() => {
324
+ return Object.assign({}, getConfig().select.optionConfig, props.optionConfig)
325
+ })
326
+
327
+ const computeMultiMaxCharNum = computed(() => {
328
+ return XEUtils.toNumber(props.multiCharOverflow)
329
+ })
330
+
331
+ const computePopupWrapperStyle = computed(() => {
332
+ const popupOpts = computePopupOpts.value
333
+ const { height, width } = popupOpts
334
+ const stys: VxeComponentStyleType = {}
335
+ if (width) {
336
+ stys.width = toCssUnit(width)
337
+ }
338
+ if (height) {
339
+ stys.height = toCssUnit(height)
340
+ stys.maxHeight = toCssUnit(height)
341
+ }
342
+ return stys
343
+ })
344
+
345
+ const computeSelectVals = computed(() => {
346
+ const { modelValue, multiple } = props
347
+ let vals: (string | number | boolean)[] = []
348
+ if (XEUtils.isArray(modelValue)) {
349
+ vals = modelValue
350
+ } else {
351
+ if (multiple) {
352
+ if (!eqEmptyValue(modelValue)) {
353
+ vals = `${modelValue}`.indexOf(',') > -1 ? `${modelValue}`.split(',') : [modelValue] as any[]
354
+ }
355
+ } else {
356
+ vals = modelValue === null || modelValue === undefined ? [] : [modelValue]
357
+ }
358
+ }
359
+ return vals
360
+ })
361
+
362
+ const computeFullLabel = computed(() => {
363
+ const { remote } = props
364
+ const { reactFlag } = reactData
365
+ const selectVals = computeSelectVals.value
366
+ if (remote && reactFlag) {
367
+ return selectVals.map(val => getRemoteSelectLabel(val)).join(', ')
368
+ }
369
+ return selectVals.map((val) => getSelectLabel(val)).join(', ')
370
+ })
371
+
372
+ const computeSelectLabel = computed(() => {
373
+ const { remote, multiple } = props
374
+ const { reactFlag } = reactData
375
+ const multiMaxCharNum = computeMultiMaxCharNum.value
376
+ const selectVals = computeSelectVals.value
377
+ if (remote && reactFlag) {
378
+ return selectVals.map(val => getRemoteSelectLabel(val)).join(', ')
379
+ }
380
+ const labels = selectVals.map((val) => getSelectLabel(val))
381
+ if (multiple && multiMaxCharNum > 0 && labels.length > multiMaxCharNum) {
382
+ return `${labels.slice(0, multiMaxCharNum)}...`
383
+ }
384
+ return labels.join(', ')
385
+ })
386
+
387
+ const callSlot = <T>(slotFunc: ((params: T) => VxeComponentSlotType | VxeComponentSlotType[]) | string | null, params: T) => {
388
+ if (slotFunc) {
389
+ if (XEUtils.isString(slotFunc)) {
390
+ slotFunc = slots[slotFunc] || null
391
+ }
392
+ if (XEUtils.isFunction(slotFunc)) {
393
+ return getSlotVNs(slotFunc(params))
394
+ }
395
+ }
396
+ return []
397
+ }
398
+
399
+ const dispatchEvent = (type: ValueOf<VxeSelectEmits>, params: Record<string, any>, evnt: Event | null) => {
400
+ emit(type, createEvent(evnt, { $select: $xeSelect }, params))
401
+ }
402
+
403
+ const emitModel = (value: any) => {
404
+ emit('update:modelValue', value)
405
+ }
406
+
407
+ const emitDefaultValue = (value: any) => {
408
+ emitModel(value)
409
+ dispatchEvent('default-change', { value }, null)
410
+ }
411
+
412
+ const getOptKey = () => {
413
+ const optionOpts = computeOptionOpts.value
414
+ return optionOpts.keyField || props.optionId || '_X_OPTION_KEY'
415
+ }
416
+
417
+ const getOptId = (option: any) => {
418
+ const optid = option[getOptKey()]
419
+ return optid ? encodeURIComponent(optid) : ''
420
+ }
421
+
422
+ const checkMaxLimit = (selectVals: VxeSelectPropTypes.ModelValue[]) => {
423
+ const { multiple, max } = props
424
+ if (multiple && max) {
425
+ return selectVals.length >= XEUtils.toNumber(max)
426
+ }
427
+ return false
428
+ }
429
+
430
+ const getRemoteSelectLabel = (value: any) => {
431
+ const { lazyOptions } = props
432
+ const { remoteValMaps, optFullValMaps } = internalData
433
+ const valueField = computeValueField.value
434
+ const labelField = computeLabelField.value
435
+ const remoteItem = remoteValMaps[value] || optFullValMaps[value]
436
+ const item = remoteItem ? remoteItem.item : null
437
+ if (item) {
438
+ return XEUtils.toValueString(item[labelField])
439
+ }
440
+ if (lazyOptions) {
441
+ const lazyItem = lazyOptions.find(item => item[valueField] === value)
442
+ if (lazyItem) {
443
+ return lazyItem[labelField]
444
+ }
445
+ }
446
+ return value
447
+ }
448
+
449
+ const getSelectLabel = (value: any) => {
450
+ const { lazyOptions } = props
451
+ const { optFullValMaps } = internalData
452
+ const valueField = computeValueField.value
453
+ const labelField = computeLabelField.value
454
+ const cacheItem = reactData.reactFlag ? optFullValMaps[value] : null
455
+ if (cacheItem) {
456
+ return cacheItem.item[labelField as 'label']
457
+ }
458
+ if (lazyOptions) {
459
+ const lazyItem = lazyOptions.find(item => item[valueField] === value)
460
+ if (lazyItem) {
461
+ return lazyItem[labelField]
462
+ }
463
+ }
464
+ return value
465
+ }
466
+
467
+ const cacheItemMap = (datas: any[]) => {
468
+ const groupOptionsField = computeGroupOptionsField.value
469
+ const valueField = computeValueField.value
470
+ const key = getOptKey()
471
+ const groupKeyMaps: Record<string, any> = {}
472
+ const fullKeyMaps: Record<string, VxeSelectDefines.OptCacheItem> = {}
473
+ const list: any[] = []
474
+ const handleOptItem = (item: any) => {
475
+ list.push(item)
476
+ let optid = getOptId(item)
477
+ if (!optid) {
478
+ optid = getOptUniqueId()
479
+ item[key] = optid
480
+ }
481
+ fullKeyMaps[item[valueField]] = {
482
+ key: optid,
483
+ item,
484
+ _index: -1
485
+ }
486
+ }
487
+ datas.forEach((group: any) => {
488
+ handleOptItem(group)
489
+ if (group[groupOptionsField]) {
490
+ groupKeyMaps[group[key]] = group
491
+ group[groupOptionsField].forEach(handleOptItem)
492
+ }
493
+ })
494
+ internalData.fullData = list
495
+ internalData.optGroupKeyMaps = groupKeyMaps
496
+ internalData.optFullValMaps = fullKeyMaps
497
+ reactData.reactFlag++
498
+ handleOption()
499
+ }
500
+
501
+ /**
502
+ * 处理选项,当选项被动态显示/隐藏时可能会用到
503
+ */
504
+ const handleOption = () => {
505
+ const { remote, modelValue, filterable } = props
506
+ const { searchValue } = reactData
507
+ const { fullData, optFullValMaps } = internalData
508
+ const labelField = computeLabelField.value
509
+ const valueField = computeValueField.value
510
+ const filterOpts = computeFilterOpts.value
511
+ const frMethod = filterOpts.filterMethod || props.filterMethod
512
+ const searchStr = `${searchValue || ''}`.toLowerCase()
513
+ let avList: any[] = []
514
+ if (remote) {
515
+ avList = fullData.filter(isOptionVisible)
516
+ } else {
517
+ if (filterable && frMethod) {
518
+ avList = fullData.filter(option => isOptionVisible(option) && frMethod({ $select: $xeSelect, group: null, option, searchValue, value: modelValue }))
519
+ } else if (filterable) {
520
+ avList = fullData.filter(option => isOptionVisible(option) && (!searchStr || `${option[labelField] || option[valueField]}`.toLowerCase().indexOf(searchStr) > -1))
521
+ } else {
522
+ avList = fullData.filter(isOptionVisible)
523
+ }
524
+ }
525
+ avList.forEach((item, index) => {
526
+ const cacheItem = optFullValMaps[item[valueField]]
527
+ if (cacheItem) {
528
+ cacheItem._index = index
529
+ }
530
+ })
531
+ internalData.afterVisibleList = avList
532
+ return nextTick()
533
+ }
534
+
535
+ const setCurrentOption = (option: any) => {
536
+ if (option) {
537
+ reactData.currentOption = option
538
+ }
539
+ }
540
+
541
+ const updateZIndex = () => {
542
+ const popupOpts = computePopupOpts.value
543
+ const customZIndex = popupOpts.zIndex || props.zIndex
544
+ if (customZIndex) {
545
+ reactData.panelIndex = XEUtils.toNumber(customZIndex)
546
+ } else if (reactData.panelIndex < getLastZIndex()) {
547
+ reactData.panelIndex = nextZIndex()
548
+ }
549
+ }
550
+
551
+ const updatePlacement = () => {
552
+ const { placement } = props
553
+ const { panelIndex } = reactData
554
+ const targetElem = refElem.value
555
+ const panelElem = refOptionPanel.value
556
+ const btnTransfer = computeBtnTransfer.value
557
+ const popupOpts = computePopupOpts.value
558
+ const handleStyle = () => {
559
+ const ppObj = updatePanelPlacement(targetElem, panelElem, {
560
+ placement: popupOpts.placement || placement,
561
+ defaultPlacement: popupOpts.defaultPlacement,
562
+ teleportTo: btnTransfer
563
+ })
564
+ const panelStyle: { [key: string]: string | number } = Object.assign(ppObj.style, {
565
+ zIndex: panelIndex
566
+ })
567
+ reactData.panelStyle = panelStyle
568
+ reactData.panelPlacement = ppObj.placement
569
+ }
570
+ handleStyle()
571
+ return nextTick().then(handleStyle)
572
+ }
573
+
574
+ const handleScrollSelect = () => {
575
+ nextTick(() => {
576
+ const { isAniVisible, visiblePanel } = reactData
577
+ const { optFullValMaps } = internalData
578
+ const selectVals = computeSelectVals.value
579
+ if (selectVals.length && isAniVisible && visiblePanel) {
580
+ const cacheItem = reactData.reactFlag ? optFullValMaps[`${selectVals[0]}`] : null
581
+ if (cacheItem) {
582
+ handleScrollToOption(cacheItem.item)
583
+ }
584
+ }
585
+ })
586
+ }
587
+
588
+ const showOptionPanel = () => {
589
+ const { loading, filterable, remote } = props
590
+ const { fullData, hpTimeout } = internalData
591
+ const isDisabled = computeIsDisabled.value
592
+ const remoteOpts = computeRemoteOpts.value
593
+ if (!loading && !isDisabled) {
594
+ if (hpTimeout) {
595
+ clearTimeout(hpTimeout)
596
+ internalData.hpTimeout = undefined
597
+ }
598
+ if (!reactData.initialized) {
599
+ reactData.initialized = true
600
+ }
601
+ reactData.isActivated = true
602
+ reactData.isAniVisible = true
603
+ if (filterable) {
604
+ if (remote && remoteOpts.enabled && ((remoteOpts.autoLoad && !fullData.length) || (fullData.length && remoteOpts.clearOnClose))) {
605
+ handleSearchEvent()
606
+ } else {
607
+ handleOption()
608
+ updateYData()
609
+ }
610
+ }
611
+ setTimeout(() => {
612
+ reactData.visiblePanel = true
613
+ handleFocusSearch()
614
+ recalculate().then(() => {
615
+ handleScrollSelect()
616
+ refreshScroll()
617
+ })
618
+ updatePlacement()
619
+ }, 10)
620
+ setTimeout(() => {
621
+ recalculate().then(() => refreshScroll())
622
+ }, 100)
623
+ updateZIndex()
624
+ updatePlacement()
625
+ dispatchEvent('visible-change', { visible: true }, null)
626
+ }
627
+ }
628
+
629
+ const hideOptionPanel = () => {
630
+ const { filterable, remote } = props
631
+ const filterOpts = computeFilterOpts.value
632
+ const remoteOpts = computeRemoteOpts.value
633
+ if (remote) {
634
+ if (remoteOpts.clearOnClose) {
635
+ reactData.searchValue = ''
636
+ }
637
+ } else if (filterable) {
638
+ if (filterOpts.clearOnClose) {
639
+ reactData.searchValue = ''
640
+ }
641
+ } else {
642
+ reactData.searchValue = ''
643
+ }
644
+ reactData.searchLoading = false
645
+ reactData.visiblePanel = false
646
+ internalData.hpTimeout = setTimeout(() => {
647
+ reactData.isAniVisible = false
648
+ }, 350)
649
+ dispatchEvent('visible-change', { visible: false }, null)
650
+ }
651
+
652
+ const changeEvent = (evnt: Event, selectValue: any, option: any) => {
653
+ emitModel(selectValue)
654
+ if (selectValue !== props.modelValue) {
655
+ dispatchEvent('change', { value: selectValue, option }, evnt)
656
+ // 自动更新校验状态
657
+ if ($xeForm && formItemInfo) {
658
+ $xeForm.triggerItemEvent(evnt, formItemInfo.itemConfig.field, selectValue)
659
+ }
660
+ }
661
+ }
662
+
663
+ const clearValueEvent = (evnt: Event, selectValue: any) => {
664
+ internalData.remoteValMaps = {}
665
+ changeEvent(evnt, selectValue, null)
666
+ dispatchEvent('clear', { value: selectValue }, evnt)
667
+ }
668
+
669
+ const clearEvent: VxeInputEvents.Clear = (params) => {
670
+ const { $event } = params
671
+ clearValueEvent($event, null)
672
+ hideOptionPanel()
673
+ }
674
+
675
+ const allCheckedPanelEvent: VxeButtonEvents.Click = (params) => {
676
+ const { $event } = params
677
+ const { multiple, max } = props
678
+ const { optList } = reactData
679
+ const valueField = computeValueField.value
680
+ if (multiple) {
681
+ const selectVals = computeSelectVals.value
682
+ const currVlas = selectVals.slice(0)
683
+ for (let i = 0; i < optList.length; i++) {
684
+ const option = optList[i]
685
+ const selectValue = option[valueField]
686
+ // 检测是否超过最大可选数量
687
+ if (checkMaxLimit(currVlas)) {
688
+ if (VxeUI) {
689
+ VxeUI.modal.message({
690
+ content: getI18n('vxe.select.overSizeErr', [max]),
691
+ status: 'warning'
692
+ })
693
+ }
694
+ break
695
+ }
696
+ if (!currVlas.some(val => val === selectValue)) {
697
+ currVlas.push(selectValue)
698
+ }
699
+ }
700
+ changeEvent($event, currVlas, optList[0])
701
+ dispatchEvent('all-change', { value: currVlas }, $event)
702
+ }
703
+ }
704
+
705
+ const clearCheckedPanelEvent: VxeButtonEvents.Click = (params) => {
706
+ const { $event } = params
707
+ clearValueEvent($event, null)
708
+ hideOptionPanel()
709
+ }
710
+
711
+ const changeOptionEvent = (evnt: Event, option: any) => {
712
+ const { multiple } = props
713
+ const { remoteValMaps } = internalData
714
+ const valueField = computeValueField.value
715
+ const selectValue = option[valueField]
716
+ const remoteItem = remoteValMaps[selectValue]
717
+ if (!reactData.visiblePanel) {
718
+ return
719
+ }
720
+ if (remoteItem) {
721
+ remoteItem.item = option
722
+ } else {
723
+ remoteValMaps[selectValue] = {
724
+ key: getOptId(option),
725
+ item: option,
726
+ _index: -1
727
+ }
728
+ }
729
+ if (multiple) {
730
+ let multipleValue: any[] = []
731
+ const selectVals = computeSelectVals.value
732
+ const index = XEUtils.findIndexOf(selectVals, val => val === selectValue)
733
+ if (index === -1) {
734
+ multipleValue = selectVals.concat([selectValue])
735
+ } else {
736
+ multipleValue = selectVals.filter((val) => val !== selectValue)
737
+ }
738
+ changeEvent(evnt, multipleValue, option)
739
+ } else {
740
+ changeEvent(evnt, selectValue, option)
741
+ hideOptionPanel()
742
+ }
743
+ reactData.reactFlag++
744
+ }
745
+
746
+ const handleGlobalMousewheelEvent = (evnt: MouseEvent) => {
747
+ const { visiblePanel } = reactData
748
+ const isDisabled = computeIsDisabled.value
749
+ if (!isDisabled) {
750
+ if (visiblePanel) {
751
+ const panelElem = refOptionPanel.value
752
+ if (getEventTargetNode(evnt, panelElem).flag) {
753
+ updatePlacement()
754
+ } else {
755
+ hideOptionPanel()
756
+ }
757
+ }
758
+ }
759
+ }
760
+
761
+ const handleGlobalMousedownEvent = (evnt: MouseEvent) => {
762
+ const { visiblePanel } = reactData
763
+ const isDisabled = computeIsDisabled.value
764
+ const popupOpts = computePopupOpts.value
765
+ const { trigger } = popupOpts
766
+ if (!isDisabled) {
767
+ const el = refElem.value
768
+ const panelElem = refOptionPanel.value
769
+ reactData.isActivated = getEventTargetNode(evnt, el).flag || getEventTargetNode(evnt, panelElem).flag
770
+ if (visiblePanel && !reactData.isActivated) {
771
+ if (trigger !== 'manual') {
772
+ hideOptionPanel()
773
+ }
774
+ }
775
+ }
776
+ }
777
+
778
+ const validOffsetOption = (option: any) => {
779
+ const isDisabled = option.disabled
780
+ const optid = getOptId(option)
781
+ if (!isDisabled && !hasOptGroupById(optid)) {
782
+ return true
783
+ }
784
+ return false
785
+ }
786
+
787
+ const findOffsetOption = (option: any, isDwArrow: boolean) => {
788
+ const { allowCreate } = props
789
+ const { optList } = reactData
790
+ const { optFullValMaps, optAddMaps, afterVisibleList } = internalData
791
+ const valueField = computeValueField.value
792
+ let fullList = afterVisibleList
793
+ let offsetAddIndex = 0
794
+ if (allowCreate && optList.length) {
795
+ const firstItem = optList[0]
796
+ const optid = getOptId(firstItem)
797
+ if (optAddMaps[optid]) {
798
+ offsetAddIndex = 1
799
+ fullList = [optAddMaps[optid]].concat(fullList)
800
+ }
801
+ }
802
+ if (!option) {
803
+ if (isDwArrow) {
804
+ for (let i = 0; i < fullList.length; i++) {
805
+ const item = fullList[i]
806
+ if (validOffsetOption(item)) {
807
+ return item
808
+ }
809
+ }
810
+ } else {
811
+ for (let len = fullList.length - 1; len >= 0; len--) {
812
+ const item = fullList[len]
813
+ if (validOffsetOption(item)) {
814
+ return item
815
+ }
816
+ }
817
+ }
818
+ }
819
+ let avIndex = 0
820
+ const cacheItem = option ? optFullValMaps[option[valueField]] : null
821
+ if (cacheItem) {
822
+ avIndex = cacheItem._index + offsetAddIndex
823
+ }
824
+ if (avIndex > -1) {
825
+ if (isDwArrow) {
826
+ for (let i = avIndex + 1; i <= fullList.length - 1; i++) {
827
+ const item = fullList[i]
828
+ if (validOffsetOption(item)) {
829
+ return item
830
+ }
831
+ }
832
+ } else {
833
+ if (avIndex > 0) {
834
+ for (let len = avIndex - 1; len >= 0; len--) {
835
+ const item = fullList[len]
836
+ if (validOffsetOption(item)) {
837
+ return item
838
+ }
839
+ }
840
+ }
841
+ }
842
+ }
843
+ return null
844
+ }
845
+
846
+ const handleGlobalKeydownEvent = (evnt: KeyboardEvent) => {
847
+ const { clearable } = props
848
+ const { visiblePanel, currentOption } = reactData
849
+ const isDisabled = computeIsDisabled.value
850
+ const popupOpts = computePopupOpts.value
851
+ const { trigger } = popupOpts
852
+ if (!isDisabled) {
853
+ const isTab = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.TAB)
854
+ const isEnter = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ENTER)
855
+ const isEsc = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ESCAPE)
856
+ const isUpArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_UP)
857
+ const isDwArrow = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.ARROW_DOWN)
858
+ const isDel = globalEvents.hasKey(evnt, GLOBAL_EVENT_KEYS.DELETE)
859
+ if (isTab) {
860
+ reactData.isActivated = false
861
+ }
862
+ if (visiblePanel) {
863
+ if (isEsc || isTab) {
864
+ if (trigger !== 'manual') {
865
+ hideOptionPanel()
866
+ }
867
+ } else if (isEnter) {
868
+ if (currentOption) {
869
+ evnt.preventDefault()
870
+ evnt.stopPropagation()
871
+ changeOptionEvent(evnt, currentOption)
872
+ }
873
+ } else if (isUpArrow || isDwArrow) {
874
+ evnt.preventDefault()
875
+ let offsetOption = findOffsetOption(currentOption, isDwArrow)
876
+ // 如果不匹配,默认最接近一个
877
+ if (!offsetOption) {
878
+ offsetOption = findOffsetOption(null, isDwArrow)
879
+ }
880
+ if (offsetOption) {
881
+ setCurrentOption(offsetOption)
882
+ handleScrollToOption(offsetOption, isDwArrow)
883
+ }
884
+ }
885
+ } else if ((isUpArrow || isDwArrow || isEnter) && reactData.isActivated) {
886
+ evnt.preventDefault()
887
+ showOptionPanel()
888
+ }
889
+ if (reactData.isActivated) {
890
+ if (isDel && clearable) {
891
+ clearValueEvent(evnt, null)
892
+ }
893
+ }
894
+ }
895
+ }
896
+
897
+ const handleGlobalBlurEvent = () => {
898
+ const { visiblePanel, isActivated } = reactData
899
+ const popupOpts = computePopupOpts.value
900
+ const { trigger } = popupOpts
901
+ if (visiblePanel) {
902
+ if (trigger !== 'manual') {
903
+ hideOptionPanel()
904
+ }
905
+ }
906
+ if (isActivated) {
907
+ reactData.isActivated = false
908
+ }
909
+ if (visiblePanel || isActivated) {
910
+ const $input = refInput.value
911
+ if ($input) {
912
+ $input.blur()
913
+ }
914
+ }
915
+ }
916
+
917
+ const handleGlobalResizeEvent = () => {
918
+ const { visiblePanel } = reactData
919
+ if (visiblePanel) {
920
+ updatePlacement()
921
+ }
922
+ }
923
+
924
+ const handleFocusSearch = () => {
925
+ if (props.filterable) {
926
+ nextTick(() => {
927
+ const inpSearch = refInpSearch.value
928
+ if (inpSearch) {
929
+ inpSearch.focus()
930
+ }
931
+ })
932
+ }
933
+ }
934
+
935
+ const focusEvent = (evnt: FocusEvent) => {
936
+ const isDisabled = computeIsDisabled.value
937
+ const popupOpts = computePopupOpts.value
938
+ const { trigger } = popupOpts
939
+ if (!isDisabled) {
940
+ if (!reactData.visiblePanel) {
941
+ if (!trigger || trigger === 'default') {
942
+ reactData.triggerFocusPanel = true
943
+ showOptionPanel()
944
+ setTimeout(() => {
945
+ reactData.triggerFocusPanel = false
946
+ }, 500)
947
+ }
948
+ }
949
+ }
950
+ dispatchEvent('focus', {}, evnt)
951
+ }
952
+
953
+ const clickEvent = (evnt: MouseEvent) => {
954
+ const popupOpts = computePopupOpts.value
955
+ const { trigger } = popupOpts
956
+ if (!trigger || trigger === 'default') {
957
+ togglePanelEvent(evnt)
958
+ }
959
+ dispatchEvent('click', { triggerButton: false, visible: reactData.visiblePanel }, evnt)
960
+ }
961
+
962
+ const blurEvent = (evnt: FocusEvent) => {
963
+ reactData.isActivated = false
964
+ dispatchEvent('blur', {}, evnt)
965
+ }
966
+
967
+ const suffixClickEvent = (evnt: MouseEvent) => {
968
+ const popupOpts = computePopupOpts.value
969
+ const { trigger } = popupOpts
970
+ if (!trigger || trigger === 'default' || trigger === 'icon') {
971
+ togglePanelEvent(evnt)
972
+ }
973
+ dispatchEvent('click', { triggerButton: true, visible: reactData.visiblePanel }, evnt)
974
+ }
975
+
976
+ const modelSearchEvent = (value: string) => {
977
+ reactData.searchValue = value
978
+ }
979
+
980
+ const focusSearchEvent = () => {
981
+ reactData.isActivated = true
982
+ }
983
+
984
+ const handleSearchEvent = () => {
985
+ const { modelValue, remote } = props
986
+ const { searchValue } = reactData
987
+ const remoteOpts = computeRemoteOpts.value
988
+ const qyMethod = remoteOpts.queryMethod || props.remoteMethod
989
+ if (remote && qyMethod && remoteOpts.enabled) {
990
+ reactData.searchLoading = true
991
+ Promise.resolve(
992
+ qyMethod({ $select: $xeSelect, searchValue, value: modelValue })
993
+ ).then(() => nextTick())
994
+ .catch(() => nextTick())
995
+ .finally(() => {
996
+ reactData.searchLoading = false
997
+ handleOption()
998
+ updateYData()
999
+ })
1000
+ } else {
1001
+ handleOption()
1002
+ updateYData()
1003
+ }
1004
+ }
1005
+
1006
+ const triggerSearchEvent = XEUtils.debounce(handleSearchEvent, 350, { trailing: true })
1007
+
1008
+ const togglePanelEvent = (params: any) => {
1009
+ const { $event } = params
1010
+ $event.preventDefault()
1011
+ if (reactData.triggerFocusPanel) {
1012
+ reactData.triggerFocusPanel = false
1013
+ } else {
1014
+ if (reactData.visiblePanel) {
1015
+ hideOptionPanel()
1016
+ } else {
1017
+ showOptionPanel()
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ const checkOptionDisabled = (isSelected: any, option: VxeOptionProps) => {
1023
+ if (option.disabled) {
1024
+ return true
1025
+ }
1026
+ const isMaximize = computeIsMaximize.value
1027
+ if (isMaximize && !isSelected) {
1028
+ return true
1029
+ }
1030
+ return false
1031
+ }
1032
+
1033
+ const updateYSpace = () => {
1034
+ const { scrollYLoad } = reactData
1035
+ const { scrollYStore, afterVisibleList } = internalData
1036
+ reactData.bodyHeight = scrollYLoad ? afterVisibleList.length * scrollYStore.rowHeight : 0
1037
+ reactData.topSpaceHeight = scrollYLoad ? Math.max(scrollYStore.startIndex * scrollYStore.rowHeight, 0) : 0
1038
+ }
1039
+
1040
+ const handleData = () => {
1041
+ const { filterable, allowCreate } = props
1042
+ const { scrollYLoad, searchValue } = reactData
1043
+ const { optAddMaps, scrollYStore, afterVisibleList } = internalData
1044
+ const labelField = computeLabelField.value
1045
+ const valueField = computeValueField.value
1046
+ const restList = scrollYLoad ? afterVisibleList.slice(scrollYStore.startIndex, scrollYStore.endIndex) : afterVisibleList.slice(0)
1047
+ if (filterable && allowCreate && searchValue) {
1048
+ if (!restList.some(option => option[labelField] === searchValue)) {
1049
+ const addItem = optAddMaps[searchValue] || reactive({
1050
+ [getOptKey()]: searchValue,
1051
+ [labelField]: searchValue,
1052
+ [valueField]: searchValue
1053
+ })
1054
+ optAddMaps[searchValue] = addItem
1055
+ restList.unshift(addItem)
1056
+ }
1057
+ }
1058
+ reactData.optList = restList
1059
+ return nextTick()
1060
+ }
1061
+
1062
+ const updateYData = () => {
1063
+ handleData()
1064
+ updateYSpace()
1065
+ }
1066
+
1067
+ const computeScrollLoad = () => {
1068
+ return nextTick().then(() => {
1069
+ const { scrollYLoad } = reactData
1070
+ const { scrollYStore } = internalData
1071
+ const virtualBodyElem = refVirtualBody.value
1072
+ const virtualYOpts = computeVirtualYOpts.value
1073
+ let rowHeight = 0
1074
+ let firstItemElem: HTMLElement | undefined
1075
+ if (virtualBodyElem) {
1076
+ if (!firstItemElem) {
1077
+ firstItemElem = virtualBodyElem.children[0] as HTMLElement
1078
+ }
1079
+ }
1080
+ if (firstItemElem) {
1081
+ rowHeight = firstItemElem.offsetHeight
1082
+ }
1083
+ rowHeight = Math.max(20, rowHeight)
1084
+ scrollYStore.rowHeight = rowHeight
1085
+ // 计算 Y 逻辑
1086
+ if (scrollYLoad) {
1087
+ const scrollBodyElem = refVirtualWrapper.value
1088
+ const visibleYSize = Math.max(8, scrollBodyElem ? Math.ceil(scrollBodyElem.clientHeight / rowHeight) : 0)
1089
+ const offsetYSize = Math.max(0, Math.min(2, XEUtils.toNumber(virtualYOpts.oSize)))
1090
+ scrollYStore.offsetSize = offsetYSize
1091
+ scrollYStore.visibleSize = visibleYSize
1092
+ scrollYStore.endIndex = Math.max(scrollYStore.startIndex, visibleYSize + offsetYSize, scrollYStore.endIndex)
1093
+ updateYData()
1094
+ } else {
1095
+ updateYSpace()
1096
+ }
1097
+ })
1098
+ }
1099
+
1100
+ const handleScrollToOption = (option: any, isDwArrow?: boolean) => {
1101
+ const { scrollYLoad } = reactData
1102
+ const { optFullValMaps, scrollYStore } = internalData
1103
+ const valueField = computeValueField.value
1104
+ const cacheItem = optFullValMaps[option[valueField]]
1105
+ if (cacheItem) {
1106
+ const optid = cacheItem.key
1107
+ const avIndex = cacheItem._index
1108
+ if (avIndex > -1) {
1109
+ const optWrapperElem = refVirtualWrapper.value
1110
+ const panelElem = refOptionPanel.value
1111
+ if (!panelElem) {
1112
+ return
1113
+ }
1114
+ const optElem = panelElem.querySelector(`[optid='${optid}']`) as HTMLElement
1115
+ if (optWrapperElem) {
1116
+ if (optElem) {
1117
+ const wrapperHeight = optWrapperElem.offsetHeight
1118
+ const offsetPadding = 1
1119
+ if (isDwArrow) {
1120
+ if (optElem.offsetTop + optElem.offsetHeight - optWrapperElem.scrollTop > wrapperHeight) {
1121
+ optWrapperElem.scrollTop = optElem.offsetTop + optElem.offsetHeight - wrapperHeight
1122
+ } else if (optElem.offsetTop + offsetPadding < optWrapperElem.scrollTop || optElem.offsetTop + offsetPadding > optWrapperElem.scrollTop + optWrapperElem.clientHeight) {
1123
+ optWrapperElem.scrollTop = optElem.offsetTop - offsetPadding
1124
+ }
1125
+ } else {
1126
+ if (optElem.offsetTop + offsetPadding < optWrapperElem.scrollTop || optElem.offsetTop + offsetPadding > optWrapperElem.scrollTop + optWrapperElem.clientHeight) {
1127
+ optWrapperElem.scrollTop = optElem.offsetTop - offsetPadding
1128
+ } else if (optElem.offsetTop + optElem.offsetHeight - optWrapperElem.scrollTop > wrapperHeight) {
1129
+ optWrapperElem.scrollTop = optElem.offsetTop + optElem.offsetHeight - wrapperHeight
1130
+ }
1131
+ }
1132
+ } else if (scrollYLoad) {
1133
+ if (isDwArrow) {
1134
+ optWrapperElem.scrollTop = avIndex * scrollYStore.rowHeight - optWrapperElem.clientHeight + scrollYStore.rowHeight
1135
+ } else {
1136
+ optWrapperElem.scrollTop = avIndex * scrollYStore.rowHeight
1137
+ }
1138
+ }
1139
+ }
1140
+ }
1141
+ }
1142
+ }
1143
+
1144
+ /**
1145
+ * 如果有滚动条,则滚动到对应的位置
1146
+ * @param {Number} scrollLeft 左距离
1147
+ * @param {Number} scrollTop 上距离
1148
+ */
1149
+ const scrollTo = (scrollLeft: number | null, scrollTop?: number | null) => {
1150
+ const scrollBodyElem = refVirtualWrapper.value
1151
+ if (scrollBodyElem) {
1152
+ if (XEUtils.isNumber(scrollLeft)) {
1153
+ scrollBodyElem.scrollLeft = scrollLeft
1154
+ }
1155
+ if (XEUtils.isNumber(scrollTop)) {
1156
+ scrollBodyElem.scrollTop = scrollTop
1157
+ }
1158
+ }
1159
+ if (reactData.scrollYLoad) {
1160
+ return new Promise<void>(resolve => {
1161
+ setTimeout(() => {
1162
+ nextTick(() => {
1163
+ resolve()
1164
+ })
1165
+ }, 50)
1166
+ })
1167
+ }
1168
+ return nextTick()
1169
+ }
1170
+
1171
+ /**
1172
+ * 刷新滚动条
1173
+ */
1174
+ const refreshScroll = () => {
1175
+ const { lastScrollLeft, lastScrollTop } = internalData
1176
+ return clearScroll().then(() => {
1177
+ if (lastScrollLeft || lastScrollTop) {
1178
+ internalData.lastScrollLeft = 0
1179
+ internalData.lastScrollTop = 0
1180
+ return scrollTo(lastScrollLeft, lastScrollTop)
1181
+ }
1182
+ })
1183
+ }
1184
+
1185
+ /**
1186
+ * 重新计算列表
1187
+ */
1188
+ const recalculate = () => {
1189
+ const el = refElem.value
1190
+ if (el && el.clientWidth && el.clientHeight) {
1191
+ return computeScrollLoad()
1192
+ }
1193
+ return Promise.resolve()
1194
+ }
1195
+
1196
+ const loadYData = (evnt: Event) => {
1197
+ const { scrollYStore } = internalData
1198
+ const { startIndex, endIndex, visibleSize, offsetSize, rowHeight } = scrollYStore
1199
+ const scrollBodyElem = evnt.target as HTMLDivElement
1200
+ const scrollTop = scrollBodyElem.scrollTop
1201
+ const toVisibleIndex = Math.floor(scrollTop / rowHeight)
1202
+ const offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize)
1203
+ const offsetEndIndex = toVisibleIndex + visibleSize + offsetSize
1204
+ if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
1205
+ if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
1206
+ scrollYStore.startIndex = offsetStartIndex
1207
+ scrollYStore.endIndex = offsetEndIndex
1208
+ updateYData()
1209
+ }
1210
+ }
1211
+ }
1212
+
1213
+ // 滚动、拖动过程中不需要触发
1214
+ const isVMScrollProcess = () => {
1215
+ const delayHover = 250
1216
+ const { lastScrollTime } = internalData
1217
+ return !!(lastScrollTime && Date.now() < lastScrollTime + delayHover)
1218
+ }
1219
+
1220
+ const scrollEvent = (evnt: Event) => {
1221
+ const scrollBodyElem = evnt.target as HTMLDivElement
1222
+ const scrollTop = scrollBodyElem.scrollTop
1223
+ const scrollLeft = scrollBodyElem.scrollLeft
1224
+ const isX = scrollLeft !== internalData.lastScrollLeft
1225
+ const isY = scrollTop !== internalData.lastScrollTop
1226
+ internalData.lastScrollTop = scrollTop
1227
+ internalData.lastScrollLeft = scrollLeft
1228
+ if (reactData.scrollYLoad) {
1229
+ loadYData(evnt)
1230
+ }
1231
+ internalData.lastScrollTime = Date.now()
1232
+ dispatchEvent('scroll', { scrollLeft, scrollTop, isX, isY }, evnt)
1233
+ }
1234
+
1235
+ /**
1236
+ * 加载数据
1237
+ * @param {Array} datas 数据
1238
+ */
1239
+ const loadData = (datas: any[]) => {
1240
+ cacheItemMap(datas || [])
1241
+ const { multiple } = props
1242
+ const { isLoaded, fullData, scrollYStore } = internalData
1243
+ const defaultOpts = computeDefaultOpts.value
1244
+ const virtualYOpts = computeVirtualYOpts.value
1245
+ const valueField = computeValueField.value
1246
+ Object.assign(scrollYStore, {
1247
+ startIndex: 0,
1248
+ endIndex: 1,
1249
+ visibleSize: 0
1250
+ })
1251
+ internalData.synchData = datas || []
1252
+ // 如果gt为0,则总是启用
1253
+ reactData.scrollYLoad = !!virtualYOpts.enabled && virtualYOpts.gt > -1 && (virtualYOpts.gt === 0 || virtualYOpts.gt <= fullData.length)
1254
+ handleData()
1255
+ if (!isLoaded) {
1256
+ const { selectMode } = defaultOpts
1257
+ if (datas.length > 0 && XEUtils.eqNull(props.modelValue)) {
1258
+ if (selectMode === 'all') {
1259
+ if (multiple) {
1260
+ nextTick(() => {
1261
+ emitDefaultValue(datas.map(item => item[valueField]))
1262
+ })
1263
+ } else {
1264
+ errLog('vxe.error.notConflictProp', ['default-config.selectMode=all', 'multiple=true'])
1265
+ }
1266
+ } else if (selectMode === 'first' || selectMode === 'last') {
1267
+ const selectItem = XEUtils[selectMode](datas)
1268
+ if (selectItem) {
1269
+ nextTick(() => {
1270
+ if (XEUtils.eqNull(props.modelValue)) {
1271
+ emitDefaultValue(selectItem[valueField])
1272
+ }
1273
+ })
1274
+ }
1275
+ }
1276
+ internalData.isLoaded = true
1277
+ }
1278
+ }
1279
+ return computeScrollLoad().then(() => {
1280
+ refreshScroll()
1281
+ })
1282
+ }
1283
+
1284
+ const clearScroll = () => {
1285
+ const scrollBodyElem = refVirtualWrapper.value
1286
+ if (scrollBodyElem) {
1287
+ scrollBodyElem.scrollTop = 0
1288
+ scrollBodyElem.scrollLeft = 0
1289
+ }
1290
+ internalData.lastScrollTop = 0
1291
+ internalData.lastScrollLeft = 0
1292
+ return nextTick()
1293
+ }
1294
+
1295
+ const hasOptGroupById = (optid: any) => {
1296
+ const { optGroupKeyMaps } = internalData
1297
+ return !!optGroupKeyMaps[optid]
1298
+ }
1299
+
1300
+ const selectMethods: SelectMethods = {
1301
+ dispatchEvent,
1302
+ loadData,
1303
+ reloadData (datas) {
1304
+ internalData.isLoaded = false
1305
+ clearScroll()
1306
+ return loadData(datas)
1307
+ },
1308
+ isPanelVisible () {
1309
+ return reactData.visiblePanel
1310
+ },
1311
+ togglePanel () {
1312
+ if (reactData.visiblePanel) {
1313
+ hideOptionPanel()
1314
+ } else {
1315
+ showOptionPanel()
1316
+ }
1317
+ return nextTick()
1318
+ },
1319
+ hidePanel () {
1320
+ if (reactData.visiblePanel) {
1321
+ hideOptionPanel()
1322
+ }
1323
+ return nextTick()
1324
+ },
1325
+ showPanel () {
1326
+ if (!reactData.visiblePanel) {
1327
+ showOptionPanel()
1328
+ }
1329
+ return nextTick()
1330
+ },
1331
+ refreshOption () {
1332
+ handleOption()
1333
+ updateYData()
1334
+ return nextTick()
1335
+ },
1336
+ focus () {
1337
+ const $input = refInput.value
1338
+ if ($input) {
1339
+ $input.blur()
1340
+ }
1341
+ reactData.isActivated = true
1342
+ return nextTick()
1343
+ },
1344
+ blur () {
1345
+ const $input = refInput.value
1346
+ if ($input) {
1347
+ $input.blur()
1348
+ }
1349
+ reactData.isActivated = false
1350
+ return nextTick()
1351
+ },
1352
+ recalculate,
1353
+ clearScroll
1354
+ }
1355
+
1356
+ Object.assign($xeSelect, selectMethods)
1357
+
1358
+ const renderOption = (list: VxeOptionProps[]) => {
1359
+ const { allowCreate, optionKey } = props
1360
+ const { currentOption } = reactData
1361
+ const { optAddMaps } = internalData
1362
+ const optionOpts = computeOptionOpts.value
1363
+ const labelField = computeLabelField.value
1364
+ const valueField = computeValueField.value
1365
+ const groupLabelField = computeGroupLabelField.value
1366
+ const selectVals = computeSelectVals.value
1367
+ const { useKey, height } = optionOpts
1368
+ const optionSlot = slots.option
1369
+ return list.map((option, cIndex) => {
1370
+ const { slots, className } = option
1371
+ const optid = getOptId(option)
1372
+ const optionValue = option[valueField as 'value']
1373
+ const isOptGroup = hasOptGroupById(optid)
1374
+ const isAdd = !!(allowCreate && optAddMaps[optid])
1375
+ const isSelected = !isAdd && selectVals.indexOf(optionValue) > -1
1376
+ const isVisible = isAdd || (!isOptGroup || isOptionVisible(option))
1377
+ const isDisabled = !isAdd && checkOptionDisabled(isSelected, option)
1378
+ const defaultSlot = slots ? slots.default : null
1379
+ const optParams = { option, group: isOptGroup ? option : null, $select: $xeSelect }
1380
+ let optLabel = ''
1381
+ let optVNs: string | VxeComponentSlotType[] = []
1382
+ if (optionSlot) {
1383
+ optVNs = callSlot(optionSlot, optParams)
1384
+ } else if (defaultSlot) {
1385
+ optVNs = callSlot(defaultSlot, optParams)
1386
+ } else {
1387
+ optLabel = getFuncText(option[(isOptGroup ? groupLabelField : labelField) as 'label'] || optionValue)
1388
+ optVNs = optLabel
1389
+ }
1390
+
1391
+ return isVisible
1392
+ ? h('div', {
1393
+ key: useKey || optionKey ? optid : cIndex,
1394
+ class: ['vxe-select-option', className ? (XEUtils.isFunction(className) ? className(optParams) : className) : '', {
1395
+ 'vxe-select-optgroup': isOptGroup,
1396
+ 'is--disabled': isDisabled,
1397
+ 'is--selected': isSelected,
1398
+ 'is--add': isAdd,
1399
+ 'is--hover': currentOption && getOptId(currentOption) === optid
1400
+ }],
1401
+ optid: optid,
1402
+ title: optLabel || null,
1403
+ style: height
1404
+ ? {
1405
+ height: toCssUnit(height)
1406
+ }
1407
+ : undefined,
1408
+ onMousedown: (evnt: MouseEvent) => {
1409
+ const isLeftBtn = evnt.button === 0
1410
+ if (isLeftBtn) {
1411
+ evnt.stopPropagation()
1412
+ }
1413
+ },
1414
+ onClick: (evnt: MouseEvent) => {
1415
+ if (!isDisabled && !isOptGroup) {
1416
+ changeOptionEvent(evnt, option)
1417
+ }
1418
+ },
1419
+ onMouseenter: () => {
1420
+ if (!isDisabled && !isOptGroup && !isVMScrollProcess()) {
1421
+ setCurrentOption(option)
1422
+ }
1423
+ }
1424
+ }, allowCreate
1425
+ ? [
1426
+ h('span', {
1427
+ key: 1,
1428
+ class: 'vxe-select-option--label'
1429
+ }, optVNs),
1430
+ isAdd
1431
+ ? h('span', {
1432
+ key: 2,
1433
+ class: 'vxe-select-option--add-icon'
1434
+ }, [
1435
+ h('i', {
1436
+ class: getIcon().SELECT_ADD_OPTION
1437
+ })
1438
+ ])
1439
+ : renderEmptyElement($xeSelect)
1440
+ ]
1441
+ : optVNs)
1442
+ : renderEmptyElement($xeSelect)
1443
+ })
1444
+ }
1445
+
1446
+ const renderOpts = () => {
1447
+ const { optList, searchLoading } = reactData
1448
+ if (searchLoading) {
1449
+ return [
1450
+ h('div', {
1451
+ class: 'vxe-select--search-loading'
1452
+ }, [
1453
+ h('i', {
1454
+ class: ['vxe-select--search-icon', getIcon().SELECT_LOADED]
1455
+ }),
1456
+ h('span', {
1457
+ class: 'vxe-select--search-text'
1458
+ }, getI18n('vxe.select.loadingText'))
1459
+ ])
1460
+ ]
1461
+ }
1462
+ if (optList.length) {
1463
+ return renderOption(optList)
1464
+ }
1465
+ return [
1466
+ h('div', {
1467
+ class: 'vxe-select--empty-placeholder'
1468
+ }, props.emptyText || getI18n('vxe.select.emptyText'))
1469
+ ]
1470
+ }
1471
+
1472
+ const renderVN = () => {
1473
+ const { className, multiple, loading, filterable, showTotalButoon, showCheckedButoon, showClearButton } = props
1474
+ const { initialized, isActivated, isAniVisible, optList, visiblePanel, bodyHeight, topSpaceHeight } = reactData
1475
+ const vSize = computeSize.value
1476
+ const isDisabled = computeIsDisabled.value
1477
+ const selectLabel = computeSelectLabel.value
1478
+ const fullLabel = computeFullLabel.value
1479
+ const btnTransfer = computeBtnTransfer.value
1480
+ const formReadonly = computeFormReadonly.value
1481
+ const inpPlaceholder = computeInpPlaceholder.value
1482
+ const popupWrapperStyle = computePopupWrapperStyle.value
1483
+ const popupOpts = computePopupOpts.value
1484
+ const defaultSlot = slots.default
1485
+ const headerSlot = slots.header
1486
+ const footerSlot = slots.footer
1487
+ const prefixSlot = slots.prefix
1488
+ const ppClassName = popupOpts.className || props.popupClassName
1489
+ if (formReadonly) {
1490
+ return h('div', {
1491
+ ref: refElem,
1492
+ class: ['vxe-select--readonly', className]
1493
+ }, [
1494
+ h('div', {
1495
+ class: 'vxe-select-slots',
1496
+ ref: 'hideOption'
1497
+ }, defaultSlot ? defaultSlot({}) : []),
1498
+ h('span', {
1499
+ class: 'vxe-select-label',
1500
+ title: fullLabel
1501
+ }, selectLabel)
1502
+ ])
1503
+ }
1504
+ const selectVals = computeSelectVals.value
1505
+ return h('div', {
1506
+ ref: refElem,
1507
+ class: ['vxe-select', className ? (XEUtils.isFunction(className) ? className({ $select: $xeSelect }) : className) : '', {
1508
+ [`size--${vSize}`]: vSize,
1509
+ 'is--visible': visiblePanel,
1510
+ 'is--disabled': isDisabled,
1511
+ 'is--filter': filterable,
1512
+ 'is--loading': loading,
1513
+ 'is--active': isActivated
1514
+ }]
1515
+ }, [
1516
+ h('div', {
1517
+ class: 'vxe-select-slots',
1518
+ ref: 'hideOption'
1519
+ }, defaultSlot ? defaultSlot({}) : []),
1520
+ h(VxeInputComponent, {
1521
+ ref: refInput,
1522
+ clearable: props.clearable,
1523
+ placeholder: inpPlaceholder,
1524
+ editable: false,
1525
+ disabled: isDisabled,
1526
+ type: 'text',
1527
+ prefixIcon: props.prefixIcon,
1528
+ suffixIcon: loading ? getIcon().SELECT_LOADED : (visiblePanel ? getIcon().SELECT_OPEN : getIcon().SELECT_CLOSE),
1529
+ autoFocus: false,
1530
+ title: fullLabel,
1531
+ modelValue: selectLabel,
1532
+ onClear: clearEvent,
1533
+ onClick: clickEvent,
1534
+ onFocus: focusEvent,
1535
+ onBlur: blurEvent,
1536
+ onSuffixClick: suffixClickEvent
1537
+ }, prefixSlot
1538
+ ? {
1539
+ prefix: () => prefixSlot({})
1540
+ }
1541
+ : {}),
1542
+ h(Teleport, {
1543
+ to: 'body',
1544
+ disabled: btnTransfer ? !initialized : true
1545
+ }, [
1546
+ h('div', {
1547
+ ref: refOptionPanel,
1548
+ class: ['vxe-table--ignore-clear vxe-select--panel', ppClassName ? (XEUtils.isFunction(ppClassName) ? ppClassName({ $select: $xeSelect }) : ppClassName) : '', {
1549
+ [`size--${vSize}`]: vSize,
1550
+ 'is--transfer': btnTransfer,
1551
+ 'ani--leave': !loading && isAniVisible,
1552
+ 'ani--enter': !loading && visiblePanel
1553
+ }],
1554
+ placement: reactData.panelPlacement,
1555
+ style: reactData.panelStyle
1556
+ }, initialized && (visiblePanel || isAniVisible)
1557
+ ? [
1558
+ h('div', {
1559
+ class: 'vxe-select--panel-wrapper',
1560
+ style: popupWrapperStyle
1561
+ }, [
1562
+ filterable
1563
+ ? h('div', {
1564
+ class: 'vxe-select--panel-search'
1565
+ }, [
1566
+ h(VxeInputComponent, {
1567
+ ref: refInpSearch,
1568
+ class: 'vxe-select-search--input',
1569
+ modelValue: reactData.searchValue,
1570
+ type: 'text',
1571
+ clearable: true,
1572
+ disabled: false,
1573
+ readonly: false,
1574
+ placeholder: getI18n('vxe.select.search'),
1575
+ prefixIcon: getIcon().INPUT_SEARCH,
1576
+ 'onUpdate:modelValue': modelSearchEvent,
1577
+ onFocus: focusSearchEvent,
1578
+ onChange: triggerSearchEvent,
1579
+ onSearch: triggerSearchEvent
1580
+ })
1581
+ ])
1582
+ : renderEmptyElement($xeSelect),
1583
+ showTotalButoon || (showCheckedButoon && multiple) || showClearButton || headerSlot
1584
+ ? h('div', {
1585
+ class: 'vxe-select--panel-header'
1586
+ }, headerSlot
1587
+ ? callSlot(headerSlot, {})
1588
+ : [
1589
+ h('div', {
1590
+ class: 'vxe-select--header-button'
1591
+ }, [
1592
+ showTotalButoon
1593
+ ? h('div', {
1594
+ class: 'vxe-select--header-total'
1595
+ }, getI18n('vxe.select.total', [selectVals.length, optList.length]))
1596
+ : renderEmptyElement($xeSelect),
1597
+ h('div', {
1598
+ class: 'vxe-select--header-btns'
1599
+ }, [
1600
+ (showCheckedButoon && multiple)
1601
+ ? h(VxeButtonComponent, {
1602
+ content: getI18n('vxe.select.allChecked'),
1603
+ mode: 'text',
1604
+ onClick: allCheckedPanelEvent
1605
+ })
1606
+ : renderEmptyElement($xeSelect),
1607
+ showClearButton
1608
+ ? h(VxeButtonComponent, {
1609
+ content: getI18n('vxe.select.clear'),
1610
+ mode: 'text',
1611
+ onClick: clearCheckedPanelEvent
1612
+ })
1613
+ : renderEmptyElement($xeSelect)
1614
+ ])
1615
+ ])
1616
+ ])
1617
+ : renderEmptyElement($xeSelect),
1618
+ h('div', {
1619
+ class: 'vxe-select--panel-body'
1620
+ }, [
1621
+ h('div', {
1622
+ ref: refVirtualWrapper,
1623
+ class: 'vxe-select-option--wrapper',
1624
+ onScroll: scrollEvent
1625
+ }, [
1626
+ h('div', {
1627
+ class: 'vxe-select--y-space',
1628
+ style: {
1629
+ height: bodyHeight ? `${bodyHeight}px` : ''
1630
+ }
1631
+ }),
1632
+ h('div', {
1633
+ ref: refVirtualBody,
1634
+ class: 'vxe-select--body',
1635
+ style: {
1636
+ transform: `translateY(${topSpaceHeight}px)`
1637
+ }
1638
+ }, renderOpts())
1639
+ ])
1640
+ ]),
1641
+ footerSlot
1642
+ ? h('div', {
1643
+ class: 'vxe-select--panel-footer'
1644
+ }, callSlot(footerSlot, {}))
1645
+ : renderEmptyElement($xeSelect)
1646
+ ])
1647
+ ]
1648
+ : [])
1649
+ ])
1650
+ ])
1651
+ }
1652
+
1653
+ watch(() => reactData.staticOptions, (val) => {
1654
+ loadData(val)
1655
+ })
1656
+
1657
+ watch(() => props.options, (val) => {
1658
+ loadData(val || [])
1659
+ })
1660
+
1661
+ watch(() => props.optionGroups, (val) => {
1662
+ loadData(val || [])
1663
+ })
1664
+
1665
+ onMounted(() => {
1666
+ nextTick(() => {
1667
+ const { options, optionGroups } = props
1668
+ if (optionGroups) {
1669
+ loadData(optionGroups)
1670
+ } else if (options) {
1671
+ loadData(options)
1672
+ }
1673
+ })
1674
+ globalEvents.on($xeSelect, 'mousewheel', handleGlobalMousewheelEvent)
1675
+ globalEvents.on($xeSelect, 'mousedown', handleGlobalMousedownEvent)
1676
+ globalEvents.on($xeSelect, 'keydown', handleGlobalKeydownEvent)
1677
+ globalEvents.on($xeSelect, 'blur', handleGlobalBlurEvent)
1678
+ globalEvents.on($xeSelect, 'resize', handleGlobalResizeEvent)
1679
+ })
1680
+
1681
+ onUnmounted(() => {
1682
+ globalEvents.off($xeSelect, 'mousewheel')
1683
+ globalEvents.off($xeSelect, 'mousedown')
1684
+ globalEvents.off($xeSelect, 'keydown')
1685
+ globalEvents.off($xeSelect, 'blur')
1686
+ globalEvents.off($xeSelect, 'resize')
1687
+ XEUtils.assign(internalData, createInternalData())
1688
+ })
1689
+
1690
+ provide('$xeSelect', $xeSelect)
1691
+
1692
+ $xeSelect.renderVN = renderVN
1693
+
1694
+ return $xeSelect
1695
+ },
1696
+ render () {
1697
+ return this.renderVN()
1698
+ }
1699
+ })