taro-uno-ui 0.9.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/README.md +21 -0
  2. package/dist/js/{index-DffLRSro.js → index-CDFsvu80.js} +15369 -10741
  3. package/dist/js/index-CDFsvu80.js.map +1 -0
  4. package/dist/js/index-DFdcksbe.js.map +1 -1
  5. package/dist/js/index-DXRIkWX1.js.map +1 -1
  6. package/dist/js/{index-6NJ3A1Dn.js → index-JffnTUrv.js} +15430 -10801
  7. package/dist/js/index-JffnTUrv.js.map +1 -0
  8. package/dist/utils/http/request.d.ts +280 -0
  9. package/package.json +14 -10
  10. package/src/components/basic/Button/Button.tsx +53 -13
  11. package/src/components/basic/Button/Button.types.ts +45 -9
  12. package/src/components/basic/Divider/Divider.tsx +60 -29
  13. package/src/components/basic/Icon/Icon.data.ts +474 -0
  14. package/src/components/basic/Icon/Icon.test.tsx +2 -2
  15. package/src/components/basic/Icon/Icon.tsx +48 -35
  16. package/src/components/basic/Icon/IconManager.ts +229 -0
  17. package/src/components/basic/Text/Text.styles.ts +3 -3
  18. package/src/components/basic/Text/Text.types.ts +14 -4
  19. package/src/components/basic/Typography/Typography.styles.ts +10 -9
  20. package/src/components/basic/Typography/Typography.tsx +15 -13
  21. package/src/components/basic/Typography/Typography.types.ts +41 -41
  22. package/src/components/basic/Typography/index.tsx +1 -1
  23. package/src/components/basic/Video/Video.styles.ts +777 -0
  24. package/src/components/basic/Video/Video.test.tsx +490 -0
  25. package/src/components/basic/Video/Video.tsx +1468 -0
  26. package/src/components/basic/Video/Video.types.ts +500 -0
  27. package/src/components/basic/Video/index.tsx +26 -0
  28. package/src/components/basic/index.tsx +13 -15
  29. package/src/components/common/ErrorBoundary.tsx +1 -1
  30. package/src/components/common/LazyComponent.tsx +9 -8
  31. package/src/components/common/SecurityProvider.tsx +2 -14
  32. package/src/components/common/ThemeProvider.tsx +43 -56
  33. package/src/components/common/VirtualList.tsx +187 -205
  34. package/src/components/common/index.tsx +25 -0
  35. package/src/components/display/Avatar/Avatar.styles.ts +1 -1
  36. package/src/components/display/Avatar/Avatar.tsx +6 -19
  37. package/src/components/display/Avatar/Avatar.types.ts +1 -1
  38. package/src/components/display/Avatar/index.ts +1 -1
  39. package/src/components/display/Badge/Badge.tsx +3 -16
  40. package/src/components/display/Badge/Badge.types.ts +1 -1
  41. package/src/components/display/Badge/index.ts +1 -1
  42. package/src/components/display/Calendar/Calendar.styles.ts +36 -36
  43. package/src/components/display/Calendar/Calendar.test.tsx +27 -15
  44. package/src/components/display/Calendar/Calendar.tsx +56 -35
  45. package/src/components/display/Calendar/Calendar.types.ts +1 -1
  46. package/src/components/display/Calendar/index.ts +1 -1
  47. package/src/components/display/Card/Card.styles.ts +2 -2
  48. package/src/components/display/Card/Card.test.tsx +6 -4
  49. package/src/components/display/Card/Card.tsx +1 -1
  50. package/src/components/display/Card/Card.types.ts +4 -4
  51. package/src/components/display/Card/index.ts +1 -1
  52. package/src/components/display/Carousel/Carousel.styles.ts +31 -31
  53. package/src/components/display/Carousel/Carousel.tsx +34 -39
  54. package/src/components/display/Carousel/Carousel.types.ts +1 -1
  55. package/src/components/display/Carousel/index.ts +1 -1
  56. package/src/components/display/List/List.styles.ts +3 -3
  57. package/src/components/display/List/List.tsx +0 -1
  58. package/src/components/display/List/index.ts +1 -1
  59. package/src/components/display/Rate/Rate.styles.ts +5 -17
  60. package/src/components/display/Rate/Rate.tsx +6 -14
  61. package/src/components/display/Rate/Rate.types.ts +4 -3
  62. package/src/components/display/Rate/index.ts +3 -11
  63. package/src/components/display/Table/Table.test.tsx +2 -0
  64. package/src/components/display/Table/Table.tsx +3 -7
  65. package/src/components/display/Table/Table.types.ts +3 -2
  66. package/src/components/display/Tag/Tag.styles.ts +31 -31
  67. package/src/components/display/Tag/Tag.tsx +9 -26
  68. package/src/components/display/Tag/Tag.types.ts +1 -1
  69. package/src/components/display/Tag/index.ts +1 -1
  70. package/src/components/display/Timeline/Timeline.styles.ts +32 -32
  71. package/src/components/display/Timeline/Timeline.tsx +23 -42
  72. package/src/components/display/Timeline/Timeline.types.ts +1 -1
  73. package/src/components/display/Timeline/index.ts +1 -1
  74. package/src/components/display/index.tsx +33 -29
  75. package/src/components/feedback/Loading/Loading.tsx +6 -1
  76. package/src/components/feedback/Loading/index.ts +2 -5
  77. package/src/components/feedback/Message/Message.styles.ts +3 -3
  78. package/src/components/feedback/Message/index.ts +2 -5
  79. package/src/components/feedback/Modal/Modal.styles.ts +1 -1
  80. package/src/components/feedback/Modal/Modal.tsx +9 -31
  81. package/src/components/feedback/Modal/Modal.types.ts +12 -2
  82. package/src/components/feedback/Notification/Notification.styles.ts +49 -39
  83. package/src/components/feedback/Notification/Notification.test.tsx +1 -1
  84. package/src/components/feedback/Notification/Notification.tsx +97 -120
  85. package/src/components/feedback/Notification/Notification.types.ts +11 -8
  86. package/src/components/feedback/Notification/NotificationManager.tsx +135 -106
  87. package/src/components/feedback/Notification/index.ts +10 -3
  88. package/src/components/feedback/Notification/index.tsx +16 -26
  89. package/src/components/feedback/Progress/Progress.styles.ts +23 -14
  90. package/src/components/feedback/Progress/Progress.tsx +93 -113
  91. package/src/components/feedback/Progress/Progress.types.ts +1 -1
  92. package/src/components/feedback/Progress/index.ts +1 -1
  93. package/src/components/feedback/Progress/utils/animation.ts +12 -23
  94. package/src/components/feedback/Progress/utils/index.ts +2 -2
  95. package/src/components/feedback/Progress/utils/progress-calculator.ts +14 -32
  96. package/src/components/feedback/Result/Result.styles.ts +29 -29
  97. package/src/components/feedback/Result/Result.tsx +8 -20
  98. package/src/components/feedback/Result/Result.types.ts +7 -7
  99. package/src/components/feedback/Result/index.tsx +1 -1
  100. package/src/components/feedback/Toast/Toast.styles.ts +1 -1
  101. package/src/components/feedback/Toast/Toast.tsx +25 -13
  102. package/src/components/feedback/Tooltip/Tooltip.examples.tsx +21 -44
  103. package/src/components/feedback/Tooltip/Tooltip.styles.ts +16 -22
  104. package/src/components/feedback/Tooltip/Tooltip.test.tsx +1 -1
  105. package/src/components/feedback/Tooltip/Tooltip.tsx +65 -46
  106. package/src/components/feedback/Tooltip/Tooltip.types.ts +14 -20
  107. package/src/components/feedback/Tooltip/index.ts +1 -1
  108. package/src/components/feedback/Tooltip/index.tsx +12 -24
  109. package/src/components/feedback/index.tsx +54 -42
  110. package/src/components/form/Cascader/Cascader.styles.ts +2 -2
  111. package/src/components/form/Cascader/Cascader.tsx +84 -88
  112. package/src/components/form/Cascader/Cascader.types.ts +49 -50
  113. package/src/components/form/Cascader/hooks/useCascaderFieldNames.ts +11 -8
  114. package/src/components/form/Cascader/hooks/useCascaderOptions.ts +73 -55
  115. package/src/components/form/Cascader/hooks/useCascaderState.ts +31 -25
  116. package/src/components/form/Cascader/index.ts +1 -1
  117. package/src/components/form/Cascader/utils/formatDisplayValue.ts +4 -4
  118. package/src/components/form/Checkbox/Checkbox.styles.ts +83 -84
  119. package/src/components/form/Checkbox/Checkbox.tsx +2 -9
  120. package/src/components/form/Checkbox/CheckboxGroup.tsx +7 -7
  121. package/src/components/form/DatePicker/DatePicker.test.tsx +1 -1
  122. package/src/components/form/DatePicker/DatePicker.tsx +91 -75
  123. package/src/components/form/DatePicker/DatePicker.types.ts +4 -1
  124. package/src/components/form/Form/Form.tsx +66 -504
  125. package/src/components/form/Form/Form.types.ts +16 -1
  126. package/src/components/form/Form/useFormLogic.ts +497 -0
  127. package/src/components/form/Input/Input.styles.ts +8 -1
  128. package/src/components/form/Input/Input.tsx +55 -291
  129. package/src/components/form/Input/Input.types.ts +13 -1
  130. package/src/components/form/Input/useInputLogic.test.ts +82 -0
  131. package/src/components/form/Input/useInputLogic.ts +260 -0
  132. package/src/components/form/InputNumber/InputNumber.styles.ts +76 -25
  133. package/src/components/form/InputNumber/InputNumber.tsx +53 -21
  134. package/src/components/form/InputNumber/InputNumber.types.ts +21 -3
  135. package/src/components/form/InputNumber/components/InputNumberClearButton.tsx +3 -11
  136. package/src/components/form/InputNumber/components/InputNumberControls.tsx +3 -12
  137. package/src/components/form/InputNumber/hooks/index.ts +1 -1
  138. package/src/components/form/InputNumber/hooks/useInputNumberState.ts +7 -9
  139. package/src/components/form/InputNumber/hooks/useInputNumberValidation.ts +18 -17
  140. package/src/components/form/InputNumber/index.ts +7 -7
  141. package/src/components/form/Radio/Radio.styles.ts +1 -8
  142. package/src/components/form/Radio/Radio.tsx +3 -9
  143. package/src/components/form/Radio/Radio.types.ts +5 -1
  144. package/src/components/form/Select/Select.styles.ts +5 -1
  145. package/src/components/form/Select/Select.tsx +15 -15
  146. package/src/components/form/Select/Select.types.ts +2 -1
  147. package/src/components/form/Slider/Slider.styles.ts +13 -13
  148. package/src/components/form/Slider/Slider.tsx +19 -33
  149. package/src/components/form/Slider/Slider.types.ts +14 -12
  150. package/src/components/form/Slider/index.tsx +2 -9
  151. package/src/components/form/Switch/Switch.styles.ts +1 -7
  152. package/src/components/form/Switch/Switch.tsx +7 -13
  153. package/src/components/form/Textarea/Textarea.styles.ts +4 -4
  154. package/src/components/form/Textarea/Textarea.tsx +7 -1
  155. package/src/components/form/Textarea/Textarea.types.ts +4 -1
  156. package/src/components/form/TimePicker/TimePicker.styles.ts +8 -12
  157. package/src/components/form/TimePicker/TimePicker.tsx +122 -100
  158. package/src/components/form/TimePicker/TimePicker.types.ts +2 -2
  159. package/src/components/form/TimePicker/index.ts +1 -1
  160. package/src/components/form/Transfer/Transfer.styles.ts +3 -15
  161. package/src/components/form/Transfer/Transfer.tsx +146 -134
  162. package/src/components/form/Transfer/Transfer.types.ts +34 -26
  163. package/src/components/form/Transfer/components/TransferItem.tsx +55 -62
  164. package/src/components/form/Transfer/components/TransferList.tsx +212 -199
  165. package/src/components/form/Transfer/components/TransferOperations.tsx +52 -55
  166. package/src/components/form/Transfer/components/TransferPagination.tsx +115 -111
  167. package/src/components/form/Transfer/components/TransferSearch.tsx +52 -55
  168. package/src/components/form/Transfer/hooks/useTransferData.ts +91 -81
  169. package/src/components/form/Transfer/hooks/useTransferState.ts +22 -16
  170. package/src/components/form/Transfer/index.ts +2 -8
  171. package/src/components/form/Upload/Upload.styles.ts +21 -21
  172. package/src/components/form/Upload/Upload.tsx +189 -142
  173. package/src/components/form/Upload/Upload.types.ts +31 -31
  174. package/src/components/form/Upload/index.tsx +1 -1
  175. package/src/components/form/index.tsx +60 -29
  176. package/src/components/index.tsx +0 -1
  177. package/src/components/layout/Affix/Affix.styles.ts +16 -11
  178. package/src/components/layout/Affix/Affix.tsx +67 -75
  179. package/src/components/layout/Affix/Affix.types.ts +18 -18
  180. package/src/components/layout/Affix/index.tsx +1 -1
  181. package/src/components/layout/Col/Col.styles.ts +17 -17
  182. package/src/components/layout/Col/Col.test.tsx +7 -5
  183. package/src/components/layout/Col/Col.tsx +3 -21
  184. package/src/components/layout/Col/Col.types.ts +1 -1
  185. package/src/components/layout/Container/Container.styles.ts +3 -1
  186. package/src/components/layout/Container/Container.tsx +2 -11
  187. package/src/components/layout/Grid/Grid.tsx +3 -53
  188. package/src/components/layout/Layout/Content.tsx +24 -32
  189. package/src/components/layout/Layout/Footer.tsx +24 -32
  190. package/src/components/layout/Layout/Header.tsx +24 -32
  191. package/src/components/layout/Layout/Layout.styles.ts +17 -17
  192. package/src/components/layout/Layout/Layout.tsx +14 -25
  193. package/src/components/layout/Layout/Layout.types.ts +29 -29
  194. package/src/components/layout/Layout/Sider.tsx +44 -56
  195. package/src/components/layout/Layout/index.tsx +16 -2
  196. package/src/components/layout/Row/Row.tsx +15 -43
  197. package/src/components/layout/Space/Space.tsx +3 -11
  198. package/src/components/layout/Space/Space.types.ts +1 -1
  199. package/src/components/layout/index.tsx +29 -19
  200. package/src/components/navigation/Menu/Menu.constants.ts +69 -0
  201. package/src/components/navigation/Menu/Menu.stories.tsx +107 -0
  202. package/src/components/navigation/Menu/Menu.styles.ts +25 -37
  203. package/src/components/navigation/Menu/Menu.tsx +8 -11
  204. package/src/components/navigation/Menu/Menu.types.ts +2 -2
  205. package/src/components/navigation/Menu/Menu.utils.ts +17 -17
  206. package/src/components/navigation/Menu/MenuItem.tsx +9 -11
  207. package/src/components/navigation/Menu/SubMenu.tsx +8 -6
  208. package/src/components/navigation/Menu/index.tsx +4 -69
  209. package/src/components/navigation/NavBar/NavBar.styles.ts +1 -1
  210. package/src/components/navigation/NavBar/NavBar.tsx +7 -10
  211. package/src/components/navigation/NavBar/NavBar.types.ts +3 -3
  212. package/src/components/navigation/NavBar/index.tsx +1 -1
  213. package/src/components/navigation/Pagination/Pagination.test.tsx +2 -3
  214. package/src/components/navigation/Pagination/Pagination.tsx +3 -3
  215. package/src/components/navigation/Pagination/Pagination.types.ts +3 -2
  216. package/src/components/navigation/Pagination/index.ts +9 -3
  217. package/src/components/navigation/Steps/Step.tsx +24 -44
  218. package/src/components/navigation/Steps/Steps.styles.ts +28 -13
  219. package/src/components/navigation/Steps/Steps.test.tsx +2 -0
  220. package/src/components/navigation/Steps/Steps.tsx +88 -89
  221. package/src/components/navigation/Steps/Steps.types.ts +30 -30
  222. package/src/components/navigation/Steps/index.tsx +1 -1
  223. package/src/components/navigation/Tabs/Tabs.test.tsx +3 -2
  224. package/src/components/navigation/Tabs/Tabs.types.ts +4 -3
  225. package/src/components/navigation/index.tsx +21 -16
  226. package/src/constants/index.ts +1 -1
  227. package/src/hooks/index.ts +52 -102
  228. package/src/hooks/types.ts +4 -5
  229. package/src/hooks/useAsync.ts +46 -47
  230. package/src/hooks/useClickOutside.ts +52 -0
  231. package/src/hooks/useCounter.ts +87 -0
  232. package/src/hooks/useDebounce.ts +150 -0
  233. package/src/hooks/useDeepCompareEffect.ts +88 -0
  234. package/src/hooks/useEventListener.ts +77 -0
  235. package/src/hooks/useMediaQuery.ts +75 -0
  236. package/src/hooks/useMutation.ts +233 -0
  237. package/src/hooks/usePerformance.ts +1 -64
  238. package/src/hooks/usePlatform.ts +3 -1
  239. package/src/hooks/usePrevious.ts +25 -0
  240. package/src/hooks/useRequest.ts +12 -7
  241. package/src/hooks/useStateManagement.ts +1 -1
  242. package/src/hooks/useStorage.ts +169 -0
  243. package/src/hooks/useStyle.ts +8 -2
  244. package/src/hooks/useToggle.ts +54 -0
  245. package/src/index.ts +34 -9
  246. package/src/theme/ThemeProvider.tsx +3 -7
  247. package/src/theme/ThemeProvider.types.ts +1 -1
  248. package/src/theme/defaults.ts +1 -1
  249. package/src/theme/design-system.ts +2 -2
  250. package/src/theme/design-tokens.ts +85 -99
  251. package/src/theme/generated/dark-theme.scss +1 -1
  252. package/src/theme/generated/tokens.scss +82 -18
  253. package/src/theme/index.ts +8 -29
  254. package/src/theme/responsive.tsx +36 -34
  255. package/src/theme/styles.ts +1 -1
  256. package/src/theme/useThemeUtils.ts +43 -43
  257. package/src/theme/utils.ts +32 -32
  258. package/src/theme/variables.ts +70 -51
  259. package/src/types/accessibility.ts +36 -37
  260. package/src/types/button.ts +25 -27
  261. package/src/types/component-props.ts +6 -1
  262. package/src/types/glob.d.ts +4 -0
  263. package/src/types/index.ts +2 -2
  264. package/src/types/standardized-components.ts +9 -3
  265. package/src/types/utils.ts +13 -23
  266. package/src/utils/__tests__/responsiveUtils.test.ts +5 -4
  267. package/src/utils/abort-controller.ts +48 -0
  268. package/src/utils/cache.ts +2 -6
  269. package/src/utils/createNamespace.ts +4 -4
  270. package/src/utils/environment.ts +26 -6
  271. package/src/utils/error-handler.ts +2 -2
  272. package/src/utils/errorLogger.ts +16 -20
  273. package/src/utils/formatUtils.ts +38 -70
  274. package/src/utils/http/error-codes.ts +314 -0
  275. package/src/utils/http/http-client.test.ts +63 -0
  276. package/src/utils/{network → http}/http-client.ts +45 -35
  277. package/src/utils/http/request-cache.ts +127 -0
  278. package/src/utils/http/request.ts +954 -0
  279. package/src/utils/http/taro-adapter.test.ts +74 -0
  280. package/src/utils/http/taro-adapter.ts +24 -0
  281. package/src/utils/http/types.ts +414 -0
  282. package/src/utils/http/web-adapter.ts +33 -0
  283. package/src/utils/index.ts +5 -8
  284. package/src/utils/inputValidator.ts +17 -14
  285. package/src/utils/performance/performance.ts +60 -71
  286. package/src/utils/responsiveUtils.ts +7 -16
  287. package/src/utils/rtl-support.ts +29 -19
  288. package/src/utils/security/api-security.ts +47 -39
  289. package/src/utils/securityHeaders.ts +61 -67
  290. package/src/utils/typeHelpers.ts +10 -10
  291. package/src/utils/types/dataProcessing.ts +93 -92
  292. package/src/utils/types/typeHelpers.ts +31 -21
  293. package/src/utils/xssProtection.ts +96 -48
  294. package/dist/js/index-6NJ3A1Dn.js.map +0 -1
  295. package/dist/js/index-DffLRSro.js.map +0 -1
  296. package/src/components/form/Input/Input.enhanced.tsx +0 -732
  297. package/src/components/navigation/Menu/__tests__/Menu.test.tsx +0 -687
  298. package/src/components/navigation/Tree/Tree.styles.ts +0 -553
  299. package/src/components/navigation/Tree/Tree.test.basic.tsx +0 -7
  300. package/src/components/navigation/Tree/Tree.test.functional.tsx +0 -496
  301. package/src/components/navigation/Tree/Tree.test.import.check.tsx +0 -6
  302. package/src/components/navigation/Tree/Tree.test.import.tsx +0 -6
  303. package/src/components/navigation/Tree/Tree.test.minimal.tsx +0 -5
  304. package/src/components/navigation/Tree/Tree.test.simple.tsx +0 -30
  305. package/src/components/navigation/Tree/Tree.test.tsx +0 -908
  306. package/src/components/navigation/Tree/Tree.test.working.tsx +0 -673
  307. package/src/components/navigation/Tree/Tree.tsx +0 -600
  308. package/src/components/navigation/Tree/Tree.types.ts +0 -909
  309. package/src/components/navigation/Tree/Tree.utils.ts +0 -452
  310. package/src/components/navigation/Tree/index.ts +0 -33
  311. package/src/components/navigation/Tree/index.tsx +0 -23
  312. package/src/utils/network/http-client.test.ts +0 -18
@@ -0,0 +1,233 @@
1
+ /**
2
+ * useMutation Hook
3
+ * React hook for data mutation operations (POST, PUT, DELETE, PATCH)
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const { mutate, loading, error } = useMutation<User, CreateUserInput>({
8
+ * url: '/api/users',
9
+ * method: 'POST',
10
+ * onSuccess: (data) => {
11
+ * console.log('User created:', data);
12
+ * },
13
+ * });
14
+ *
15
+ * // Trigger mutation
16
+ * await mutate({ name: 'John Doe', email: 'john@example.com' });
17
+ * ```
18
+ */
19
+
20
+ import { useState, useCallback, useRef, useEffect } from 'react';
21
+ import { Request } from '../utils/http/request';
22
+ import type { RequestOptions, UseMutationOptions, MutationState } from '../utils/http/types';
23
+
24
+ export interface UseMutationResult<T, V = any> extends MutationState<T, V> {
25
+ /** Execute mutation */
26
+ mutate: (variables: V, options?: Partial<RequestOptions>) => Promise<T | undefined>;
27
+ /** Execute mutation (async version) */
28
+ mutateAsync: (variables: V, options?: Partial<RequestOptions>) => Promise<T>;
29
+ /** Reset mutation state */
30
+ reset: () => void;
31
+ }
32
+
33
+ /**
34
+ * Hook for mutation operations (POST, PUT, DELETE, PATCH)
35
+ */
36
+ export function useMutation<T = any, V = any>(
37
+ options: RequestOptions & UseMutationOptions<T, V>,
38
+ ): UseMutationResult<T, V> {
39
+ const {
40
+ optimisticData,
41
+ rollbackOnError = false,
42
+ onError,
43
+ onSuccess,
44
+ onMutate,
45
+ onCompleted,
46
+ ...requestOptions
47
+ } = options;
48
+
49
+ const [state, setState] = useState<MutationState<T, V>>({
50
+ data: null,
51
+ error: null,
52
+ loading: false,
53
+ variables: null,
54
+ });
55
+
56
+ const clientRef = useRef<Request>(new Request());
57
+ const previousDataRef = useRef<T | null>(null);
58
+ const mountedRef = useRef(true);
59
+
60
+ // Cleanup on unmount
61
+ useEffect(() => {
62
+ return () => {
63
+ mountedRef.current = false;
64
+ };
65
+ }, []);
66
+
67
+ /**
68
+ * Execute mutation
69
+ */
70
+ const mutateAsync = useCallback(
71
+ async (variables: V, overrideOptions?: Partial<RequestOptions>): Promise<T> => {
72
+ const mergedOptions = {
73
+ ...requestOptions,
74
+ ...overrideOptions,
75
+ data: variables,
76
+ };
77
+
78
+ // Store previous data for potential rollback
79
+ previousDataRef.current = state.data;
80
+
81
+ // Call onMutate hook
82
+ if (onMutate) {
83
+ await onMutate(variables);
84
+ }
85
+
86
+ // Apply optimistic update
87
+ if (optimisticData) {
88
+ const optimisticResult = optimisticData(variables);
89
+ setState({
90
+ data: optimisticResult,
91
+ error: null,
92
+ loading: true,
93
+ variables,
94
+ });
95
+ } else {
96
+ setState((prev) => ({
97
+ ...prev,
98
+ loading: true,
99
+ error: null,
100
+ variables,
101
+ }));
102
+ }
103
+
104
+ try {
105
+ const result = await clientRef.current.request<T>(mergedOptions);
106
+
107
+ if (mountedRef.current) {
108
+ setState({
109
+ data: result,
110
+ error: null,
111
+ loading: false,
112
+ variables,
113
+ });
114
+
115
+ onSuccess?.(result, variables);
116
+ onCompleted?.(result, null, variables);
117
+ }
118
+
119
+ return result;
120
+ } catch (error) {
121
+ const err = error as Error;
122
+
123
+ if (mountedRef.current) {
124
+ // Rollback optimistic update if enabled
125
+ const finalData = rollbackOnError ? previousDataRef.current : state.data;
126
+
127
+ setState({
128
+ data: finalData,
129
+ error: err,
130
+ loading: false,
131
+ variables,
132
+ });
133
+
134
+ onError?.(err, variables);
135
+ onCompleted?.(null, err, variables);
136
+ }
137
+
138
+ throw err;
139
+ }
140
+ },
141
+ [requestOptions, optimisticData, rollbackOnError, onMutate, onError, onSuccess, onCompleted, state.data],
142
+ );
143
+
144
+ /**
145
+ * Execute mutation (returns undefined on error for compatibility)
146
+ */
147
+ const mutate = useCallback(
148
+ async (variables: V, overrideOptions?: Partial<RequestOptions>): Promise<T | undefined> => {
149
+ try {
150
+ return await mutateAsync(variables, overrideOptions);
151
+ } catch {
152
+ return undefined;
153
+ }
154
+ },
155
+ [mutateAsync],
156
+ );
157
+
158
+ /**
159
+ * Reset mutation state
160
+ */
161
+ const reset = useCallback(() => {
162
+ setState({
163
+ data: null,
164
+ error: null,
165
+ loading: false,
166
+ variables: null,
167
+ });
168
+ previousDataRef.current = null;
169
+ }, []);
170
+
171
+ return {
172
+ ...state,
173
+ mutate,
174
+ mutateAsync,
175
+ reset,
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Hook for POST mutations
181
+ */
182
+ export function usePost<T = any, V = any>(
183
+ url: string,
184
+ options: Omit<UseMutationOptions<T, V>, 'url' | 'method'> = {},
185
+ ): UseMutationResult<T, V> {
186
+ return useMutation<T, V>({
187
+ ...options,
188
+ url,
189
+ method: 'POST',
190
+ });
191
+ }
192
+
193
+ /**
194
+ * Hook for PUT mutations
195
+ */
196
+ export function usePut<T = any, V = any>(
197
+ url: string,
198
+ options: Omit<UseMutationOptions<T, V>, 'url' | 'method'> = {},
199
+ ): UseMutationResult<T, V> {
200
+ return useMutation<T, V>({
201
+ ...options,
202
+ url,
203
+ method: 'PUT',
204
+ });
205
+ }
206
+
207
+ /**
208
+ * Hook for PATCH mutations
209
+ */
210
+ export function usePatch<T = any, V = any>(
211
+ url: string,
212
+ options: Omit<UseMutationOptions<T, V>, 'url' | 'method'> = {},
213
+ ): UseMutationResult<T, V> {
214
+ return useMutation<T, V>({
215
+ ...options,
216
+ url,
217
+ method: 'PATCH',
218
+ });
219
+ }
220
+
221
+ /**
222
+ * Hook for DELETE mutations
223
+ */
224
+ export function useDelete<T = any, V = any>(
225
+ url: string,
226
+ options: Omit<UseMutationOptions<T, V>, 'url' | 'method'> = {},
227
+ ): UseMutationResult<T, V> {
228
+ return useMutation<T, V>({
229
+ ...options,
230
+ url,
231
+ method: 'DELETE',
232
+ });
233
+ }
@@ -372,70 +372,7 @@ export function usePriorityUpdates<T>(
372
372
  };
373
373
  }
374
374
 
375
- // ==================== 性能监控 ====================
376
-
377
- interface PerformanceMetrics {
378
- renderTime: number;
379
- updateTime: number;
380
- memoryUsage?: {
381
- usedJSHeapSize: number;
382
- totalJSHeapSize: number;
383
- };
384
- }
385
-
386
- /** 性能监控hook */
387
- export function usePerformanceMonitor(_componentName: string) {
388
- const [metrics, setMetrics] = useState<PerformanceMetrics>({
389
- renderTime: 0,
390
- updateTime: 0,
391
- });
392
-
393
- const startTimeRef = useRef<number>(0);
394
-
395
- const startMeasure = useCallback(() => {
396
- startTimeRef.current = performance.now();
397
- }, []);
398
-
399
- const endMeasure = useCallback(() => {
400
- const endTime = performance.now();
401
- const renderTime = endTime - startTimeRef.current;
402
-
403
- setMetrics((prev) => ({
404
- ...prev,
405
- renderTime,
406
- updateTime: prev.updateTime + renderTime,
407
- }));
408
-
409
- // 获取内存使用情况
410
- if (typeof performance !== 'undefined' && 'memory' in performance) {
411
- const memory = (performance as unknown as { memory?: { usedJSHeapSize: number; totalJSHeapSize: number } })
412
- .memory;
413
- setMetrics((prev) => ({
414
- ...prev,
415
- memoryUsage: memory
416
- ? {
417
- usedJSHeapSize: memory.usedJSHeapSize,
418
- totalJSHeapSize: memory.totalJSHeapSize,
419
- }
420
- : prev.memoryUsage,
421
- }));
422
- }
423
- }, []);
424
-
425
- const resetMetrics = useCallback(() => {
426
- setMetrics({
427
- renderTime: 0,
428
- updateTime: 0,
429
- });
430
- }, []);
431
-
432
- return {
433
- metrics,
434
- startMeasure,
435
- endMeasure,
436
- resetMetrics,
437
- };
438
- }
375
+ // usePerformanceMonitor removed to avoid conflict with usePerformanceMonitor.ts
439
376
 
440
377
  // ==================== 导出 ====================
441
378
  // 所有函数已在文件开头单独导出
@@ -15,7 +15,9 @@ export const usePlatform = () => {
15
15
  const env = String(Taro.getEnv()).toLowerCase();
16
16
  return env as any;
17
17
  }
18
- } catch {}
18
+ } catch {
19
+ // ignore
20
+ }
19
21
 
20
22
  if (typeof import.meta !== 'undefined' && (import.meta as any)?.env?.TARO_ENV) {
21
23
  return (import.meta as any).env.TARO_ENV as string;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * usePrevious Hook
3
+ * Get the previous value of a variable from the last render
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const [count, setCount] = useState(0);
8
+ * const prevCount = usePrevious(count); // Get the previous count value
9
+ * ```
10
+ */
11
+
12
+ import { useRef, useEffect } from 'react';
13
+
14
+ /**
15
+ * Hook for getting the previous value of a variable from the last render
16
+ */
17
+ export function usePrevious<T>(value: T): T | undefined {
18
+ const ref = useRef<T | undefined>(undefined);
19
+
20
+ useEffect(() => {
21
+ ref.current = value;
22
+ }, [value]);
23
+
24
+ return ref.current;
25
+ }
@@ -1,12 +1,13 @@
1
1
  import { useCallback, useEffect, useMemo } from 'react';
2
- import { httpClient, HttpClient, RequestOptions } from '@/utils/network/http-client';
2
+ import { request as httpClient, Request } from '@/utils/http/request';
3
3
  import { dataFetcher } from '@/utils/cache';
4
4
  import { useAsync } from './useAsync';
5
+ import type { RequestOptions as UnifiedRequestOptions } from '@/utils/http/types';
5
6
 
6
7
  export interface UseRequestOptions<T = unknown> {
7
- client?: HttpClient;
8
- service?: ((client: HttpClient) => Promise<T>) | string;
9
- method?: RequestOptions['method'];
8
+ client?: Request;
9
+ service?: ((client: Request) => Promise<T>) | string;
10
+ method?: UnifiedRequestOptions['method'];
10
11
  params?: Record<string, unknown>;
11
12
  data?: unknown;
12
13
  manual?: boolean;
@@ -53,15 +54,19 @@ export function useRequest<T = unknown>(options: UseRequestOptions<T>): UseReque
53
54
  const exec = useCallback(async () => {
54
55
  const fetcher = async (): Promise<T> => {
55
56
  if (typeof options.service === 'string') {
56
- return await client.request<T>(options.service, {
57
+ return await client.request<T>({
58
+ url: options.service,
57
59
  method: options.method || 'GET',
58
60
  params: options.params ?? {},
59
61
  data: options.data,
60
62
  timeout: options.staleTime ? Math.max(options.staleTime, 1000) : 15000,
61
- retries: options.retry ?? (options.method === 'GET' ? 3 : 0),
63
+ retry: {
64
+ retries: options.retry ?? (options.method === 'GET' ? 3 : 0),
65
+ retryDelay: options.retryDelay ?? 1000,
66
+ },
62
67
  });
63
68
  }
64
- return await (options.service as (c: HttpClient) => Promise<T>)(client);
69
+ return await (options.service as (c: Request) => Promise<T>)(client);
65
70
  };
66
71
 
67
72
  const result = await dataFetcher.fetch<T>(key, fetcher, {
@@ -206,7 +206,7 @@ export function useValidatedState<T>(
206
206
  // ==================== 状态批量更新 ====================
207
207
 
208
208
  /** 状态批量更新hook */
209
- export function useBatchUpdate<T extends Record<string, unknown>>(initialState: T) {
209
+ export function useBatchStateUpdate<T extends Record<string, unknown>>(initialState: T) {
210
210
  const [state, setState] = useState<T>(initialState);
211
211
  const pendingUpdates = useRef<Partial<T>>({});
212
212
 
@@ -0,0 +1,169 @@
1
+ /**
2
+ * useLocalStorage Hook
3
+ * Persist state to localStorage with automatic serialization
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const [user, setUser, removeUser] = useLocalStorage<User>('user', null);
8
+ * setUser({ id: 1, name: 'John' }); // Saved to localStorage['user']
9
+ * removeUser(); // Clears from localStorage
10
+ * ```
11
+ */
12
+
13
+ import { useState, useCallback, useEffect } from 'react';
14
+ import Taro from '@tarojs/taro';
15
+
16
+ export interface UseStorageOptions<T> {
17
+ /** Custom serializer */
18
+ serializer?: (value: T) => string;
19
+ /** Custom deserializer */
20
+ deserializer?: (value: string) => T;
21
+ /** Initialize from storage on mount */
22
+ initializeWithValue?: boolean;
23
+ }
24
+
25
+ /**
26
+ * Hook for persisting state to localStorage
27
+ */
28
+ export function useLocalStorage<T>(
29
+ key: string,
30
+ initialValue: T,
31
+ options: UseStorageOptions<T> = {},
32
+ ): [T, (value: T | ((prev: T) => T)) => void, () => void] {
33
+ const { serializer = JSON.stringify, deserializer = JSON.parse, initializeWithValue = true } = options;
34
+
35
+ // Get initial value from storage or use provided initial value
36
+ const readValue = useCallback((): T => {
37
+ try {
38
+ // In Taro, we need to use async storage API, but for initial value
39
+ // we'll use the provided initial value and fetch asynchronously later
40
+ return initialValue;
41
+ } catch (error) {
42
+ console.warn(`Error reading storage key "${key}":`, error);
43
+ return initialValue;
44
+ }
45
+ }, [key, initialValue, deserializer]);
46
+
47
+ const [storedValue, setStoredValue] = useState<T>(() => {
48
+ if (initializeWithValue) {
49
+ return readValue();
50
+ }
51
+ return initialValue;
52
+ });
53
+
54
+ // Set value in storage
55
+ const setValue = useCallback(
56
+ (value: T | ((prev: T) => T)) => {
57
+ try {
58
+ // Allow value to be a function so we have same API as useState
59
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
60
+
61
+ // Save to state
62
+ setStoredValue(valueToStore);
63
+
64
+ // Save to storage using Taro API
65
+ Taro.setStorageSync(key, serializer(valueToStore));
66
+ } catch (error) {
67
+ console.warn(`Error setting storage key "${key}":`, error);
68
+ }
69
+ },
70
+ [key, serializer, storedValue],
71
+ );
72
+
73
+ // Remove value from storage
74
+ const removeValue = useCallback(() => {
75
+ try {
76
+ Taro.removeStorageSync(key);
77
+ setStoredValue(initialValue);
78
+ } catch (error) {
79
+ console.warn(`Error removing storage key "${key}":`, error);
80
+ }
81
+ }, [key, initialValue]);
82
+
83
+ // Fetch initial value from storage asynchronously
84
+ useEffect(() => {
85
+ const fetchInitialValue = () => {
86
+ try {
87
+ const item = Taro.getStorageSync(key);
88
+ if (item.data) {
89
+ setStoredValue(deserializer(item.data));
90
+ }
91
+ } catch (error) {
92
+ console.warn(`Error reading storage key "${key}":`, error);
93
+ }
94
+ };
95
+
96
+ fetchInitialValue();
97
+ }, [key, initialValue, deserializer]);
98
+
99
+ // Fetch initial value from storage asynchronously
100
+ useEffect(() => {
101
+ const fetchInitialValue = () => {
102
+ try {
103
+ const item = Taro.getStorageSync(key);
104
+ if (item.data) {
105
+ setStoredValue(deserializer(item.data));
106
+ }
107
+ } catch (error) {
108
+ console.warn(`Error reading storage key "${key}":`, error);
109
+ }
110
+ };
111
+
112
+ fetchInitialValue();
113
+ }, [key, initialValue, deserializer]);
114
+
115
+ return [storedValue, setValue, removeValue];
116
+ }
117
+
118
+ /**
119
+ * Hook for persisting state to sessionStorage
120
+ */
121
+ export function useSessionStorage<T>(
122
+ key: string,
123
+ initialValue: T,
124
+ options: UseStorageOptions<T> = {},
125
+ ): [T, (value: T | ((prev: T) => T)) => void, () => void] {
126
+ const { serializer = JSON.stringify, deserializer = JSON.parse, initializeWithValue = true } = options;
127
+
128
+ const readValue = useCallback((): T => {
129
+ try {
130
+ // In Taro, we need to use async storage API, but for initial value
131
+ // we'll use the provided initial value and fetch asynchronously later
132
+ return initialValue;
133
+ } catch (error) {
134
+ console.warn(`Error reading storage key "${key}":`, error);
135
+ return initialValue;
136
+ }
137
+ }, [key, initialValue, deserializer]);
138
+
139
+ const [storedValue, setStoredValue] = useState<T>(() => {
140
+ if (initializeWithValue) {
141
+ return readValue();
142
+ }
143
+ return initialValue;
144
+ });
145
+
146
+ const setValue = useCallback(
147
+ (value: T | ((prev: T) => T)) => {
148
+ try {
149
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
150
+ setStoredValue(valueToStore);
151
+ Taro.setStorageSync(key, serializer(valueToStore));
152
+ } catch (error) {
153
+ console.warn(`Error setting storage key "${key}":`, error);
154
+ }
155
+ },
156
+ [key, serializer, storedValue],
157
+ );
158
+
159
+ const removeValue = useCallback(() => {
160
+ try {
161
+ Taro.removeStorageSync(key);
162
+ setStoredValue(initialValue);
163
+ } catch (error) {
164
+ console.warn(`Error removing storage key "${key}":`, error);
165
+ }
166
+ }, [key, initialValue]);
167
+
168
+ return [storedValue, setValue, removeValue];
169
+ }
@@ -137,7 +137,10 @@ export const useStyle = () => {
137
137
  * @param baseStyle 基础样式
138
138
  * @returns 包含激活效果的样式对象
139
139
  */
140
- const active = (activeStyle: Record<string, unknown>, baseStyle?: Record<string, unknown>): Record<string, unknown> => {
140
+ const active = (
141
+ activeStyle: Record<string, unknown>,
142
+ baseStyle?: Record<string, unknown>,
143
+ ): Record<string, unknown> => {
141
144
  return {
142
145
  ...baseStyle,
143
146
  '&:active': activeStyle,
@@ -150,7 +153,10 @@ export const useStyle = () => {
150
153
  * @param baseStyle 基础样式
151
154
  * @returns 包含禁用效果的样式对象
152
155
  */
153
- const disabled = (disabledStyle: Record<string, unknown>, baseStyle?: Record<string, unknown>): Record<string, unknown> => {
156
+ const disabled = (
157
+ disabledStyle: Record<string, unknown>,
158
+ baseStyle?: Record<string, unknown>,
159
+ ): Record<string, unknown> => {
154
160
  return {
155
161
  ...baseStyle,
156
162
  '&:disabled': disabledStyle,
@@ -0,0 +1,54 @@
1
+ /**
2
+ * useToggle Hook
3
+ * Simple boolean state toggle with optional callbacks
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const [isOpen, toggle, setIsOpen] = useToggle(false);
8
+ * toggle(); // true
9
+ * toggle(); // false
10
+ * setIsOpen(true); // true
11
+ * ```
12
+ */
13
+
14
+ import { useState, useCallback } from 'react';
15
+
16
+ export interface UseToggleReturn {
17
+ /** Current boolean value */
18
+ value: boolean;
19
+ /** Toggle the value */
20
+ toggle: () => void;
21
+ /** Set to true */
22
+ setTrue: () => void;
23
+ /** Set to false */
24
+ setFalse: () => void;
25
+ /** Set to specific value */
26
+ setValue: (value: boolean) => void;
27
+ }
28
+
29
+ /**
30
+ * Hook for managing boolean toggle state
31
+ */
32
+ export function useToggle(initialValue: boolean = false): UseToggleReturn {
33
+ const [value, setValue] = useState(initialValue);
34
+
35
+ const toggle = useCallback(() => {
36
+ setValue((v) => !v);
37
+ }, []);
38
+
39
+ const setTrue = useCallback(() => {
40
+ setValue(true);
41
+ }, []);
42
+
43
+ const setFalse = useCallback(() => {
44
+ setValue(false);
45
+ }, []);
46
+
47
+ return {
48
+ value,
49
+ toggle,
50
+ setTrue,
51
+ setFalse,
52
+ setValue,
53
+ };
54
+ }