@kine-design/core 0.0.1-beta.1 → 0.0.1-beta.3

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 (325) hide show
  1. package/assets/style/global.css +1 -0
  2. package/assets/style/var/Wuxing.css +71 -0
  3. package/assets/style/var.css +23 -0
  4. package/components/base/affix/api.ts +16 -0
  5. package/components/base/affix/index.ts +17 -0
  6. package/components/base/affix/props.d.ts +34 -0
  7. package/components/base/affix/useAffix.ts +123 -0
  8. package/components/base/alert/api.ts +18 -0
  9. package/components/base/alert/index.ts +15 -0
  10. package/components/base/alert/props.d.ts +50 -0
  11. package/components/base/anchor/api.ts +20 -0
  12. package/components/base/anchor/index.ts +18 -0
  13. package/components/base/anchor/props.d.ts +46 -0
  14. package/components/base/anchor/useAnchor.ts +83 -0
  15. package/components/base/autoComplete/api.ts +24 -0
  16. package/components/base/autoComplete/index.ts +17 -0
  17. package/components/base/autoComplete/props.d.ts +75 -0
  18. package/components/base/autoComplete/useAutoComplete.ts +149 -0
  19. package/components/base/avatar/api.ts +17 -0
  20. package/components/base/avatar/avatar.css +61 -0
  21. package/components/base/avatar/index.ts +15 -0
  22. package/components/base/avatar/props.d.ts +37 -0
  23. package/components/base/backTop/api.ts +17 -0
  24. package/components/base/backTop/index.ts +17 -0
  25. package/components/base/backTop/props.d.ts +38 -0
  26. package/components/base/backTop/useBackTop.ts +62 -0
  27. package/components/base/badge/api.ts +22 -0
  28. package/components/base/badge/index.ts +15 -0
  29. package/components/base/badge/props.d.ts +50 -0
  30. package/components/base/button/api.ts +28 -0
  31. package/components/base/button/button.css +34 -0
  32. package/components/base/button/index.ts +17 -0
  33. package/components/base/button/props.d.ts +64 -0
  34. package/components/base/button/useButton.ts +37 -0
  35. package/components/base/card/api.ts +17 -0
  36. package/components/base/card/index.ts +15 -0
  37. package/components/base/card/props.d.ts +37 -0
  38. package/components/base/carousel/api.ts +28 -0
  39. package/components/base/carousel/index.ts +17 -0
  40. package/components/base/carousel/props.d.ts +72 -0
  41. package/components/base/carousel/useCarousel.ts +149 -0
  42. package/components/base/cascader/api.ts +23 -0
  43. package/components/base/cascader/index.ts +18 -0
  44. package/components/base/cascader/props.d.ts +103 -0
  45. package/components/base/cascader/useCascader.ts +334 -0
  46. package/components/base/checkbox/api.ts +24 -0
  47. package/components/base/checkbox/checkbox.css +0 -0
  48. package/components/base/checkbox/index.ts +17 -0
  49. package/components/base/checkbox/props.d.ts +77 -0
  50. package/components/base/checkbox/useCheckbox.ts +42 -0
  51. package/components/base/collapse/api.ts +21 -0
  52. package/components/base/collapse/index.ts +18 -0
  53. package/components/base/collapse/props.d.ts +45 -0
  54. package/components/base/collapse/useCollapse.ts +80 -0
  55. package/components/base/datePicker/api.ts +18 -0
  56. package/components/base/datePicker/index.ts +19 -0
  57. package/components/base/datePicker/props.d.ts +60 -0
  58. package/components/base/datePicker/useDatePicker.ts +392 -0
  59. package/components/base/divider/api.ts +15 -0
  60. package/components/base/divider/divider.css +11 -0
  61. package/components/base/divider/index.ts +15 -0
  62. package/components/base/divider/props.d.ts +30 -0
  63. package/components/base/dropdown/api.ts +33 -0
  64. package/components/base/dropdown/index.ts +18 -0
  65. package/components/base/dropdown/props.d.ts +60 -0
  66. package/components/base/dropdown/useDropdown.ts +123 -0
  67. package/components/base/empty/api.ts +15 -0
  68. package/components/base/empty/index.ts +15 -0
  69. package/components/base/empty/props.d.ts +26 -0
  70. package/components/base/image/api.ts +25 -0
  71. package/components/base/image/index.ts +18 -0
  72. package/components/base/image/props.d.ts +67 -0
  73. package/components/base/image/useImage.ts +119 -0
  74. package/components/base/input/api.ts +19 -0
  75. package/components/base/input/index.ts +17 -0
  76. package/components/base/input/input.css +19 -0
  77. package/components/base/input/props.d.ts +60 -0
  78. package/components/base/input/useInput.ts +53 -0
  79. package/components/base/inputNumber/api.ts +21 -0
  80. package/components/base/inputNumber/index.ts +17 -0
  81. package/components/base/inputNumber/props.d.ts +64 -0
  82. package/components/base/inputNumber/useInputNumber.ts +140 -0
  83. package/components/base/li/api.ts +15 -0
  84. package/components/base/li/index.ts +15 -0
  85. package/components/base/li/props.d.ts +30 -0
  86. package/components/base/list/api.ts +16 -0
  87. package/components/base/list/index.ts +17 -0
  88. package/components/base/list/props.d.ts +33 -0
  89. package/components/base/list/useList.ts +36 -0
  90. package/components/base/loading/api.ts +17 -0
  91. package/components/base/loading/index.ts +15 -0
  92. package/components/base/loading/props.d.ts +38 -0
  93. package/components/base/popover/api.ts +28 -0
  94. package/components/base/popover/index.ts +17 -0
  95. package/components/base/popover/props.d.ts +73 -0
  96. package/components/base/popover/usePopover.ts +192 -0
  97. package/components/base/progress/api.ts +18 -0
  98. package/components/base/progress/index.ts +17 -0
  99. package/components/base/progress/props.d.ts +53 -0
  100. package/components/base/progress/useProgress.ts +28 -0
  101. package/components/base/radio/api.ts +19 -0
  102. package/components/base/radio/index.ts +19 -0
  103. package/components/base/radio/props.d.ts +59 -0
  104. package/components/base/radio/useRadio.ts +11 -0
  105. package/components/base/rate/api.ts +18 -0
  106. package/components/base/rate/index.ts +17 -0
  107. package/components/base/rate/props.d.ts +49 -0
  108. package/components/base/rate/useRate.ts +75 -0
  109. package/components/base/result/api.ts +20 -0
  110. package/components/base/result/index.ts +15 -0
  111. package/components/base/result/props.d.ts +36 -0
  112. package/components/base/select/api.ts +31 -0
  113. package/components/base/select/index.ts +18 -0
  114. package/components/base/select/props.d.ts +132 -0
  115. package/components/base/select/select.css +7 -0
  116. package/components/base/select/useSelect.ts +280 -0
  117. package/components/base/select/useSelectTools.ts +60 -0
  118. package/components/base/skeleton/api.ts +18 -0
  119. package/components/base/skeleton/index.ts +15 -0
  120. package/components/base/skeleton/props.d.ts +41 -0
  121. package/components/base/slider/api.ts +20 -0
  122. package/components/base/slider/index.ts +17 -0
  123. package/components/base/slider/props.d.ts +65 -0
  124. package/components/base/slider/useSlider.ts +83 -0
  125. package/components/base/space/api.ts +17 -0
  126. package/components/base/space/index.ts +15 -0
  127. package/components/base/space/props.d.ts +39 -0
  128. package/components/base/steps/api.ts +30 -0
  129. package/components/base/steps/index.ts +22 -0
  130. package/components/base/steps/props.d.ts +88 -0
  131. package/components/base/steps/useSteps.ts +101 -0
  132. package/components/base/switch/api.ts +22 -0
  133. package/components/base/switch/index.ts +19 -0
  134. package/components/base/switch/props.d.ts +66 -0
  135. package/components/base/switch/useSwitch.tsx +79 -0
  136. package/components/base/tabs/api.ts +23 -0
  137. package/components/base/tabs/index.ts +18 -0
  138. package/components/base/tabs/props.d.ts +41 -0
  139. package/components/base/tabs/useTabs.ts +66 -0
  140. package/components/base/tag/api.ts +17 -0
  141. package/components/base/tag/index.ts +15 -0
  142. package/components/base/tag/props.d.ts +49 -0
  143. package/components/base/timePicker/api.ts +21 -0
  144. package/components/base/timePicker/index.ts +18 -0
  145. package/components/base/timePicker/props.d.ts +66 -0
  146. package/components/base/timePicker/useTimePicker.ts +161 -0
  147. package/components/base/timeline/api.ts +24 -0
  148. package/components/base/timeline/index.ts +16 -0
  149. package/components/base/timeline/props.d.ts +60 -0
  150. package/components/base/tooltip/api.ts +19 -0
  151. package/components/base/tooltip/index.ts +17 -0
  152. package/components/base/tooltip/props.d.ts +34 -0
  153. package/components/base/tooltip/useTooltip.ts +89 -0
  154. package/components/base/transfer/api.ts +18 -0
  155. package/components/base/transfer/index.ts +17 -0
  156. package/components/base/transfer/props.d.ts +63 -0
  157. package/components/base/transfer/useTransfer.ts +207 -0
  158. package/components/base/tree/api.ts +47 -0
  159. package/components/base/tree/index.ts +29 -0
  160. package/components/base/tree/props.d.ts +108 -0
  161. package/components/base/tree/tree.ts +263 -0
  162. package/components/base/tree/useTree.ts +114 -0
  163. package/components/message/confirm/api.ts +21 -0
  164. package/components/message/confirm/index.ts +15 -0
  165. package/components/message/confirm/props.d.ts +69 -0
  166. package/components/message/dialog/api.ts +19 -0
  167. package/components/message/dialog/index.ts +15 -0
  168. package/components/message/dialog/props.d.ts +55 -0
  169. package/components/message/drawer/api.ts +32 -0
  170. package/components/message/drawer/index.ts +15 -0
  171. package/components/message/drawer/props.d.ts +73 -0
  172. package/components/message/message/api.ts +27 -0
  173. package/components/message/message/index.ts +20 -0
  174. package/components/message/message/props.d.ts +54 -0
  175. package/components/message/message/useMessage.ts +61 -0
  176. package/components/message/notification/api.ts +23 -0
  177. package/components/message/notification/index.ts +19 -0
  178. package/components/message/notification/props.d.ts +64 -0
  179. package/components/message/notification/useNotification.ts +79 -0
  180. package/components/message/popover/MPopover.tsx +94 -0
  181. package/components/message/popover/api.ts +54 -0
  182. package/components/message/popover/index.ts +17 -0
  183. package/components/message/popover/popover.css +21 -0
  184. package/components/message/popover/props.d.ts +76 -0
  185. package/components/message/popover/usePopover.ts +234 -0
  186. package/components/other/darkMode/api.ts +17 -0
  187. package/components/other/darkMode/index.ts +17 -0
  188. package/components/other/darkMode/props.d.ts +37 -0
  189. package/components/other/darkMode/useDarkMode.ts +129 -0
  190. package/components/template/border/api.ts +18 -0
  191. package/components/template/border/index.ts +15 -0
  192. package/components/template/border/props.d.ts +41 -0
  193. package/components/template/breadcrumb/api.ts +15 -0
  194. package/components/template/breadcrumb/index.ts +15 -0
  195. package/components/template/breadcrumb/props.d.ts +45 -0
  196. package/components/template/descriptions/api.ts +23 -0
  197. package/components/template/descriptions/index.ts +16 -0
  198. package/components/template/descriptions/props.d.ts +54 -0
  199. package/components/template/form/api.ts +23 -0
  200. package/components/template/form/index.ts +20 -0
  201. package/components/template/form/props.d.ts +60 -0
  202. package/components/template/grid/api.ts +20 -0
  203. package/components/template/grid/index.ts +15 -0
  204. package/components/template/grid/props.d.ts +48 -0
  205. package/components/template/menu/api.ts +26 -0
  206. package/components/template/menu/index.ts +18 -0
  207. package/components/template/menu/props.d.ts +93 -0
  208. package/components/template/menu/useMenu.ts +155 -0
  209. package/components/template/pagination/api.ts +22 -0
  210. package/components/template/pagination/index.ts +19 -0
  211. package/components/template/pagination/props.d.ts +65 -0
  212. package/components/template/pagination/usePagination.ts +186 -0
  213. package/components/template/table/api.ts +18 -0
  214. package/components/template/table/index.ts +18 -0
  215. package/components/template/table/props.d.ts +36 -0
  216. package/components/template/table/useTable.ts +138 -0
  217. package/components/template/tableColumn/api.ts +17 -0
  218. package/components/template/tableColumn/index.ts +15 -0
  219. package/components/template/tableColumn/props.d.ts +32 -0
  220. package/components/template/virtualList/api.ts +16 -0
  221. package/components/template/virtualList/index.ts +17 -0
  222. package/components/template/virtualList/props.d.ts +25 -0
  223. package/components/template/virtualList/useVirtualList.ts +237 -0
  224. package/components/types/hook.d.ts +13 -0
  225. package/components/types/props.d.ts +52 -0
  226. package/components/types/template.d.ts +59 -0
  227. package/compositions/common/defineCore.ts +55 -0
  228. package/compositions/common/useDebounceFn.ts +27 -0
  229. package/compositions/common/useDrag.ts +65 -0
  230. package/compositions/common/useElementSize.ts +37 -0
  231. package/compositions/common/useEventListener.ts +48 -0
  232. package/compositions/common/usePopover.ts +45 -0
  233. package/compositions/common/useResizeObserver.ts +43 -0
  234. package/compositions/common/useTeleport.ts +24 -0
  235. package/compositions/input/useBooleanInput.ts +52 -0
  236. package/compositions/modal/useModal.ts +72 -0
  237. package/compositions/popper/useClickAway.ts +41 -0
  238. package/compositions/popper/usePopper.ts +63 -0
  239. package/compositions/utils/filters.ts +135 -0
  240. package/compositions/virtualList/enums.ts +52 -0
  241. package/compositions/virtualList/useContainerObserver.ts +89 -0
  242. package/compositions/virtualList/useEntries.ts +248 -0
  243. package/compositions/virtualList/useHeightCache.ts +83 -0
  244. package/compositions/virtualList/useSentinelObserver.ts +81 -0
  245. package/dist/components/base/affix/index.d.ts +2 -1
  246. package/dist/components/base/affix/useAffix.d.ts +6 -5
  247. package/dist/components/base/anchor/index.d.ts +2 -1
  248. package/dist/components/base/anchor/useAnchor.d.ts +2 -2
  249. package/dist/components/base/autoComplete/useAutoComplete.d.ts +12 -4
  250. package/dist/components/base/avatar/index.d.ts +1 -0
  251. package/dist/components/base/backTop/index.d.ts +2 -1
  252. package/dist/components/base/backTop/useBackTop.d.ts +2 -2
  253. package/dist/components/base/button/index.d.ts +3 -21
  254. package/dist/components/base/button/useButton.d.ts +5 -2
  255. package/dist/components/base/carousel/useCarousel.d.ts +6 -3
  256. package/dist/components/base/cascader/useCascader.d.ts +23 -11
  257. package/dist/components/base/checkbox/index.d.ts +2 -1
  258. package/dist/components/base/checkbox/useCheckbox.d.ts +4 -3
  259. package/dist/components/base/collapse/index.d.ts +2 -1
  260. package/dist/components/base/collapse/useCollapse.d.ts +3 -3
  261. package/dist/components/base/datePicker/useDatePicker.d.ts +140 -8
  262. package/dist/components/base/dropdown/index.d.ts +2 -1
  263. package/dist/components/base/dropdown/useDropdown.d.ts +12 -6
  264. package/dist/components/base/image/useImage.d.ts +5 -5
  265. package/dist/components/base/input/index.d.ts +2 -1
  266. package/dist/components/base/input/useInput.d.ts +1 -2
  267. package/dist/components/base/inputNumber/index.d.ts +2 -1
  268. package/dist/components/base/inputNumber/useInputNumber.d.ts +3 -3
  269. package/dist/components/base/li/index.d.ts +1 -0
  270. package/dist/components/base/list/index.d.ts +2 -1
  271. package/dist/components/base/list/useList.d.ts +1 -1
  272. package/dist/components/base/popover/index.d.ts +2 -1
  273. package/dist/components/base/popover/usePopover.d.ts +9 -9
  274. package/dist/components/base/progress/index.d.ts +2 -1
  275. package/dist/components/base/progress/useProgress.d.ts +2 -2
  276. package/dist/components/base/rate/index.d.ts +2 -1
  277. package/dist/components/base/rate/useRate.d.ts +2 -2
  278. package/dist/components/base/select/useSelect.d.ts +8 -8
  279. package/dist/components/base/slider/index.d.ts +2 -1
  280. package/dist/components/base/slider/useSlider.d.ts +4 -4
  281. package/dist/components/base/steps/index.d.ts +1 -1
  282. package/dist/components/base/steps/useSteps.d.ts +5 -5
  283. package/dist/components/base/switch/index.d.ts +2 -1
  284. package/dist/components/base/switch/useSwitch.d.ts +8 -3
  285. package/dist/components/base/tabs/index.d.ts +1 -1
  286. package/dist/components/base/tabs/useTabs.d.ts +3 -3
  287. package/dist/components/base/tag/index.d.ts +1 -0
  288. package/dist/components/base/timePicker/useTimePicker.d.ts +14 -6
  289. package/dist/components/base/tooltip/index.d.ts +1 -1
  290. package/dist/components/base/tooltip/useTooltip.d.ts +15 -5
  291. package/dist/components/base/transfer/useTransfer.d.ts +15 -15
  292. package/dist/components/base/tree/index.d.ts +1 -1
  293. package/dist/components/base/tree/useTree.d.ts +2 -1
  294. package/dist/components/message/drawer/index.d.ts +2 -2
  295. package/dist/components/message/message/useMessage.d.ts +11 -1
  296. package/dist/components/message/notification/useNotification.d.ts +17 -1
  297. package/dist/components/message/popover/MPopover.d.ts +6 -1
  298. package/dist/components/message/popover/index.d.ts +1 -1
  299. package/dist/components/message/popover/usePopover.d.ts +6 -6
  300. package/dist/components/other/darkMode/useDarkMode.d.ts +1 -1
  301. package/dist/components/template/menu/index.d.ts +0 -1
  302. package/dist/components/template/menu/useMenu.d.ts +2 -1
  303. package/dist/components/template/pagination/index.d.ts +2 -1
  304. package/dist/components/template/virtualList/index.d.ts +0 -1
  305. package/dist/components/template/virtualList/useVirtualList.d.ts +10 -7
  306. package/dist/compositions/common/useDrag.d.ts +1 -1
  307. package/dist/compositions/common/useElementSize.d.ts +2 -2
  308. package/dist/compositions/common/useTeleport.d.ts +4 -2
  309. package/dist/compositions/modal/useModal.d.ts +1 -1
  310. package/dist/core.js +6147 -4186
  311. package/dist/runtime/defineHook.d.ts +1 -1
  312. package/index.css +1 -0
  313. package/index.ts +71 -0
  314. package/package.json +19 -16
  315. package/runtime/defineHook.ts +21 -0
  316. package/tools/empty.ts +81 -0
  317. package/tools/index.ts +15 -0
  318. package/tools/types.ts +11 -0
  319. package/tsconfig.json +8 -0
  320. package/types/common/common.d.ts +25 -0
  321. package/types/common/model.d.ts +25 -0
  322. package/types/index.d.ts +11 -0
  323. package/types/props.d.ts +13 -0
  324. package/vite.config.build.ts +41 -0
  325. package/dist/vite.config.build.d.ts +0 -2
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @description 虚拟列表 action 枚举
3
+ * @author 阿怪
4
+ * @date 2026/2/25 13:30
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+
10
+ /** 元素可见性变化的动作类型 */
11
+ export enum ACTION {
12
+ /** 从顶部进入可视区域(开始露出) */
13
+ ENTER_TOP_START,
14
+ /** 从顶部完全进入可视区域 */
15
+ ENTER_TOP_END,
16
+ /** 从底部进入可视区域(开始露出) */
17
+ ENTER_BOTTOM_START,
18
+ /** 从底部完全进入可视区域 */
19
+ ENTER_BOTTOM_END,
20
+ /** 从顶部开始离开可视区域 */
21
+ LEAVE_TOP_START,
22
+ /** 从顶部完全离开可视区域 */
23
+ LEAVE_TOP_END,
24
+ /** 从底部开始离开可视区域 */
25
+ LEAVE_BOTTOM_START,
26
+ /** 从底部完全离开可视区域 */
27
+ LEAVE_BOTTOM_END,
28
+ /** 未知状态 */
29
+ UNKNOWN,
30
+ }
31
+
32
+ /** 元素相对于容器的位置类型 */
33
+ export enum POSITION_TYPE {
34
+ /** 完全在可视区域上方 */
35
+ TOP,
36
+ /** 部分在可视区域上方(上半部分露出) */
37
+ TOP_VISIBLE,
38
+ /** 完全在可视区域内 */
39
+ VISIBLE,
40
+ /** 部分在可视区域下方(下半部分露出) */
41
+ BOTTOM_VISIBLE,
42
+ /** 完全在可视区域下方 */
43
+ BOTTOM,
44
+ }
45
+
46
+ /** 元素信息记录 */
47
+ export type EntryInfo = {
48
+ ratio: number;
49
+ position: POSITION_TYPE;
50
+ realIndex: number;
51
+ translateY: number;
52
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @description 容器 IntersectionObserver 管理
3
+ * @author 阿怪
4
+ * @date 2026/2/25 13:30
5
+ * @version v2.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ *
9
+ * 管理 IntersectionObserver 的创建、observe/unobserve,配合 ResizeObserver 处理容器尺寸变化
10
+ */
11
+ import { onBeforeUnmount, Ref } from 'vue';
12
+ import { useResizeObserver } from '../common/useResizeObserver';
13
+
14
+ export default function useContainerObserver(options: {
15
+ containerRef: Ref<HTMLElement | null>;
16
+ threshold?: number | number[];
17
+ getTarget: () => ArrayLike<Element>;
18
+ callback: (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void;
19
+ }) {
20
+ let ob: IntersectionObserver | undefined;
21
+ const observeList: Element[] = [];
22
+
23
+ // 队列:在 observer 创建前缓存操作
24
+ const eventQueue: Array<{ target: ArrayLike<Element> | Element; type: 'observe' | 'unobserve' }> = [];
25
+
26
+ const processTarget = (target: ArrayLike<Element> | Element, type: 'observe' | 'unobserve') => {
27
+ if (!ob) {
28
+ eventQueue.push({ target, type });
29
+ return;
30
+ }
31
+ if ('length' in target) {
32
+ for (let i = 0; i < target.length; i++) {
33
+ if (target[i]) {
34
+ ob[type](target[i]);
35
+ }
36
+ }
37
+ } else {
38
+ ob[type](target);
39
+ }
40
+ };
41
+
42
+ const clearQueue = () => {
43
+ while (eventQueue.length) {
44
+ const { target, type } = eventQueue.shift()!;
45
+ processTarget(target, type);
46
+ }
47
+ };
48
+
49
+ const reObserve = (target: ArrayLike<Element>) => {
50
+ // 先 unobserve 所有已观察的
51
+ processTarget(observeList, 'unobserve');
52
+ observeList.length = 0;
53
+ // 再 observe 新的
54
+ for (let i = 0; i < target.length; i++) {
55
+ observeList.push(target[i]);
56
+ }
57
+ processTarget(target, 'observe');
58
+ };
59
+
60
+ const initOb = () => {
61
+ if (ob) {
62
+ ob.disconnect();
63
+ }
64
+ ob = new IntersectionObserver(options.callback, {
65
+ root: options.containerRef.value,
66
+ threshold: options.threshold ?? [0, 1],
67
+ });
68
+ clearQueue();
69
+ };
70
+
71
+ useResizeObserver(options.containerRef, () => {
72
+ if (options.containerRef.value) {
73
+ if (!ob) {
74
+ initOb();
75
+ }
76
+ const target = options.getTarget();
77
+ reObserve(target);
78
+ }
79
+ });
80
+
81
+ onBeforeUnmount(() => {
82
+ if (ob) {
83
+ ob.disconnect();
84
+ ob = undefined;
85
+ }
86
+ });
87
+
88
+ return { reObserve };
89
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * @description 虚拟列表 IntersectionObserver 回调处理
3
+ * @author 阿怪
4
+ * @date 2026/2/25 13:30
5
+ * @version v2.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ *
9
+ * 基于 IntersectionObserver 方案,通过观察子元素可见性变化判断滚动方向和位置
10
+ */
11
+ import { Ref } from 'vue';
12
+ import { ACTION, POSITION_TYPE, EntryInfo } from './enums';
13
+
14
+ /** 位置变化 → 动作映射表 */
15
+ const ACTION_POSITION_MAP: Record<POSITION_TYPE, Partial<Record<POSITION_TYPE, ACTION>>> = {
16
+ [POSITION_TYPE.TOP]: {
17
+ [POSITION_TYPE.TOP_VISIBLE]: ACTION.LEAVE_TOP_START,
18
+ [POSITION_TYPE.VISIBLE]: ACTION.LEAVE_TOP_END,
19
+ [POSITION_TYPE.BOTTOM_VISIBLE]: ACTION.ENTER_BOTTOM_START,
20
+ [POSITION_TYPE.BOTTOM]: ACTION.ENTER_BOTTOM_END,
21
+ },
22
+ [POSITION_TYPE.TOP_VISIBLE]: {
23
+ [POSITION_TYPE.TOP]: ACTION.ENTER_TOP_END,
24
+ [POSITION_TYPE.VISIBLE]: ACTION.LEAVE_TOP_END,
25
+ [POSITION_TYPE.BOTTOM_VISIBLE]: ACTION.ENTER_BOTTOM_START,
26
+ [POSITION_TYPE.BOTTOM]: ACTION.ENTER_BOTTOM_END,
27
+ },
28
+ [POSITION_TYPE.VISIBLE]: {
29
+ [POSITION_TYPE.TOP]: ACTION.ENTER_TOP_END,
30
+ [POSITION_TYPE.TOP_VISIBLE]: ACTION.ENTER_TOP_START,
31
+ [POSITION_TYPE.BOTTOM_VISIBLE]: ACTION.ENTER_BOTTOM_START,
32
+ [POSITION_TYPE.BOTTOM]: ACTION.ENTER_BOTTOM_END,
33
+ },
34
+ [POSITION_TYPE.BOTTOM_VISIBLE]: {
35
+ [POSITION_TYPE.TOP]: ACTION.ENTER_TOP_END,
36
+ [POSITION_TYPE.TOP_VISIBLE]: ACTION.ENTER_TOP_START,
37
+ [POSITION_TYPE.VISIBLE]: ACTION.LEAVE_BOTTOM_END,
38
+ [POSITION_TYPE.BOTTOM]: ACTION.ENTER_BOTTOM_END,
39
+ },
40
+ [POSITION_TYPE.BOTTOM]: {
41
+ [POSITION_TYPE.TOP]: ACTION.ENTER_TOP_END,
42
+ [POSITION_TYPE.TOP_VISIBLE]: ACTION.ENTER_TOP_START,
43
+ [POSITION_TYPE.VISIBLE]: ACTION.LEAVE_BOTTOM_END,
44
+ [POSITION_TYPE.BOTTOM_VISIBLE]: ACTION.LEAVE_BOTTOM_START,
45
+ },
46
+ };
47
+
48
+ /** 根据 entry 计算元素相对于容器的位置 */
49
+ const getPosition = (entry: IntersectionObserverEntry): POSITION_TYPE => {
50
+ const { top, bottom } = entry.rootBounds!;
51
+ const { top: entryTop, bottom: entryBottom } = entry.boundingClientRect;
52
+ const ratio = entry.intersectionRatio;
53
+
54
+ if (entryTop >= top) {
55
+ if (entryBottom <= bottom) {
56
+ return POSITION_TYPE.VISIBLE;
57
+ }
58
+ return ratio > 0 ? POSITION_TYPE.BOTTOM_VISIBLE : POSITION_TYPE.BOTTOM;
59
+ }
60
+
61
+ return ratio > 0 ? POSITION_TYPE.TOP_VISIBLE : POSITION_TYPE.TOP;
62
+ };
63
+
64
+ /** 根据前后位置变化得出动作 */
65
+ const getAction = (entry: IntersectionObserverEntry, prevInfo: EntryInfo): ACTION => {
66
+ const prevPosition = prevInfo.position;
67
+ const currentPosition = getPosition(entry);
68
+
69
+ let action: ACTION;
70
+
71
+ if (prevPosition === currentPosition) {
72
+ const ratioSub = entry.intersectionRatio - prevInfo.ratio;
73
+ if (prevPosition === POSITION_TYPE.TOP_VISIBLE) {
74
+ action = ratioSub > 0 ? ACTION.ENTER_TOP_START : ACTION.LEAVE_TOP_END;
75
+ } else if (prevPosition === POSITION_TYPE.BOTTOM_VISIBLE) {
76
+ action = ratioSub > 0 ? ACTION.ENTER_BOTTOM_START : ACTION.LEAVE_BOTTOM_END;
77
+ } else {
78
+ action = ACTION.UNKNOWN;
79
+ }
80
+ } else {
81
+ action = ACTION_POSITION_MAP[prevPosition]?.[currentPosition] ?? ACTION.UNKNOWN;
82
+ }
83
+
84
+ prevInfo.position = currentPosition;
85
+ return action;
86
+ };
87
+
88
+
89
+ export interface UseEntriesOptions {
90
+ /** 获取列表子元素 */
91
+ getChildren: () => ArrayLike<Element>;
92
+ /** 获取当前可见数量 */
93
+ getVisibleCount: () => number;
94
+ /** 从指定位置重新渲染列表 */
95
+ getList: (from: number) => void;
96
+ /** 获取当前渲染边界信息 */
97
+ getInfo: () => {
98
+ renderFrom: number;
99
+ realFrom: number;
100
+ realEnd: number;
101
+ renderEnd: number;
102
+ };
103
+ /** 设置可见数量 */
104
+ setVisibleCount: (count: number) => void;
105
+ /** 获取总数 */
106
+ getTotal: () => number;
107
+ /** 触底回调 */
108
+ reachBottom: () => void;
109
+ /** translateY 样式 ref */
110
+ styleRef: Ref<{ transform: string }>;
111
+ }
112
+
113
+ export default function useEntries(options: UseEntriesOptions) {
114
+ const entriesInfoWeakMap: WeakMap<Element, EntryInfo> = new WeakMap();
115
+ const transformYList: number[] = [0];
116
+
117
+ /** 首次全部元素进入时的初始化 */
118
+ const onInit = (entries: IntersectionObserverEntry[]) => {
119
+ const info = options.getInfo();
120
+ const { renderFrom, realFrom, realEnd } = info;
121
+
122
+ // 检查可视范围内的元素是否都可见,用于计算 visibleCount
123
+ const realFromEntry = entries[realFrom - renderFrom];
124
+ const realEndEntry = entries[realEnd - renderFrom - 1];
125
+ if (realFromEntry?.isIntersecting && realEndEntry?.isIntersecting) {
126
+ const totalHeight = entries.reduce((sum, e) => sum + e.boundingClientRect.height, 0);
127
+ const avgHeight = totalHeight / entries.length;
128
+ const rootHeight = entries[0].rootBounds!.height;
129
+ options.setVisibleCount(Math.ceil(rootHeight / avgHeight));
130
+ options.getList(info.realFrom);
131
+ }
132
+
133
+ const visibleCount = options.getVisibleCount();
134
+ entries.forEach((e, i) => {
135
+ const realIndex = i + renderFrom;
136
+ if (realIndex < visibleCount) {
137
+ transformYList[realIndex] = 0;
138
+ } else {
139
+ const prevH = transformYList[realIndex - 1];
140
+ if (prevH != null) {
141
+ transformYList[realIndex] = prevH + e.boundingClientRect.height;
142
+ }
143
+ }
144
+
145
+ entriesInfoWeakMap.set(e.target, {
146
+ ratio: e.intersectionRatio,
147
+ position: getPosition(e),
148
+ realIndex,
149
+ translateY: transformYList[realIndex] ?? 0,
150
+ });
151
+ });
152
+ };
153
+
154
+ /** 处理元素可见性变化 */
155
+ const entriesHandler = (entries: IntersectionObserverEntry[]) => {
156
+ const maxIndex = options.getTotal() - 1;
157
+ let touchBottom = false;
158
+
159
+ const actionList = entries.map(e => {
160
+ const prevInfo = entriesInfoWeakMap.get(e.target);
161
+ if (!prevInfo) {
162
+ return { action: ACTION.UNKNOWN, target: e.target };
163
+ }
164
+ const action = getAction(e, prevInfo);
165
+ prevInfo.ratio = e.intersectionRatio;
166
+
167
+ if (prevInfo.realIndex === maxIndex && e.isIntersecting) {
168
+ touchBottom = true;
169
+ }
170
+
171
+ return { action, target: e.target };
172
+ });
173
+
174
+ if (touchBottom) {
175
+ options.reachBottom();
176
+ }
177
+
178
+ // 按 action 分组
179
+ const actionMap = new Map<ACTION, Element[]>();
180
+ actionList.forEach(({ action, target }) => {
181
+ const list = actionMap.get(action);
182
+ if (list) {
183
+ list.push(target);
184
+ } else {
185
+ actionMap.set(action, [target]);
186
+ }
187
+ });
188
+
189
+ // 上拉:元素从顶部完全离开 → 列表向下滚动
190
+ const leaveTopTargets = actionMap.get(ACTION.LEAVE_TOP_END);
191
+ if (leaveTopTargets) {
192
+ const target = leaveTopTargets[0];
193
+ const info = entriesInfoWeakMap.get(target);
194
+ if (info) {
195
+ options.getList(info.realIndex);
196
+ const ty = transformYList[info.realIndex - 1] ?? 0;
197
+ options.styleRef.value = { transform: `translateY(${ty}px)` };
198
+ }
199
+ return;
200
+ }
201
+
202
+ // 下拉:元素从顶部进入 → 列表向上滚动
203
+ const enterTopTargets = actionMap.get(ACTION.ENTER_TOP_END);
204
+ if (enterTopTargets) {
205
+ const target = enterTopTargets[enterTopTargets.length - 1];
206
+ const info = entriesInfoWeakMap.get(target);
207
+ if (info) {
208
+ options.getList(info.realIndex);
209
+ const ty = transformYList[info.realIndex - 1] ?? 0;
210
+ options.styleRef.value = { transform: `translateY(${ty}px)` };
211
+ }
212
+ return;
213
+ }
214
+
215
+ // 快速滚动到底部的边界修正
216
+ const enterBottomTargets = actionMap.get(ACTION.ENTER_BOTTOM_END);
217
+ if (enterBottomTargets) {
218
+ requestAnimationFrame(() => {
219
+ const firstEntry = entries[0];
220
+ const firstInfo = entriesInfoWeakMap.get(firstEntry.target);
221
+ if (firstInfo?.position === POSITION_TYPE.TOP) {
222
+ // 所有元素都已经滚过去了,重置到顶部
223
+ const children = options.getChildren();
224
+ if (children.length > 0) {
225
+ const firstChild = children[0];
226
+ const rect = firstChild.getBoundingClientRect();
227
+ const rootBottom = firstEntry.rootBounds?.bottom ?? 0;
228
+ if (rect.bottom > rootBottom) {
229
+ options.getList(0);
230
+ options.styleRef.value = { transform: 'translateY(0px)' };
231
+ }
232
+ }
233
+ }
234
+ });
235
+ }
236
+ };
237
+
238
+ /** IntersectionObserver 回调 */
239
+ const cb = (entries: IntersectionObserverEntry[], _observer: IntersectionObserver) => {
240
+ if (entries.length === options.getChildren().length) {
241
+ onInit(entries);
242
+ return;
243
+ }
244
+ entriesHandler(entries);
245
+ };
246
+
247
+ return { cb };
248
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @description 虚拟列表高度缓存
3
+ * @author 阿怪
4
+ * @date 2026/2/25 14:00
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ *
9
+ * 管理每个列表项的高度缓存,支持预估高度和实际高度
10
+ * 提供基于 scrollTop 的二分查找定位
11
+ */
12
+
13
+ export interface HeightCache {
14
+ /** 更新指定索引的实际高度 */
15
+ update: (index: number, height: number) => void;
16
+ /** 获取指定索引的高度(实际或预估) */
17
+ getHeight: (index: number) => number;
18
+ /** 获取 [0, index) 的累计高度(即第 index 项的顶部偏移) */
19
+ getOffset: (index: number) => number;
20
+ /** 获取所有项的总高度 */
21
+ getTotalHeight: () => number;
22
+ /** 根据 scrollTop 二分查找对应的起始索引 */
23
+ findIndex: (scrollTop: number) => number;
24
+ /** 重置缓存(列表数据变化时) */
25
+ reset: (total: number) => void;
26
+ }
27
+
28
+ export function createHeightCache(total: number, estimatedHeight: number): HeightCache {
29
+ // 存储实际测量的高度,null 表示未测量
30
+ const heights: (number | null)[] = Array.from({ length: total }, () => null);
31
+
32
+ const getHeight = (index: number): number => {
33
+ return heights[index] ?? estimatedHeight;
34
+ };
35
+
36
+ const update = (index: number, height: number) => {
37
+ if (index >= 0 && index < heights.length) {
38
+ heights[index] = height;
39
+ }
40
+ };
41
+
42
+ const getOffset = (index: number): number => {
43
+ let offset = 0;
44
+ const end = Math.min(index, heights.length);
45
+ for (let i = 0; i < end; i++) {
46
+ offset += getHeight(i);
47
+ }
48
+ return offset;
49
+ };
50
+
51
+ const getTotalHeight = (): number => {
52
+ return getOffset(heights.length);
53
+ };
54
+
55
+ /** 二分查找:scrollTop 对应的第一个可见项索引 */
56
+ const findIndex = (scrollTop: number): number => {
57
+ let low = 0;
58
+ let high = heights.length - 1;
59
+
60
+ while (low <= high) {
61
+ const mid = (low + high) >>> 1;
62
+ const offset = getOffset(mid);
63
+ const offsetEnd = offset + getHeight(mid);
64
+
65
+ if (offsetEnd <= scrollTop) {
66
+ low = mid + 1;
67
+ } else if (offset > scrollTop) {
68
+ high = mid - 1;
69
+ } else {
70
+ return mid;
71
+ }
72
+ }
73
+
74
+ return Math.min(low, heights.length - 1);
75
+ };
76
+
77
+ const reset = (newTotal: number) => {
78
+ heights.length = newTotal;
79
+ heights.fill(null);
80
+ };
81
+
82
+ return { update, getHeight, getOffset, getTotalHeight, findIndex, reset };
83
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @description sentinel 哨兵元素 IntersectionObserver
3
+ * @author 阿怪
4
+ * @date 2026/2/25 14:00
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ *
9
+ * 只观察两个哨兵元素(顶部和底部),替代对每个列表项的 observe
10
+ * 哨兵进入可视区触发回调,配合 scrollTop 定位
11
+ */
12
+ import { Ref, watch, onBeforeUnmount } from 'vue';
13
+
14
+ export interface SentinelObserverOptions {
15
+ containerRef: Ref<HTMLElement | null>;
16
+ topSentinelRef: Ref<HTMLElement | null>;
17
+ bottomSentinelRef: Ref<HTMLElement | null>;
18
+ /** 需要更新可视列表时调用 */
19
+ onUpdate: () => void;
20
+ /** 底部哨兵完全进入可视区(触底) */
21
+ onReachBottom?: () => void;
22
+ }
23
+
24
+ export function useSentinelObserver(options: SentinelObserverOptions) {
25
+ let ob: IntersectionObserver | undefined;
26
+
27
+ const cleanup = () => {
28
+ if (ob) {
29
+ ob.disconnect();
30
+ ob = undefined;
31
+ }
32
+ };
33
+
34
+ const initObserver = () => {
35
+ const container = options.containerRef.value;
36
+ if (!container) return;
37
+
38
+ cleanup();
39
+
40
+ ob = new IntersectionObserver(
41
+ (entries) => {
42
+ for (const entry of entries) {
43
+ if (!entry.isIntersecting) continue;
44
+
45
+ if (entry.target === options.bottomSentinelRef.value) {
46
+ options.onUpdate();
47
+ options.onReachBottom?.();
48
+ } else if (entry.target === options.topSentinelRef.value) {
49
+ options.onUpdate();
50
+ }
51
+ }
52
+ },
53
+ {
54
+ root: container,
55
+ threshold: 0,
56
+ },
57
+ );
58
+
59
+ if (options.topSentinelRef.value) {
60
+ ob.observe(options.topSentinelRef.value);
61
+ }
62
+ if (options.bottomSentinelRef.value) {
63
+ ob.observe(options.bottomSentinelRef.value);
64
+ }
65
+ };
66
+
67
+ /** 重新观察哨兵(列表更新后哨兵 DOM 可能重建) */
68
+ const reobserve = () => {
69
+ initObserver();
70
+ };
71
+
72
+ watch(options.containerRef, () => {
73
+ if (options.containerRef.value) {
74
+ initObserver();
75
+ }
76
+ });
77
+
78
+ onBeforeUnmount(cleanup);
79
+
80
+ return { reobserve, cleanup };
81
+ }
@@ -1,5 +1,6 @@
1
- import { default as useAffix } from './useAffix';
1
+ import { useAffix } from './useAffix';
2
2
  export declare const AffixCore: {
3
3
  props: import('../../types/props').MCOPO<import('./props').AffixProps>;
4
4
  useAffix: typeof useAffix;
5
5
  };
6
+ export type { AffixProps } from './props';
@@ -1,7 +1,8 @@
1
1
  import { AffixProps } from './props';
2
- export default function useAffix(props: Required<AffixProps>, emit: (event: string, ...args: unknown[]) => void): {
3
- wrapRef: any;
4
- affixed: any;
5
- affixStyle: any;
6
- placeholderHeight: any;
2
+ export declare function useAffix(props: Required<AffixProps>, emit: (...args: any[]) => void): {
3
+ wrapperRef: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
4
+ wrapRef: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
5
+ affixed: import('vue').Ref<boolean, boolean>;
6
+ affixStyle: import('vue').Ref<Record<string, string>, Record<string, string>>;
7
+ placeholderHeight: import('vue').Ref<number, number>;
7
8
  };
@@ -1,6 +1,7 @@
1
- import { default as useAnchor } from './useAnchor';
1
+ import { useAnchor } from './useAnchor';
2
2
  export declare const AnchorCore: {
3
3
  props: import('../../types/props').MCOPO<import('./props').AnchorProps>;
4
4
  anchorLinkProps: import('../../types/props').MCOPO<import('./props').AnchorLinkProps>;
5
5
  useAnchor: typeof useAnchor;
6
6
  };
7
+ export type { AnchorProps, AnchorLinkProps } from './props';
@@ -1,6 +1,6 @@
1
1
  import { AnchorProps } from './props';
2
- export default function useAnchor(props: Required<AnchorProps>, emit: (event: string, ...args: unknown[]) => void): {
3
- currentLink: any;
2
+ export declare function useAnchor(props: Required<AnchorProps>, emit: (...args: any[]) => void): {
3
+ currentLink: import('vue').Ref<string, string>;
4
4
  registerLink: (href: string) => void;
5
5
  unregisterLink: (href: string) => void;
6
6
  handleClick: (href: string) => void;
@@ -1,9 +1,17 @@
1
1
  import { AutoCompleteProps, AutoCompleteOption } from './props';
2
2
  export declare function useAutoComplete(props: AutoCompleteProps, ctx: any): {
3
- inputValue: any;
4
- isOpen: any;
5
- loading: any;
6
- suggestions: any;
3
+ inputValue: import('vue').Ref<string, string>;
4
+ isOpen: import('vue').Ref<boolean, boolean>;
5
+ loading: import('vue').Ref<boolean, boolean>;
6
+ suggestions: import('vue').Ref<{
7
+ [x: string]: unknown;
8
+ value: string;
9
+ label?: string | undefined;
10
+ }[], AutoCompleteOption[] | {
11
+ [x: string]: unknown;
12
+ value: string;
13
+ label?: string | undefined;
14
+ }[]>;
7
15
  onInput: (e: Event) => void;
8
16
  onFocus: (e: FocusEvent) => void;
9
17
  onBlur: (e: FocusEvent) => void;
@@ -1,3 +1,4 @@
1
1
  export declare const AvatarCore: {
2
2
  props: import('../../types/props').MCOPO<import('./props').AvatarProps>;
3
3
  };
4
+ export type { AvatarProps } from './props';
@@ -1,5 +1,6 @@
1
- import { default as useBackTop } from './useBackTop';
1
+ import { useBackTop } from './useBackTop';
2
2
  export declare const BackTopCore: {
3
3
  props: import('../../types/props').MCOPO<import('./props').BackTopProps>;
4
4
  useBackTop: typeof useBackTop;
5
5
  };
6
+ export type { BackTopProps } from './props';
@@ -1,5 +1,5 @@
1
1
  import { BackTopProps } from './props';
2
- export default function useBackTop(props: Required<BackTopProps>): {
3
- visible: any;
2
+ export declare function useBackTop(props: Required<BackTopProps>): {
3
+ visible: import('vue').Ref<boolean, boolean>;
4
4
  scrollToTop: () => void;
5
5
  };
@@ -1,24 +1,6 @@
1
+ import { useButton } from './useButton';
1
2
  export declare const ButtonCore: {
2
3
  props: import('../../types/props').MCOPO<import('./props').ButtonProps>;
3
- useButton: (props: import('./props').ButtonProps, ctx: SetupContext<E, S>) => {
4
- domType: string;
5
- slot: any;
6
- domProps: {
7
- class: (string | {
8
- 'm-button-disabled': boolean | undefined;
9
- 'm-button-loading'?: undefined;
10
- 'm-button-plain'?: undefined;
11
- } | {
12
- 'm-button-loading': boolean | undefined;
13
- 'm-button-disabled'?: undefined;
14
- 'm-button-plain'?: undefined;
15
- } | {
16
- 'm-button-plain': boolean | undefined;
17
- 'm-button-disabled'?: undefined;
18
- 'm-button-loading'?: undefined;
19
- })[];
20
- disabled: boolean | undefined;
21
- };
22
- isDisabled: boolean | undefined;
23
- };
4
+ useButton: typeof useButton;
24
5
  };
6
+ export type { ButtonProps } from './props';
@@ -1,7 +1,10 @@
1
+ import { SetupContext } from 'vue';
1
2
  import { ButtonProps } from './props';
2
- export declare const useButton: (props: ButtonProps, ctx: SetupContext<E, S>) => {
3
+ export declare function useButton(props: ButtonProps, { slots }: SetupContext): {
3
4
  domType: string;
4
- slot: any;
5
+ slot: string | import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
6
+ [key: string]: any;
7
+ }>[] | undefined;
5
8
  domProps: {
6
9
  class: (string | {
7
10
  'm-button-disabled': boolean | undefined;