oxy-uni-ui 1.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 (355) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/attributes.json +1 -0
  4. package/components/common/AbortablePromise.ts +28 -0
  5. package/components/common/abstracts/_config.scss +7 -0
  6. package/components/common/abstracts/_function.scss +89 -0
  7. package/components/common/abstracts/_mixin.scss +385 -0
  8. package/components/common/abstracts/variable.scss +974 -0
  9. package/components/common/base64.ts +29 -0
  10. package/components/common/canvasHelper.ts +49 -0
  11. package/components/common/clickoutside.ts +25 -0
  12. package/components/common/event.ts +8 -0
  13. package/components/common/interceptor.ts +43 -0
  14. package/components/common/props.ts +51 -0
  15. package/components/common/util.ts +778 -0
  16. package/components/composables/index.ts +11 -0
  17. package/components/composables/useCell.ts +13 -0
  18. package/components/composables/useChildren.ts +113 -0
  19. package/components/composables/useCountDown.ts +138 -0
  20. package/components/composables/useLockScroll.ts +37 -0
  21. package/components/composables/useParent.ts +41 -0
  22. package/components/composables/usePopover.ts +176 -0
  23. package/components/composables/useQueue.ts +52 -0
  24. package/components/composables/useRaf.ts +37 -0
  25. package/components/composables/useTouch.ts +43 -0
  26. package/components/composables/useTranslate.ts +12 -0
  27. package/components/composables/useUpload.ts +364 -0
  28. package/components/oxy-action-sheet/index.scss +204 -0
  29. package/components/oxy-action-sheet/oxy-action-sheet.vue +155 -0
  30. package/components/oxy-action-sheet/types.ts +118 -0
  31. package/components/oxy-backtop/index.scss +25 -0
  32. package/components/oxy-backtop/oxy-backtop.vue +45 -0
  33. package/components/oxy-backtop/types.ts +37 -0
  34. package/components/oxy-badge/index.scss +63 -0
  35. package/components/oxy-badge/oxy-badge.vue +61 -0
  36. package/components/oxy-badge/types.ts +41 -0
  37. package/components/oxy-button/index.scss +336 -0
  38. package/components/oxy-button/oxy-button.vue +195 -0
  39. package/components/oxy-button/types.ts +133 -0
  40. package/components/oxy-calendar/index.scss +158 -0
  41. package/components/oxy-calendar/oxy-calendar.vue +451 -0
  42. package/components/oxy-calendar/types.ts +217 -0
  43. package/components/oxy-calendar-view/index.scss +0 -0
  44. package/components/oxy-calendar-view/month/index.scss +162 -0
  45. package/components/oxy-calendar-view/month/month.vue +389 -0
  46. package/components/oxy-calendar-view/month/types.ts +20 -0
  47. package/components/oxy-calendar-view/monthPanel/index.scss +89 -0
  48. package/components/oxy-calendar-view/monthPanel/month-panel.vue +374 -0
  49. package/components/oxy-calendar-view/monthPanel/types.ts +48 -0
  50. package/components/oxy-calendar-view/oxy-calendar-view.vue +111 -0
  51. package/components/oxy-calendar-view/types.ts +109 -0
  52. package/components/oxy-calendar-view/utils.ts +429 -0
  53. package/components/oxy-calendar-view/year/index.scss +153 -0
  54. package/components/oxy-calendar-view/year/types.ts +20 -0
  55. package/components/oxy-calendar-view/year/year.vue +202 -0
  56. package/components/oxy-calendar-view/yearPanel/index.scss +24 -0
  57. package/components/oxy-calendar-view/yearPanel/types.ts +38 -0
  58. package/components/oxy-calendar-view/yearPanel/year-panel.vue +135 -0
  59. package/components/oxy-card/index.scss +71 -0
  60. package/components/oxy-card/oxy-card.vue +37 -0
  61. package/components/oxy-card/types.ts +30 -0
  62. package/components/oxy-cell/index.scss +206 -0
  63. package/components/oxy-cell/oxy-cell.vue +140 -0
  64. package/components/oxy-cell/types.ts +111 -0
  65. package/components/oxy-cell-group/index.scss +56 -0
  66. package/components/oxy-cell-group/oxy-cell-group.vue +45 -0
  67. package/components/oxy-cell-group/types.ts +32 -0
  68. package/components/oxy-checkbox/index.scss +285 -0
  69. package/components/oxy-checkbox/oxy-checkbox.vue +177 -0
  70. package/components/oxy-checkbox/types.ts +68 -0
  71. package/components/oxy-checkbox-group/index.scss +20 -0
  72. package/components/oxy-checkbox-group/oxy-checkbox-group.vue +100 -0
  73. package/components/oxy-checkbox-group/types.ts +59 -0
  74. package/components/oxy-circle/index.scss +18 -0
  75. package/components/oxy-circle/oxy-circle.vue +296 -0
  76. package/components/oxy-circle/types.ts +54 -0
  77. package/components/oxy-col/index.scss +19 -0
  78. package/components/oxy-col/oxy-col.vue +49 -0
  79. package/components/oxy-col/types.ts +15 -0
  80. package/components/oxy-col-picker/index.scss +168 -0
  81. package/components/oxy-col-picker/oxy-col-picker.vue +498 -0
  82. package/components/oxy-col-picker/types.ts +166 -0
  83. package/components/oxy-collapse/index.scss +55 -0
  84. package/components/oxy-collapse/oxy-collapse.vue +151 -0
  85. package/components/oxy-collapse/types.ts +58 -0
  86. package/components/oxy-collapse-item/index.scss +90 -0
  87. package/components/oxy-collapse-item/oxy-collapse-item.vue +171 -0
  88. package/components/oxy-collapse-item/types.ts +48 -0
  89. package/components/oxy-config-provider/oxy-config-provider.vue +73 -0
  90. package/components/oxy-config-provider/types.ts +1052 -0
  91. package/components/oxy-count-down/index.scss +15 -0
  92. package/components/oxy-count-down/oxy-count-down.vue +60 -0
  93. package/components/oxy-count-down/types.ts +41 -0
  94. package/components/oxy-count-down/utils.ts +52 -0
  95. package/components/oxy-count-to/index.scss +7 -0
  96. package/components/oxy-count-to/oxy-count-to.vue +125 -0
  97. package/components/oxy-count-to/types.ts +117 -0
  98. package/components/oxy-curtain/index.scss +85 -0
  99. package/components/oxy-curtain/oxy-curtain.vue +172 -0
  100. package/components/oxy-curtain/types.ts +73 -0
  101. package/components/oxy-datetime-picker/index.scss +164 -0
  102. package/components/oxy-datetime-picker/oxy-datetime-picker.vue +801 -0
  103. package/components/oxy-datetime-picker/types.ts +231 -0
  104. package/components/oxy-datetime-picker-view/oxy-datetime-picker-view.vue +499 -0
  105. package/components/oxy-datetime-picker-view/types.ts +120 -0
  106. package/components/oxy-datetime-picker-view/util.ts +30 -0
  107. package/components/oxy-design-uni/oxy-design-uni.vue +5 -0
  108. package/components/oxy-divider/index.scss +100 -0
  109. package/components/oxy-divider/oxy-divider.vue +52 -0
  110. package/components/oxy-divider/types.ts +35 -0
  111. package/components/oxy-drop-menu/index.scss +86 -0
  112. package/components/oxy-drop-menu/oxy-drop-menu.vue +166 -0
  113. package/components/oxy-drop-menu/types.ts +38 -0
  114. package/components/oxy-drop-menu-item/index.scss +66 -0
  115. package/components/oxy-drop-menu-item/oxy-drop-menu-item.vue +221 -0
  116. package/components/oxy-drop-menu-item/types.ts +94 -0
  117. package/components/oxy-fab/index.scss +116 -0
  118. package/components/oxy-fab/oxy-fab.vue +276 -0
  119. package/components/oxy-fab/types.ts +66 -0
  120. package/components/oxy-floating-panel/index.scss +64 -0
  121. package/components/oxy-floating-panel/oxy-floating-panel.vue +140 -0
  122. package/components/oxy-floating-panel/type.ts +32 -0
  123. package/components/oxy-form/oxy-form.vue +207 -0
  124. package/components/oxy-form/types.ts +76 -0
  125. package/components/oxy-form-item/index.scss +18 -0
  126. package/components/oxy-form-item/oxy-form-item.vue +56 -0
  127. package/components/oxy-form-item/types.ts +16 -0
  128. package/components/oxy-gap/index.scss +9 -0
  129. package/components/oxy-gap/oxy-gap.vue +36 -0
  130. package/components/oxy-gap/types.ts +17 -0
  131. package/components/oxy-grid/index.scss +9 -0
  132. package/components/oxy-grid/oxy-grid.vue +106 -0
  133. package/components/oxy-grid/types.ts +50 -0
  134. package/components/oxy-grid-item/index.scss +148 -0
  135. package/components/oxy-grid-item/oxy-grid-item.vue +176 -0
  136. package/components/oxy-grid-item/types.ts +77 -0
  137. package/components/oxy-icon/index.scss +1230 -0
  138. package/components/oxy-icon/oxy-icon.vue +53 -0
  139. package/components/oxy-icon/oxy-icons.ttf +0 -0
  140. package/components/oxy-icon/types.ts +21 -0
  141. package/components/oxy-img/index.scss +19 -0
  142. package/components/oxy-img/oxy-img.vue +81 -0
  143. package/components/oxy-img/types.ts +61 -0
  144. package/components/oxy-img-cropper/index.scss +231 -0
  145. package/components/oxy-img-cropper/oxy-img-cropper.vue +664 -0
  146. package/components/oxy-img-cropper/types.ts +76 -0
  147. package/components/oxy-index-anchor/index.scss +35 -0
  148. package/components/oxy-index-anchor/oxy-index-anchor.vue +55 -0
  149. package/components/oxy-index-anchor/type.ts +9 -0
  150. package/components/oxy-index-bar/index.scss +39 -0
  151. package/components/oxy-index-bar/oxy-index-bar.vue +156 -0
  152. package/components/oxy-index-bar/type.ts +23 -0
  153. package/components/oxy-input/index.scss +323 -0
  154. package/components/oxy-input/oxy-input.vue +300 -0
  155. package/components/oxy-input/placeholder.scss +21 -0
  156. package/components/oxy-input/types.ts +189 -0
  157. package/components/oxy-input-number/index.scss +132 -0
  158. package/components/oxy-input-number/oxy-input-number.vue +464 -0
  159. package/components/oxy-input-number/types.ts +101 -0
  160. package/components/oxy-keyboard/constants.ts +81 -0
  161. package/components/oxy-keyboard/index.scss +102 -0
  162. package/components/oxy-keyboard/key/index.scss +79 -0
  163. package/components/oxy-keyboard/key/index.vue +76 -0
  164. package/components/oxy-keyboard/key/types.ts +11 -0
  165. package/components/oxy-keyboard/oxy-keyboard.vue +206 -0
  166. package/components/oxy-keyboard/types.ts +92 -0
  167. package/components/oxy-loading/index.scss +37 -0
  168. package/components/oxy-loading/oxy-loading.vue +90 -0
  169. package/components/oxy-loading/types.ts +22 -0
  170. package/components/oxy-loadmore/index.scss +39 -0
  171. package/components/oxy-loadmore/oxy-loadmore.vue +59 -0
  172. package/components/oxy-loadmore/types.ts +30 -0
  173. package/components/oxy-message-box/index.scss +108 -0
  174. package/components/oxy-message-box/index.ts +87 -0
  175. package/components/oxy-message-box/oxy-message-box.vue +291 -0
  176. package/components/oxy-message-box/types.ts +132 -0
  177. package/components/oxy-navbar/index.scss +93 -0
  178. package/components/oxy-navbar/oxy-navbar.vue +111 -0
  179. package/components/oxy-navbar/types.ts +52 -0
  180. package/components/oxy-navbar-capsule/index.scss +66 -0
  181. package/components/oxy-navbar-capsule/oxy-navbar-capsule.vue +35 -0
  182. package/components/oxy-navbar-capsule/types.ts +8 -0
  183. package/components/oxy-notice-bar/index.scss +68 -0
  184. package/components/oxy-notice-bar/oxy-notice-bar.vue +266 -0
  185. package/components/oxy-notice-bar/types.ts +67 -0
  186. package/components/oxy-notify/index.scss +34 -0
  187. package/components/oxy-notify/index.ts +61 -0
  188. package/components/oxy-notify/oxy-notify.vue +85 -0
  189. package/components/oxy-notify/types.ts +66 -0
  190. package/components/oxy-number-keyboard/index.scss +78 -0
  191. package/components/oxy-number-keyboard/key/index.scss +81 -0
  192. package/components/oxy-number-keyboard/key/index.vue +78 -0
  193. package/components/oxy-number-keyboard/key/types.ts +11 -0
  194. package/components/oxy-number-keyboard/oxy-number-keyboard.vue +151 -0
  195. package/components/oxy-number-keyboard/types.ts +83 -0
  196. package/components/oxy-overlay/index.scss +17 -0
  197. package/components/oxy-overlay/oxy-overlay.vue +47 -0
  198. package/components/oxy-overlay/types.ts +25 -0
  199. package/components/oxy-pagination/index.scss +57 -0
  200. package/components/oxy-pagination/oxy-pagination.vue +110 -0
  201. package/components/oxy-pagination/types.ts +41 -0
  202. package/components/oxy-password-input/index.scss +124 -0
  203. package/components/oxy-password-input/oxy-password-input.vue +49 -0
  204. package/components/oxy-password-input/types.ts +33 -0
  205. package/components/oxy-picker/index.scss +110 -0
  206. package/components/oxy-picker/oxy-picker.vue +412 -0
  207. package/components/oxy-picker/types.ts +189 -0
  208. package/components/oxy-picker-view/index.scss +92 -0
  209. package/components/oxy-picker-view/oxy-picker-view.vue +369 -0
  210. package/components/oxy-picker-view/types.ts +152 -0
  211. package/components/oxy-popover/index.scss +116 -0
  212. package/components/oxy-popover/oxy-popover.vue +180 -0
  213. package/components/oxy-popover/types.ts +69 -0
  214. package/components/oxy-popup/index.scss +84 -0
  215. package/components/oxy-popup/oxy-popup.vue +169 -0
  216. package/components/oxy-popup/types.ts +95 -0
  217. package/components/oxy-progress/index.scss +68 -0
  218. package/components/oxy-progress/oxy-progress.vue +197 -0
  219. package/components/oxy-progress/types.ts +35 -0
  220. package/components/oxy-radio/index.scss +301 -0
  221. package/components/oxy-radio/oxy-radio.vue +118 -0
  222. package/components/oxy-radio/types.ts +42 -0
  223. package/components/oxy-radio-group/index.scss +23 -0
  224. package/components/oxy-radio-group/oxy-radio-group.vue +51 -0
  225. package/components/oxy-radio-group/types.ts +39 -0
  226. package/components/oxy-rate/index.scss +25 -0
  227. package/components/oxy-rate/oxy-rate.vue +178 -0
  228. package/components/oxy-rate/types.ts +103 -0
  229. package/components/oxy-resize/index.scss +27 -0
  230. package/components/oxy-resize/oxy-resize.vue +144 -0
  231. package/components/oxy-resize/types.ts +6 -0
  232. package/components/oxy-root-portal/oxy-root-portal.vue +50 -0
  233. package/components/oxy-row/index.scss +10 -0
  234. package/components/oxy-row/oxy-row.vue +42 -0
  235. package/components/oxy-row/types.ts +16 -0
  236. package/components/oxy-search/index.scss +148 -0
  237. package/components/oxy-search/oxy-search.vue +187 -0
  238. package/components/oxy-search/types.ts +93 -0
  239. package/components/oxy-segmented/index.scss +101 -0
  240. package/components/oxy-segmented/oxy-segmented.vue +143 -0
  241. package/components/oxy-segmented/types.ts +71 -0
  242. package/components/oxy-select-picker/index.scss +102 -0
  243. package/components/oxy-select-picker/oxy-select-picker.vue +432 -0
  244. package/components/oxy-select-picker/types.ts +123 -0
  245. package/components/oxy-sidebar/index.scss +25 -0
  246. package/components/oxy-sidebar/oxy-sidebar.vue +63 -0
  247. package/components/oxy-sidebar/types.ts +38 -0
  248. package/components/oxy-sidebar-item/index.scss +97 -0
  249. package/components/oxy-sidebar-item/oxy-sidebar-item.vue +116 -0
  250. package/components/oxy-sidebar-item/types.ts +31 -0
  251. package/components/oxy-signature/index.scss +31 -0
  252. package/components/oxy-signature/oxy-signature.vue +630 -0
  253. package/components/oxy-signature/types.ts +108 -0
  254. package/components/oxy-skeleton/index.scss +96 -0
  255. package/components/oxy-skeleton/index.ts +1 -0
  256. package/components/oxy-skeleton/oxy-skeleton.vue +110 -0
  257. package/components/oxy-skeleton/types.ts +69 -0
  258. package/components/oxy-slider/index.scss +98 -0
  259. package/components/oxy-slider/oxy-slider.vue +356 -0
  260. package/components/oxy-slider/types.ts +138 -0
  261. package/components/oxy-sort-button/index.scss +89 -0
  262. package/components/oxy-sort-button/oxy-sort-button.vue +69 -0
  263. package/components/oxy-sort-button/types.ts +43 -0
  264. package/components/oxy-status-tip/images/collect.png +0 -0
  265. package/components/oxy-status-tip/images/content.png +0 -0
  266. package/components/oxy-status-tip/images/network.png +0 -0
  267. package/components/oxy-status-tip/images/search.png +0 -0
  268. package/components/oxy-status-tip/index.scss +37 -0
  269. package/components/oxy-status-tip/oxy-status-tip.vue +71 -0
  270. package/components/oxy-status-tip/types.ts +50 -0
  271. package/components/oxy-step/index.scss +235 -0
  272. package/components/oxy-step/oxy-step.vue +150 -0
  273. package/components/oxy-step/types.ts +33 -0
  274. package/components/oxy-steps/index.scss +10 -0
  275. package/components/oxy-steps/oxy-steps.vue +28 -0
  276. package/components/oxy-steps/types.ts +50 -0
  277. package/components/oxy-sticky/index.scss +9 -0
  278. package/components/oxy-sticky/oxy-sticky.vue +190 -0
  279. package/components/oxy-sticky/types.ts +13 -0
  280. package/components/oxy-sticky-box/index.scss +6 -0
  281. package/components/oxy-sticky-box/oxy-sticky-box.vue +155 -0
  282. package/components/oxy-sticky-box/types.ts +11 -0
  283. package/components/oxy-swipe-action/index.scss +22 -0
  284. package/components/oxy-swipe-action/oxy-swipe-action.vue +294 -0
  285. package/components/oxy-swipe-action/types.ts +40 -0
  286. package/components/oxy-swiper/index.scss +53 -0
  287. package/components/oxy-swiper/oxy-swiper.vue +318 -0
  288. package/components/oxy-swiper/types.ts +264 -0
  289. package/components/oxy-swiper-nav/index.scss +159 -0
  290. package/components/oxy-swiper-nav/oxy-swiper-nav.vue +37 -0
  291. package/components/oxy-swiper-nav/types.ts +42 -0
  292. package/components/oxy-switch/index.scss +58 -0
  293. package/components/oxy-switch/oxy-switch.vue +83 -0
  294. package/components/oxy-switch/types.ts +58 -0
  295. package/components/oxy-tab/index.scss +16 -0
  296. package/components/oxy-tab/oxy-tab.vue +88 -0
  297. package/components/oxy-tab/types.ts +30 -0
  298. package/components/oxy-tabbar/index.scss +62 -0
  299. package/components/oxy-tabbar/oxy-tabbar.vue +91 -0
  300. package/components/oxy-tabbar/types.ts +73 -0
  301. package/components/oxy-tabbar-item/index.scss +55 -0
  302. package/components/oxy-tabbar-item/oxy-tabbar-item.vue +99 -0
  303. package/components/oxy-tabbar-item/types.ts +51 -0
  304. package/components/oxy-table/index.scss +163 -0
  305. package/components/oxy-table/oxy-table.vue +283 -0
  306. package/components/oxy-table/types.ts +58 -0
  307. package/components/oxy-table-col/index.scss +46 -0
  308. package/components/oxy-table-col/oxy-table-col.vue +149 -0
  309. package/components/oxy-table-col/types.ts +54 -0
  310. package/components/oxy-tabs/index.scss +299 -0
  311. package/components/oxy-tabs/oxy-tabs.vue +443 -0
  312. package/components/oxy-tabs/types.ts +107 -0
  313. package/components/oxy-tag/index.scss +115 -0
  314. package/components/oxy-tag/oxy-tag.vue +148 -0
  315. package/components/oxy-tag/types.ts +81 -0
  316. package/components/oxy-text/index.scss +37 -0
  317. package/components/oxy-text/oxy-text.vue +139 -0
  318. package/components/oxy-text/types.ts +98 -0
  319. package/components/oxy-textarea/index.scss +340 -0
  320. package/components/oxy-textarea/oxy-textarea.vue +296 -0
  321. package/components/oxy-textarea/placeholder.scss +20 -0
  322. package/components/oxy-textarea/types.ts +288 -0
  323. package/components/oxy-toast/index.scss +75 -0
  324. package/components/oxy-toast/index.ts +92 -0
  325. package/components/oxy-toast/oxy-toast.vue +198 -0
  326. package/components/oxy-toast/types.ts +181 -0
  327. package/components/oxy-tooltip/index.scss +66 -0
  328. package/components/oxy-tooltip/oxy-tooltip.vue +141 -0
  329. package/components/oxy-tooltip/types.ts +107 -0
  330. package/components/oxy-transition/index.scss +95 -0
  331. package/components/oxy-transition/oxy-transition.vue +232 -0
  332. package/components/oxy-transition/types.ts +98 -0
  333. package/components/oxy-upload/index.scss +175 -0
  334. package/components/oxy-upload/oxy-upload.vue +673 -0
  335. package/components/oxy-upload/types.ts +391 -0
  336. package/components/oxy-video-preview/index.scss +34 -0
  337. package/components/oxy-video-preview/oxy-video-preview.vue +72 -0
  338. package/components/oxy-video-preview/types.ts +23 -0
  339. package/components/oxy-watermark/index.scss +18 -0
  340. package/components/oxy-watermark/oxy-watermark.vue +486 -0
  341. package/components/oxy-watermark/types.ts +76 -0
  342. package/dayjs/constant.js +26 -0
  343. package/dayjs/index.d.ts +430 -0
  344. package/dayjs/index.js +542 -0
  345. package/dayjs/locale/en.js +13 -0
  346. package/dayjs/utils.js +59 -0
  347. package/global.d.ts +101 -0
  348. package/index.ts +12 -0
  349. package/locale/index.ts +32 -0
  350. package/locale/lang/ar-SA.ts +133 -0
  351. package/locale/lang/en-US.ts +133 -0
  352. package/locale/lang/zh-CN.ts +137 -0
  353. package/package.json +1 -0
  354. package/tags.json +1 -0
  355. package/web-types.json +1 -0
@@ -0,0 +1,190 @@
1
+ <template>
2
+ <view :style="`${rootStyle};display: inline-block;`">
3
+ <view :class="`oxy-sticky ${customClass}`" :style="stickyStyle" :id="styckyId">
4
+ <view class="oxy-sticky__container" :style="containerStyle">
5
+ <oxy-resize @resize="handleResize" custom-style="display: inline-block;">
6
+ <slot />
7
+ </oxy-resize>
8
+ </view>
9
+ </view>
10
+ </view>
11
+ </template>
12
+
13
+ <script lang="ts">
14
+ export default {
15
+ name: 'oxy-sticky',
16
+ options: {
17
+ addGlobalClass: true,
18
+ virtualHost: true,
19
+ styleIsolation: 'shared'
20
+ }
21
+ }
22
+ </script>
23
+
24
+ <script lang="ts" setup>
25
+ import OxyResize from '../oxy-resize/oxy-resize.vue'
26
+ import { computed, getCurrentInstance, reactive, ref, type CSSProperties } from 'vue'
27
+ import { addUnit, getRect, objToStyle, pause, uuid } from '../common/util'
28
+ import { stickyProps } from './types'
29
+ import { useParent } from '../composables/useParent'
30
+ import { STICKY_BOX_KEY } from '../oxy-sticky-box/types'
31
+
32
+ const props = defineProps(stickyProps)
33
+ const styckyId = ref<string>(`oxy-sticky${uuid()}`)
34
+ const observerList = ref<UniApp.IntersectionObserver[]>([])
35
+
36
+ const stickyState = reactive({
37
+ position: 'absolute',
38
+ boxLeaved: false,
39
+ top: 0,
40
+ height: 0,
41
+ width: 0,
42
+ state: ''
43
+ })
44
+
45
+ const { parent: stickyBox } = useParent(STICKY_BOX_KEY)
46
+
47
+ const { proxy } = getCurrentInstance() as any
48
+
49
+ const rootStyle = computed(() => {
50
+ const style: CSSProperties = {
51
+ 'z-index': props.zIndex,
52
+ height: addUnit(stickyState.height),
53
+ width: addUnit(stickyState.width)
54
+ }
55
+ if (!stickyState.boxLeaved) {
56
+ style['position'] = 'relative'
57
+ }
58
+ return `${objToStyle(style)}${props.customStyle}`
59
+ })
60
+
61
+ const stickyStyle = computed(() => {
62
+ const style: CSSProperties = {
63
+ 'z-index': props.zIndex,
64
+ height: addUnit(stickyState.height),
65
+ width: addUnit(stickyState.width)
66
+ }
67
+ if (!stickyState.boxLeaved) {
68
+ style['position'] = 'relative'
69
+ }
70
+ return `${objToStyle(style)}`
71
+ })
72
+
73
+ const containerStyle = computed(() => {
74
+ const style: CSSProperties = {
75
+ position: stickyState.position as 'static' | 'relative' | 'absolute' | 'sticky' | 'fixed',
76
+ top: addUnit(stickyState.top)
77
+ }
78
+ return objToStyle(style)
79
+ })
80
+
81
+ const innerOffsetTop = computed(() => {
82
+ let top: number = 0
83
+ // #ifdef H5
84
+ // H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
85
+ // H5的导航栏高度为44px
86
+ top = 44
87
+ // #endif
88
+
89
+ return top + props.offsetTop
90
+ })
91
+
92
+ /**
93
+ * 清除对当前组件的监听
94
+ */
95
+ function clearObserver() {
96
+ while (observerList.value.length !== 0) {
97
+ observerList.value.pop()!.disconnect()
98
+ }
99
+ }
100
+ /**
101
+ * 添加对当前组件的监听
102
+ */
103
+ function createObserver() {
104
+ const observer = uni.createIntersectionObserver(proxy, { thresholds: [0, 0.5] })
105
+ observerList.value.push(observer)
106
+ return observer
107
+ }
108
+ /**
109
+ * 当前内容高度发生变化时重置监听
110
+ */
111
+ async function handleResize(detail: any) {
112
+ stickyState.width = detail.width
113
+ stickyState.height = detail.height
114
+ await pause()
115
+ observerContentScroll()
116
+ if (!stickyBox || !stickyBox.observerForChild) return
117
+ stickyBox.observerForChild(proxy)
118
+ }
119
+ /**
120
+ * 监听吸顶元素滚动事件
121
+ */
122
+ function observerContentScroll() {
123
+ if (stickyState.height === 0 && stickyState.width === 0) return
124
+ const offset = innerOffsetTop.value + stickyState.height
125
+ clearObserver()
126
+ createObserver()
127
+ .relativeToViewport({
128
+ top: -offset
129
+ })
130
+ .observe(`#${styckyId.value}`, (result) => {
131
+ handleRelativeTo(result)
132
+ })
133
+ getRect(`#${styckyId.value}`, false, proxy).then((res) => {
134
+ // #ifdef H5
135
+ // H5端,查询节点信息未计算导航栏高度
136
+ res.bottom = Number(res.bottom) + 44
137
+ // #endif
138
+ if (Number(res.bottom) <= offset) handleRelativeTo({ boundingClientRect: res })
139
+ })
140
+ }
141
+ /**
142
+ * @description 根据位置进行吸顶
143
+ */
144
+ function handleRelativeTo({ boundingClientRect }: any) {
145
+ // sticky 高度大于或等于 oxy-sticky-box,使用 oxy-sticky-box 无任何意义
146
+ if (stickyBox && stickyBox.boxStyle && stickyState.height >= stickyBox.boxStyle.height) {
147
+ stickyState.position = 'absolute'
148
+ stickyState.top = 0
149
+ return
150
+ }
151
+
152
+ let isStycky = boundingClientRect.top <= innerOffsetTop.value
153
+ // #ifdef H5 || APP-PLUS
154
+ isStycky = boundingClientRect.top < innerOffsetTop.value
155
+ // #endif
156
+
157
+ if (isStycky) {
158
+ stickyState.state = 'sticky'
159
+ stickyState.boxLeaved = false
160
+ stickyState.position = 'fixed'
161
+ stickyState.top = innerOffsetTop.value
162
+ } else {
163
+ stickyState.state = 'normal'
164
+ stickyState.boxLeaved = false
165
+ stickyState.position = 'absolute'
166
+ stickyState.top = 0
167
+ }
168
+ }
169
+
170
+ /**
171
+ * 设置位置
172
+ * @param setboxLeaved
173
+ * @param setPosition
174
+ * @param setTop
175
+ */
176
+ function setPosition(boxLeaved: boolean, position: string, top: number) {
177
+ stickyState.boxLeaved = boxLeaved
178
+ stickyState.position = position
179
+ stickyState.top = top
180
+ }
181
+
182
+ defineExpose({
183
+ setPosition,
184
+ stickyState,
185
+ offsetTop: props.offsetTop
186
+ })
187
+ </script>
188
+ <style lang="scss" scoped>
189
+ @import './index.scss';
190
+ </style>
@@ -0,0 +1,13 @@
1
+ import { baseProps, makeNumberProp } from '../common/props'
2
+
3
+ export const stickyProps = {
4
+ ...baseProps,
5
+ /**
6
+ * 层级
7
+ */
8
+ zIndex: makeNumberProp(1),
9
+ /**
10
+ * 吸顶距离
11
+ */
12
+ offsetTop: makeNumberProp(0)
13
+ }
@@ -0,0 +1,6 @@
1
+ @import '../common/abstracts/variable';
2
+ @import '../common/abstracts/mixin';
3
+
4
+ @include b(sticky-box) {
5
+ position: relative;
6
+ }
@@ -0,0 +1,155 @@
1
+ <template>
2
+ <view style="position: relative">
3
+ <view :class="`oxy-sticky-box ${props.customClass}`" :style="customStyle" :id="styckyBoxId">
4
+ <oxy-resize @resize="handleResize">
5
+ <slot />
6
+ </oxy-resize>
7
+ </view>
8
+ </view>
9
+ </template>
10
+
11
+ <script lang="ts">
12
+ export default {
13
+ name: 'oxy-sticky-box',
14
+ options: {
15
+ addGlobalClass: true,
16
+ // virtualHost: true,
17
+ styleIsolation: 'shared'
18
+ }
19
+ }
20
+ </script>
21
+
22
+ <script lang="ts" setup>
23
+ import OxyResize from '../oxy-resize/oxy-resize.vue'
24
+ import { getCurrentInstance, onBeforeMount, reactive, ref } from 'vue'
25
+ import { getRect, uuid } from '../common/util'
26
+ import { baseProps } from '../common/props'
27
+ import { STICKY_BOX_KEY } from './types'
28
+ import { useChildren } from '../composables/useChildren'
29
+
30
+ const props = defineProps(baseProps)
31
+
32
+ const styckyBoxId = ref<string>(`oxy-sticky-box${uuid()}`)
33
+
34
+ const observerMap = ref<Map<any, any>>(new Map())
35
+
36
+ const boxStyle = reactive({
37
+ height: 0,
38
+ width: 0
39
+ })
40
+
41
+ const { proxy } = getCurrentInstance() as any
42
+
43
+ const { children: stickyList, linkChildren } = useChildren(STICKY_BOX_KEY)
44
+ linkChildren({
45
+ boxStyle: boxStyle,
46
+ observerForChild
47
+ })
48
+
49
+ onBeforeMount(() => {
50
+ observerMap.value = new Map()
51
+ })
52
+
53
+ /**
54
+ * 容器大小变化后重新监听sticky组件与box组件的交叉状态
55
+ * @param detail
56
+ */
57
+ function handleResize(detail: any) {
58
+ // 相对的容器大小改变后,同步设置 oxy-sticky-box 的大小
59
+ boxStyle.width = detail.width
60
+ boxStyle.height = detail.height
61
+ // oxy-sticky-box 大小变化时,重新监听所有吸顶元素
62
+ const temp = observerMap.value
63
+ observerMap.value = new Map()
64
+ for (const [uid] of temp) {
65
+ const child = stickyList.find((sticky) => {
66
+ return sticky.$.uid === uid
67
+ })
68
+ observerForChild(child)
69
+ }
70
+ temp.forEach((observer) => {
71
+ observer.disconnect()
72
+ })
73
+ temp.clear()
74
+ }
75
+ /**
76
+ * 删除对指定sticky的监听
77
+ * @param child 指定的子组件
78
+ */
79
+ function deleteObserver(child: any) {
80
+ const observer = observerMap.value.get(child.$.uid)
81
+ if (!observer) return
82
+ observer.disconnect()
83
+ observerMap.value.delete(child.$.uid)
84
+ }
85
+ /**
86
+ * 针对指定sticky添加监听
87
+ * @param child 指定的子组件
88
+ */
89
+ function createObserver(child: any) {
90
+ const observer = uni.createIntersectionObserver(proxy, { thresholds: [0, 0.5] })
91
+ observerMap.value.set(child.$.uid, observer)
92
+ return observer
93
+ }
94
+ /**
95
+ * 监听子组件
96
+ * @param child 子组件
97
+ */
98
+ function observerForChild(child: any) {
99
+ deleteObserver(child)
100
+ const observer = createObserver(child)
101
+ const exposed = child.$.exposed
102
+ let offset = exposed.stickyState.height + exposed.offsetTop
103
+ // #ifdef H5
104
+ // H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
105
+ // H5的导航栏高度为44px
106
+ offset = offset + 44
107
+ // #endif
108
+
109
+ if (boxStyle.height <= exposed.stickyState.height) {
110
+ exposed.setPosition(false, 'absolute', 0)
111
+ }
112
+ observer.relativeToViewport({ top: -offset }).observe(`#${styckyBoxId.value}`, (result) => {
113
+ handleRelativeTo(exposed, result)
114
+ })
115
+ // 当子组件默认处于边界外且永远不会进入边界内时,需要手动调用一次
116
+ getRect(`#${styckyBoxId.value}`, false, proxy)
117
+ .then((res) => {
118
+ // #ifdef H5
119
+ // H5端,查询节点信息未计算导航栏高度
120
+ res.bottom = Number(res.bottom) + 44
121
+ // #endif
122
+ if (Number(res.bottom) <= offset) handleRelativeTo(exposed, { boundingClientRect: res })
123
+ })
124
+ .catch((res) => {
125
+ console.log(res)
126
+ })
127
+ }
128
+ /**
129
+ * 监听容器组件
130
+ * @param {Object} exposed oxy-sticky实例暴露出的事件
131
+ * @param {Object} boundingClientRect 边界信息
132
+ */
133
+ function handleRelativeTo(exposed: any, { boundingClientRect }: any) {
134
+ let childOffsetTop = exposed.offsetTop
135
+ // #ifdef H5
136
+ // H5端,导航栏为普通元素,需要将组件移动到导航栏的下边沿
137
+ // H5的导航栏高度为44px
138
+ childOffsetTop = childOffsetTop + 44
139
+ // #endif
140
+ const offset = exposed.stickyState.height + childOffsetTop
141
+ let isAbsolute = boundingClientRect.bottom <= offset
142
+ // #ifdef H5 || APP-PLUS
143
+ isAbsolute = boundingClientRect.bottom < offset
144
+ // #endif
145
+ if (isAbsolute) {
146
+ exposed.setPosition(true, 'absolute', boundingClientRect.height - exposed.stickyState.height)
147
+ } else if (boundingClientRect.top <= offset && !isAbsolute) {
148
+ if (exposed.stickyState.state === 'normal') return
149
+ exposed.setPosition(false, 'fixed', childOffsetTop)
150
+ }
151
+ }
152
+ </script>
153
+ <style lang="scss" scoped>
154
+ @import './index.scss';
155
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { ComponentInternalInstance, InjectionKey } from 'vue'
2
+
3
+ export type stickyBoxProvide = {
4
+ boxStyle: {
5
+ height: number // 高度
6
+ width: number // 宽度
7
+ }
8
+ observerForChild: (child: ComponentInternalInstance) => void // 监听子组件
9
+ }
10
+
11
+ export const STICKY_BOX_KEY: InjectionKey<stickyBoxProvide> = Symbol('oxy-sticky-box')
@@ -0,0 +1,22 @@
1
+ @import '../common/abstracts/variable';
2
+ @import '../common/abstracts/mixin';
3
+
4
+ @include b(swipe-action) {
5
+ position: relative;
6
+ overflow: hidden;
7
+ @include e(left) {
8
+ left: 0;
9
+ transform: translate3d(-100%, 0, 0);
10
+ }
11
+ @include e(right) {
12
+ right: 0;
13
+ transform: translate3d(100%, 0, 0);
14
+ }
15
+ }
16
+
17
+ .oxy-swipe-action__left,
18
+ .oxy-swipe-action__right {
19
+ position: absolute;
20
+ top: 0;
21
+ height: 100%;
22
+ }
@@ -0,0 +1,294 @@
1
+ <template>
2
+ <!--注意阻止横向滑动的穿透:横向移动时阻止冒泡-->
3
+ <view
4
+ :class="`oxy-swipe-action ${customClass}`"
5
+ :style="customStyle"
6
+ @click.stop="onClick()"
7
+ @touchstart="startDrag"
8
+ @touchmove="onDrag"
9
+ @touchend="endDrag"
10
+ @touchcancel="endDrag"
11
+ >
12
+ <!--容器-->
13
+ <view class="oxy-swipe-action__wrapper" :style="wrapperStyle">
14
+ <!--左侧操作-->
15
+ <view class="oxy-swipe-action__left" @click="onClick('left')">
16
+ <slot name="left" />
17
+ </view>
18
+ <!--内容-->
19
+ <slot />
20
+ <!--右侧操作-->
21
+ <view class="oxy-swipe-action__right" @click="onClick('right')">
22
+ <slot name="right" />
23
+ </view>
24
+ </view>
25
+ </view>
26
+ </template>
27
+ <script lang="ts">
28
+ export default {
29
+ name: 'oxy-swipe-action',
30
+ options: {
31
+ addGlobalClass: true,
32
+ virtualHost: true,
33
+ styleIsolation: 'shared'
34
+ }
35
+ }
36
+ </script>
37
+ <script lang="ts" setup>
38
+ import { getCurrentInstance, inject, onBeforeMount, onBeforeUnmount, onMounted, ref, watch } from 'vue'
39
+ import { closeOther, pushToQueue, removeFromQueue } from '../common/clickoutside'
40
+ import { type Queue, queueKey } from '../composables/useQueue'
41
+ import { useTouch } from '../composables/useTouch'
42
+ import { getRect } from '../common/util'
43
+ import { swipeActionProps, type SwipeActionPosition, type SwipeActionReason, type SwipeActionStatus } from './types'
44
+
45
+ const props = defineProps(swipeActionProps)
46
+ const emit = defineEmits(['click', 'update:modelValue'])
47
+
48
+ const queue = inject<Queue | null>(queueKey, null)
49
+
50
+ const wrapperStyle = ref<string>('')
51
+
52
+ // 滑动开始时,wrapper的偏移量
53
+ const originOffset = ref<number>(0)
54
+ // wrapper现在的偏移量
55
+ const wrapperOffset = ref<number>(0)
56
+ // 是否处于滑动状态
57
+ const touching = ref<boolean>(false)
58
+
59
+ const touch = useTouch()
60
+
61
+ const { proxy } = getCurrentInstance() as any
62
+
63
+ watch(
64
+ () => props.modelValue,
65
+ (value, old) => {
66
+ changeState(value, old)
67
+ },
68
+ {
69
+ deep: true
70
+ }
71
+ )
72
+
73
+ onBeforeMount(() => {
74
+ if (queue && queue.pushToQueue) {
75
+ queue.pushToQueue(proxy)
76
+ } else {
77
+ pushToQueue(proxy)
78
+ }
79
+ // 滑动开始时,wrapper的偏移量
80
+ originOffset.value = 0
81
+ // wrapper现在的偏移量
82
+ wrapperOffset.value = 0
83
+ // 是否处于滑动状态
84
+ touching.value = false
85
+ })
86
+
87
+ onMounted(() => {
88
+ touching.value = true
89
+ changeState(props.modelValue)
90
+ touching.value = false
91
+ })
92
+
93
+ onBeforeUnmount(() => {
94
+ if (queue && queue.removeFromQueue) {
95
+ queue.removeFromQueue(proxy)
96
+ } else {
97
+ removeFromQueue(proxy)
98
+ }
99
+ })
100
+
101
+ function changeState(value: SwipeActionStatus, old?: SwipeActionStatus) {
102
+ if (props.disabled) {
103
+ return
104
+ }
105
+ getWidths().then(([leftWidth, rightWidth]) => {
106
+ switch (value) {
107
+ case 'close':
108
+ // 调用此函数时,偏移量本就是0
109
+ if (wrapperOffset.value === 0) return
110
+ close('value', old)
111
+ break
112
+ case 'left':
113
+ swipeMove(leftWidth)
114
+ break
115
+ case 'right':
116
+ swipeMove(-rightWidth)
117
+ break
118
+ }
119
+ })
120
+ }
121
+
122
+ /**
123
+ * @description 获取左/右操作按钮的宽度
124
+ * @return {Promise<[Number, Number]>} 左宽度、右宽度
125
+ */
126
+ function getWidths() {
127
+ return Promise.all([
128
+ getRect('.oxy-swipe-action__left', false, proxy).then((rect) => {
129
+ return rect.width ? rect.width : 0
130
+ }),
131
+ getRect('.oxy-swipe-action__right', false, proxy).then((rect) => {
132
+ return rect.width ? rect.width : 0
133
+ })
134
+ ])
135
+ }
136
+ /**
137
+ * @description wrapper滑动函数
138
+ * @param {Number} offset 滑动漂移量
139
+ */
140
+ function swipeMove(offset = 0) {
141
+ // this.offset = offset
142
+ const transform = `translate3d(${offset}px, 0, 0)`
143
+ // 跟随手指滑动,不需要动画
144
+ const transition = touching.value ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
145
+ wrapperStyle.value = `
146
+ -webkit-transform: ${transform};
147
+ -webkit-transition: ${transition};
148
+ transform: ${transform};
149
+ transition: ${transition};
150
+ `
151
+ // 记录容器当前偏移的量
152
+ wrapperOffset.value = offset
153
+ }
154
+ /**
155
+ * @description click的handler
156
+ * @param event
157
+ */
158
+ function onClick(position?: SwipeActionPosition) {
159
+ if (props.disabled || wrapperOffset.value === 0) {
160
+ return
161
+ }
162
+
163
+ position = position || 'inside'
164
+ close('click', position)
165
+ emit('click', {
166
+ value: position
167
+ })
168
+ }
169
+ /**
170
+ * @description 开始滑动
171
+ */
172
+ function startDrag(event: TouchEvent) {
173
+ if (props.disabled) return
174
+
175
+ originOffset.value = wrapperOffset.value
176
+ touch.touchStart(event)
177
+ if (queue && queue.closeOther) {
178
+ queue.closeOther(proxy)
179
+ } else {
180
+ closeOther(proxy)
181
+ }
182
+ }
183
+ /**
184
+ * @description 滑动时,逐渐展示按钮
185
+ * @param event
186
+ */
187
+ function onDrag(event: TouchEvent) {
188
+ if (props.disabled) return
189
+
190
+ touch.touchMove(event)
191
+ if (touch.direction.value === 'vertical') {
192
+ return
193
+ } else {
194
+ event.preventDefault()
195
+ event.stopPropagation()
196
+ }
197
+
198
+ touching.value = true
199
+
200
+ // 本次滑动,wrapper应该设置的偏移量
201
+ const offset = originOffset.value + touch.deltaX.value
202
+ getWidths().then(([leftWidth, rightWidth]) => {
203
+ // 如果需要想滑出来的按钮不存在,对应的按钮肯定滑不出来,容器处于初始状态。此时需要模拟一下位于此处的start事件。
204
+ if ((leftWidth === 0 && offset > 0) || (rightWidth === 0 && offset < 0)) {
205
+ swipeMove(0)
206
+ return startDrag(event)
207
+ }
208
+ // 按钮已经展示完了,再滑动没有任何意义,相当于滑动结束。此时需要模拟一下位于此处的start事件。
209
+ if (leftWidth !== 0 && offset >= leftWidth) {
210
+ swipeMove(leftWidth)
211
+ return startDrag(event)
212
+ } else if (rightWidth !== 0 && -offset >= rightWidth) {
213
+ swipeMove(-rightWidth)
214
+ return startDrag(event)
215
+ }
216
+ swipeMove(offset)
217
+ })
218
+ }
219
+ /**
220
+ * @description 滑动结束,自动修正位置
221
+ */
222
+ function endDrag() {
223
+ if (props.disabled) return
224
+ // 滑出"操作按钮"的阈值
225
+ const THRESHOLD = 0.3
226
+ touching.value = false
227
+
228
+ getWidths().then(([leftWidth, rightWidth]) => {
229
+ if (
230
+ originOffset.value < 0 && // 之前展示的是右按钮
231
+ wrapperOffset.value < 0 && // 目前仍然是右按钮
232
+ wrapperOffset.value - originOffset.value < rightWidth * THRESHOLD // 并且滑动的范围不超过右边框阀值
233
+ ) {
234
+ swipeMove(-rightWidth) // 回归右按钮
235
+ emit('update:modelValue', 'right')
236
+ } else if (
237
+ originOffset.value > 0 && // 之前展示的是左按钮
238
+ wrapperOffset.value > 0 && // 现在仍然是左按钮
239
+ originOffset.value - wrapperOffset.value < leftWidth * THRESHOLD // 并且滑动的范围不超过左按钮阀值
240
+ ) {
241
+ swipeMove(leftWidth) // 回归左按钮
242
+ emit('update:modelValue', 'left')
243
+ } else if (
244
+ rightWidth > 0 &&
245
+ originOffset.value >= 0 && // 之前是初始状态或者展示左按钮显
246
+ wrapperOffset.value < 0 && // 现在展示右按钮
247
+ Math.abs(wrapperOffset.value) > rightWidth * THRESHOLD // 视图中已经展示的右按钮长度超过阀值
248
+ ) {
249
+ swipeMove(-rightWidth)
250
+ emit('update:modelValue', 'right')
251
+ } else if (
252
+ leftWidth > 0 &&
253
+ originOffset.value <= 0 && // 之前初始状态或者右按钮显示
254
+ wrapperOffset.value > 0 && // 现在左按钮
255
+ Math.abs(wrapperOffset.value) > leftWidth * THRESHOLD // 视图中已经展示的左按钮长度超过阀值
256
+ ) {
257
+ swipeMove(leftWidth)
258
+ emit('update:modelValue', 'left')
259
+ } else {
260
+ // 回归初始状态
261
+ close('swipe')
262
+ }
263
+ })
264
+ }
265
+ /**
266
+ * @description 关闭操过按钮,并在合适的时候调用 beforeClose
267
+ */
268
+ function close(reason: SwipeActionReason, position?: SwipeActionPosition) {
269
+ if (reason === 'swipe' && originOffset.value === 0) {
270
+ // offset:0 ——> offset:0
271
+ return swipeMove(0)
272
+ } else if (reason === 'swipe' && originOffset.value > 0) {
273
+ // offset > 0 ——> offset:0
274
+ position = 'left'
275
+ } else if (reason === 'swipe' && originOffset.value < 0) {
276
+ // offset < 0 ——> offset:0
277
+ position = 'right'
278
+ }
279
+
280
+ if (reason && position) {
281
+ props.beforeClose && props.beforeClose(reason, position)
282
+ }
283
+
284
+ swipeMove(0)
285
+ if (props.modelValue !== 'close') {
286
+ emit('update:modelValue', 'close')
287
+ }
288
+ }
289
+
290
+ defineExpose({ close })
291
+ </script>
292
+ <style lang="scss" scoped>
293
+ @import './index.scss';
294
+ </style>