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

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 (300) 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 +15 -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 +16 -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 +14 -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 +15 -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 +16 -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 +151 -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 +16 -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 +16 -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 +16 -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 +16 -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 +15 -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 +13 -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 +15 -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 +15 -0
  95. package/components/base/popover/props.d.ts +73 -0
  96. package/components/base/popover/usePopover.ts +188 -0
  97. package/components/base/progress/api.ts +18 -0
  98. package/components/base/progress/index.ts +15 -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 +15 -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 +15 -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 +17 -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 +13 -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 +230 -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 +19 -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 +18 -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 +18 -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 +82 -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/useAffix.d.ts +5 -4
  246. package/dist/components/base/anchor/useAnchor.d.ts +1 -1
  247. package/dist/components/base/autoComplete/useAutoComplete.d.ts +12 -4
  248. package/dist/components/base/backTop/useBackTop.d.ts +1 -1
  249. package/dist/components/base/button/index.d.ts +11 -2
  250. package/dist/components/base/button/useButton.d.ts +11 -2
  251. package/dist/components/base/carousel/useCarousel.d.ts +6 -3
  252. package/dist/components/base/cascader/useCascader.d.ts +23 -11
  253. package/dist/components/base/checkbox/useCheckbox.d.ts +4 -3
  254. package/dist/components/base/collapse/useCollapse.d.ts +2 -2
  255. package/dist/components/base/datePicker/useDatePicker.d.ts +140 -8
  256. package/dist/components/base/dropdown/useDropdown.d.ts +11 -5
  257. package/dist/components/base/image/useImage.d.ts +5 -5
  258. package/dist/components/base/input/useInput.d.ts +1 -2
  259. package/dist/components/base/inputNumber/useInputNumber.d.ts +2 -2
  260. package/dist/components/base/popover/usePopover.d.ts +8 -8
  261. package/dist/components/base/progress/useProgress.d.ts +1 -1
  262. package/dist/components/base/rate/useRate.d.ts +1 -1
  263. package/dist/components/base/select/useSelect.d.ts +8 -8
  264. package/dist/components/base/slider/useSlider.d.ts +3 -3
  265. package/dist/components/base/steps/index.d.ts +1 -1
  266. package/dist/components/base/steps/useSteps.d.ts +5 -5
  267. package/dist/components/base/switch/useSwitch.d.ts +8 -3
  268. package/dist/components/base/tabs/useTabs.d.ts +2 -2
  269. package/dist/components/base/timePicker/useTimePicker.d.ts +14 -6
  270. package/dist/components/base/tooltip/useTooltip.d.ts +14 -4
  271. package/dist/components/base/transfer/useTransfer.d.ts +15 -15
  272. package/dist/components/base/tree/index.d.ts +1 -1
  273. package/dist/components/base/tree/useTree.d.ts +2 -1
  274. package/dist/components/message/message/useMessage.d.ts +11 -1
  275. package/dist/components/message/notification/useNotification.d.ts +17 -1
  276. package/dist/components/message/popover/MPopover.d.ts +6 -1
  277. package/dist/components/message/popover/usePopover.d.ts +6 -6
  278. package/dist/components/other/darkMode/useDarkMode.d.ts +1 -1
  279. package/dist/components/template/menu/useMenu.d.ts +1 -0
  280. package/dist/components/template/virtualList/useVirtualList.d.ts +10 -7
  281. package/dist/compositions/common/useDrag.d.ts +1 -1
  282. package/dist/compositions/common/useElementSize.d.ts +2 -2
  283. package/dist/compositions/common/useTeleport.d.ts +4 -2
  284. package/dist/compositions/modal/useModal.d.ts +1 -1
  285. package/dist/core.js +6137 -4186
  286. package/dist/runtime/defineHook.d.ts +1 -1
  287. package/index.css +1 -0
  288. package/index.ts +71 -0
  289. package/package.json +19 -16
  290. package/runtime/defineHook.ts +21 -0
  291. package/tools/empty.ts +81 -0
  292. package/tools/index.ts +15 -0
  293. package/tools/types.ts +11 -0
  294. package/tsconfig.json +8 -0
  295. package/types/common/common.d.ts +25 -0
  296. package/types/common/model.d.ts +25 -0
  297. package/types/index.d.ts +11 -0
  298. package/types/props.d.ts +13 -0
  299. package/vite.config.build.ts +41 -0
  300. package/dist/vite.config.build.d.ts +0 -2
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @description menu props 类型定义
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+
10
+ /**
11
+ * 菜单数据项
12
+ */
13
+ export interface MenuData {
14
+ key: string | number;
15
+ label?: string;
16
+ value?: string | number;
17
+ children?: MenuData[];
18
+ disabled?: boolean;
19
+ [k: string]: unknown;
20
+ }
21
+
22
+ /**
23
+ * 菜单内部节点数据(带状态)
24
+ */
25
+ export interface MenuNodeData extends MenuData {
26
+ /** 是否展开 */
27
+ expand?: boolean;
28
+ /** 是否激活 */
29
+ isActive?: boolean;
30
+ /** 是否选中(checkbox 模式) */
31
+ checked?: boolean;
32
+ /** 半选状态 */
33
+ indeterminate?: boolean;
34
+ /** 子节点 */
35
+ children?: MenuNodeData[];
36
+ /** 父节点引用 */
37
+ parent?: MenuNodeData | null;
38
+ /** 是否根节点 */
39
+ isRoot?: boolean;
40
+ }
41
+
42
+ /**
43
+ * 菜单字段映射配置
44
+ */
45
+ export interface MenuConfig {
46
+ key: string;
47
+ label: string;
48
+ children: string;
49
+ }
50
+
51
+ export declare type MenuProps = {
52
+ /**
53
+ * @description 菜单数据
54
+ * @type MenuData[]
55
+ * @default []
56
+ */
57
+ data?: MenuData[];
58
+ /**
59
+ * @description 字段映射配置
60
+ * @type MenuConfig
61
+ * @default { key: 'key', label: 'label', children: 'children' }
62
+ */
63
+ config?: MenuConfig;
64
+ /**
65
+ * @description 是否使用 checkbox
66
+ * @type boolean
67
+ * @default false
68
+ */
69
+ checkbox?: boolean;
70
+ /**
71
+ * @description 默认展开所有节点
72
+ * @type boolean
73
+ * @default false
74
+ */
75
+ defaultExpandAll?: boolean;
76
+ /**
77
+ * @description 选中的 key 列表
78
+ * @type Array<string|number>
79
+ * @default []
80
+ */
81
+ checkedKeys?: Array<string | number>;
82
+ /**
83
+ * @description 菜单排列方向
84
+ * @type 'vertical' | 'horizontal'
85
+ * @default 'vertical'
86
+ */
87
+ mode?: 'vertical' | 'horizontal';
88
+ /**
89
+ * @description 当前激活的菜单项 key(v-model:active)
90
+ * @type string | number
91
+ */
92
+ active?: string | number;
93
+ };
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @description menu 核心 composable,内建简化版树数据管理
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ import { shallowRef, triggerRef, ShallowRef } from 'vue';
10
+ import { MenuData, MenuNodeData, MenuConfig, MenuProps } from './props';
11
+
12
+ const DEFAULT_CONFIG: MenuConfig = { key: 'key', label: 'label', children: 'children' };
13
+
14
+ /**
15
+ * 递归构建节点树,附加状态属性
16
+ */
17
+ function buildNodes(
18
+ data: MenuData[],
19
+ config: MenuConfig,
20
+ nodeMap: Map<string | number, MenuNodeData>,
21
+ defaultExpandAll: boolean = false,
22
+ parent: MenuNodeData | null,
23
+ ): MenuNodeData[] {
24
+ return data.map(item => {
25
+ const key = item[config.key] as string | number;
26
+ const childrenKey = config.children;
27
+ const node: MenuNodeData = {
28
+ ...item,
29
+ expand: defaultExpandAll,
30
+ isActive: false,
31
+ checked: false,
32
+ indeterminate: false,
33
+ parent,
34
+ isRoot: !parent,
35
+ };
36
+ nodeMap.set(key, node);
37
+
38
+ const rawChildren = item[childrenKey];
39
+ if (Array.isArray(rawChildren) && rawChildren.length > 0) {
40
+ node.children = buildNodes(
41
+ rawChildren as MenuData[],
42
+ config,
43
+ nodeMap,
44
+ defaultExpandAll,
45
+ node,
46
+ );
47
+ }
48
+
49
+ return node;
50
+ });
51
+ }
52
+
53
+ export function useMenu(props: MenuProps, emit?: (event: string, ...args: unknown[]) => void) {
54
+ const config: MenuConfig = { ...DEFAULT_CONFIG, ...props.config };
55
+ const nodeMap = new Map<string | number, MenuNodeData>();
56
+ const nodesRef: ShallowRef<MenuNodeData[]> = shallowRef([]);
57
+
58
+ /**
59
+ * 将原始 MenuData[] 转换为带状态的 MenuNodeData[]
60
+ * 供初始化或 data prop 变更时调用
61
+ */
62
+ const initNodes = (data: MenuData[] = []) => {
63
+ nodeMap.clear();
64
+ nodesRef.value = buildNodes(data, config, nodeMap, props.defaultExpandAll ?? false, null);
65
+
66
+ // 处理外部传入的 checkedKeys
67
+ if (props.checkedKeys?.length) {
68
+ props.checkedKeys.forEach(key => {
69
+ const node = nodeMap.get(key);
70
+ if (node) {
71
+ node.checked = true;
72
+ }
73
+ });
74
+ }
75
+
76
+ triggerRef(nodesRef);
77
+ };
78
+
79
+ // 首次初始化
80
+ initNodes(props.data ?? []);
81
+
82
+ // 受控模式:根据外部 active prop 初始化激活状态
83
+ if (props.active !== undefined) {
84
+ const activeNode = nodeMap.get(props.active);
85
+ if (activeNode) {
86
+ activeNode.isActive = true;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * 切换节点展开/收起状态
92
+ */
93
+ const toggleExpand = (node: MenuNodeData) => {
94
+ node.expand = !node.expand;
95
+ triggerRef(nodesRef);
96
+ };
97
+
98
+ /**
99
+ * 设置节点为激活状态,同时取消其他节点的激活,并触发 update:active
100
+ */
101
+ const setActive = (node: MenuNodeData) => {
102
+ nodeMap.forEach(n => {
103
+ n.isActive = false;
104
+ });
105
+ node.isActive = true;
106
+ triggerRef(nodesRef);
107
+ if (emit) {
108
+ const key = node[config.key] as string | number;
109
+ emit('update:active', key);
110
+ }
111
+ };
112
+
113
+ /**
114
+ * 切换 checkbox 选中状态
115
+ */
116
+ const toggleChecked = (node: MenuNodeData, checked: boolean) => {
117
+ node.checked = checked;
118
+ node.indeterminate = false;
119
+ triggerRef(nodesRef);
120
+ };
121
+
122
+ /**
123
+ * 获取当前所有选中节点的 key 列表
124
+ */
125
+ const getCheckedKeys = (): (string | number)[] => {
126
+ const keys: (string | number)[] = [];
127
+ nodeMap.forEach((node, key) => {
128
+ if (node.checked && !node.indeterminate) {
129
+ keys.push(key);
130
+ }
131
+ });
132
+ return keys;
133
+ };
134
+
135
+ /**
136
+ * 根据 key 列表批量获取节点
137
+ */
138
+ const getNodesByKeys = (keys: (string | number)[]): MenuNodeData[] => {
139
+ return keys
140
+ .map(key => nodeMap.get(key))
141
+ .filter((n): n is MenuNodeData => n !== undefined);
142
+ };
143
+
144
+ return {
145
+ nodesRef,
146
+ nodeMap,
147
+ initNodes,
148
+ toggleExpand,
149
+ setActive,
150
+ toggleChecked,
151
+ getCheckedKeys,
152
+ getNodesByKeys,
153
+ config,
154
+ };
155
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @description pagination 运行时 props
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ import { MCOPO } from '../../types/props';
10
+ import { PaginationProps } from './props';
11
+
12
+ export const props: MCOPO<PaginationProps> = {
13
+ total: { type: Number, default: 0 },
14
+ modelValue: { type: Number, default: undefined },
15
+ defaultCurrent: { type: Number, default: 1 },
16
+ pageSize: { type: Number, default: 10 },
17
+ pageSizes: { type: Array, default: () => [10, 20, 30, 40, 50, 100] },
18
+ layout: { type: String, default: 'prev, pager, next, total' },
19
+ foldedMaxPageBtn: { type: Number, default: 5 },
20
+ maxPageBtn: { type: Number, default: 10 },
21
+ showEdgePageNum: { type: Boolean, default: true },
22
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @description pagination core 导出
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ import { props } from './api';
10
+ import { usePagination } from './usePagination';
11
+
12
+ export const PaginationCore = {
13
+ props,
14
+ usePagination,
15
+ };
16
+
17
+ export type { PaginationProps } from './props';
18
+ export { usePagination, type Pager } from './usePagination';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @description pagination props 类型定义
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+
10
+ export declare type PaginationProps = {
11
+ /**
12
+ * @description 分页总条数
13
+ * @type number
14
+ * @default 0
15
+ */
16
+ total?: number;
17
+ /**
18
+ * @description 当前页(受控)
19
+ * @type number
20
+ * @default undefined
21
+ */
22
+ modelValue?: number;
23
+ /**
24
+ * @description 默认当前页(非受控初始值)
25
+ * @type number
26
+ * @default 1
27
+ */
28
+ defaultCurrent?: number;
29
+ /**
30
+ * @description 每页数量
31
+ * @type number
32
+ * @default 10
33
+ */
34
+ pageSize?: number;
35
+ /**
36
+ * @description 可选每页数量列表
37
+ * @type number[]
38
+ * @default [10, 20, 30, 40, 50, 100]
39
+ */
40
+ pageSizes?: number[];
41
+ /**
42
+ * @description 组件布局,逗号分隔,可选值:prev, pager, next, total
43
+ * @type string
44
+ * @default 'prev, pager, next, total'
45
+ */
46
+ layout?: string;
47
+ /**
48
+ * @description 折叠时最多显示的页码按钮数(必须为奇数,偶数自动 +1)
49
+ * @type number | null
50
+ * @default 5
51
+ */
52
+ foldedMaxPageBtn?: number | null;
53
+ /**
54
+ * @description 不折叠时最大显示页数,超过后启用折叠逻辑
55
+ * @type number | null
56
+ * @default 10
57
+ */
58
+ maxPageBtn?: number | null;
59
+ /**
60
+ * @description 是否显示首尾边缘页码
61
+ * @type boolean
62
+ * @default true
63
+ */
64
+ showEdgePageNum?: boolean;
65
+ };
@@ -0,0 +1,186 @@
1
+ /**
2
+ * @description pagination 核心逻辑(分页按钮列表计算)
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ import { Ref } from 'vue';
10
+ import { PaginationProps } from './props';
11
+
12
+
13
+ /**
14
+ * 由于靠近按钮时需要优雅的交互,按钮需要对称渲染,因此折叠区域数量必须为奇数
15
+ */
16
+ const oddNum = (num: number) => {
17
+ return num % 2 === 0 ? num + 1 : num;
18
+ };
19
+
20
+ /**
21
+ * 页码按钮描述类型
22
+ * - type 为 'number' 时表示普通页码按钮
23
+ * - type 为 'folded' 时表示折叠省略号,jump 为点击后跳转的目标页
24
+ */
25
+ export type Pager = {
26
+ value: number;
27
+ type: 'number';
28
+ isCurrent: boolean;
29
+ jump?: number;
30
+ } | {
31
+ value: string;
32
+ type: 'folded';
33
+ isCurrent: false;
34
+ jump: number;
35
+ };
36
+
37
+ /**
38
+ * 分页核心 hook
39
+ * @param props 分页组件 props(需包含 total / pageSize / foldedMaxPageBtn / maxPageBtn / showEdgePageNum)
40
+ * @param currentValue 当前页的响应式引用,由调用方维护
41
+ */
42
+ export function usePagination(props: PaginationProps, currentValue: Ref<number>) {
43
+ /**
44
+ * 计算总页数
45
+ */
46
+ const getPageBtnLength = () => {
47
+ const total = props.total ?? 0;
48
+ const pageSize = props.pageSize ?? 10;
49
+ return Math.ceil(total / pageSize);
50
+ };
51
+
52
+ /**
53
+ * 构造普通页码 Pager 对象
54
+ */
55
+ const toPager = (value: number | string, config?: Partial<Omit<Pager, 'value'>>): Pager => {
56
+ return {
57
+ value,
58
+ type: config?.type ?? 'number',
59
+ isCurrent: currentValue.value === value,
60
+ jump: config?.jump ?? (value as number),
61
+ } as Pager;
62
+ };
63
+
64
+ /**
65
+ * 构造折叠省略号 Pager 对象
66
+ */
67
+ const toFoldedPager = (jump: number): Pager => {
68
+ return toPager('...', { type: 'folded', jump });
69
+ };
70
+
71
+ /**
72
+ * 生成从 start 开始、长度为 length 的连续页码列表
73
+ */
74
+ const getPageNumListRange = (start: number, length: number): Pager[] => {
75
+ return Array.from({ length }, (_, i) => toPager(i + start));
76
+ };
77
+
78
+ /**
79
+ * 生成完整的页码按钮列表,包含折叠逻辑
80
+ *
81
+ * 折叠规则:
82
+ * - 总页数 ≤ 1 页时:直接返回 [1]
83
+ * - 总页数 ≤ maxPageBtn 或 foldedMaxPageBtn ≥ 总页数-1 时:不折叠,显示全部
84
+ * - 当前页靠近左边缘:左侧全显 + 右侧折叠
85
+ * - 当前页靠近右边缘:左侧折叠 + 右侧全显
86
+ * - 当前页居中:两侧折叠
87
+ */
88
+ const getPageNumList = (): Pager[] => {
89
+ const pageBtnLength = getPageBtnLength();
90
+ const total = props.total ?? 0;
91
+ const pageSize = props.pageSize ?? 10;
92
+ const foldedMaxPageBtn = props.foldedMaxPageBtn ?? 5;
93
+ const maxPageBtn = props.maxPageBtn ?? 10;
94
+ const showEdgePageNum = props.showEdgePageNum ?? true;
95
+
96
+ // 只有一页时无需完整分页列表
97
+ if (total <= pageSize) {
98
+ return [toPager(1)];
99
+ }
100
+
101
+ // 总页数未超过 maxPageBtn,或 foldedMaxPageBtn 已足够覆盖大部分页数时不折叠
102
+ // eslint-disable-next-line @stylistic/no-mixed-operators
103
+ if (!maxPageBtn || pageBtnLength <= maxPageBtn || foldedMaxPageBtn && foldedMaxPageBtn >= pageBtnLength - 1) {
104
+ return getPageNumListRange(1, pageBtnLength);
105
+ }
106
+
107
+ // 折叠区域页码数必须为奇数,保证两侧对称
108
+ const foldedMaxPageBtnOdd = Math.max(oddNum(foldedMaxPageBtn ?? 5), 1);
109
+
110
+ const edgeConfig = {
111
+ // showEdgePageNum 时首尾各占 1 个槽位
112
+ length: showEdgePageNum ? 1 : 0,
113
+ // 右侧起始位置的偏移修正
114
+ rightStartSub: showEdgePageNum ? 0 : 1,
115
+ };
116
+
117
+ // 折叠区去掉首尾边缘页码后,剩余的中间页码数
118
+ const btnNumWithoutEdge = foldedMaxPageBtnOdd - (showEdgePageNum ? 2 : 0);
119
+ // 当前页两侧各显示的页码数
120
+ const pageEdge = (btnNumWithoutEdge - 1) / 2;
121
+
122
+ // 当前页 ≤ leftEdgeNum 时认为靠左,右侧折叠
123
+ const leftEdgeNum = pageEdge + 2;
124
+ // 当前页 ≥ rightEdgeNum 时认为靠右,左侧折叠
125
+ const rightEdgeNum = pageBtnLength - pageEdge - 1;
126
+ // 靠右时右侧连续区域的起始页
127
+ const rightStart = pageBtnLength - foldedMaxPageBtnOdd + 2 - edgeConfig.rightStartSub;
128
+
129
+ // ---- 靠左:左侧全显 + 右侧折叠 ----
130
+ if (currentValue.value <= leftEdgeNum) {
131
+ const numLength = foldedMaxPageBtnOdd - edgeConfig.length;
132
+ const res: Pager[] = [
133
+ ...getPageNumListRange(1, numLength),
134
+ toFoldedPager(1 + numLength),
135
+ ];
136
+ if (showEdgePageNum) {
137
+ res.push(toPager(pageBtnLength));
138
+ }
139
+ return res;
140
+ }
141
+
142
+ // ---- 靠右:左侧折叠 + 右侧全显 ----
143
+ if (currentValue.value >= rightEdgeNum) {
144
+ const res: Pager[] = [];
145
+ if (showEdgePageNum) {
146
+ res.push(toPager(1));
147
+ }
148
+ res.push(toFoldedPager(rightStart - 1), ...getPageNumListRange(rightStart, foldedMaxPageBtnOdd - edgeConfig.length));
149
+ return res;
150
+ }
151
+
152
+ // ---- 居中:两侧折叠 ----
153
+ const leftStart = currentValue.value - pageEdge;
154
+ const rightEnd = currentValue.value + pageEdge;
155
+
156
+ // 左侧折叠符:距离边缘超过 2 格时用省略号,否则直接显示相邻页码
157
+ const leftFolded = Math.abs(leftStart - 1) > 2 || !showEdgePageNum
158
+ ? toFoldedPager(leftStart - 1)
159
+ : toPager(showEdgePageNum ? 2 : 1);
160
+
161
+ // 右侧折叠符:同理
162
+ const rightFolded = Math.abs(rightEnd - pageBtnLength) > 2 || !showEdgePageNum
163
+ ? toFoldedPager(rightEnd + 1)
164
+ : toPager(showEdgePageNum ? pageBtnLength - 1 : pageBtnLength);
165
+
166
+ const res: Pager[] = [];
167
+ if (showEdgePageNum) {
168
+ res.push(toPager(1));
169
+ }
170
+ res.push(
171
+ leftFolded,
172
+ ...getPageNumListRange(leftStart, foldedMaxPageBtnOdd - edgeConfig.length * 2),
173
+ rightFolded,
174
+ );
175
+ if (showEdgePageNum) {
176
+ res.push(toPager(pageBtnLength));
177
+ }
178
+
179
+ return res;
180
+ };
181
+
182
+ return {
183
+ getPageNumList,
184
+ getPageBtnLength,
185
+ };
186
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @description table api
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ import { MCOPO } from '../../types/props';
10
+ import { TableProps } from './props';
11
+
12
+
13
+ export const props: MCOPO<TableProps> = {
14
+ data: { type: Array, default: () => [] },
15
+ height: { type: String, default: null },
16
+ paramClass: { type: Boolean, default: false },
17
+ loading: { type: Boolean, default: false },
18
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @description table core 导出
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+ import { props } from './api';
10
+ import { useTable } from './useTable';
11
+
12
+ export const TableCore = {
13
+ props,
14
+ useTable,
15
+ };
16
+
17
+ export type { TableProps } from './props';
18
+ export { useTable } from './useTable';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @description table 组件类型定义
3
+ * @author 阿怪
4
+ * @date 2026/2/25
5
+ * @version v1.0.0
6
+ *
7
+ * 江湖的业务千篇一律,复杂的代码好几百行。
8
+ */
9
+
10
+ export declare type TableProps = {
11
+ /**
12
+ * @description table data
13
+ * 表格内容
14
+ * @type any[]
15
+ */
16
+ data?: Array<any>,
17
+ /**
18
+ * @description table height
19
+ * 表格高度
20
+ * @type string
21
+ */
22
+ height?: string | null,
23
+ /**
24
+ * @description auto add param class
25
+ * 自动添加key class
26
+ * @type boolean
27
+ * @default false
28
+ */
29
+ paramClass?: boolean,
30
+ /**
31
+ * @description 加载中状态,显示覆盖层
32
+ * @type boolean
33
+ * @default false
34
+ */
35
+ loading?: boolean
36
+ };