@tplc/wot 0.0.1

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 (328) hide show
  1. package/components/common/AbortablePromise.ts +36 -0
  2. package/components/common/abstracts/_config.scss +7 -0
  3. package/components/common/abstracts/_function.scss +76 -0
  4. package/components/common/abstracts/_mixin.scss +339 -0
  5. package/components/common/abstracts/variable.scss +1346 -0
  6. package/components/common/base64.ts +30 -0
  7. package/components/common/canvasHelper.ts +49 -0
  8. package/components/common/clickoutside.ts +34 -0
  9. package/components/common/dayjs.ts +157 -0
  10. package/components/common/event.ts +8 -0
  11. package/components/common/props.ts +51 -0
  12. package/components/common/util.ts +751 -0
  13. package/components/composables/useCell.ts +13 -0
  14. package/components/composables/useChildren.ts +122 -0
  15. package/components/composables/useCountDown.ts +138 -0
  16. package/components/composables/useLockScroll.ts +39 -0
  17. package/components/composables/useParent.ts +41 -0
  18. package/components/composables/usePopover.ts +193 -0
  19. package/components/composables/useQueue.ts +52 -0
  20. package/components/composables/useRaf.ts +37 -0
  21. package/components/composables/useTouch.ts +44 -0
  22. package/components/composables/useTranslate.ts +22 -0
  23. package/components/wd-action-sheet/index.scss +204 -0
  24. package/components/wd-action-sheet/types.ts +128 -0
  25. package/components/wd-action-sheet/wd-action-sheet.vue +174 -0
  26. package/components/wd-backtop/index.scss +25 -0
  27. package/components/wd-backtop/types.ts +37 -0
  28. package/components/wd-backtop/wd-backtop.vue +48 -0
  29. package/components/wd-badge/index.scss +59 -0
  30. package/components/wd-badge/types.ts +53 -0
  31. package/components/wd-badge/wd-badge.vue +69 -0
  32. package/components/wd-button/index.scss +340 -0
  33. package/components/wd-button/types.ts +112 -0
  34. package/components/wd-button/wd-button.vue +176 -0
  35. package/components/wd-calendar/index.scss +244 -0
  36. package/components/wd-calendar/types.ts +235 -0
  37. package/components/wd-calendar/wd-calendar.vue +456 -0
  38. package/components/wd-calendar-view/index.scss +9 -0
  39. package/components/wd-calendar-view/month/index.scss +151 -0
  40. package/components/wd-calendar-view/month/month.vue +391 -0
  41. package/components/wd-calendar-view/month/types.ts +19 -0
  42. package/components/wd-calendar-view/monthPanel/index.scss +89 -0
  43. package/components/wd-calendar-view/monthPanel/month-panel.vue +388 -0
  44. package/components/wd-calendar-view/monthPanel/types.ts +48 -0
  45. package/components/wd-calendar-view/types.ts +134 -0
  46. package/components/wd-calendar-view/utils.ts +451 -0
  47. package/components/wd-calendar-view/wd-calendar-view.vue +111 -0
  48. package/components/wd-calendar-view/year/index.scss +148 -0
  49. package/components/wd-calendar-view/year/types.ts +19 -0
  50. package/components/wd-calendar-view/year/year.vue +220 -0
  51. package/components/wd-calendar-view/yearPanel/index.scss +24 -0
  52. package/components/wd-calendar-view/yearPanel/types.ts +38 -0
  53. package/components/wd-calendar-view/yearPanel/year-panel.vue +140 -0
  54. package/components/wd-card/index.scss +70 -0
  55. package/components/wd-card/types.ts +30 -0
  56. package/components/wd-card/wd-card.vue +40 -0
  57. package/components/wd-cell/index.scss +189 -0
  58. package/components/wd-cell/types.ts +96 -0
  59. package/components/wd-cell/wd-cell.vue +135 -0
  60. package/components/wd-cell-group/index.scss +55 -0
  61. package/components/wd-cell-group/types.ts +41 -0
  62. package/components/wd-cell-group/wd-cell-group.vue +45 -0
  63. package/components/wd-checkbox/index.scss +285 -0
  64. package/components/wd-checkbox/types.ts +68 -0
  65. package/components/wd-checkbox/wd-checkbox.vue +185 -0
  66. package/components/wd-checkbox-group/index.scss +20 -0
  67. package/components/wd-checkbox-group/types.ts +59 -0
  68. package/components/wd-checkbox-group/wd-checkbox-group.vue +103 -0
  69. package/components/wd-circle/index.scss +18 -0
  70. package/components/wd-circle/types.ts +54 -0
  71. package/components/wd-circle/wd-circle.vue +318 -0
  72. package/components/wd-col/index.scss +19 -0
  73. package/components/wd-col/types.ts +15 -0
  74. package/components/wd-col/wd-col.vue +91 -0
  75. package/components/wd-col-picker/index.scss +241 -0
  76. package/components/wd-col-picker/types.ts +170 -0
  77. package/components/wd-col-picker/wd-col-picker.vue +550 -0
  78. package/components/wd-collapse/index.scss +55 -0
  79. package/components/wd-collapse/types.ts +63 -0
  80. package/components/wd-collapse/wd-collapse.vue +160 -0
  81. package/components/wd-collapse-item/index.scss +79 -0
  82. package/components/wd-collapse-item/types.ts +36 -0
  83. package/components/wd-collapse-item/wd-collapse-item.vue +182 -0
  84. package/components/wd-config-provider/types.ts +1023 -0
  85. package/components/wd-config-provider/wd-config-provider.vue +82 -0
  86. package/components/wd-count-down/index.scss +14 -0
  87. package/components/wd-count-down/types.ts +41 -0
  88. package/components/wd-count-down/utils.ts +52 -0
  89. package/components/wd-count-down/wd-count-down.vue +60 -0
  90. package/components/wd-count-to/index.scss +6 -0
  91. package/components/wd-count-to/types.ts +110 -0
  92. package/components/wd-count-to/wd-count-to.vue +134 -0
  93. package/components/wd-curtain/index.scss +80 -0
  94. package/components/wd-curtain/types.ts +45 -0
  95. package/components/wd-curtain/wd-curtain.vue +174 -0
  96. package/components/wd-datetime-picker/index.scss +243 -0
  97. package/components/wd-datetime-picker/types.ts +225 -0
  98. package/components/wd-datetime-picker/wd-datetime-picker.vue +827 -0
  99. package/components/wd-datetime-picker-view/index.scss +0 -0
  100. package/components/wd-datetime-picker-view/types.ts +137 -0
  101. package/components/wd-datetime-picker-view/wd-datetime-picker-view.vue +514 -0
  102. package/components/wd-divider/index.scss +32 -0
  103. package/components/wd-divider/types.ts +12 -0
  104. package/components/wd-divider/wd-divider.vue +29 -0
  105. package/components/wd-drop-menu/index.scss +89 -0
  106. package/components/wd-drop-menu/types.ts +38 -0
  107. package/components/wd-drop-menu/wd-drop-menu.vue +128 -0
  108. package/components/wd-drop-menu-item/index.scss +66 -0
  109. package/components/wd-drop-menu-item/types.ts +78 -0
  110. package/components/wd-drop-menu-item/wd-drop-menu-item.vue +230 -0
  111. package/components/wd-fab/index.scss +115 -0
  112. package/components/wd-fab/types.ts +61 -0
  113. package/components/wd-fab/wd-fab.vue +257 -0
  114. package/components/wd-form/index.scss +10 -0
  115. package/components/wd-form/types.ts +93 -0
  116. package/components/wd-form/wd-form.vue +185 -0
  117. package/components/wd-form-item/index.scss +17 -0
  118. package/components/wd-form-item/types.ts +22 -0
  119. package/components/wd-form-item/wd-form-item.vue +65 -0
  120. package/components/wd-gap/index.scss +9 -0
  121. package/components/wd-gap/types.ts +23 -0
  122. package/components/wd-gap/wd-gap.vue +39 -0
  123. package/components/wd-grid/index.scss +9 -0
  124. package/components/wd-grid/types.ts +54 -0
  125. package/components/wd-grid/wd-grid.vue +107 -0
  126. package/components/wd-grid-item/index.scss +137 -0
  127. package/components/wd-grid-item/types.ts +74 -0
  128. package/components/wd-grid-item/wd-grid-item.vue +181 -0
  129. package/components/wd-icon/index.scss +1222 -0
  130. package/components/wd-icon/types.ts +21 -0
  131. package/components/wd-icon/wd-icon.vue +53 -0
  132. package/components/wd-icon/wd-icons.ttf +0 -0
  133. package/components/wd-img/index.scss +19 -0
  134. package/components/wd-img/types.ts +53 -0
  135. package/components/wd-img/wd-img.vue +76 -0
  136. package/components/wd-img-cropper/index.scss +227 -0
  137. package/components/wd-img-cropper/types.ts +87 -0
  138. package/components/wd-img-cropper/wd-img-cropper.vue +659 -0
  139. package/components/wd-index-anchor/index.scss +34 -0
  140. package/components/wd-index-anchor/type.ts +9 -0
  141. package/components/wd-index-anchor/wd-index-anchor.vue +57 -0
  142. package/components/wd-index-bar/index.scss +39 -0
  143. package/components/wd-index-bar/type.ts +28 -0
  144. package/components/wd-index-bar/wd-index-bar.vue +158 -0
  145. package/components/wd-input/index.scss +326 -0
  146. package/components/wd-input/types.ts +182 -0
  147. package/components/wd-input/wd-input.vue +327 -0
  148. package/components/wd-input-number/index.scss +132 -0
  149. package/components/wd-input-number/types.ts +78 -0
  150. package/components/wd-input-number/wd-input-number.vue +221 -0
  151. package/components/wd-loading/index.scss +34 -0
  152. package/components/wd-loading/types.ts +31 -0
  153. package/components/wd-loading/wd-loading.vue +90 -0
  154. package/components/wd-loadmore/index.scss +39 -0
  155. package/components/wd-loadmore/types.ts +24 -0
  156. package/components/wd-loadmore/wd-loadmore.vue +53 -0
  157. package/components/wd-message-box/index.scss +121 -0
  158. package/components/wd-message-box/index.ts +95 -0
  159. package/components/wd-message-box/types.ts +116 -0
  160. package/components/wd-message-box/wd-message-box.vue +326 -0
  161. package/components/wd-navbar/index.scss +103 -0
  162. package/components/wd-navbar/types.ts +52 -0
  163. package/components/wd-navbar/wd-navbar.vue +142 -0
  164. package/components/wd-navbar-capsule/index.scss +65 -0
  165. package/components/wd-navbar-capsule/types.ts +0 -0
  166. package/components/wd-navbar-capsule/wd-navbar-capsule.vue +31 -0
  167. package/components/wd-notice-bar/index.scss +86 -0
  168. package/components/wd-notice-bar/types.ts +56 -0
  169. package/components/wd-notice-bar/wd-notice-bar.vue +223 -0
  170. package/components/wd-notify/index.scss +34 -0
  171. package/components/wd-notify/index.ts +59 -0
  172. package/components/wd-notify/types.ts +62 -0
  173. package/components/wd-notify/wd-notify.vue +83 -0
  174. package/components/wd-number-keyboard/index.scss +78 -0
  175. package/components/wd-number-keyboard/key/index.scss +79 -0
  176. package/components/wd-number-keyboard/key/index.vue +76 -0
  177. package/components/wd-number-keyboard/key/types.ts +11 -0
  178. package/components/wd-number-keyboard/types.ts +79 -0
  179. package/components/wd-number-keyboard/wd-number-keyboard.vue +173 -0
  180. package/components/wd-overlay/index.scss +17 -0
  181. package/components/wd-overlay/types.ts +25 -0
  182. package/components/wd-overlay/wd-overlay.vue +46 -0
  183. package/components/wd-pagination/index.scss +57 -0
  184. package/components/wd-pagination/types.ts +41 -0
  185. package/components/wd-pagination/wd-pagination.vue +121 -0
  186. package/components/wd-password-input/index.scss +123 -0
  187. package/components/wd-password-input/types.ts +48 -0
  188. package/components/wd-password-input/wd-password-input.vue +58 -0
  189. package/components/wd-picker/index.scss +216 -0
  190. package/components/wd-picker/types.ts +186 -0
  191. package/components/wd-picker/wd-picker.vue +409 -0
  192. package/components/wd-picker-view/index.scss +91 -0
  193. package/components/wd-picker-view/types.ts +162 -0
  194. package/components/wd-picker-view/wd-picker-view.vue +361 -0
  195. package/components/wd-popover/index.scss +123 -0
  196. package/components/wd-popover/types.ts +69 -0
  197. package/components/wd-popover/wd-popover.vue +216 -0
  198. package/components/wd-popup/index.scss +112 -0
  199. package/components/wd-popup/types.ts +68 -0
  200. package/components/wd-popup/wd-popup.vue +227 -0
  201. package/components/wd-progress/index.scss +62 -0
  202. package/components/wd-progress/types.ts +40 -0
  203. package/components/wd-progress/wd-progress.vue +201 -0
  204. package/components/wd-radio/index.scss +300 -0
  205. package/components/wd-radio/types.ts +42 -0
  206. package/components/wd-radio/wd-radio.vue +136 -0
  207. package/components/wd-radio-group/index.scss +23 -0
  208. package/components/wd-radio-group/types.ts +36 -0
  209. package/components/wd-radio-group/wd-radio-group.vue +54 -0
  210. package/components/wd-rate/index.scss +24 -0
  211. package/components/wd-rate/types.ts +91 -0
  212. package/components/wd-rate/wd-rate.vue +131 -0
  213. package/components/wd-resize/index.scss +26 -0
  214. package/components/wd-resize/types.ts +6 -0
  215. package/components/wd-resize/wd-resize.vue +155 -0
  216. package/components/wd-row/index.scss +10 -0
  217. package/components/wd-row/types.ts +16 -0
  218. package/components/wd-row/wd-row.vue +63 -0
  219. package/components/wd-search/index.scss +148 -0
  220. package/components/wd-search/types.ts +83 -0
  221. package/components/wd-search/wd-search.vue +237 -0
  222. package/components/wd-segmented/index.scss +97 -0
  223. package/components/wd-segmented/types.ts +68 -0
  224. package/components/wd-segmented/wd-segmented.vue +143 -0
  225. package/components/wd-select-picker/index.scss +177 -0
  226. package/components/wd-select-picker/types.ts +116 -0
  227. package/components/wd-select-picker/wd-select-picker.vue +486 -0
  228. package/components/wd-sidebar/index.scss +25 -0
  229. package/components/wd-sidebar/types.ts +28 -0
  230. package/components/wd-sidebar/wd-sidebar.vue +41 -0
  231. package/components/wd-sidebar-item/index.scss +93 -0
  232. package/components/wd-sidebar-item/types.ts +31 -0
  233. package/components/wd-sidebar-item/wd-sidebar-item.vue +114 -0
  234. package/components/wd-skeleton/index.scss +101 -0
  235. package/components/wd-skeleton/index.ts +1 -0
  236. package/components/wd-skeleton/types.ts +69 -0
  237. package/components/wd-skeleton/wd-skeleton.vue +135 -0
  238. package/components/wd-slider/index.scss +91 -0
  239. package/components/wd-slider/types.ts +104 -0
  240. package/components/wd-slider/wd-slider.vue +377 -0
  241. package/components/wd-sort-button/index.scss +86 -0
  242. package/components/wd-sort-button/types.ts +43 -0
  243. package/components/wd-sort-button/wd-sort-button.vue +76 -0
  244. package/components/wd-status-tip/index.scss +37 -0
  245. package/components/wd-status-tip/types.ts +59 -0
  246. package/components/wd-status-tip/wd-status-tip.vue +94 -0
  247. package/components/wd-step/index.scss +236 -0
  248. package/components/wd-step/types.ts +33 -0
  249. package/components/wd-step/wd-step.vue +151 -0
  250. package/components/wd-steps/index.scss +10 -0
  251. package/components/wd-steps/types.ts +59 -0
  252. package/components/wd-steps/wd-steps.vue +37 -0
  253. package/components/wd-sticky/index.scss +9 -0
  254. package/components/wd-sticky/types.ts +13 -0
  255. package/components/wd-sticky/wd-sticky.vue +190 -0
  256. package/components/wd-sticky-box/index.scss +6 -0
  257. package/components/wd-sticky-box/types.ts +20 -0
  258. package/components/wd-sticky-box/wd-sticky-box.vue +154 -0
  259. package/components/wd-swipe-action/index.scss +22 -0
  260. package/components/wd-swipe-action/types.ts +43 -0
  261. package/components/wd-swipe-action/wd-swipe-action.vue +307 -0
  262. package/components/wd-swiper/index.scss +23 -0
  263. package/components/wd-swiper/types.ts +189 -0
  264. package/components/wd-swiper/wd-swiper.vue +202 -0
  265. package/components/wd-swiper-nav/index.scss +153 -0
  266. package/components/wd-swiper-nav/types.ts +42 -0
  267. package/components/wd-swiper-nav/wd-swiper-nav.vue +37 -0
  268. package/components/wd-switch/index.scss +58 -0
  269. package/components/wd-switch/types.ts +56 -0
  270. package/components/wd-switch/wd-switch.vue +83 -0
  271. package/components/wd-tab/index.scss +8 -0
  272. package/components/wd-tab/types.ts +20 -0
  273. package/components/wd-tab/wd-tab.vue +100 -0
  274. package/components/wd-tabbar/index.scss +57 -0
  275. package/components/wd-tabbar/types.ts +88 -0
  276. package/components/wd-tabbar/wd-tabbar.vue +104 -0
  277. package/components/wd-tabbar-item/index.scss +52 -0
  278. package/components/wd-tabbar-item/types.ts +51 -0
  279. package/components/wd-tabbar-item/wd-tabbar-item.vue +101 -0
  280. package/components/wd-table/index.scss +132 -0
  281. package/components/wd-table/types.ts +69 -0
  282. package/components/wd-table/wd-table.vue +255 -0
  283. package/components/wd-table-col/index.scss +44 -0
  284. package/components/wd-table-col/types.ts +54 -0
  285. package/components/wd-table-col/wd-table-col.vue +149 -0
  286. package/components/wd-tabs/index.scss +280 -0
  287. package/components/wd-tabs/types.ts +71 -0
  288. package/components/wd-tabs/wd-tabs.vue +528 -0
  289. package/components/wd-tag/index.scss +115 -0
  290. package/components/wd-tag/types.ts +81 -0
  291. package/components/wd-tag/wd-tag.vue +154 -0
  292. package/components/wd-text/index.scss +34 -0
  293. package/components/wd-text/types.ts +98 -0
  294. package/components/wd-text/wd-text.vue +138 -0
  295. package/components/wd-textarea/index.scss +343 -0
  296. package/components/wd-textarea/types.ts +298 -0
  297. package/components/wd-textarea/wd-textarea.vue +303 -0
  298. package/components/wd-toast/index.scss +66 -0
  299. package/components/wd-toast/index.ts +109 -0
  300. package/components/wd-toast/types.ts +76 -0
  301. package/components/wd-toast/wd-toast.vue +212 -0
  302. package/components/wd-tooltip/index.scss +61 -0
  303. package/components/wd-tooltip/types.ts +102 -0
  304. package/components/wd-tooltip/wd-tooltip.vue +167 -0
  305. package/components/wd-transition/index.scss +91 -0
  306. package/components/wd-transition/types.ts +89 -0
  307. package/components/wd-transition/wd-transition.vue +221 -0
  308. package/components/wd-upload/index.scss +173 -0
  309. package/components/wd-upload/types.ts +378 -0
  310. package/components/wd-upload/utils.ts +152 -0
  311. package/components/wd-upload/wd-upload.vue +737 -0
  312. package/components/wd-video-preview/index.scss +34 -0
  313. package/components/wd-video-preview/types.ts +32 -0
  314. package/components/wd-video-preview/wd-video-preview.vue +76 -0
  315. package/components/wd-watermark/index.scss +18 -0
  316. package/components/wd-watermark/types.ts +82 -0
  317. package/components/wd-watermark/wd-watermark.vue +592 -0
  318. package/components/wot-design-uni/wot-design-uni.vue +14 -0
  319. package/global.d.ts +108 -0
  320. package/index.ts +30 -0
  321. package/locale/index.ts +41 -0
  322. package/locale/lang/en-US.ts +128 -0
  323. package/locale/lang/th-TH.ts +127 -0
  324. package/locale/lang/vi-VN.ts +89 -0
  325. package/locale/lang/zh-CN.ts +127 -0
  326. package/locale/lang/zh-HK.ts +84 -0
  327. package/locale/lang/zh-TW.ts +84 -0
  328. package/package.json +20 -0
@@ -0,0 +1,528 @@
1
+ <template>
2
+ <template v-if="sticky">
3
+ <wd-sticky-box>
4
+ <view
5
+ :class="`wd-tabs ${customClass} ${slidableNum < items.length ? 'is-slide' : ''} ${mapNum < items.length && mapNum !== 0 ? 'is-map' : ''}`"
6
+ :style="customStyle"
7
+ >
8
+ <wd-sticky :offset-top="offsetTop">
9
+ <!--头部导航容器-->
10
+ <view class="wd-tabs__nav wd-tabs__nav--sticky">
11
+ <view class="wd-tabs__nav--wrap">
12
+ <scroll-view
13
+ :scroll-x="slidableNum < items.length"
14
+ scroll-with-animation
15
+ :scroll-left="state.scrollLeft"
16
+ >
17
+ <view class="wd-tabs__nav-container">
18
+ <!--nav列表-->
19
+ <view
20
+ @click="handleSelect(index)"
21
+ v-for="(item, index) in items"
22
+ :key="index"
23
+ :class="`wd-tabs__nav-item ${state.activeIndex === index ? 'is-active' : ''} ${item.disabled ? 'is-disabled' : ''}`"
24
+ :style="
25
+ state.activeIndex === index
26
+ ? color
27
+ ? 'color:' + color
28
+ : ''
29
+ : inactiveColor
30
+ ? 'color:' + inactiveColor
31
+ : ''
32
+ "
33
+ >
34
+ {{ item.title }}
35
+ </view>
36
+ <!--下划线-->
37
+ <view class="wd-tabs__line" :style="state.lineStyle"></view>
38
+ </view>
39
+ </scroll-view>
40
+ </view>
41
+ <!--map表-->
42
+ <view class="wd-tabs__map" v-if="mapNum < items.length && mapNum !== 0">
43
+ <view
44
+ :class="`wd-tabs__map-btn ${state.animating ? 'is-open' : ''}`"
45
+ @click="toggleMap"
46
+ >
47
+ <view :class="`wd-tabs__map-arrow ${state.animating ? 'is-open' : ''}`">
48
+ <wd-icon name="arrow-down" />
49
+ </view>
50
+ </view>
51
+ <view
52
+ class="wd-tabs__map-header"
53
+ :style="`${state.mapShow ? '' : 'display:none;'} ${state.animating ? 'opacity:1;' : ''}`"
54
+ >
55
+ {{ translate('all') }}
56
+ </view>
57
+ <view
58
+ :class="`wd-tabs__map-body ${state.animating ? 'is-open' : ''}`"
59
+ :style="state.mapShow ? '' : 'display:none'"
60
+ >
61
+ <view
62
+ class="wd-tabs__map-nav-item"
63
+ v-for="(item, index) in items"
64
+ :key="index"
65
+ @click="handleSelect(index)"
66
+ >
67
+ <view
68
+ :class="`wd-tabs__map-nav-btn ${state.activeIndex === index ? 'is-active' : ''} ${item.disabled ? 'is-disabled' : ''}`"
69
+ :style="
70
+ state.activeIndex === index
71
+ ? color
72
+ ? 'color:' + color + ';border-color:' + color
73
+ : ''
74
+ : inactiveColor
75
+ ? 'color:' + inactiveColor
76
+ : ''
77
+ "
78
+ >
79
+ {{ item.title }}
80
+ </view>
81
+ </view>
82
+ </view>
83
+ </view>
84
+ </view>
85
+ </wd-sticky>
86
+
87
+ <!--标签页-->
88
+ <view
89
+ class="wd-tabs__container"
90
+ @touchstart="onTouchStart"
91
+ @touchmove="onTouchMove"
92
+ @touchend="onTouchEnd"
93
+ @touchcancel="onTouchEnd"
94
+ >
95
+ <view :class="['wd-tabs__body', animated ? 'is-animated' : '']" :style="bodyStyle">
96
+ <slot />
97
+ </view>
98
+ </view>
99
+
100
+ <!--map表的阴影浮层-->
101
+ <view
102
+ class="wd-tabs__mask"
103
+ :style="`${state.mapShow ? '' : 'display:none;'} ${state.animating ? 'opacity:1;' : ''}`"
104
+ @click="toggleMap"
105
+ ></view>
106
+ </view>
107
+ </wd-sticky-box>
108
+ </template>
109
+
110
+ <template v-else>
111
+ <view
112
+ :class="`wd-tabs ${customClass} ${slidableNum < items.length ? 'is-slide' : ''} ${mapNum < items.length && mapNum !== 0 ? 'is-map' : ''}`"
113
+ >
114
+ <!--头部导航容器-->
115
+ <view class="wd-tabs__nav">
116
+ <view class="wd-tabs__nav--wrap">
117
+ <scroll-view
118
+ :scroll-x="slidableNum < items.length"
119
+ scroll-with-animation
120
+ :scroll-left="state.scrollLeft"
121
+ >
122
+ <view class="wd-tabs__nav-container">
123
+ <!--nav列表-->
124
+ <view
125
+ v-for="(item, index) in items"
126
+ @click="handleSelect(index)"
127
+ :key="index"
128
+ :class="`wd-tabs__nav-item ${state.activeIndex === index ? 'is-active' : ''} ${item.disabled ? 'is-disabled' : ''}`"
129
+ :style="
130
+ state.activeIndex === index
131
+ ? color
132
+ ? 'color:' + color
133
+ : ''
134
+ : inactiveColor
135
+ ? 'color:' + inactiveColor
136
+ : ''
137
+ "
138
+ >
139
+ {{ item.title }}
140
+ </view>
141
+ <!--下划线-->
142
+ <view class="wd-tabs__line" :style="state.lineStyle"></view>
143
+ </view>
144
+ </scroll-view>
145
+ </view>
146
+ <!--map表-->
147
+ <view class="wd-tabs__map" v-if="mapNum < items.length && mapNum !== 0">
148
+ <view class="wd-tabs__map-btn" @click="toggleMap">
149
+ <view :class="`wd-tabs__map-arrow ${state.animating ? 'is-open' : ''}`">
150
+ <wd-icon name="arrow-down" />
151
+ </view>
152
+ </view>
153
+ <view
154
+ class="wd-tabs__map-header"
155
+ :style="`${state.mapShow ? '' : 'display:none;'} ${state.animating ? 'opacity:1;' : ''}`"
156
+ >
157
+ {{ translate('all') }}
158
+ </view>
159
+ <view
160
+ :class="`wd-tabs__map-body ${state.animating ? 'is-open' : ''}`"
161
+ :style="state.mapShow ? '' : 'display:none'"
162
+ >
163
+ <view
164
+ class="wd-tabs__map-nav-item"
165
+ v-for="(item, index) in items"
166
+ :key="index"
167
+ @click="handleSelect(index)"
168
+ >
169
+ <view
170
+ :class="`wd-tabs__map-nav-btn ${state.activeIndex === index ? 'is-active' : ''} ${item.disabled ? 'is-disabled' : ''}`"
171
+ >
172
+ {{ item.title }}
173
+ </view>
174
+ </view>
175
+ </view>
176
+ </view>
177
+ </view>
178
+
179
+ <!--标签页-->
180
+ <view
181
+ class="wd-tabs__container"
182
+ @touchstart="onTouchStart"
183
+ @touchmove="onTouchMove"
184
+ @touchend="onTouchEnd"
185
+ @touchcancel="onTouchEnd"
186
+ >
187
+ <view :class="['wd-tabs__body', animated ? 'is-animated' : '']" :style="bodyStyle">
188
+ <slot />
189
+ </view>
190
+ </view>
191
+
192
+ <!--map表的阴影浮层-->
193
+ <view
194
+ class="wd-tabs__mask"
195
+ :style="`${state.mapShow ? '' : 'display:none;'} ${state.animating ? 'opacity:1' : ''}`"
196
+ @click="toggleMap"
197
+ ></view>
198
+ </view>
199
+ </template>
200
+ </template>
201
+ <script lang="ts">
202
+ export default {
203
+ name: 'wd-tabs',
204
+ options: {
205
+ addGlobalClass: true,
206
+ virtualHost: true,
207
+ styleIsolation: 'shared',
208
+ },
209
+ }
210
+ </script>
211
+ <script lang="ts" setup>
212
+ import {
213
+ computed,
214
+ getCurrentInstance,
215
+ onMounted,
216
+ ref,
217
+ watch,
218
+ nextTick,
219
+ reactive,
220
+ type CSSProperties,
221
+ } from 'vue'
222
+ import {
223
+ addUnit,
224
+ checkNumRange,
225
+ debounce,
226
+ getRect,
227
+ isDef,
228
+ isNumber,
229
+ isString,
230
+ objToStyle,
231
+ } from '../common/util'
232
+ import { useTouch } from '../composables/useTouch'
233
+ import { TABS_KEY, tabsProps } from './types'
234
+ import { useChildren } from '../composables/useChildren'
235
+ import { useTranslate } from '../composables/useTranslate'
236
+
237
+ const $item = '.wd-tabs__nav-item'
238
+ const $container = '.wd-tabs__nav-container'
239
+
240
+ const props = defineProps(tabsProps)
241
+ const emit = defineEmits(['change', 'disabled', 'click', 'update:modelValue'])
242
+
243
+ const { translate } = useTranslate('tabs')
244
+
245
+ const state = reactive({
246
+ activeIndex: 0, // 选中值的索引,默认第一个
247
+ lineStyle: 'display:none;', // 激活项边框线样式
248
+ inited: false, // 是否初始化
249
+ animating: false, // 是否动画中
250
+ mapShow: false, // map的开关
251
+ scrollLeft: 0, // scroll-view偏移量
252
+ })
253
+
254
+ // map的开关
255
+
256
+ const { children, linkChildren } = useChildren(TABS_KEY)
257
+ linkChildren({ state })
258
+
259
+ const { proxy } = getCurrentInstance() as any
260
+
261
+ const touch = useTouch()
262
+
263
+ // tabs数据
264
+ const items = computed(() => {
265
+ return children.map((child, index) => {
266
+ return {
267
+ disabled: child.disabled,
268
+ title: child.title,
269
+ name: isDef(child.name) ? child.name : index,
270
+ }
271
+ })
272
+ })
273
+
274
+ const bodyStyle = computed(() => {
275
+ if (!props.animated) {
276
+ return ''
277
+ }
278
+
279
+ return objToStyle({
280
+ left: -100 * state.activeIndex + '%',
281
+ 'transition-duration': props.duration + 'ms',
282
+ '-webkit-transition-duration': props.duration + 'ms',
283
+ })
284
+ })
285
+
286
+ /**
287
+ * @description 修改选中的tab Index
288
+ * @param {String |Number } value - radio绑定的value或者tab索引,默认值0
289
+ * @param {Boolean } init - 是否伴随初始化操作
290
+ */
291
+ const setActive = debounce(
292
+ function (value: number | string = 0, init: boolean = false, setScroll: boolean = true) {
293
+ // 没有tab子元素,不执行任何操作
294
+ if (items.value.length === 0) return
295
+
296
+ value = getActiveIndex(value)
297
+ // 被禁用,不执行任何操作
298
+ if (items.value[value].disabled) return
299
+ state.activeIndex = value
300
+ if (setScroll) {
301
+ updateLineStyle(init === false)
302
+ scrollIntoView()
303
+ }
304
+ setActiveTab()
305
+ },
306
+ 100,
307
+ { leading: false },
308
+ )
309
+
310
+ watch(
311
+ () => props.modelValue,
312
+ (newValue) => {
313
+ if (!isNumber(newValue) && !isString(newValue)) {
314
+ console.error('[wot design] error(wd-tabs): the type of value should be number or string')
315
+ }
316
+ // 保证不为非空字符串,小于0的数字
317
+ if (newValue === '' || !isDef(newValue)) {
318
+ // eslint-disable-next-line quotes
319
+ console.error("[wot design] error(wd-tabs): tabs's value cannot be '' null or undefined")
320
+ }
321
+ if (typeof newValue === 'number' && newValue < 0) {
322
+ // eslint-disable-next-line quotes
323
+ console.error("[wot design] error(wd-tabs): tabs's value cannot be less than zero")
324
+ }
325
+ },
326
+ {
327
+ immediate: true,
328
+ deep: true,
329
+ },
330
+ )
331
+
332
+ watch(
333
+ () => props.modelValue,
334
+ (newValue) => {
335
+ const index = getActiveIndex(newValue)
336
+ setActive(newValue, false, index !== state.activeIndex)
337
+ },
338
+ {
339
+ immediate: false,
340
+ deep: true,
341
+ },
342
+ )
343
+
344
+ watch(
345
+ () => children.length,
346
+ () => {
347
+ if (state.inited) {
348
+ nextTick(() => {
349
+ setActive(props.modelValue)
350
+ })
351
+ }
352
+ },
353
+ )
354
+
355
+ watch(
356
+ () => props.slidableNum,
357
+ (newValue) => {
358
+ checkNumRange(newValue, 'slidableNum')
359
+ },
360
+ )
361
+
362
+ watch(
363
+ () => props.mapNum,
364
+ (newValue) => {
365
+ checkNumRange(newValue, 'mapNum')
366
+ },
367
+ )
368
+
369
+ onMounted(() => {
370
+ state.inited = true
371
+ nextTick(() => {
372
+ setActive(props.modelValue, true)
373
+ })
374
+ })
375
+
376
+ /**
377
+ * @description nav map list 开关
378
+ */
379
+ function toggleMap() {
380
+ // 必须保证display和transition不在同一个帧
381
+ if (state.mapShow) {
382
+ state.animating = false
383
+ setTimeout(() => {
384
+ state.mapShow = false
385
+ }, 300)
386
+ } else {
387
+ state.mapShow = true
388
+ setTimeout(() => {
389
+ state.animating = true
390
+ }, 100)
391
+ }
392
+ }
393
+
394
+ /**
395
+ * @description 更新navBar underline的偏移量
396
+ * @param {Boolean} animation 是否伴随动画
397
+ */
398
+ function updateLineStyle(animation: boolean = true) {
399
+ if (!state.inited) return
400
+ const { lineWidth, lineHeight } = props
401
+ getRect($item, true, proxy).then((rects) => {
402
+ const lineStyle: CSSProperties = {}
403
+
404
+ if (isDef(lineWidth)) {
405
+ lineStyle.width = addUnit(lineWidth)
406
+ }
407
+ if (isDef(lineHeight)) {
408
+ lineStyle.height = addUnit(lineHeight)
409
+ lineStyle.borderRadius = `calc(${addUnit(lineHeight)} / 2)`
410
+ }
411
+ const rect = rects[state.activeIndex]
412
+ const left =
413
+ rects.slice(0, state.activeIndex).reduce((prev, curr) => prev + Number(curr.width), 0) +
414
+ Number(rect.width) / 2
415
+ lineStyle.transform = `translateX(${left}px) translateX(-50%)`
416
+ if (animation) {
417
+ lineStyle.transition = 'width 300ms ease, transform 300ms ease'
418
+ }
419
+ state.lineStyle = objToStyle(lineStyle)
420
+ })
421
+ }
422
+ /**
423
+ * @description 通过控制tab的active来展示选定的tab
424
+ */
425
+ function setActiveTab() {
426
+ if (!state.inited) return
427
+ if (items.value[state.activeIndex].name !== props.modelValue) {
428
+ emit('change', {
429
+ index: state.activeIndex,
430
+ name: items.value[state.activeIndex].name,
431
+ })
432
+ emit('update:modelValue', items.value[state.activeIndex].name)
433
+ }
434
+ }
435
+ /**
436
+ * @description scroll-view滑动到active的tab_nav
437
+ */
438
+ function scrollIntoView() {
439
+ if (!state.inited) return
440
+ Promise.all([getRect($item, true, proxy), getRect($container, false, proxy)]).then(
441
+ ([navItemsRects, navRect]) => {
442
+ // 选中元素
443
+ const selectItem = navItemsRects[state.activeIndex]
444
+ // 选中元素之前的节点的宽度总和
445
+ const offsetLeft = (navItemsRects as any)
446
+ .slice(0, state.activeIndex)
447
+ .reduce((prev: any, curr: any) => prev + curr.width, 0)
448
+ // scroll-view滑动到selectItem的偏移量
449
+ const left = offsetLeft - ((navRect as any).width - Number(selectItem.width)) / 2
450
+ if (left === state.scrollLeft) {
451
+ state.scrollLeft = left + Math.random() / 10000
452
+ } else {
453
+ state.scrollLeft = left
454
+ }
455
+ },
456
+ )
457
+ }
458
+ /**
459
+ * @description 单击tab的处理
460
+ * @param index
461
+ */
462
+ function handleSelect(index: number) {
463
+ if (index === undefined) return
464
+ const { name, disabled } = items.value[index]
465
+ if (disabled) {
466
+ emit('disabled', {
467
+ index,
468
+ name,
469
+ })
470
+ return
471
+ }
472
+ state.mapShow && toggleMap()
473
+ setActive(index)
474
+ emit('click', {
475
+ index,
476
+ name,
477
+ })
478
+ }
479
+ /**
480
+ * @description touch handle
481
+ * @param event
482
+ */
483
+ function onTouchStart(event: any) {
484
+ if (!props.swipeable) return
485
+ touch.touchStart(event)
486
+ }
487
+ function onTouchMove(event: any) {
488
+ if (!props.swipeable) return
489
+ touch.touchMove(event)
490
+ }
491
+ function onTouchEnd() {
492
+ if (!props.swipeable) return
493
+ const { direction, deltaX, offsetX } = touch
494
+ const minSwipeDistance = 50
495
+ if (direction.value === 'horizontal' && offsetX.value >= minSwipeDistance) {
496
+ if (deltaX.value > 0 && state.activeIndex !== 0) {
497
+ setActive(state.activeIndex - 1)
498
+ } else if (deltaX.value < 0 && state.activeIndex !== items.value.length - 1) {
499
+ setActive(state.activeIndex + 1)
500
+ setActive(state.activeIndex + 1)
501
+ }
502
+ }
503
+ }
504
+ function getActiveIndex(value: number | string) {
505
+ // name代表的索引超过了items的边界,自动用0兜底
506
+ if (isNumber(value) && value >= items.value.length) {
507
+ // eslint-disable-next-line prettier/prettier
508
+ console.error('[wot design] warning(wd-tabs): the type of tabs\' value is Number shouldn\'t be less than its children')
509
+ value = 0
510
+ }
511
+ // 如果是字符串直接匹配,匹配不到用0兜底
512
+ if (isString(value)) {
513
+ const index = items.value.findIndex((item) => item.name === value)
514
+ value = index === -1 ? 0 : index
515
+ }
516
+
517
+ return value
518
+ }
519
+
520
+ defineExpose({
521
+ setActive,
522
+ scrollIntoView,
523
+ updateLineStyle,
524
+ })
525
+ </script>
526
+ <style lang="scss" scoped>
527
+ @import './index';
528
+ </style>
@@ -0,0 +1,115 @@
1
+ @import '../common/abstracts/variable';
2
+ @import '../common/abstracts/mixin';
3
+
4
+ @mixin tag-type-style($normalColor, $normalBg) {
5
+ background: $normalBg;
6
+
7
+ @include when(plain) {
8
+ padding: 0 4px;
9
+ color: $normalColor;
10
+ background: transparent;
11
+ border: 1px solid $normalColor;
12
+ }
13
+ @include when(round) {
14
+ padding: 4px 11px;
15
+ font-size: $-tag-fs;
16
+ line-height: 1.2;
17
+ color: if($normalColor != $-tag-info-color, $normalColor, $-tag-round-color);
18
+ background: transparent;
19
+ border: 1px solid if($normalColor != $-tag-info-color, $normalColor, $-tag-round-border-color);
20
+ border-radius: $-tag-round-radius;
21
+ }
22
+ @include when(mark) {
23
+ padding: 1px 6px;
24
+ border-radius: $-tag-mark-radius;
25
+
26
+ @include when(plain) {
27
+ padding: 0 6px;
28
+ }
29
+ }
30
+ @include when(active) {
31
+ color: $-tag-primary-color;
32
+ border-color: $-tag-primary-color;
33
+ }
34
+ }
35
+ @include b(tag) {
36
+ display: inline-block;
37
+ padding: 0 3px;
38
+ font-size: $-tag-small-fs;
39
+ line-height: initial;
40
+ color: $-tag-color;
41
+ vertical-align: middle;
42
+ border-radius: 2px;
43
+ transition: opacity 0.3s;
44
+
45
+ @include when(default) {
46
+ @include tag-type-style($-tag-info-color, $-tag-info-bg);
47
+ }
48
+ @include when(primary) {
49
+ @include tag-type-style($-tag-primary-color, $-tag-primary-bg);
50
+ }
51
+ @include when(danger) {
52
+ @include tag-type-style($-tag-danger-color, $-tag-danger-bg);
53
+ }
54
+ @include when(warning) {
55
+ @include tag-type-style($-tag-warning-color, $-tag-warning-bg);
56
+ }
57
+ @include when(success) {
58
+ @include tag-type-style($-tag-success-color, $-tag-success-bg);
59
+ }
60
+ @include when(icon) {
61
+ padding: 2px 5px;
62
+ font-size: $-tag-fs;
63
+ line-height: 1.2;
64
+ }
65
+ @include when(dynamic) {
66
+ box-sizing: border-box;
67
+ width: 88px;
68
+ transition: 0.3s;
69
+
70
+ &:active {
71
+ color: $-tag-primary-color;
72
+ border-color: $-tag-primary-color;
73
+ }
74
+ }
75
+ @include when(dynamic-input) {
76
+ border-color: $-tag-primary-color;
77
+ }
78
+ @include edeep(icon) {
79
+ display: inline-block;
80
+ margin-right: 4px;
81
+ font-size: $-tag-fs;
82
+ line-height: 1.2;
83
+ vertical-align: baseline;
84
+ }
85
+ @include e(text) {
86
+ display: inline-block;
87
+ vertical-align: text-top;
88
+ }
89
+ @include e(add-text) {
90
+ display: inline-block;
91
+ width: 60px;
92
+ height: 14px;
93
+ min-height: 14px;
94
+ padding: 0;
95
+ font-size: $-tag-fs;
96
+ vertical-align: middle;
97
+ }
98
+ @include e(close) {
99
+ display: inline-block;
100
+ height: 14px;
101
+ margin-right: -4px;
102
+ margin-left: 24px;
103
+ font-size: $-tag-close-size;
104
+ line-height: 1.1;
105
+ color: $-tag-close-color;
106
+ vertical-align: text-bottom;
107
+
108
+ &:active {
109
+ color: $-tag-close-active-color;
110
+ }
111
+ }
112
+ @include edeep(add) {
113
+ vertical-align: bottom;
114
+ }
115
+ }