@wot-ui/ui 1.0.0 → 2.0.0-alpha.4

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 (386) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/attributes.json +1 -0
  4. package/changelog.md +63 -0
  5. package/common/AbortablePromise.ts +28 -0
  6. package/common/canvasHelper.ts +49 -0
  7. package/common/clickoutside.ts +25 -0
  8. package/common/event.ts +8 -0
  9. package/common/formatDate.ts +68 -0
  10. package/common/interceptor.ts +43 -0
  11. package/common/props.ts +53 -0
  12. package/common/util.ts +836 -0
  13. package/components/wd-action-sheet/index.scss +232 -0
  14. package/components/wd-action-sheet/types.ts +155 -0
  15. package/components/wd-action-sheet/wd-action-sheet.vue +176 -0
  16. package/components/wd-avatar/index.scss +150 -0
  17. package/components/wd-avatar/types.ts +98 -0
  18. package/components/wd-avatar/wd-avatar.vue +184 -0
  19. package/components/wd-avatar-group/index.scss +11 -0
  20. package/components/wd-avatar-group/types.ts +61 -0
  21. package/components/wd-avatar-group/wd-avatar-group.vue +115 -0
  22. package/components/wd-backtop/index.scss +67 -0
  23. package/components/wd-backtop/types.ts +66 -0
  24. package/components/wd-backtop/wd-backtop.vue +57 -0
  25. package/components/wd-badge/index.scss +116 -0
  26. package/components/wd-badge/types.ts +94 -0
  27. package/components/wd-badge/wd-badge.vue +78 -0
  28. package/components/wd-button/index.scss +436 -0
  29. package/components/wd-button/types.ts +204 -0
  30. package/components/wd-button/wd-button.vue +210 -0
  31. package/components/wd-calendar/index.scss +97 -0
  32. package/components/wd-calendar/types.ts +221 -0
  33. package/components/wd-calendar/wd-calendar.vue +339 -0
  34. package/components/wd-calendar-view/index.scss +41 -0
  35. package/components/wd-calendar-view/month/index.scss +144 -0
  36. package/components/wd-calendar-view/month/month.vue +389 -0
  37. package/components/wd-calendar-view/month/types.ts +70 -0
  38. package/components/wd-calendar-view/monthPanel/index.scss +84 -0
  39. package/components/wd-calendar-view/monthPanel/month-panel.vue +541 -0
  40. package/components/wd-calendar-view/monthPanel/types.ts +151 -0
  41. package/components/wd-calendar-view/types.ts +166 -0
  42. package/components/wd-calendar-view/utils.ts +318 -0
  43. package/components/wd-calendar-view/wd-calendar-view.vue +117 -0
  44. package/components/wd-calendar-view/year/index.scss +148 -0
  45. package/components/wd-calendar-view/year/types.ts +74 -0
  46. package/components/wd-calendar-view/year/year.vue +206 -0
  47. package/components/wd-calendar-view/yearPanel/index.scss +42 -0
  48. package/components/wd-calendar-view/yearPanel/types.ts +96 -0
  49. package/components/wd-calendar-view/yearPanel/year-panel.vue +249 -0
  50. package/components/wd-card/index.scss +104 -0
  51. package/components/wd-card/types.ts +47 -0
  52. package/components/wd-card/wd-card.vue +38 -0
  53. package/components/wd-cascader/index.scss +154 -0
  54. package/components/wd-cascader/types.ts +191 -0
  55. package/components/wd-cascader/wd-cascader.vue +589 -0
  56. package/components/wd-cell/index.scss +244 -0
  57. package/components/wd-cell/types.ts +205 -0
  58. package/components/wd-cell/wd-cell.vue +172 -0
  59. package/components/wd-cell-group/index.scss +53 -0
  60. package/components/wd-cell-group/types.ts +97 -0
  61. package/components/wd-cell-group/wd-cell-group.vue +48 -0
  62. package/components/wd-checkbox/index.scss +166 -0
  63. package/components/wd-checkbox/types.ts +118 -0
  64. package/components/wd-checkbox/wd-checkbox.vue +216 -0
  65. package/components/wd-checkbox-group/index.scss +5 -0
  66. package/components/wd-checkbox-group/types.ts +93 -0
  67. package/components/wd-checkbox-group/wd-checkbox-group.vue +148 -0
  68. package/components/wd-circle/index.scss +28 -0
  69. package/components/wd-circle/types.ts +54 -0
  70. package/components/wd-circle/wd-circle.vue +306 -0
  71. package/components/wd-col/index.scss +5 -0
  72. package/components/wd-col/types.ts +16 -0
  73. package/components/wd-col/wd-col.vue +83 -0
  74. package/components/wd-collapse/index.scss +71 -0
  75. package/components/wd-collapse/types.ts +68 -0
  76. package/components/wd-collapse/wd-collapse.vue +165 -0
  77. package/components/wd-collapse-item/index.scss +86 -0
  78. package/components/wd-collapse-item/types.ts +62 -0
  79. package/components/wd-collapse-item/wd-collapse-item.vue +184 -0
  80. package/components/wd-config-provider/index.scss +10 -0
  81. package/components/wd-config-provider/types.ts +2061 -0
  82. package/components/wd-config-provider/wd-config-provider.vue +61 -0
  83. package/components/wd-count-down/index.scss +16 -0
  84. package/components/wd-count-down/types.ts +58 -0
  85. package/components/wd-count-down/utils.ts +52 -0
  86. package/components/wd-count-down/wd-count-down.vue +62 -0
  87. package/components/wd-count-to/index.scss +25 -0
  88. package/components/wd-count-to/types.ts +121 -0
  89. package/components/wd-count-to/wd-count-to.vue +126 -0
  90. package/components/wd-curtain/index.scss +96 -0
  91. package/components/wd-curtain/types.ts +82 -0
  92. package/components/wd-curtain/wd-curtain.vue +172 -0
  93. package/components/wd-datetime-picker/index.scss +133 -0
  94. package/components/wd-datetime-picker/types.ts +198 -0
  95. package/components/wd-datetime-picker/wd-datetime-picker.vue +526 -0
  96. package/components/wd-datetime-picker-view/types.ts +171 -0
  97. package/components/wd-datetime-picker-view/util.ts +30 -0
  98. package/components/wd-datetime-picker-view/wd-datetime-picker-view.vue +402 -0
  99. package/components/wd-dialog/index.scss +281 -0
  100. package/components/wd-dialog/index.ts +168 -0
  101. package/components/wd-dialog/types.ts +452 -0
  102. package/components/wd-dialog/wd-dialog.vue +586 -0
  103. package/components/wd-divider/index.scss +122 -0
  104. package/components/wd-divider/types.ts +50 -0
  105. package/components/wd-divider/wd-divider.vue +54 -0
  106. package/components/wd-drop-menu/index.scss +90 -0
  107. package/components/wd-drop-menu/types.ts +38 -0
  108. package/components/wd-drop-menu/wd-drop-menu.vue +168 -0
  109. package/components/wd-drop-menu-item/index.scss +96 -0
  110. package/components/wd-drop-menu-item/types.ts +93 -0
  111. package/components/wd-drop-menu-item/wd-drop-menu-item.vue +205 -0
  112. package/components/wd-empty/index.scss +46 -0
  113. package/components/wd-empty/types.ts +37 -0
  114. package/components/wd-empty/wd-empty.vue +47 -0
  115. package/components/wd-fab/index.scss +124 -0
  116. package/components/wd-fab/types.ts +119 -0
  117. package/components/wd-fab/wd-fab.vue +322 -0
  118. package/components/wd-floating-panel/index.scss +73 -0
  119. package/components/wd-floating-panel/type.ts +32 -0
  120. package/components/wd-floating-panel/wd-floating-panel.vue +142 -0
  121. package/components/wd-form/adapters/zod.ts +56 -0
  122. package/components/wd-form/index.ts +2 -0
  123. package/components/wd-form/types.ts +133 -0
  124. package/components/wd-form/wd-form.vue +121 -0
  125. package/components/wd-form-item/index.scss +26 -0
  126. package/components/wd-form-item/types.ts +134 -0
  127. package/components/wd-form-item/wd-form-item.vue +182 -0
  128. package/components/wd-gap/index.scss +9 -0
  129. package/components/wd-gap/types.ts +26 -0
  130. package/components/wd-gap/wd-gap.vue +38 -0
  131. package/components/wd-grid/index.scss +11 -0
  132. package/components/wd-grid/types.ts +97 -0
  133. package/components/wd-grid/wd-grid.vue +48 -0
  134. package/components/wd-grid-item/index.scss +187 -0
  135. package/components/wd-grid-item/types.ts +98 -0
  136. package/components/wd-grid-item/wd-grid-item.vue +295 -0
  137. package/components/wd-icon/index.scss +46 -0
  138. package/components/wd-icon/types.ts +44 -0
  139. package/components/wd-icon/wd-icon.vue +66 -0
  140. package/components/wd-image-preview/index.scss +94 -0
  141. package/components/wd-image-preview/index.ts +95 -0
  142. package/components/wd-image-preview/types.ts +165 -0
  143. package/components/wd-image-preview/wd-image-preview.vue +233 -0
  144. package/components/wd-img/index.scss +82 -0
  145. package/components/wd-img/types.ts +96 -0
  146. package/components/wd-img/wd-img.vue +91 -0
  147. package/components/wd-img-cropper/index.scss +259 -0
  148. package/components/wd-img-cropper/types.ts +101 -0
  149. package/components/wd-img-cropper/wd-img-cropper.vue +653 -0
  150. package/components/wd-index-anchor/index.scss +34 -0
  151. package/components/wd-index-anchor/type.ts +9 -0
  152. package/components/wd-index-anchor/wd-index-anchor.vue +55 -0
  153. package/components/wd-index-bar/index.scss +68 -0
  154. package/components/wd-index-bar/type.ts +23 -0
  155. package/components/wd-index-bar/wd-index-bar.vue +157 -0
  156. package/components/wd-input/index.scss +129 -0
  157. package/components/wd-input/types.ts +165 -0
  158. package/components/wd-input/wd-input.vue +237 -0
  159. package/components/wd-input-number/index.scss +233 -0
  160. package/components/wd-input-number/types.ts +131 -0
  161. package/components/wd-input-number/wd-input-number.vue +473 -0
  162. package/components/wd-keyboard/constants.ts +81 -0
  163. package/components/wd-keyboard/index.scss +104 -0
  164. package/components/wd-keyboard/key/index.scss +103 -0
  165. package/components/wd-keyboard/key/index.vue +84 -0
  166. package/components/wd-keyboard/key/types.ts +44 -0
  167. package/components/wd-keyboard/types.ts +138 -0
  168. package/components/wd-keyboard/wd-keyboard.vue +236 -0
  169. package/components/wd-loading/index.scss +205 -0
  170. package/components/wd-loading/types.ts +61 -0
  171. package/components/wd-loading/wd-loading.vue +70 -0
  172. package/components/wd-loadmore/index.scss +62 -0
  173. package/components/wd-loadmore/types.ts +42 -0
  174. package/components/wd-loadmore/wd-loadmore.vue +68 -0
  175. package/components/wd-navbar/index.scss +96 -0
  176. package/components/wd-navbar/types.ts +74 -0
  177. package/components/wd-navbar/wd-navbar.vue +136 -0
  178. package/components/wd-navbar-capsule/index.scss +70 -0
  179. package/components/wd-navbar-capsule/types.ts +11 -0
  180. package/components/wd-navbar-capsule/wd-navbar-capsule.vue +48 -0
  181. package/components/wd-notice-bar/index.scss +94 -0
  182. package/components/wd-notice-bar/types.ts +97 -0
  183. package/components/wd-notice-bar/wd-notice-bar.vue +270 -0
  184. package/components/wd-notify/index.scss +114 -0
  185. package/components/wd-notify/index.ts +63 -0
  186. package/components/wd-notify/types.ts +130 -0
  187. package/components/wd-notify/wd-notify.vue +162 -0
  188. package/components/wd-overlay/index.scss +14 -0
  189. package/components/wd-overlay/types.ts +42 -0
  190. package/components/wd-overlay/wd-overlay.vue +55 -0
  191. package/components/wd-pagination/index.scss +71 -0
  192. package/components/wd-pagination/types.ts +69 -0
  193. package/components/wd-pagination/wd-pagination.vue +118 -0
  194. package/components/wd-password-input/index.scss +134 -0
  195. package/components/wd-password-input/types.ts +42 -0
  196. package/components/wd-password-input/wd-password-input.vue +51 -0
  197. package/components/wd-picker/index.scss +72 -0
  198. package/components/wd-picker/types.ts +141 -0
  199. package/components/wd-picker/wd-picker.vue +220 -0
  200. package/components/wd-picker-view/index.scss +93 -0
  201. package/components/wd-picker-view/types.ts +145 -0
  202. package/components/wd-picker-view/useSelection.ts +385 -0
  203. package/components/wd-picker-view/wd-picker-view.vue +227 -0
  204. package/components/wd-popover/index.scss +117 -0
  205. package/components/wd-popover/types.ts +106 -0
  206. package/components/wd-popover/wd-popover.vue +212 -0
  207. package/components/wd-popup/index.scss +89 -0
  208. package/components/wd-popup/types.ts +110 -0
  209. package/components/wd-popup/wd-popup.vue +174 -0
  210. package/components/wd-progress/index.scss +155 -0
  211. package/components/wd-progress/types.ts +94 -0
  212. package/components/wd-progress/wd-progress.vue +249 -0
  213. package/components/wd-radio/index.scss +189 -0
  214. package/components/wd-radio/types.ts +64 -0
  215. package/components/wd-radio/wd-radio.vue +164 -0
  216. package/components/wd-radio-group/index.scss +5 -0
  217. package/components/wd-radio-group/types.ts +70 -0
  218. package/components/wd-radio-group/wd-radio-group.vue +53 -0
  219. package/components/wd-rate/index.scss +57 -0
  220. package/components/wd-rate/types.ts +86 -0
  221. package/components/wd-rate/wd-rate.vue +168 -0
  222. package/components/wd-resize/index.scss +31 -0
  223. package/components/wd-resize/types.ts +14 -0
  224. package/components/wd-resize/wd-resize.vue +157 -0
  225. package/components/wd-root-portal/wd-root-portal.vue +77 -0
  226. package/components/wd-row/index.scss +6 -0
  227. package/components/wd-row/types.ts +36 -0
  228. package/components/wd-row/wd-row.vue +88 -0
  229. package/components/wd-search/index.scss +171 -0
  230. package/components/wd-search/types.ts +107 -0
  231. package/components/wd-search/wd-search.vue +198 -0
  232. package/components/wd-segmented/index.scss +155 -0
  233. package/components/wd-segmented/types.ts +81 -0
  234. package/components/wd-segmented/wd-segmented.vue +169 -0
  235. package/components/wd-select-picker/index.scss +72 -0
  236. package/components/wd-select-picker/types.ts +72 -0
  237. package/components/wd-select-picker/wd-select-picker.vue +371 -0
  238. package/components/wd-sidebar/index.scss +25 -0
  239. package/components/wd-sidebar/types.ts +34 -0
  240. package/components/wd-sidebar/wd-sidebar.vue +57 -0
  241. package/components/wd-sidebar-item/index.scss +91 -0
  242. package/components/wd-sidebar-item/types.ts +28 -0
  243. package/components/wd-sidebar-item/wd-sidebar-item.vue +118 -0
  244. package/components/wd-signature/index.scss +42 -0
  245. package/components/wd-signature/types.ts +295 -0
  246. package/components/wd-signature/wd-signature.vue +664 -0
  247. package/components/wd-skeleton/index.scss +112 -0
  248. package/components/wd-skeleton/types.ts +124 -0
  249. package/components/wd-skeleton/wd-skeleton.vue +110 -0
  250. package/components/wd-slide-verify/index.scss +112 -0
  251. package/components/wd-slide-verify/types.ts +98 -0
  252. package/components/wd-slide-verify/wd-slide-verify.vue +222 -0
  253. package/components/wd-slider/index.scss +485 -0
  254. package/components/wd-slider/types.ts +166 -0
  255. package/components/wd-slider/wd-slider.vue +529 -0
  256. package/components/wd-sort-button/index.scss +126 -0
  257. package/components/wd-sort-button/types.ts +68 -0
  258. package/components/wd-sort-button/wd-sort-button.vue +67 -0
  259. package/components/wd-step/index.scss +366 -0
  260. package/components/wd-step/types.ts +43 -0
  261. package/components/wd-step/wd-step.vue +181 -0
  262. package/components/wd-steps/index.scss +7 -0
  263. package/components/wd-steps/types.ts +50 -0
  264. package/components/wd-steps/wd-steps.vue +39 -0
  265. package/components/wd-sticky/index.scss +9 -0
  266. package/components/wd-sticky/types.ts +13 -0
  267. package/components/wd-sticky/wd-sticky.vue +192 -0
  268. package/components/wd-sticky-box/index.scss +6 -0
  269. package/components/wd-sticky-box/types.ts +20 -0
  270. package/components/wd-sticky-box/wd-sticky-box.vue +157 -0
  271. package/components/wd-swipe-action/index.scss +22 -0
  272. package/components/wd-swipe-action/types.ts +87 -0
  273. package/components/wd-swipe-action/wd-swipe-action.vue +320 -0
  274. package/components/wd-swiper/index.scss +69 -0
  275. package/components/wd-swiper/types.ts +275 -0
  276. package/components/wd-swiper/wd-swiper.vue +332 -0
  277. package/components/wd-swiper-nav/index.scss +179 -0
  278. package/components/wd-swiper-nav/types.ts +42 -0
  279. package/components/wd-swiper-nav/wd-swiper-nav.vue +42 -0
  280. package/components/wd-switch/index.scss +177 -0
  281. package/components/wd-switch/types.ts +93 -0
  282. package/components/wd-switch/wd-switch.vue +107 -0
  283. package/components/wd-tab/index.scss +16 -0
  284. package/components/wd-tab/types.ts +45 -0
  285. package/components/wd-tab/wd-tab.vue +99 -0
  286. package/components/wd-tabbar/index.scss +71 -0
  287. package/components/wd-tabbar/types.ts +79 -0
  288. package/components/wd-tabbar/wd-tabbar.vue +109 -0
  289. package/components/wd-tabbar-item/index.scss +50 -0
  290. package/components/wd-tabbar-item/types.ts +45 -0
  291. package/components/wd-tabbar-item/wd-tabbar-item.vue +101 -0
  292. package/components/wd-table/index.scss +128 -0
  293. package/components/wd-table/types.ts +160 -0
  294. package/components/wd-table/wd-table.vue +331 -0
  295. package/components/wd-table-column/index.scss +15 -0
  296. package/components/wd-table-column/types.ts +81 -0
  297. package/components/wd-table-column/wd-table-column.vue +198 -0
  298. package/components/wd-tabs/index.scss +332 -0
  299. package/components/wd-tabs/types.ts +155 -0
  300. package/components/wd-tabs/wd-tabs.vue +508 -0
  301. package/components/wd-tag/index.scss +325 -0
  302. package/components/wd-tag/types.ts +90 -0
  303. package/components/wd-tag/wd-tag.vue +158 -0
  304. package/components/wd-text/index.scss +52 -0
  305. package/components/wd-text/types.ts +107 -0
  306. package/components/wd-text/wd-text.vue +141 -0
  307. package/components/wd-textarea/index.scss +112 -0
  308. package/components/wd-textarea/types.ts +151 -0
  309. package/components/wd-textarea/wd-textarea.vue +212 -0
  310. package/components/wd-toast/index.scss +92 -0
  311. package/components/wd-toast/index.ts +97 -0
  312. package/components/wd-toast/types.ts +190 -0
  313. package/components/wd-toast/wd-toast.vue +158 -0
  314. package/components/wd-tooltip/index.scss +77 -0
  315. package/components/wd-tooltip/types.ts +105 -0
  316. package/components/wd-tooltip/wd-tooltip.vue +169 -0
  317. package/components/wd-tour/index.scss +106 -0
  318. package/components/wd-tour/types.ts +268 -0
  319. package/components/wd-tour/wd-tour.vue +518 -0
  320. package/components/wd-transition/index.scss +67 -0
  321. package/components/wd-transition/types.ts +106 -0
  322. package/components/wd-transition/wd-transition.vue +238 -0
  323. package/components/wd-upload/index.scss +204 -0
  324. package/components/wd-upload/types.ts +390 -0
  325. package/components/wd-upload/wd-upload.vue +565 -0
  326. package/components/wd-video-preview/index.scss +54 -0
  327. package/components/wd-video-preview/index.ts +64 -0
  328. package/components/wd-video-preview/types.ts +66 -0
  329. package/components/wd-video-preview/wd-video-preview.vue +141 -0
  330. package/components/wd-watermark/index.scss +21 -0
  331. package/components/wd-watermark/types.ts +130 -0
  332. package/components/wd-watermark/wd-watermark.vue +718 -0
  333. package/components/wot-ui/wot-ui.vue +5 -0
  334. package/composables/index.ts +16 -0
  335. package/composables/useCell.ts +34 -0
  336. package/composables/useChildren.ts +120 -0
  337. package/composables/useConfigProvider.ts +45 -0
  338. package/composables/useCountDown.ts +138 -0
  339. package/composables/useDeviceInfo.ts +136 -0
  340. package/composables/useLockScroll.ts +37 -0
  341. package/composables/useParent.ts +51 -0
  342. package/composables/usePopover.ts +212 -0
  343. package/composables/useQueue.ts +52 -0
  344. package/composables/useRaf.ts +37 -0
  345. package/composables/useTouch.ts +43 -0
  346. package/composables/useTranslate.ts +12 -0
  347. package/composables/useUpload.ts +366 -0
  348. package/global.d.ts +106 -0
  349. package/index.ts +6 -0
  350. package/locale/index.ts +32 -0
  351. package/locale/lang/ar-SA.ts +150 -0
  352. package/locale/lang/de-DE.ts +150 -0
  353. package/locale/lang/en-US.ts +150 -0
  354. package/locale/lang/es-ES.ts +150 -0
  355. package/locale/lang/fr-FR.ts +150 -0
  356. package/locale/lang/ja-JP.ts +150 -0
  357. package/locale/lang/ko-KR.ts +150 -0
  358. package/locale/lang/pt-PT.ts +150 -0
  359. package/locale/lang/ru-RU.ts +150 -0
  360. package/locale/lang/th-TH.ts +150 -0
  361. package/locale/lang/tr-TR.ts +155 -0
  362. package/locale/lang/ug-CN.ts +154 -0
  363. package/locale/lang/vi-VN.ts +89 -0
  364. package/locale/lang/zh-CN.ts +154 -0
  365. package/locale/lang/zh-HK.ts +78 -0
  366. package/locale/lang/zh-TW.ts +78 -0
  367. package/package.json +1 -11
  368. package/styles/iconfont/iconfont.scss +1243 -0
  369. package/styles/mixin/_config.scss +7 -0
  370. package/styles/mixin/_function.scss +44 -0
  371. package/styles/mixin/_mixin.scss +473 -0
  372. package/styles/theme/base/color.scss +210 -0
  373. package/styles/theme/base/font.scss +13 -0
  374. package/styles/theme/base/index.scss +8 -0
  375. package/styles/theme/base/insets.scss +32 -0
  376. package/styles/theme/base/number.scss +36 -0
  377. package/styles/theme/base/opacity.scss +9 -0
  378. package/styles/theme/base/radius.scss +13 -0
  379. package/styles/theme/base/stroke.scss +9 -0
  380. package/styles/theme/base/typography.scss +44 -0
  381. package/styles/theme/dark.scss +101 -0
  382. package/styles/theme/index.scss +16 -0
  383. package/styles/theme/light.scss +101 -0
  384. package/styles/variable.scss +472 -0
  385. package/tags.json +1 -0
  386. package/web-types.json +1 -0
@@ -0,0 +1,166 @@
1
+ import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
2
+ import { baseProps, makeBooleanProp, makeNumberProp, makeStringProp } from '../../common/props'
3
+
4
+ /**
5
+ * 滑块值类型 - 单滑块为数字,双滑块为数组
6
+ */
7
+ export type SliderValue = number | number[]
8
+
9
+ /**
10
+ * 滑块风格类型
11
+ */
12
+ export type SliderTheme = 'default' | 'capsule'
13
+
14
+ /**
15
+ * 气泡显示模式
16
+ */
17
+ export type SliderPopoverVisible = 'always' | 'normal' | 'never'
18
+
19
+ /**
20
+ * 刻度标记类型
21
+ * - 数组形式: [0, 25, 50, 75, 100]
22
+ * - 对象形式: { 0: '0%', 25: '25%', 50: '50%', 75: '75%', 100: '100%' }
23
+ */
24
+ export type SliderMarks = number[] | Record<number, string>
25
+
26
+ export const sliderProps = {
27
+ ...baseProps,
28
+
29
+ /**
30
+ * 绑定的值
31
+ * 类型: number | number[]
32
+ * 默认值: 0
33
+ */
34
+ modelValue: {
35
+ type: [Number, Array] as PropType<SliderValue>,
36
+ default: 0
37
+ },
38
+
39
+ /**
40
+ * 最小值
41
+ * 类型: number
42
+ * 默认值: 0
43
+ */
44
+ min: makeNumberProp(0),
45
+
46
+ /**
47
+ * 最大值
48
+ * 类型: number
49
+ * 默认值: 100
50
+ */
51
+ max: makeNumberProp(100),
52
+
53
+ /**
54
+ * 步长
55
+ * 类型: number
56
+ * 默认值: 1
57
+ */
58
+ step: makeNumberProp(1),
59
+
60
+ /**
61
+ * 是否为双向滑块模式
62
+ * 类型: boolean
63
+ * 默认值: false
64
+ */
65
+ range: makeBooleanProp(false),
66
+
67
+ /**
68
+ * 是否垂直展示
69
+ * 类型: boolean
70
+ * 默认值: false
71
+ */
72
+ vertical: makeBooleanProp(false),
73
+
74
+ /**
75
+ * 滑块风格
76
+ * 类型: 'default' | 'capsule'
77
+ * 可选值: 'default' | 'capsule'
78
+ * 默认值: 'default'
79
+ */
80
+ theme: makeStringProp<SliderTheme>('default'),
81
+
82
+ /**
83
+ * 是否禁用滑块
84
+ * 类型: boolean
85
+ * 默认值: false
86
+ */
87
+ disabled: makeBooleanProp(false),
88
+
89
+ /**
90
+ * 是否显示最大最小值文本
91
+ * 类型: boolean
92
+ * 默认值: false
93
+ */
94
+ showExtremeValue: makeBooleanProp(false),
95
+
96
+ /**
97
+ * 气泡显示模式
98
+ * 类型: 'always' | 'normal' | 'never'
99
+ * 可选值: 'always' | 'normal' | 'never'
100
+ * 默认值: 'normal'
101
+ */
102
+ popoverVisible: makeStringProp<SliderPopoverVisible>('normal'),
103
+
104
+ /**
105
+ * 刻度标记
106
+ * 类型: number[] | Record<number, string>
107
+ * 默认值: -
108
+ */
109
+ marks: [Array, Object] as PropType<SliderMarks>,
110
+
111
+ /**
112
+ * 进度条激活态颜色
113
+ * 类型: string
114
+ * 默认值: ''
115
+ */
116
+ activeColor: makeStringProp(''),
117
+
118
+ /**
119
+ * 进度条未激活态颜色
120
+ * 类型: string
121
+ * 默认值: ''
122
+ */
123
+ inactiveColor: makeStringProp('')
124
+ }
125
+
126
+ /**
127
+ * 滑块拖动事件参数
128
+ */
129
+ export interface SliderDragEvent {
130
+ /** 当前滑块的值 */
131
+ value: SliderValue
132
+ }
133
+
134
+ /**
135
+ * 滑块组件事件类型定义
136
+ */
137
+ export type SliderEmits = {
138
+ /** 开始拖动滑块时触发 */
139
+ dragstart: [event: SliderDragEvent]
140
+ /** 拖动滑块过程中触发 */
141
+ dragmove: [event: SliderDragEvent]
142
+ /** 结束拖动滑块时触发 */
143
+ dragend: [event: SliderDragEvent]
144
+ /** 值变化时触发(拖动结束或点击轨道后) */
145
+ change: [value: SliderValue]
146
+ /** 更新滑块值时触发,用于 v-model 绑定 */
147
+ 'update:modelValue': [value: SliderValue]
148
+ }
149
+
150
+ /**
151
+ * 滑块组件暴露的方法
152
+ */
153
+ export type SliderExpose = {
154
+ /** 初始化 slider 尺寸 */
155
+ initSlider: () => void
156
+ }
157
+
158
+ /**
159
+ * 滑块组件 Props
160
+ */
161
+ export type SliderProps = ExtractPropTypes<typeof sliderProps>
162
+
163
+ /**
164
+ * 滑块组件实例
165
+ */
166
+ export type SliderInstance = ComponentPublicInstance<SliderProps, SliderExpose>
@@ -0,0 +1,529 @@
1
+ <template>
2
+ <view :class="rootClass" :style="rootStyle">
3
+ <!-- #ifdef MP-DINGTALK -->
4
+ <view style="flex: 1" :class="rootClass">
5
+ <!-- #endif -->
6
+ <!-- 最小值文本 -->
7
+ <view v-if="showExtremeValue" :class="`wd-slider__value wd-slider__value--min`">
8
+ {{ min }}
9
+ </view>
10
+
11
+ <!-- 轨道 -->
12
+ <view :id="sliderId" :class="barClass" :style="barStyle" @click.stop="onBarClick">
13
+ <!-- 可滑动有效轨道(用于尺寸测量与 marks 定位) -->
14
+ <view :id="trackId" class="wd-slider__track">
15
+ <template v-if="hasMarks">
16
+ <view v-for="(mark, index) in scaleList" :key="index" :class="scaleItemClass(mark.val)" :style="scaleItemStyle(mark.position)">
17
+ <view
18
+ v-if="mark.label"
19
+ :class="`wd-slider__scale-desc ${props.theme === 'capsule' ? 'wd-slider__scale-desc--capsule' : 'wd-slider__scale-desc--default'}`"
20
+ >
21
+ {{ mark.label }}
22
+ </view>
23
+ </view>
24
+ </template>
25
+ </view>
26
+
27
+ <!-- 进度条 + 滑块 -->
28
+ <view :class="lineClass" :style="lineStyle">
29
+ <!-- 单滑块 / 双滑块左侧 -->
30
+ <view
31
+ :class="`wd-slider__dot ${range ? 'wd-slider__dot--left' : ''}`"
32
+ @touchstart.stop="(e: any) => onTouchStart(e, 0)"
33
+ @touchmove.stop.prevent="onTouchMove"
34
+ @touchend.stop="onTouchEnd"
35
+ @touchcancel.stop="onTouchEnd"
36
+ >
37
+ <view v-if="popoverVisible !== 'never'" class="wd-slider__dot-popover" :class="{ 'is-visible': showDotPopover(0) }">
38
+ <text class="wd-slider__dot-popover-text">{{ dotDisplayValue(0) }}</text>
39
+ <view class="wd-slider__dot-popover-arrow"></view>
40
+ </view>
41
+ <view class="wd-slider__dot-slider">
42
+ <wd-icon name="multiple-horizontal" size="14px" color="#868a9c" />
43
+ </view>
44
+ </view>
45
+
46
+ <!-- 双滑块右侧 -->
47
+ <view
48
+ v-if="range"
49
+ :class="`wd-slider__dot wd-slider__dot--right`"
50
+ @touchstart.stop="(e: any) => onTouchStart(e, 1)"
51
+ @touchmove.stop.prevent="onTouchMove"
52
+ @touchend.stop="onTouchEnd"
53
+ @touchcancel.stop="onTouchEnd"
54
+ >
55
+ <view v-if="popoverVisible !== 'never'" class="wd-slider__dot-popover" :class="{ 'is-visible': showDotPopover(1) }">
56
+ <text class="wd-slider__dot-popover-text">{{ dotDisplayValue(1) }}</text>
57
+ <view class="wd-slider__dot-popover-arrow"></view>
58
+ </view>
59
+ <view class="wd-slider__dot-slider">
60
+ <wd-icon name="multiple-horizontal" size="14px" color="#868a9c" />
61
+ </view>
62
+ </view>
63
+ </view>
64
+ </view>
65
+
66
+ <!-- 最大值文本 -->
67
+ <view v-if="showExtremeValue" :class="`wd-slider__value wd-slider__value--max`">
68
+ {{ max }}
69
+ </view>
70
+ <!-- #ifdef MP-DINGTALK -->
71
+ </view>
72
+ <!-- #endif -->
73
+ </view>
74
+ </template>
75
+
76
+ <script lang="ts">
77
+ export default {
78
+ name: 'wd-slider',
79
+ options: {
80
+ addGlobalClass: true,
81
+ // #ifndef MP-TOUTIAO
82
+ virtualHost: true,
83
+ // #endif
84
+ styleIsolation: 'shared'
85
+ }
86
+ }
87
+ </script>
88
+
89
+ <script lang="ts" setup>
90
+ import { computed, type CSSProperties, getCurrentInstance, onMounted, ref, watch } from 'vue'
91
+ import { deepClone, getRect, isArray, isDef, isEqual, objToStyle, uuid } from '../../common/util'
92
+ import { useTouch } from '../../composables/useTouch'
93
+ import { sliderProps, type SliderExpose, type SliderEmits, type SliderValue, type SliderMarks, type SliderPopoverVisible } from './types'
94
+
95
+ const props = defineProps(sliderProps)
96
+ const emit = defineEmits<SliderEmits>()
97
+
98
+ const sliderId = ref<string>(`wd-slider-${uuid()}`)
99
+ const trackId = ref<string>(`${sliderId.value}-track`)
100
+ const touch = useTouch()
101
+ const touchIndex = ref<number>(0) // 当前正在拖动的滑块索引 (0 为左/单,1 为右)
102
+ const isDragging = ref<boolean>(false) // 是否正在拖动
103
+ const { proxy } = getCurrentInstance() as any
104
+
105
+ /**
106
+ * 轨道长度 (水平为宽度,垂直为高度)
107
+ */
108
+ const trackSize = ref<number>(0)
109
+ const startValue = ref<SliderValue>(0) // 拖动开始时的初始值
110
+ const modelValue = ref<SliderValue>(getInitValue()) // 内部维护的滑块值
111
+
112
+ /**
113
+ * 计算滑块的取值范围大小
114
+ */
115
+ const scope = computed(() => props.max - props.min)
116
+
117
+ /**
118
+ * 步长值(确保大于 0)
119
+ */
120
+ const validStep = computed(() => {
121
+ if (props.step <= 0) {
122
+ console.warn('[wot ui] warning(wd-slider): step must be greater than 0')
123
+ return 1
124
+ }
125
+ return props.step
126
+ })
127
+
128
+ /**
129
+ * 当前值始终返回 [left, right] 格式方便统一处理
130
+ */
131
+ const currentValue = computed<[number, number]>(() => {
132
+ if (props.range && isArray(modelValue.value)) {
133
+ return normalizeRangeValues(modelValue.value as number[])
134
+ }
135
+ return [modelValue.value as number, 0]
136
+ })
137
+
138
+ /**
139
+ * 是否有刻度标记
140
+ */
141
+ const hasMarks = computed(() => isDef(props.marks))
142
+
143
+ /**
144
+ * 刻度列表
145
+ */
146
+ const scaleList = computed(() => {
147
+ if (!props.marks) return []
148
+
149
+ let markValues: number[] = []
150
+ let markLabels: Record<number, string> = {}
151
+
152
+ if (isArray(props.marks)) {
153
+ markValues = props.marks as number[]
154
+ } else {
155
+ markValues = Object.keys(props.marks).map(Number)
156
+ markLabels = props.marks as Record<number, string>
157
+ }
158
+
159
+ return markValues.map((val) => ({
160
+ val,
161
+ label: isDef(markLabels[val]) ? markLabels[val] : String(val),
162
+ position: scope.value === 0 ? 0 : ((val - props.min) / scope.value) * 100
163
+ }))
164
+ })
165
+
166
+ /**
167
+ * 根类名计算
168
+ */
169
+ const rootClass = computed(() => {
170
+ const classes = ['wd-slider']
171
+ classes.push(`wd-slider--theme-${props.theme}`)
172
+ if (props.disabled) classes.push('is-disabled')
173
+ if (props.vertical) {
174
+ classes.push('wd-slider--vertical')
175
+ } else {
176
+ classes.push('wd-slider--horizontal')
177
+ }
178
+ if (hasMarks.value) classes.push('wd-slider--marks')
179
+ if (props.showExtremeValue) classes.push('wd-slider--with-extreme')
180
+ if (props.range) classes.push('is-range')
181
+ if (props.customClass) classes.push(props.customClass)
182
+ return classes.join(' ')
183
+ })
184
+
185
+ /**
186
+ * 根节点样式
187
+ */
188
+ const rootStyle = computed(() => {
189
+ return props.customStyle || ''
190
+ })
191
+
192
+ /**
193
+ * 轨道类名
194
+ */
195
+ const barClass = computed(() => {
196
+ const classes = ['wd-slider__bar', `wd-slider__bar--${props.theme}`]
197
+ if (props.disabled) classes.push('is-disabled')
198
+ return classes.join(' ')
199
+ })
200
+
201
+ /**
202
+ * 轨道样式
203
+ */
204
+ const barStyle = computed(() => {
205
+ const style: CSSProperties = {}
206
+ if (props.inactiveColor) {
207
+ style.background = props.inactiveColor
208
+ }
209
+ return objToStyle(style)
210
+ })
211
+
212
+ /**
213
+ * 进度条类名
214
+ */
215
+ const lineClass = computed(() => {
216
+ const classes = ['wd-slider__line', `wd-slider__line--${props.theme}`]
217
+ if (!props.range) classes.push('wd-slider__line--single')
218
+ if (props.disabled) classes.push('is-disabled')
219
+ return classes.join(' ')
220
+ })
221
+
222
+ /**
223
+ * 宽度/高度样式计算
224
+ */
225
+ const lineStyle = computed(() => {
226
+ const style: CSSProperties = {}
227
+
228
+ if (scope.value === 0) return objToStyle(style)
229
+
230
+ const prop = props.vertical ? 'height' : 'width'
231
+ const startProp = props.vertical ? 'top' : 'left'
232
+
233
+ if (props.range) {
234
+ const [left, right] = currentValue.value
235
+ const start = ((left - props.min) / scope.value) * 100
236
+ const size = ((right - left) / scope.value) * 100
237
+ style[startProp] = `${start}%`
238
+ style[prop] = `${size}%`
239
+ } else {
240
+ const value = modelValue.value as number
241
+ const size = ((value - props.min) / scope.value) * 100
242
+ style[startProp] = '0'
243
+ style[prop] = `${size}%`
244
+ }
245
+
246
+ if (props.activeColor) {
247
+ style.background = props.activeColor
248
+ }
249
+
250
+ return objToStyle(style)
251
+ })
252
+
253
+ // ----------- 监听器 -----------
254
+
255
+ /**
256
+ * 监听 modelValue 属性变化
257
+ */
258
+ watch(
259
+ () => props.modelValue,
260
+ (newValue) => {
261
+ if (!isEqual(newValue, modelValue.value)) {
262
+ modelValue.value = getInitValue()
263
+ }
264
+ },
265
+ { deep: true }
266
+ )
267
+
268
+ /**
269
+ * 向上发射模型值变化
270
+ */
271
+ watch(modelValue, (newVal) => {
272
+ emit('update:modelValue', newVal)
273
+ })
274
+
275
+ onMounted(() => {
276
+ initSlider()
277
+ })
278
+
279
+ /**
280
+ * 限制值在指定范围内
281
+ */
282
+ function clamp(value: number, min: number, max: number): number {
283
+ return Math.min(Math.max(value, min), max)
284
+ }
285
+
286
+ /**
287
+ * 初始化滑块尺寸
288
+ * 获取轨道的宽高用于后续计算
289
+ */
290
+ function initSlider() {
291
+ getRect(`#${trackId.value}`, false, proxy).then((data) => {
292
+ if (props.vertical) {
293
+ trackSize.value = Number(data.height)
294
+ } else {
295
+ trackSize.value = Number(data.width)
296
+ }
297
+ })
298
+ }
299
+
300
+ /**
301
+ * 获取事件触点坐标
302
+ * @param event 事件对象
303
+ * @returns {number} 水平取 x,垂直取 y
304
+ */
305
+ function getPointerPosition(event: any): number {
306
+ return props.vertical
307
+ ? Number(event.detail?.y ?? event.clientY ?? event.touches?.[0]?.clientY ?? 0)
308
+ : Number(event.detail?.x ?? event.clientX ?? event.touches?.[0]?.clientX ?? 0)
309
+ }
310
+
311
+ /**
312
+ * 获取初始值
313
+ * @returns {SliderValue} 初始化后的滑块值
314
+ */
315
+ function getInitValue(): SliderValue {
316
+ if (props.range) {
317
+ if (isArray(props.modelValue)) {
318
+ return normalizeRangeValues(props.modelValue as number[])
319
+ }
320
+ return [props.min, props.max]
321
+ }
322
+ return clamp(props.modelValue as number, props.min, props.max)
323
+ }
324
+
325
+ /**
326
+ * 标准化范围值,确保 left <= right
327
+ * @param {number[]} value 范围值
328
+ * @returns {[number, number]} 格式化后的范围值
329
+ */
330
+ function normalizeRangeValues(value: number[]): [number, number] {
331
+ if (!Array.isArray(value) || value.length < 2) {
332
+ console.warn('[wot ui] warning(wd-slider): range value should be an array with at least 2 elements')
333
+ return [props.min, props.max]
334
+ }
335
+
336
+ const left = clamp(value[0], props.min, props.max)
337
+ const right = clamp(value[1], props.min, props.max)
338
+
339
+ return left > right ? [right, left] : [left, right]
340
+ }
341
+
342
+ /**
343
+ * 将值对齐到最近的步长倍数
344
+ * @param {number} value 原始值
345
+ * @returns {number} 对齐步长后的值
346
+ */
347
+ function calcByStep(value: number): number {
348
+ value = clamp(value, props.min, props.max)
349
+ const steps = Math.round((value - props.min) / validStep.value)
350
+ return parseFloat((props.min + steps * validStep.value).toFixed(10))
351
+ }
352
+
353
+ /**
354
+ * 统一更新滑块值并触发事件
355
+ * @param {SliderValue} value 新的滑块值
356
+ */
357
+ function updateValue(value: SliderValue) {
358
+ let newValue: SliderValue = deepClone(value)
359
+
360
+ if (props.range && isArray(newValue)) {
361
+ newValue = normalizeRangeValues(newValue as number[]).map((v) => calcByStep(v)) as [number, number]
362
+ } else {
363
+ newValue = calcByStep(newValue as number)
364
+ }
365
+
366
+ if (!isEqual(newValue, modelValue.value)) {
367
+ modelValue.value = newValue
368
+ }
369
+ }
370
+
371
+ /**
372
+ * 将坐标位置转换为对应的滑块值
373
+ * @param {number} position 相对轨道起点的像素距离
374
+ * @returns {number} 转换后的数值
375
+ */
376
+ function positionToValue(position: number): number {
377
+ if (trackSize.value === 0) return props.min
378
+ return (position / trackSize.value) * scope.value + props.min
379
+ }
380
+
381
+ /**
382
+ * 计算刻度项类名
383
+ * @param {number} val 刻度对应的值
384
+ */
385
+ function scaleItemClass(val: number): string {
386
+ const classes = ['wd-slider__scale-item', `wd-slider__scale-item--${props.theme}`]
387
+
388
+ const isActive = Array.isArray(modelValue.value) ? val >= modelValue.value[0] && val <= modelValue.value[1] : val <= (modelValue.value as number)
389
+
390
+ if (isActive) classes.push('is-active')
391
+ if (props.disabled) classes.push('is-disabled')
392
+
393
+ return classes.join(' ')
394
+ }
395
+
396
+ /**
397
+ * 计算刻度项定位样式
398
+ * @param {number} position 刻度在轨道上的百分比位置
399
+ */
400
+ function scaleItemStyle(position: number): string {
401
+ if (props.vertical) {
402
+ return `top: ${position}%;`
403
+ }
404
+ return `left: ${position}%;`
405
+ }
406
+
407
+ /**
408
+ * 获取指定滑块上方气泡显示值
409
+ * @param {number} index 滑块索引
410
+ */
411
+ function dotDisplayValue(index: number): number {
412
+ if (!props.range) {
413
+ return modelValue.value as number
414
+ }
415
+ const values = currentValue.value
416
+ return values[index] ?? values[0]
417
+ }
418
+
419
+ /**
420
+ * 控制气泡显示隐藏
421
+ * @param {number} index dot 索引 (0 = 左/单滑块,1 = 右滑块)
422
+ */
423
+ function showDotPopover(index: number): boolean {
424
+ const mode = props.popoverVisible as SliderPopoverVisible
425
+ if (mode === 'always') return true
426
+ if (mode === 'normal') return isDragging.value && touchIndex.value === index
427
+ return false
428
+ }
429
+
430
+ /**
431
+ * 滑块触摸开始
432
+ * @param event 触摸事件
433
+ * @param {number} index 滑块索引
434
+ */
435
+ function onTouchStart(event: any, index: number) {
436
+ if (props.disabled) return
437
+
438
+ touchIndex.value = index
439
+ isDragging.value = true
440
+ touch.touchStart(event)
441
+
442
+ startValue.value = deepClone(modelValue.value)
443
+ emit('dragstart', { value: modelValue.value })
444
+ }
445
+
446
+ /**
447
+ * 滑块触摸移动
448
+ * @param event 触摸事件
449
+ */
450
+ function onTouchMove(event: any) {
451
+ if (props.disabled) return
452
+
453
+ touch.touchMove(event)
454
+
455
+ const delta = props.vertical ? touch.deltaY.value : touch.deltaX.value
456
+ const diff = (delta / trackSize.value) * scope.value
457
+ let newValue = deepClone(startValue.value)
458
+
459
+ if (props.range && isArray(newValue)) {
460
+ ;(newValue as number[])[touchIndex.value] += diff
461
+ } else {
462
+ newValue = (newValue as number) + diff
463
+ }
464
+
465
+ updateValue(newValue)
466
+ emit('dragmove', { value: modelValue.value })
467
+ }
468
+
469
+ /**
470
+ * 滑块触摸结束
471
+ */
472
+ function onTouchEnd() {
473
+ if (props.disabled) return
474
+
475
+ isDragging.value = false
476
+ emit('dragend', { value: modelValue.value })
477
+ emit('change', modelValue.value)
478
+ }
479
+
480
+ /**
481
+ * 点击轨道跳转
482
+ * @param event 点击事件
483
+ */
484
+ function onBarClick(event: any) {
485
+ if (props.disabled) return
486
+
487
+ // 基于可滑动有效轨道换算点击位置,避免主题内边距造成偏差
488
+ getRect(`#${trackId.value}`, false, proxy).then((data) => {
489
+ const pointer = getPointerPosition(event)
490
+ const start = props.vertical ? Number(data.top) : Number(data.left)
491
+ const pos = pointer - start
492
+ handleBarClickAt(pos)
493
+ })
494
+ }
495
+
496
+ /**
497
+ * 处理轨道点击跳转具体逻辑
498
+ * @param {number} position 相对起始点的点击位置
499
+ */
500
+ function handleBarClickAt(position: number) {
501
+ const clickValue = calcByStep(positionToValue(position))
502
+
503
+ if (props.range) {
504
+ const [left, right] = currentValue.value
505
+ const distLeft = Math.abs(clickValue - left)
506
+ const distRight = Math.abs(clickValue - right)
507
+ const newValue = [...(modelValue.value as number[])]
508
+
509
+ if (distLeft <= distRight) {
510
+ newValue[0] = clickValue
511
+ } else {
512
+ newValue[1] = clickValue
513
+ }
514
+ updateValue(newValue)
515
+ } else {
516
+ updateValue(clickValue)
517
+ }
518
+
519
+ emit('change', modelValue.value)
520
+ }
521
+
522
+ defineExpose<SliderExpose>({
523
+ initSlider
524
+ })
525
+ </script>
526
+
527
+ <style lang="scss">
528
+ @use './index.scss';
529
+ </style>