taro-uno-ui 0.9.0-beta

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 (397) hide show
  1. package/LICENSE +100 -0
  2. package/README.md +273 -0
  3. package/dist/js/index-6NJ3A1Dn.js +26535 -0
  4. package/dist/js/index-6NJ3A1Dn.js.map +1 -0
  5. package/dist/js/index-DFdcksbe.js +1165 -0
  6. package/dist/js/index-DFdcksbe.js.map +1 -0
  7. package/dist/js/index-DXRIkWX1.js +1148 -0
  8. package/dist/js/index-DXRIkWX1.js.map +1 -0
  9. package/dist/js/index-DffLRSro.js +26519 -0
  10. package/dist/js/index-DffLRSro.js.map +1 -0
  11. package/package.json +119 -0
  12. package/src/app.config.ts +55 -0
  13. package/src/app.scss +508 -0
  14. package/src/app.tsx +44 -0
  15. package/src/components/basic/Button/Button.styles.ts +130 -0
  16. package/src/components/basic/Button/Button.test.tsx +154 -0
  17. package/src/components/basic/Button/Button.tsx +93 -0
  18. package/src/components/basic/Button/Button.types.ts +45 -0
  19. package/src/components/basic/Button/index.tsx +6 -0
  20. package/src/components/basic/Divider/Divider.styles.ts +488 -0
  21. package/src/components/basic/Divider/Divider.test.tsx +551 -0
  22. package/src/components/basic/Divider/Divider.tsx +361 -0
  23. package/src/components/basic/Divider/Divider.types.ts +261 -0
  24. package/src/components/basic/Divider/index.tsx +25 -0
  25. package/src/components/basic/Icon/Icon.styles.ts +359 -0
  26. package/src/components/basic/Icon/Icon.test.tsx +357 -0
  27. package/src/components/basic/Icon/Icon.tsx +154 -0
  28. package/src/components/basic/Icon/Icon.types.ts +210 -0
  29. package/src/components/basic/Icon/index.tsx +22 -0
  30. package/src/components/basic/Text/Text.styles.ts +500 -0
  31. package/src/components/basic/Text/Text.test.tsx +299 -0
  32. package/src/components/basic/Text/Text.tsx +340 -0
  33. package/src/components/basic/Text/Text.types.ts +319 -0
  34. package/src/components/basic/Text/index.tsx +27 -0
  35. package/src/components/basic/Typography/Typography.styles.ts +346 -0
  36. package/src/components/basic/Typography/Typography.tsx +205 -0
  37. package/src/components/basic/Typography/Typography.types.ts +296 -0
  38. package/src/components/basic/Typography/index.tsx +14 -0
  39. package/src/components/basic/index.tsx +302 -0
  40. package/src/components/common/ErrorBoundary.tsx +87 -0
  41. package/src/components/common/LazyComponent.tsx +246 -0
  42. package/src/components/common/ResponsiveContainer.tsx +93 -0
  43. package/src/components/common/ResponsiveGrid.tsx +183 -0
  44. package/src/components/common/SecurityProvider.tsx +110 -0
  45. package/src/components/common/ThemeProvider.tsx +128 -0
  46. package/src/components/common/VirtualList.tsx +368 -0
  47. package/src/components/common/__tests__/ErrorBoundary.test.tsx +249 -0
  48. package/src/components/common/index.tsx +7 -0
  49. package/src/components/display/Avatar/Avatar.styles.ts +62 -0
  50. package/src/components/display/Avatar/Avatar.test.tsx +390 -0
  51. package/src/components/display/Avatar/Avatar.tsx +79 -0
  52. package/src/components/display/Avatar/Avatar.types.ts +40 -0
  53. package/src/components/display/Avatar/index.ts +3 -0
  54. package/src/components/display/Badge/Badge.tsx +42 -0
  55. package/src/components/display/Badge/Badge.types.ts +29 -0
  56. package/src/components/display/Badge/index.ts +2 -0
  57. package/src/components/display/Calendar/Calendar.styles.ts +255 -0
  58. package/src/components/display/Calendar/Calendar.test.tsx +30 -0
  59. package/src/components/display/Calendar/Calendar.tsx +337 -0
  60. package/src/components/display/Calendar/Calendar.types.ts +91 -0
  61. package/src/components/display/Calendar/index.ts +3 -0
  62. package/src/components/display/Card/Card.styles.ts +89 -0
  63. package/src/components/display/Card/Card.test.tsx +180 -0
  64. package/src/components/display/Card/Card.tsx +135 -0
  65. package/src/components/display/Card/Card.types.ts +55 -0
  66. package/src/components/display/Card/index.ts +3 -0
  67. package/src/components/display/Carousel/Carousel.styles.ts +206 -0
  68. package/src/components/display/Carousel/Carousel.tsx +295 -0
  69. package/src/components/display/Carousel/Carousel.types.ts +57 -0
  70. package/src/components/display/Carousel/index.ts +3 -0
  71. package/src/components/display/List/List.styles.ts +79 -0
  72. package/src/components/display/List/List.tsx +115 -0
  73. package/src/components/display/List/List.types.ts +68 -0
  74. package/src/components/display/List/index.ts +3 -0
  75. package/src/components/display/Rate/Rate.styles.ts +266 -0
  76. package/src/components/display/Rate/Rate.tsx +332 -0
  77. package/src/components/display/Rate/Rate.types.ts +111 -0
  78. package/src/components/display/Rate/index.ts +28 -0
  79. package/src/components/display/Table/Table.styles.ts +269 -0
  80. package/src/components/display/Table/Table.test.tsx +343 -0
  81. package/src/components/display/Table/Table.tsx +430 -0
  82. package/src/components/display/Table/Table.types.ts +255 -0
  83. package/src/components/display/Table/index.tsx +16 -0
  84. package/src/components/display/Tag/Tag.styles.ts +197 -0
  85. package/src/components/display/Tag/Tag.test.tsx +541 -0
  86. package/src/components/display/Tag/Tag.tsx +156 -0
  87. package/src/components/display/Tag/Tag.types.ts +49 -0
  88. package/src/components/display/Tag/index.ts +3 -0
  89. package/src/components/display/Timeline/Timeline.styles.ts +211 -0
  90. package/src/components/display/Timeline/Timeline.tsx +239 -0
  91. package/src/components/display/Timeline/Timeline.types.ts +56 -0
  92. package/src/components/display/Timeline/index.ts +3 -0
  93. package/src/components/display/index.tsx +143 -0
  94. package/src/components/feedback/Loading/Loading.styles.ts +117 -0
  95. package/src/components/feedback/Loading/Loading.test.tsx +534 -0
  96. package/src/components/feedback/Loading/Loading.tsx +127 -0
  97. package/src/components/feedback/Loading/Loading.types.ts +33 -0
  98. package/src/components/feedback/Loading/index.ts +9 -0
  99. package/src/components/feedback/Message/Message.styles.ts +41 -0
  100. package/src/components/feedback/Message/Message.test.tsx +234 -0
  101. package/src/components/feedback/Message/Message.tsx +96 -0
  102. package/src/components/feedback/Message/Message.types.ts +37 -0
  103. package/src/components/feedback/Message/index.ts +9 -0
  104. package/src/components/feedback/Modal/Modal.styles.ts +21 -0
  105. package/src/components/feedback/Modal/Modal.test.tsx +11 -0
  106. package/src/components/feedback/Modal/Modal.tsx +291 -0
  107. package/src/components/feedback/Modal/Modal.types.ts +141 -0
  108. package/src/components/feedback/Modal/index.tsx +11 -0
  109. package/src/components/feedback/Notification/Notification.styles.ts +443 -0
  110. package/src/components/feedback/Notification/Notification.test.tsx +401 -0
  111. package/src/components/feedback/Notification/Notification.tsx +370 -0
  112. package/src/components/feedback/Notification/Notification.types.ts +336 -0
  113. package/src/components/feedback/Notification/NotificationManager.tsx +376 -0
  114. package/src/components/feedback/Notification/index.ts +33 -0
  115. package/src/components/feedback/Notification/index.tsx +164 -0
  116. package/src/components/feedback/Progress/Progress.styles.ts +460 -0
  117. package/src/components/feedback/Progress/Progress.test.simple.tsx +14 -0
  118. package/src/components/feedback/Progress/Progress.test.tsx +312 -0
  119. package/src/components/feedback/Progress/Progress.tsx +508 -0
  120. package/src/components/feedback/Progress/Progress.types.ts +163 -0
  121. package/src/components/feedback/Progress/index.ts +3 -0
  122. package/src/components/feedback/Progress/index.tsx +38 -0
  123. package/src/components/feedback/Progress/utils/animation.ts +204 -0
  124. package/src/components/feedback/Progress/utils/index.ts +26 -0
  125. package/src/components/feedback/Progress/utils/progress-calculator.ts +217 -0
  126. package/src/components/feedback/Result/Result.styles.ts +139 -0
  127. package/src/components/feedback/Result/Result.tsx +233 -0
  128. package/src/components/feedback/Result/Result.types.ts +128 -0
  129. package/src/components/feedback/Result/index.tsx +3 -0
  130. package/src/components/feedback/Toast/Toast.styles.ts +17 -0
  131. package/src/components/feedback/Toast/Toast.test.tsx +10 -0
  132. package/src/components/feedback/Toast/Toast.tsx +372 -0
  133. package/src/components/feedback/Toast/Toast.types.ts +86 -0
  134. package/src/components/feedback/Toast/index.tsx +3 -0
  135. package/src/components/feedback/Tooltip/Tooltip.examples.tsx +458 -0
  136. package/src/components/feedback/Tooltip/Tooltip.styles.ts +346 -0
  137. package/src/components/feedback/Tooltip/Tooltip.test.tsx +446 -0
  138. package/src/components/feedback/Tooltip/Tooltip.tsx +283 -0
  139. package/src/components/feedback/Tooltip/Tooltip.types.ts +172 -0
  140. package/src/components/feedback/Tooltip/index.ts +3 -0
  141. package/src/components/feedback/Tooltip/index.tsx +258 -0
  142. package/src/components/feedback/index.tsx +164 -0
  143. package/src/components/form/Cascader/Cascader.styles.ts +526 -0
  144. package/src/components/form/Cascader/Cascader.test.tsx +77 -0
  145. package/src/components/form/Cascader/Cascader.tsx +585 -0
  146. package/src/components/form/Cascader/Cascader.types.ts +582 -0
  147. package/src/components/form/Cascader/hooks/index.ts +3 -0
  148. package/src/components/form/Cascader/hooks/useCascaderFieldNames.ts +16 -0
  149. package/src/components/form/Cascader/hooks/useCascaderOptions.ts +109 -0
  150. package/src/components/form/Cascader/hooks/useCascaderState.ts +133 -0
  151. package/src/components/form/Cascader/index.ts +25 -0
  152. package/src/components/form/Cascader/utils/formatDisplayValue.ts +19 -0
  153. package/src/components/form/Cascader/utils/index.ts +1 -0
  154. package/src/components/form/Checkbox/Checkbox.styles.ts +608 -0
  155. package/src/components/form/Checkbox/Checkbox.test.tsx +1140 -0
  156. package/src/components/form/Checkbox/Checkbox.tsx +496 -0
  157. package/src/components/form/Checkbox/Checkbox.types.ts +472 -0
  158. package/src/components/form/Checkbox/CheckboxGroup.tsx +444 -0
  159. package/src/components/form/Checkbox/index.tsx +27 -0
  160. package/src/components/form/DatePicker/DatePicker.styles.ts +393 -0
  161. package/src/components/form/DatePicker/DatePicker.test.tsx +407 -0
  162. package/src/components/form/DatePicker/DatePicker.tsx +360 -0
  163. package/src/components/form/DatePicker/DatePicker.types.ts +247 -0
  164. package/src/components/form/DatePicker/index.tsx +15 -0
  165. package/src/components/form/Form/Form.styles.ts +357 -0
  166. package/src/components/form/Form/Form.test.tsx +122 -0
  167. package/src/components/form/Form/Form.tsx +695 -0
  168. package/src/components/form/Form/Form.types.ts +407 -0
  169. package/src/components/form/Form/index.tsx +31 -0
  170. package/src/components/form/Input/Input.enhanced.tsx +732 -0
  171. package/src/components/form/Input/Input.styles.ts +438 -0
  172. package/src/components/form/Input/Input.test.tsx +494 -0
  173. package/src/components/form/Input/Input.tsx +541 -0
  174. package/src/components/form/Input/Input.types.ts +285 -0
  175. package/src/components/form/Input/index.tsx +26 -0
  176. package/src/components/form/InputNumber/InputNumber.styles.ts +665 -0
  177. package/src/components/form/InputNumber/InputNumber.tsx +370 -0
  178. package/src/components/form/InputNumber/InputNumber.types.ts +318 -0
  179. package/src/components/form/InputNumber/components/InputNumberClearButton.tsx +32 -0
  180. package/src/components/form/InputNumber/components/InputNumberControls.tsx +42 -0
  181. package/src/components/form/InputNumber/components/index.ts +2 -0
  182. package/src/components/form/InputNumber/hooks/index.ts +4 -0
  183. package/src/components/form/InputNumber/hooks/useInputNumberState.ts +315 -0
  184. package/src/components/form/InputNumber/hooks/useInputNumberValidation.ts +147 -0
  185. package/src/components/form/InputNumber/index.ts +25 -0
  186. package/src/components/form/Radio/Radio.styles.ts +458 -0
  187. package/src/components/form/Radio/Radio.test.tsx +547 -0
  188. package/src/components/form/Radio/Radio.tsx +283 -0
  189. package/src/components/form/Radio/Radio.types.ts +410 -0
  190. package/src/components/form/Radio/index.tsx +21 -0
  191. package/src/components/form/Select/Select.styles.ts +514 -0
  192. package/src/components/form/Select/Select.test.tsx +648 -0
  193. package/src/components/form/Select/Select.tsx +474 -0
  194. package/src/components/form/Select/Select.types.ts +428 -0
  195. package/src/components/form/Select/index.tsx +30 -0
  196. package/src/components/form/Slider/Slider.styles.ts +139 -0
  197. package/src/components/form/Slider/Slider.test.tsx +553 -0
  198. package/src/components/form/Slider/Slider.tsx +326 -0
  199. package/src/components/form/Slider/Slider.types.ts +108 -0
  200. package/src/components/form/Slider/index.tsx +10 -0
  201. package/src/components/form/Switch/Switch.styles.ts +540 -0
  202. package/src/components/form/Switch/Switch.test.tsx +345 -0
  203. package/src/components/form/Switch/Switch.tsx +464 -0
  204. package/src/components/form/Switch/Switch.types.ts +386 -0
  205. package/src/components/form/Switch/index.tsx +26 -0
  206. package/src/components/form/Textarea/Textarea.styles.ts +592 -0
  207. package/src/components/form/Textarea/Textarea.test.tsx +1075 -0
  208. package/src/components/form/Textarea/Textarea.tsx +602 -0
  209. package/src/components/form/Textarea/Textarea.types.ts +371 -0
  210. package/src/components/form/Textarea/index.tsx +26 -0
  211. package/src/components/form/TimePicker/TimePicker.styles.ts +438 -0
  212. package/src/components/form/TimePicker/TimePicker.test.tsx +306 -0
  213. package/src/components/form/TimePicker/TimePicker.tsx +228 -0
  214. package/src/components/form/TimePicker/TimePicker.types.ts +385 -0
  215. package/src/components/form/TimePicker/index.ts +21 -0
  216. package/src/components/form/Transfer/Transfer.styles.ts +502 -0
  217. package/src/components/form/Transfer/Transfer.test.tsx +316 -0
  218. package/src/components/form/Transfer/Transfer.tsx +402 -0
  219. package/src/components/form/Transfer/Transfer.types.ts +557 -0
  220. package/src/components/form/Transfer/components/TransferItem.tsx +101 -0
  221. package/src/components/form/Transfer/components/TransferList.tsx +285 -0
  222. package/src/components/form/Transfer/components/TransferOperations.tsx +84 -0
  223. package/src/components/form/Transfer/components/TransferPagination.tsx +135 -0
  224. package/src/components/form/Transfer/components/TransferSearch.tsx +88 -0
  225. package/src/components/form/Transfer/components/index.ts +6 -0
  226. package/src/components/form/Transfer/hooks/index.ts +3 -0
  227. package/src/components/form/Transfer/hooks/useTransferData.ts +192 -0
  228. package/src/components/form/Transfer/hooks/useTransferState.ts +114 -0
  229. package/src/components/form/Transfer/index.ts +33 -0
  230. package/src/components/form/Upload/Upload.styles.ts +145 -0
  231. package/src/components/form/Upload/Upload.test.tsx +10 -0
  232. package/src/components/form/Upload/Upload.tsx +451 -0
  233. package/src/components/form/Upload/Upload.types.ts +200 -0
  234. package/src/components/form/Upload/index.tsx +12 -0
  235. package/src/components/form/index.tsx +121 -0
  236. package/src/components/index.tsx +146 -0
  237. package/src/components/layout/Affix/Affix.styles.ts +37 -0
  238. package/src/components/layout/Affix/Affix.test.tsx +10 -0
  239. package/src/components/layout/Affix/Affix.tsx +91 -0
  240. package/src/components/layout/Affix/Affix.types.ts +29 -0
  241. package/src/components/layout/Affix/index.tsx +3 -0
  242. package/src/components/layout/Col/Col.styles.ts +185 -0
  243. package/src/components/layout/Col/Col.test.tsx +535 -0
  244. package/src/components/layout/Col/Col.tsx +115 -0
  245. package/src/components/layout/Col/Col.types.ts +59 -0
  246. package/src/components/layout/Col/index.tsx +3 -0
  247. package/src/components/layout/Container/Container.styles.ts +161 -0
  248. package/src/components/layout/Container/Container.test.tsx +380 -0
  249. package/src/components/layout/Container/Container.tsx +132 -0
  250. package/src/components/layout/Container/Container.types.ts +63 -0
  251. package/src/components/layout/Container/index.tsx +3 -0
  252. package/src/components/layout/Grid/Grid.styles.ts +183 -0
  253. package/src/components/layout/Grid/Grid.test.tsx +637 -0
  254. package/src/components/layout/Grid/Grid.tsx +173 -0
  255. package/src/components/layout/Grid/Grid.types.ts +78 -0
  256. package/src/components/layout/Grid/index.tsx +3 -0
  257. package/src/components/layout/Layout/Content.tsx +38 -0
  258. package/src/components/layout/Layout/Footer.tsx +38 -0
  259. package/src/components/layout/Layout/Header.tsx +38 -0
  260. package/src/components/layout/Layout/Layout.styles.ts +84 -0
  261. package/src/components/layout/Layout/Layout.test.tsx +10 -0
  262. package/src/components/layout/Layout/Layout.tsx +39 -0
  263. package/src/components/layout/Layout/Layout.types.ts +58 -0
  264. package/src/components/layout/Layout/Sider.tsx +56 -0
  265. package/src/components/layout/Layout/index.tsx +8 -0
  266. package/src/components/layout/Row/Row.styles.ts +159 -0
  267. package/src/components/layout/Row/Row.test.tsx +467 -0
  268. package/src/components/layout/Row/Row.tsx +139 -0
  269. package/src/components/layout/Row/Row.types.ts +60 -0
  270. package/src/components/layout/Row/index.tsx +3 -0
  271. package/src/components/layout/Space/Space.styles.ts +255 -0
  272. package/src/components/layout/Space/Space.test.tsx +682 -0
  273. package/src/components/layout/Space/Space.tsx +211 -0
  274. package/src/components/layout/Space/Space.types.ts +92 -0
  275. package/src/components/layout/Space/index.tsx +12 -0
  276. package/src/components/layout/index.tsx +68 -0
  277. package/src/components/navigation/Menu/Menu.styles.ts +779 -0
  278. package/src/components/navigation/Menu/Menu.tsx +355 -0
  279. package/src/components/navigation/Menu/Menu.types.ts +231 -0
  280. package/src/components/navigation/Menu/Menu.utils.ts +187 -0
  281. package/src/components/navigation/Menu/MenuItem.tsx +126 -0
  282. package/src/components/navigation/Menu/SubMenu.tsx +148 -0
  283. package/src/components/navigation/Menu/__tests__/Menu.test.tsx +687 -0
  284. package/src/components/navigation/Menu/index.tsx +124 -0
  285. package/src/components/navigation/NavBar/NavBar.styles.ts +129 -0
  286. package/src/components/navigation/NavBar/NavBar.test.tsx +287 -0
  287. package/src/components/navigation/NavBar/NavBar.tsx +231 -0
  288. package/src/components/navigation/NavBar/NavBar.types.ts +54 -0
  289. package/src/components/navigation/NavBar/index.tsx +3 -0
  290. package/src/components/navigation/Pagination/Pagination.styles.ts +187 -0
  291. package/src/components/navigation/Pagination/Pagination.test.tsx +673 -0
  292. package/src/components/navigation/Pagination/Pagination.tsx +395 -0
  293. package/src/components/navigation/Pagination/Pagination.types.ts +86 -0
  294. package/src/components/navigation/Pagination/index.ts +18 -0
  295. package/src/components/navigation/Pagination/index.tsx +9 -0
  296. package/src/components/navigation/Steps/Step.tsx +56 -0
  297. package/src/components/navigation/Steps/Steps.styles.ts +154 -0
  298. package/src/components/navigation/Steps/Steps.test.tsx +12 -0
  299. package/src/components/navigation/Steps/Steps.tsx +113 -0
  300. package/src/components/navigation/Steps/Steps.types.ts +47 -0
  301. package/src/components/navigation/Steps/index.tsx +3 -0
  302. package/src/components/navigation/Tabs/Tabs.styles.ts +199 -0
  303. package/src/components/navigation/Tabs/Tabs.test.tsx +661 -0
  304. package/src/components/navigation/Tabs/Tabs.tsx +253 -0
  305. package/src/components/navigation/Tabs/Tabs.types.ts +114 -0
  306. package/src/components/navigation/Tabs/index.tsx +3 -0
  307. package/src/components/navigation/Tree/Tree.styles.ts +553 -0
  308. package/src/components/navigation/Tree/Tree.test.basic.tsx +7 -0
  309. package/src/components/navigation/Tree/Tree.test.functional.tsx +496 -0
  310. package/src/components/navigation/Tree/Tree.test.import.check.tsx +6 -0
  311. package/src/components/navigation/Tree/Tree.test.import.tsx +6 -0
  312. package/src/components/navigation/Tree/Tree.test.minimal.tsx +5 -0
  313. package/src/components/navigation/Tree/Tree.test.simple.tsx +30 -0
  314. package/src/components/navigation/Tree/Tree.test.tsx +908 -0
  315. package/src/components/navigation/Tree/Tree.test.working.tsx +673 -0
  316. package/src/components/navigation/Tree/Tree.tsx +600 -0
  317. package/src/components/navigation/Tree/Tree.types.ts +909 -0
  318. package/src/components/navigation/Tree/Tree.utils.ts +452 -0
  319. package/src/components/navigation/Tree/index.ts +33 -0
  320. package/src/components/navigation/Tree/index.tsx +23 -0
  321. package/src/components/navigation/index.tsx +83 -0
  322. package/src/constants/index.ts +785 -0
  323. package/src/hooks/index.ts +110 -0
  324. package/src/hooks/types.ts +10 -0
  325. package/src/hooks/useAsync.ts +65 -0
  326. package/src/hooks/useEventHandling.ts +444 -0
  327. package/src/hooks/useLifecycle.ts +399 -0
  328. package/src/hooks/usePerformance.ts +441 -0
  329. package/src/hooks/usePerformanceMonitor.ts +348 -0
  330. package/src/hooks/usePlatform.ts +62 -0
  331. package/src/hooks/useRequest.test.ts +11 -0
  332. package/src/hooks/useRequest.ts +135 -0
  333. package/src/hooks/useStateManagement.ts +300 -0
  334. package/src/hooks/useStyle.ts +537 -0
  335. package/src/hooks/useTheme.ts +347 -0
  336. package/src/hooks/useVirtualScroll.ts +331 -0
  337. package/src/index.ts +298 -0
  338. package/src/platform/index.ts +1188 -0
  339. package/src/providers/AppProvider.test.tsx +63 -0
  340. package/src/providers/AppProvider.tsx +155 -0
  341. package/src/providers/index.ts +1 -0
  342. package/src/theme/ThemeProvider.tsx +283 -0
  343. package/src/theme/ThemeProvider.types.ts +26 -0
  344. package/src/theme/animations.tsx +660 -0
  345. package/src/theme/defaults.ts +188 -0
  346. package/src/theme/design-system.ts +562 -0
  347. package/src/theme/design-tokens.ts +1136 -0
  348. package/src/theme/generated/dark-theme.scss +120 -0
  349. package/src/theme/generated/tokens.css +441 -0
  350. package/src/theme/generated/tokens.scss +320 -0
  351. package/src/theme/index.ts +120 -0
  352. package/src/theme/responsive.tsx +193 -0
  353. package/src/theme/styles/mixins.scss +612 -0
  354. package/src/theme/styles/variables.scss +295 -0
  355. package/src/theme/styles.ts +403 -0
  356. package/src/theme/tokens/colors.ts +256 -0
  357. package/src/theme/tokens/effects.ts +260 -0
  358. package/src/theme/tokens/index.ts +217 -0
  359. package/src/theme/tokens/spacing.ts +137 -0
  360. package/src/theme/tokens/typography.ts +186 -0
  361. package/src/theme/types.ts +188 -0
  362. package/src/theme/useThemeUtils.ts +313 -0
  363. package/src/theme/utils.ts +501 -0
  364. package/src/theme/variables.ts +583 -0
  365. package/src/types/accessibility.ts +51 -0
  366. package/src/types/button.ts +562 -0
  367. package/src/types/component-props.ts +317 -0
  368. package/src/types/env.d.ts +20 -0
  369. package/src/types/index.ts +427 -0
  370. package/src/types/modules.d.ts +40 -0
  371. package/src/types/standardized-components.ts +544 -0
  372. package/src/types/taro-adapter.d.ts +174 -0
  373. package/src/types/taro-components.d.ts +73 -0
  374. package/src/types/utils.ts +410 -0
  375. package/src/utils/__tests__/inputValidator.test.ts +338 -0
  376. package/src/utils/__tests__/responsiveUtils.test.ts +310 -0
  377. package/src/utils/__tests__/xssProtection.test.ts +268 -0
  378. package/src/utils/cache.ts +83 -0
  379. package/src/utils/createNamespace.ts +24 -0
  380. package/src/utils/environment.ts +95 -0
  381. package/src/utils/error-handler.ts +88 -0
  382. package/src/utils/errorLogger.ts +197 -0
  383. package/src/utils/formatUtils.ts +444 -0
  384. package/src/utils/index.ts +115 -0
  385. package/src/utils/inputValidator.ts +261 -0
  386. package/src/utils/network/http-client.test.ts +18 -0
  387. package/src/utils/network/http-client.ts +151 -0
  388. package/src/utils/performance/performance.ts +850 -0
  389. package/src/utils/responsiveUtils.ts +357 -0
  390. package/src/utils/rtl-support.ts +344 -0
  391. package/src/utils/security/api-security.ts +386 -0
  392. package/src/utils/security/xss-protection.ts +69 -0
  393. package/src/utils/securityHeaders.ts +314 -0
  394. package/src/utils/typeHelpers.ts +16 -0
  395. package/src/utils/types/dataProcessing.ts +543 -0
  396. package/src/utils/types/typeHelpers.ts +187 -0
  397. package/src/utils/xssProtection.ts +420 -0
@@ -0,0 +1,673 @@
1
+ import React from 'react'
2
+ import { render, screen, fireEvent, act } from '@testing-library/react'
3
+ import { vi } from 'vitest'
4
+ import { Pagination } from '../Pagination'
5
+ import type { PaginationRef } from '../Pagination.types'
6
+
7
+ // Mock Taro components
8
+ vi.mock('@tarojs/components', () => ({
9
+ View: 'div',
10
+ Text: 'span',
11
+ Picker: ({ onChange, range, children, ...props }: { onChange?: (e: any) => void; range?: any[]; children?: React.ReactNode; [key: string]: any }) => {
12
+ // The Pagination component uses rangeKey="label" but the data is just an array of numbers
13
+ // We need to simulate the Picker's behavior properly
14
+ return (
15
+ <select {...props} role="combobox" onChange={(e) => {
16
+ const selectedIndex = parseInt(e.target.value);
17
+ // const selectedValue = range ? range[selectedIndex] : selectedIndex;
18
+ onChange && onChange({ detail: { value: selectedIndex } });
19
+ }}>
20
+ {range?.map((value, index) => (
21
+ <option key={index} value={index}>{value}</option>
22
+ ))}
23
+ {children}
24
+ </select>
25
+ );
26
+ },
27
+ select: ({ onChange, ...props }: { onChange?: (e: any) => void; [key: string]: any }) => {
28
+ return <select {...props} onChange={(e) => onChange && onChange({ target: { value: parseInt(e.target.value) } })} />
29
+ }
30
+ }))
31
+
32
+ // Mock the Input component from form module
33
+ vi.mock('../../form/Input', () => ({
34
+ Input: ({ onChange, onInput, value, ...props }: { onChange?: (e: any) => void; onInput?: (e: any) => void; value?: string; [key: string]: any }) => {
35
+ // Taro Input uses onInput instead of onChange for value changes
36
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
37
+ const event = {
38
+ detail: {
39
+ value: e.target.value
40
+ }
41
+ }
42
+ if (onInput) {
43
+ onInput(event)
44
+ }
45
+ if (onChange) {
46
+ onChange(event)
47
+ }
48
+ }
49
+ return <input {...props} value={value} onChange={handleChange} />
50
+ }
51
+ }))
52
+
53
+ // Mock styles
54
+ vi.mock('../Pagination.styles', () => ({
55
+ paginationStyles: {
56
+ SIZE_MAP: {
57
+ small: { padding: '4px 8px', fontSize: '12px' },
58
+ default: { padding: '8px 12px', fontSize: '14px' },
59
+ medium: { padding: '10px 14px', fontSize: '14px' },
60
+ large: { padding: '12px 16px', fontSize: '16px' }
61
+ },
62
+ getBaseStyle: (props: any) => ({
63
+ display: 'flex',
64
+ alignItems: 'center',
65
+ justifyContent: props.align === 'center' ? 'center' : props.align === 'left' ? 'flex-start' : 'flex-end',
66
+ gap: '8px',
67
+ padding: props.size === 'small' ? '4px' : props.size === 'large' ? '12px' : '8px'
68
+ }),
69
+ getButtonStyle: (props: any) => ({
70
+ padding: props.size === 'small' ? '4px 8px' : props.size === 'large' ? '12px 16px' : '8px 12px',
71
+ fontSize: props.size === 'small' ? '12px' : props.size === 'large' ? '16px' : '14px',
72
+ opacity: props.disabled ? 0.5 : 1,
73
+ cursor: props.disabled ? 'not-allowed' : 'pointer'
74
+ }),
75
+ getPageButtonStyle: (props: any) => ({
76
+ padding: props.size === 'small' ? '4px 8px' : props.size === 'large' ? '12px 16px' : '8px 12px',
77
+ fontSize: props.size === 'small' ? '12px' : props.size === 'large' ? '16px' : '14px',
78
+ backgroundColor: props.active ? '#1890ff' : 'transparent',
79
+ color: props.active ? 'white' : 'inherit',
80
+ opacity: props.disabled ? 0.5 : 1,
81
+ cursor: props.disabled ? 'not-allowed' : 'pointer'
82
+ }),
83
+ getJumpButtonStyle: (size: any) => ({
84
+ padding: size === 'small' ? '4px 8px' : size === 'large' ? '12px 16px' : '8px 12px',
85
+ fontSize: size === 'small' ? '12px' : size === 'large' ? '16px' : '14px',
86
+ cursor: 'pointer'
87
+ }),
88
+ getTotalStyle: () => ({
89
+ marginRight: '16px',
90
+ fontSize: '14px',
91
+ color: '#666'
92
+ }),
93
+ getQuickJumperStyle: () => ({
94
+ display: 'flex',
95
+ alignItems: 'center',
96
+ gap: '8px'
97
+ }),
98
+ getInputStyle: () => ({
99
+ width: '50px',
100
+ padding: '4px 8px',
101
+ border: '1px solid #d9d9d9',
102
+ borderRadius: '4px'
103
+ }),
104
+ getSelectStyle: () => ({
105
+ padding: '4px 8px',
106
+ border: '1px solid #d9d9d9',
107
+ borderRadius: '4px'
108
+ }),
109
+ getClassName: (props: any) => `taro-uno-pagination taro-uno-pagination--${props.size} taro-uno-pagination--${props.align} ${props.disabled ? 'taro-uno-pagination--disabled' : ''} ${props.simple ? 'taro-uno-pagination--simple' : ''} ${props.className || ''}`
110
+ }
111
+ }))
112
+
113
+ describe('Pagination Component', () => {
114
+ const mockRef = React.createRef<PaginationRef>()
115
+
116
+ beforeEach(() => {
117
+ vi.clearAllMocks()
118
+ })
119
+
120
+ describe('Rendering', () => {
121
+ it('renders pagination with default props', () => {
122
+ render(<Pagination total={100} data-testid="pagination" />)
123
+ const pagination = screen.getByTestId('pagination')
124
+ expect(pagination).toBeInTheDocument()
125
+ })
126
+
127
+ it('renders pagination with custom current page', () => {
128
+ render(<Pagination total={100} current={3} data-testid="pagination" />)
129
+ const pagination = screen.getByTestId('pagination')
130
+ expect(pagination).toBeInTheDocument()
131
+ })
132
+
133
+ it('renders pagination with custom page size', () => {
134
+ render(<Pagination total={100} pageSize={20} data-testid="pagination" />)
135
+ const pagination = screen.getByTestId('pagination')
136
+ expect(pagination).toBeInTheDocument()
137
+ })
138
+
139
+ it('renders pagination with custom size', () => {
140
+ render(<Pagination total={100} size="small" data-testid="pagination" />)
141
+ const pagination = screen.getByTestId('pagination')
142
+ expect(pagination).toBeInTheDocument()
143
+ })
144
+
145
+ it('renders pagination with show total', () => {
146
+ render(<Pagination total={100} showTotal data-testid="pagination" />)
147
+ const pagination = screen.getByTestId('pagination')
148
+ expect(pagination).toBeInTheDocument()
149
+ })
150
+
151
+ it('renders pagination with custom show total function', () => {
152
+ const showTotal = (total: number, range: [number, number]) => `显示 ${range[0]}-${range[1]} 条,共 ${total} 条`
153
+ render(<Pagination total={100} showTotal={showTotal} data-testid="pagination" />)
154
+ const pagination = screen.getByTestId('pagination')
155
+ expect(pagination).toBeInTheDocument()
156
+ })
157
+
158
+ it('renders pagination with quick jumper', () => {
159
+ render(<Pagination total={100} showQuickJumper data-testid="pagination" />)
160
+ const pagination = screen.getByTestId('pagination')
161
+ expect(pagination).toBeInTheDocument()
162
+ })
163
+
164
+ it('renders pagination with size changer', () => {
165
+ render(<Pagination total={100} showSizeChanger data-testid="pagination" />)
166
+ const pagination = screen.getByTestId('pagination')
167
+ expect(pagination).toBeInTheDocument()
168
+ })
169
+
170
+ it('renders pagination with disabled state', () => {
171
+ render(<Pagination total={100} disabled data-testid="pagination" />)
172
+ const pagination = screen.getByTestId('pagination')
173
+ expect(pagination).toBeInTheDocument()
174
+ })
175
+
176
+ it('renders pagination in simple mode', () => {
177
+ render(<Pagination total={100} simple data-testid="pagination" />)
178
+ const pagination = screen.getByTestId('pagination')
179
+ expect(pagination).toBeInTheDocument()
180
+ })
181
+
182
+ it('renders pagination with custom alignment', () => {
183
+ render(<Pagination total={100} align="center" data-testid="pagination" />)
184
+ const pagination = screen.getByTestId('pagination')
185
+ expect(pagination).toBeInTheDocument()
186
+ })
187
+
188
+ it('renders pagination with custom position', () => {
189
+ render(<Pagination total={100} position="top" data-testid="pagination" />)
190
+ const pagination = screen.getByTestId('pagination')
191
+ expect(pagination).toBeInTheDocument()
192
+ })
193
+
194
+ it('renders pagination with custom page size options', () => {
195
+ render(<Pagination total={100} showSizeChanger pageSizeOptions={[10, 30, 50]} data-testid="pagination" />)
196
+ const pagination = screen.getByTestId('pagination')
197
+ expect(pagination).toBeInTheDocument()
198
+ })
199
+
200
+ it('renders pagination with custom className', () => {
201
+ render(<Pagination total={100} className="custom-pagination" data-testid="pagination" />)
202
+ const pagination = screen.getByTestId('pagination')
203
+ expect(pagination).toBeInTheDocument()
204
+ expect(pagination).toHaveClass('custom-pagination')
205
+ })
206
+
207
+ it('renders pagination with custom style', () => {
208
+ const customStyle = { backgroundColor: '#f0f0f0', padding: '16px' }
209
+ render(<Pagination total={100} style={customStyle} data-testid="pagination" />)
210
+ const pagination = screen.getByTestId('pagination')
211
+ expect(pagination).toBeInTheDocument()
212
+ })
213
+
214
+ it('renders pagination with item render function', () => {
215
+ const itemRender = (page: number, type: string, element: React.ReactNode) => {
216
+ if (type === 'page') {
217
+ return <span data-testid={`page-${page}`}>[{page}]</span>
218
+ }
219
+ return element
220
+ }
221
+ render(<Pagination total={100} itemRender={itemRender} data-testid="pagination" />)
222
+ const pagination = screen.getByTestId('pagination')
223
+ expect(pagination).toBeInTheDocument()
224
+ })
225
+
226
+ it('handles empty total gracefully', () => {
227
+ render(<Pagination total={0} data-testid="pagination" />)
228
+ const pagination = screen.getByTestId('pagination')
229
+ expect(pagination).toBeInTheDocument()
230
+ })
231
+
232
+ it('handles single page gracefully', () => {
233
+ render(<Pagination total={5} pageSize={10} data-testid="pagination" />)
234
+ const pagination = screen.getByTestId('pagination')
235
+ expect(pagination).toBeInTheDocument()
236
+ })
237
+ })
238
+
239
+ describe('Page Navigation', () => {
240
+ it('navigates to next page', () => {
241
+ const handleChange = vi.fn()
242
+ render(<Pagination total={100} onChange={handleChange} data-testid="pagination" />)
243
+
244
+ const nextButton = screen.getByText('下一页')
245
+ fireEvent.click(nextButton)
246
+
247
+ expect(handleChange).toHaveBeenCalledWith(2, 10)
248
+ })
249
+
250
+ it('navigates to previous page', () => {
251
+ const handleChange = vi.fn()
252
+ render(<Pagination total={100} current={3} onChange={handleChange} data-testid="pagination" />)
253
+
254
+ const prevButton = screen.getByText('上一页')
255
+ fireEvent.click(prevButton)
256
+
257
+ expect(handleChange).toHaveBeenCalledWith(2, 10)
258
+ })
259
+
260
+ it('navigates to specific page', () => {
261
+ const handleChange = vi.fn()
262
+ render(<Pagination total={100} onChange={handleChange} data-testid="pagination" />)
263
+
264
+ const pageButton = screen.getByText('3')
265
+ fireEvent.click(pageButton)
266
+
267
+ expect(handleChange).toHaveBeenCalledWith(3, 10)
268
+ })
269
+
270
+ it('navigates using jump buttons', () => {
271
+ const handleChange = vi.fn()
272
+ render(<Pagination total={100} current={10} onChange={handleChange} data-testid="pagination" />)
273
+
274
+ const jumpButton = screen.getByText('...')
275
+ fireEvent.click(jumpButton)
276
+
277
+ expect(handleChange).toHaveBeenCalledWith(5, 10)
278
+ })
279
+
280
+ it('does not navigate when disabled', () => {
281
+ const handleChange = vi.fn()
282
+ render(<Pagination total={100} disabled onChange={handleChange} data-testid="pagination" />)
283
+
284
+ const nextButton = screen.getByText('下一页')
285
+ fireEvent.click(nextButton)
286
+
287
+ expect(handleChange).not.toHaveBeenCalled()
288
+ })
289
+
290
+ it('does not navigate prev on first page', () => {
291
+ const handleChange = vi.fn()
292
+ render(<Pagination total={100} current={1} onChange={handleChange} data-testid="pagination" />)
293
+
294
+ const prevButton = screen.getByText('上一页')
295
+ fireEvent.click(prevButton)
296
+
297
+ expect(handleChange).not.toHaveBeenCalled()
298
+ })
299
+
300
+ it('does not navigate next on last page', () => {
301
+ const handleChange = vi.fn()
302
+ render(<Pagination total={100} current={10} onChange={handleChange} data-testid="pagination" />)
303
+
304
+ const nextButton = screen.getByText('下一页')
305
+ fireEvent.click(nextButton)
306
+
307
+ expect(handleChange).not.toHaveBeenCalled()
308
+ })
309
+ })
310
+
311
+ describe('Page Size Changes', () => {
312
+ it('changes page size', () => {
313
+ const handleSizeChange = vi.fn()
314
+ const handleChange = vi.fn()
315
+ render(
316
+ <Pagination
317
+ total={100}
318
+ showSizeChanger
319
+ onShowSizeChange={handleSizeChange}
320
+ onChange={handleChange}
321
+ data-testid="pagination"
322
+ />
323
+ )
324
+
325
+ const select = screen.getByRole('combobox')
326
+ fireEvent.change(select, { target: { value: '1' } }) // Index 1 = 20 items per page
327
+
328
+ expect(handleSizeChange).toHaveBeenCalledWith(1, 20)
329
+ expect(handleChange).toHaveBeenCalledWith(1, 20)
330
+ })
331
+
332
+ it('adjusts current page when changing page size', () => {
333
+ const handleSizeChange = vi.fn()
334
+ const handleChange = vi.fn()
335
+ render(
336
+ <Pagination
337
+ total={100}
338
+ current={8}
339
+ showSizeChanger
340
+ onShowSizeChange={handleSizeChange}
341
+ onChange={handleChange}
342
+ data-testid="pagination"
343
+ />
344
+ )
345
+
346
+ const select = screen.getByRole('combobox')
347
+ fireEvent.change(select, { target: { value: '1' } }) // Index 1 = 20 items per page
348
+
349
+ expect(handleSizeChange).toHaveBeenCalledWith(5, 20)
350
+ expect(handleChange).toHaveBeenCalledWith(5, 20)
351
+ })
352
+ })
353
+
354
+ describe('Quick Jumper', () => {
355
+ it('jumps to specific page', () => {
356
+ const handleChange = vi.fn()
357
+ render(<Pagination total={100} showQuickJumper onChange={handleChange} data-testid="pagination" />)
358
+
359
+ const input = screen.getByRole('spinbutton')
360
+ fireEvent.change(input, { target: { value: '5' } })
361
+
362
+ const jumpButton = screen.getByText('确定')
363
+ fireEvent.click(jumpButton)
364
+
365
+ expect(handleChange).toHaveBeenCalledWith(5, 10)
366
+ })
367
+
368
+ it('does not jump with invalid page number', () => {
369
+ const handleChange = vi.fn()
370
+ render(<Pagination total={100} showQuickJumper onChange={handleChange} data-testid="pagination" />)
371
+
372
+ const input = screen.getByRole('spinbutton')
373
+ fireEvent.change(input, { target: { value: 'invalid' } })
374
+
375
+ const jumpButton = screen.getByText('确定')
376
+ fireEvent.click(jumpButton)
377
+
378
+ expect(handleChange).not.toHaveBeenCalled()
379
+ })
380
+
381
+ it('does not jump with out of range page number', () => {
382
+ const handleChange = vi.fn()
383
+ render(<Pagination total={100} showQuickJumper onChange={handleChange} data-testid="pagination" />)
384
+
385
+ const input = screen.getByRole('spinbutton')
386
+ fireEvent.change(input, { target: { value: '999' } })
387
+
388
+ const jumpButton = screen.getByText('确定')
389
+ fireEvent.click(jumpButton)
390
+
391
+ expect(handleChange).not.toHaveBeenCalled()
392
+ })
393
+ })
394
+
395
+ describe('Props Updates', () => {
396
+ it('updates current page correctly', () => {
397
+ const { rerender } = render(<Pagination total={100} current={2} data-testid="pagination" />)
398
+ const pagination = screen.getByTestId('pagination')
399
+ rerender(<Pagination total={100} current={5} data-testid="pagination" />)
400
+ expect(pagination).toBeInTheDocument()
401
+ })
402
+
403
+ it('updates page size correctly', () => {
404
+ const { rerender } = render(<Pagination total={100} pageSize={10} data-testid="pagination" />)
405
+ const pagination = screen.getByTestId('pagination')
406
+ rerender(<Pagination total={100} pageSize={20} data-testid="pagination" />)
407
+ expect(pagination).toBeInTheDocument()
408
+ })
409
+
410
+ it('updates total correctly', () => {
411
+ const { rerender } = render(<Pagination total={100} data-testid="pagination" />)
412
+ const pagination = screen.getByTestId('pagination')
413
+ rerender(<Pagination total={200} data-testid="pagination" />)
414
+ expect(pagination).toBeInTheDocument()
415
+ })
416
+
417
+ it('updates disabled state correctly', () => {
418
+ const { rerender } = render(<Pagination total={100} disabled={false} data-testid="pagination" />)
419
+ const pagination = screen.getByTestId('pagination')
420
+ rerender(<Pagination total={100} disabled={true} data-testid="pagination" />)
421
+ expect(pagination).toBeInTheDocument()
422
+ })
423
+
424
+ it('updates size correctly', () => {
425
+ const { rerender } = render(<Pagination total={100} size="default" data-testid="pagination" />)
426
+ const pagination = screen.getByTestId('pagination')
427
+ rerender(<Pagination total={100} size="small" data-testid="pagination" />)
428
+ expect(pagination).toBeInTheDocument()
429
+ })
430
+ })
431
+
432
+ describe('Ref API', () => {
433
+ it('exposes ref methods correctly', () => {
434
+ render(<Pagination total={100} ref={mockRef} data-testid="pagination" />)
435
+
436
+ act(() => {
437
+ expect(mockRef.current).toBeDefined()
438
+ expect(mockRef.current?.getCurrent()).toBe(1)
439
+ expect(mockRef.current?.getPageSize()).toBe(10)
440
+ expect(mockRef.current?.getTotalPages()).toBe(10)
441
+ expect(mockRef.current?.getTotal()).toBe(100)
442
+ })
443
+ })
444
+
445
+ it('sets current page via ref method', () => {
446
+ render(<Pagination total={100} defaultCurrent={1} ref={mockRef} data-testid="pagination" />)
447
+
448
+ act(() => {
449
+ if (mockRef.current) {
450
+ expect(() => mockRef.current.setCurrent(5)).not.toThrow()
451
+ }
452
+ })
453
+ })
454
+
455
+ it('sets page size via ref method', () => {
456
+ render(<Pagination total={100} defaultPageSize={10} ref={mockRef} data-testid="pagination" />)
457
+
458
+ act(() => {
459
+ if (mockRef.current) {
460
+ expect(() => mockRef.current.setPageSize(20)).not.toThrow()
461
+ }
462
+ })
463
+ })
464
+
465
+ it('navigates via ref methods', () => {
466
+ const handleChange = vi.fn()
467
+ render(<Pagination total={100} defaultCurrent={1} onChange={handleChange} ref={mockRef} data-testid="pagination" />)
468
+
469
+ act(() => {
470
+ if (mockRef.current) {
471
+ mockRef.current.next()
472
+ expect(handleChange).toHaveBeenCalled()
473
+
474
+ mockRef.current.prev()
475
+ expect(handleChange).toHaveBeenCalled()
476
+
477
+ mockRef.current.goTo(5)
478
+ expect(handleChange).toHaveBeenCalled()
479
+
480
+ mockRef.current.first()
481
+ expect(handleChange).toHaveBeenCalled()
482
+
483
+ mockRef.current.last()
484
+ expect(handleChange).toHaveBeenCalled()
485
+ }
486
+ })
487
+ })
488
+
489
+ it('provides element access via ref', () => {
490
+ render(<Pagination total={100} ref={mockRef} data-testid="pagination" />)
491
+
492
+ act(() => {
493
+ expect(mockRef.current?.element).toBeDefined()
494
+ })
495
+ })
496
+ })
497
+
498
+ describe('Controlled vs Uncontrolled', () => {
499
+ it('works in controlled mode', () => {
500
+ const handleChange = vi.fn()
501
+ render(<Pagination total={100} current={3} onChange={handleChange} data-testid="pagination" />)
502
+
503
+ const nextButton = screen.getByText('下一页')
504
+ fireEvent.click(nextButton)
505
+
506
+ expect(handleChange).toHaveBeenCalledWith(4, 10)
507
+ })
508
+
509
+ it('works in uncontrolled mode', () => {
510
+ const handleChange = vi.fn()
511
+ render(<Pagination total={100} defaultCurrent={3} onChange={handleChange} data-testid="pagination" />)
512
+
513
+ const nextButton = screen.getByText('下一页')
514
+ fireEvent.click(nextButton)
515
+
516
+ expect(handleChange).toHaveBeenCalledWith(4, 10)
517
+ })
518
+
519
+ it('handles controlled page size', () => {
520
+ const handleSizeChange = vi.fn()
521
+ render(<Pagination total={100} pageSize={20} showSizeChanger onShowSizeChange={handleSizeChange} data-testid="pagination" />)
522
+
523
+ const select = screen.getByRole('combobox')
524
+ fireEvent.change(select, { target: { value: '2' } }) // Index 2 = 50 items per page
525
+
526
+ expect(handleSizeChange).toHaveBeenCalled()
527
+ })
528
+
529
+ it('handles uncontrolled page size', () => {
530
+ const handleSizeChange = vi.fn()
531
+ render(<Pagination total={100} defaultPageSize={20} showSizeChanger onShowSizeChange={handleSizeChange} data-testid="pagination" />)
532
+
533
+ const select = screen.getByRole('combobox')
534
+ fireEvent.change(select, { target: { value: '2' } }) // Index 2 = 50 items per page
535
+
536
+ expect(handleSizeChange).toHaveBeenCalled()
537
+ })
538
+ })
539
+
540
+ describe('Accessibility', () => {
541
+ it('has proper role attribute', () => {
542
+ render(<Pagination total={100} data-testid="pagination" />)
543
+ const pagination = screen.getByTestId('pagination')
544
+ expect(pagination).toBeInTheDocument()
545
+ })
546
+
547
+ it('supports aria-label', () => {
548
+ render(<Pagination total={100} aria-label="Pagination navigation" data-testid="pagination" />)
549
+ const pagination = screen.getByTestId('pagination')
550
+ expect(pagination).toHaveAttribute('aria-label', 'Pagination navigation')
551
+ })
552
+
553
+ it('supports aria-labelledby', () => {
554
+ render(<Pagination total={100} aria-labelledby="pagination-title" data-testid="pagination" />)
555
+ const pagination = screen.getByTestId('pagination')
556
+ expect(pagination).toHaveAttribute('aria-labelledby', 'pagination-title')
557
+ })
558
+
559
+ it('supports data attributes', () => {
560
+ render(<Pagination total={100} data-testid="pagination" data-custom="value" />)
561
+ const pagination = screen.getByTestId('pagination')
562
+ expect(pagination).toHaveAttribute('data-custom', 'value')
563
+ })
564
+ })
565
+
566
+ describe('Edge Cases', () => {
567
+ it('handles negative total gracefully', () => {
568
+ render(<Pagination total={-100} data-testid="pagination" />)
569
+ const pagination = screen.getByTestId('pagination')
570
+ expect(pagination).toBeInTheDocument()
571
+ })
572
+
573
+ it('handles zero page size gracefully', () => {
574
+ render(<Pagination total={100} pageSize={0} data-testid="pagination" />)
575
+ const pagination = screen.getByTestId('pagination')
576
+ expect(pagination).toBeInTheDocument()
577
+ })
578
+
579
+ it('handles negative page size gracefully', () => {
580
+ render(<Pagination total={100} pageSize={-10} data-testid="pagination" />)
581
+ const pagination = screen.getByTestId('pagination')
582
+ expect(pagination).toBeInTheDocument()
583
+ })
584
+
585
+ it('handles current page out of range', () => {
586
+ render(<Pagination total={100} current={999} data-testid="pagination" />)
587
+ const pagination = screen.getByTestId('pagination')
588
+ expect(pagination).toBeInTheDocument()
589
+ })
590
+
591
+ it('handles negative current page gracefully', () => {
592
+ render(<Pagination total={100} current={-5} data-testid="pagination" />)
593
+ const pagination = screen.getByTestId('pagination')
594
+ expect(pagination).toBeInTheDocument()
595
+ })
596
+
597
+ it('handles very large total', () => {
598
+ render(<Pagination total={999999} data-testid="pagination" />)
599
+ const pagination = screen.getByTestId('pagination')
600
+ expect(pagination).toBeInTheDocument()
601
+ })
602
+
603
+ it('handles very small page size', () => {
604
+ render(<Pagination total={100} pageSize={1} data-testid="pagination" />)
605
+ const pagination = screen.getByTestId('pagination')
606
+ expect(pagination).toBeInTheDocument()
607
+ })
608
+
609
+ it('handles empty pageSizeOptions', () => {
610
+ render(<Pagination total={100} showSizeChanger pageSizeOptions={[]} data-testid="pagination" />)
611
+ const pagination = screen.getByTestId('pagination')
612
+ expect(pagination).toBeInTheDocument()
613
+ })
614
+ })
615
+
616
+ describe('Performance', () => {
617
+ it('renders efficiently with many pages', () => {
618
+ render(<Pagination total={10000} pageSize={10} data-testid="pagination" />)
619
+ const pagination = screen.getByTestId('pagination')
620
+ expect(pagination).toBeInTheDocument()
621
+ })
622
+
623
+ it('handles frequent prop updates efficiently', () => {
624
+ const { rerender } = render(<Pagination total={100} current={1} data-testid="pagination" />)
625
+
626
+ for (let i = 0; i < 10; i++) {
627
+ rerender(<Pagination total={100} current={i + 1} data-testid="pagination" />)
628
+ }
629
+
630
+ expect(screen.getByTestId('pagination')).toBeInTheDocument()
631
+ })
632
+ })
633
+
634
+ describe('Simple Mode', () => {
635
+ it('renders in simple mode correctly', () => {
636
+ render(<Pagination total={100} simple data-testid="pagination" />)
637
+ const pagination = screen.getByTestId('pagination')
638
+ expect(pagination).toBeInTheDocument()
639
+
640
+ // Should show current page info
641
+ expect(screen.getByText('1 / 10')).toBeInTheDocument()
642
+ })
643
+
644
+ it('navigates in simple mode', () => {
645
+ const handleChange = vi.fn()
646
+ render(<Pagination total={100} simple onChange={handleChange} data-testid="pagination" />)
647
+
648
+ const nextButton = screen.getByText('下一页')
649
+ fireEvent.click(nextButton)
650
+
651
+ expect(handleChange).toHaveBeenCalledWith(2, 10)
652
+ })
653
+
654
+ it('shows correct page info in simple mode', () => {
655
+ render(<Pagination total={100} current={5} simple data-testid="pagination" />)
656
+ expect(screen.getByText('5 / 10')).toBeInTheDocument()
657
+ })
658
+ })
659
+
660
+ describe('Show More/Less Items', () => {
661
+ it('handles showMore prop', () => {
662
+ render(<Pagination total={100} showMore={false} data-testid="pagination" />)
663
+ const pagination = screen.getByTestId('pagination')
664
+ expect(pagination).toBeInTheDocument()
665
+ })
666
+
667
+ it('handles showLessItems prop', () => {
668
+ render(<Pagination total={100} showLessItems={true} data-testid="pagination" />)
669
+ const pagination = screen.getByTestId('pagination')
670
+ expect(pagination).toBeInTheDocument()
671
+ })
672
+ })
673
+ })