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.
- package/README.md +21 -0
- package/dist/js/{index-DffLRSro.js → index-CDFsvu80.js} +15369 -10741
- package/dist/js/index-CDFsvu80.js.map +1 -0
- package/dist/js/index-DFdcksbe.js.map +1 -1
- package/dist/js/index-DXRIkWX1.js.map +1 -1
- package/dist/js/{index-6NJ3A1Dn.js → index-JffnTUrv.js} +15430 -10801
- package/dist/js/index-JffnTUrv.js.map +1 -0
- package/dist/utils/http/request.d.ts +280 -0
- package/package.json +14 -10
- package/src/components/basic/Button/Button.tsx +53 -13
- package/src/components/basic/Button/Button.types.ts +45 -9
- package/src/components/basic/Divider/Divider.tsx +60 -29
- package/src/components/basic/Icon/Icon.data.ts +474 -0
- package/src/components/basic/Icon/Icon.test.tsx +2 -2
- package/src/components/basic/Icon/Icon.tsx +48 -35
- package/src/components/basic/Icon/IconManager.ts +229 -0
- package/src/components/basic/Text/Text.styles.ts +3 -3
- package/src/components/basic/Text/Text.types.ts +14 -4
- package/src/components/basic/Typography/Typography.styles.ts +10 -9
- package/src/components/basic/Typography/Typography.tsx +15 -13
- package/src/components/basic/Typography/Typography.types.ts +41 -41
- package/src/components/basic/Typography/index.tsx +1 -1
- package/src/components/basic/Video/Video.styles.ts +777 -0
- package/src/components/basic/Video/Video.test.tsx +490 -0
- package/src/components/basic/Video/Video.tsx +1468 -0
- package/src/components/basic/Video/Video.types.ts +500 -0
- package/src/components/basic/Video/index.tsx +26 -0
- package/src/components/basic/index.tsx +13 -15
- package/src/components/common/ErrorBoundary.tsx +1 -1
- package/src/components/common/LazyComponent.tsx +9 -8
- package/src/components/common/SecurityProvider.tsx +2 -14
- package/src/components/common/ThemeProvider.tsx +43 -56
- package/src/components/common/VirtualList.tsx +187 -205
- package/src/components/common/index.tsx +25 -0
- package/src/components/display/Avatar/Avatar.styles.ts +1 -1
- package/src/components/display/Avatar/Avatar.tsx +6 -19
- package/src/components/display/Avatar/Avatar.types.ts +1 -1
- package/src/components/display/Avatar/index.ts +1 -1
- package/src/components/display/Badge/Badge.tsx +3 -16
- package/src/components/display/Badge/Badge.types.ts +1 -1
- package/src/components/display/Badge/index.ts +1 -1
- package/src/components/display/Calendar/Calendar.styles.ts +36 -36
- package/src/components/display/Calendar/Calendar.test.tsx +27 -15
- package/src/components/display/Calendar/Calendar.tsx +56 -35
- package/src/components/display/Calendar/Calendar.types.ts +1 -1
- package/src/components/display/Calendar/index.ts +1 -1
- package/src/components/display/Card/Card.styles.ts +2 -2
- package/src/components/display/Card/Card.test.tsx +6 -4
- package/src/components/display/Card/Card.tsx +1 -1
- package/src/components/display/Card/Card.types.ts +4 -4
- package/src/components/display/Card/index.ts +1 -1
- package/src/components/display/Carousel/Carousel.styles.ts +31 -31
- package/src/components/display/Carousel/Carousel.tsx +34 -39
- package/src/components/display/Carousel/Carousel.types.ts +1 -1
- package/src/components/display/Carousel/index.ts +1 -1
- package/src/components/display/List/List.styles.ts +3 -3
- package/src/components/display/List/List.tsx +0 -1
- package/src/components/display/List/index.ts +1 -1
- package/src/components/display/Rate/Rate.styles.ts +5 -17
- package/src/components/display/Rate/Rate.tsx +6 -14
- package/src/components/display/Rate/Rate.types.ts +4 -3
- package/src/components/display/Rate/index.ts +3 -11
- package/src/components/display/Table/Table.test.tsx +2 -0
- package/src/components/display/Table/Table.tsx +3 -7
- package/src/components/display/Table/Table.types.ts +3 -2
- package/src/components/display/Tag/Tag.styles.ts +31 -31
- package/src/components/display/Tag/Tag.tsx +9 -26
- package/src/components/display/Tag/Tag.types.ts +1 -1
- package/src/components/display/Tag/index.ts +1 -1
- package/src/components/display/Timeline/Timeline.styles.ts +32 -32
- package/src/components/display/Timeline/Timeline.tsx +23 -42
- package/src/components/display/Timeline/Timeline.types.ts +1 -1
- package/src/components/display/Timeline/index.ts +1 -1
- package/src/components/display/index.tsx +33 -29
- package/src/components/feedback/Loading/Loading.tsx +6 -1
- package/src/components/feedback/Loading/index.ts +2 -5
- package/src/components/feedback/Message/Message.styles.ts +3 -3
- package/src/components/feedback/Message/index.ts +2 -5
- package/src/components/feedback/Modal/Modal.styles.ts +1 -1
- package/src/components/feedback/Modal/Modal.tsx +9 -31
- package/src/components/feedback/Modal/Modal.types.ts +12 -2
- package/src/components/feedback/Notification/Notification.styles.ts +49 -39
- package/src/components/feedback/Notification/Notification.test.tsx +1 -1
- package/src/components/feedback/Notification/Notification.tsx +97 -120
- package/src/components/feedback/Notification/Notification.types.ts +11 -8
- package/src/components/feedback/Notification/NotificationManager.tsx +135 -106
- package/src/components/feedback/Notification/index.ts +10 -3
- package/src/components/feedback/Notification/index.tsx +16 -26
- package/src/components/feedback/Progress/Progress.styles.ts +23 -14
- package/src/components/feedback/Progress/Progress.tsx +93 -113
- package/src/components/feedback/Progress/Progress.types.ts +1 -1
- package/src/components/feedback/Progress/index.ts +1 -1
- package/src/components/feedback/Progress/utils/animation.ts +12 -23
- package/src/components/feedback/Progress/utils/index.ts +2 -2
- package/src/components/feedback/Progress/utils/progress-calculator.ts +14 -32
- package/src/components/feedback/Result/Result.styles.ts +29 -29
- package/src/components/feedback/Result/Result.tsx +8 -20
- package/src/components/feedback/Result/Result.types.ts +7 -7
- package/src/components/feedback/Result/index.tsx +1 -1
- package/src/components/feedback/Toast/Toast.styles.ts +1 -1
- package/src/components/feedback/Toast/Toast.tsx +25 -13
- package/src/components/feedback/Tooltip/Tooltip.examples.tsx +21 -44
- package/src/components/feedback/Tooltip/Tooltip.styles.ts +16 -22
- package/src/components/feedback/Tooltip/Tooltip.test.tsx +1 -1
- package/src/components/feedback/Tooltip/Tooltip.tsx +65 -46
- package/src/components/feedback/Tooltip/Tooltip.types.ts +14 -20
- package/src/components/feedback/Tooltip/index.ts +1 -1
- package/src/components/feedback/Tooltip/index.tsx +12 -24
- package/src/components/feedback/index.tsx +54 -42
- package/src/components/form/Cascader/Cascader.styles.ts +2 -2
- package/src/components/form/Cascader/Cascader.tsx +84 -88
- package/src/components/form/Cascader/Cascader.types.ts +49 -50
- package/src/components/form/Cascader/hooks/useCascaderFieldNames.ts +11 -8
- package/src/components/form/Cascader/hooks/useCascaderOptions.ts +73 -55
- package/src/components/form/Cascader/hooks/useCascaderState.ts +31 -25
- package/src/components/form/Cascader/index.ts +1 -1
- package/src/components/form/Cascader/utils/formatDisplayValue.ts +4 -4
- package/src/components/form/Checkbox/Checkbox.styles.ts +83 -84
- package/src/components/form/Checkbox/Checkbox.tsx +2 -9
- package/src/components/form/Checkbox/CheckboxGroup.tsx +7 -7
- package/src/components/form/DatePicker/DatePicker.test.tsx +1 -1
- package/src/components/form/DatePicker/DatePicker.tsx +91 -75
- package/src/components/form/DatePicker/DatePicker.types.ts +4 -1
- package/src/components/form/Form/Form.tsx +66 -504
- package/src/components/form/Form/Form.types.ts +16 -1
- package/src/components/form/Form/useFormLogic.ts +497 -0
- package/src/components/form/Input/Input.styles.ts +8 -1
- package/src/components/form/Input/Input.tsx +55 -291
- package/src/components/form/Input/Input.types.ts +13 -1
- package/src/components/form/Input/useInputLogic.test.ts +82 -0
- package/src/components/form/Input/useInputLogic.ts +260 -0
- package/src/components/form/InputNumber/InputNumber.styles.ts +76 -25
- package/src/components/form/InputNumber/InputNumber.tsx +53 -21
- package/src/components/form/InputNumber/InputNumber.types.ts +21 -3
- package/src/components/form/InputNumber/components/InputNumberClearButton.tsx +3 -11
- package/src/components/form/InputNumber/components/InputNumberControls.tsx +3 -12
- package/src/components/form/InputNumber/hooks/index.ts +1 -1
- package/src/components/form/InputNumber/hooks/useInputNumberState.ts +7 -9
- package/src/components/form/InputNumber/hooks/useInputNumberValidation.ts +18 -17
- package/src/components/form/InputNumber/index.ts +7 -7
- package/src/components/form/Radio/Radio.styles.ts +1 -8
- package/src/components/form/Radio/Radio.tsx +3 -9
- package/src/components/form/Radio/Radio.types.ts +5 -1
- package/src/components/form/Select/Select.styles.ts +5 -1
- package/src/components/form/Select/Select.tsx +15 -15
- package/src/components/form/Select/Select.types.ts +2 -1
- package/src/components/form/Slider/Slider.styles.ts +13 -13
- package/src/components/form/Slider/Slider.tsx +19 -33
- package/src/components/form/Slider/Slider.types.ts +14 -12
- package/src/components/form/Slider/index.tsx +2 -9
- package/src/components/form/Switch/Switch.styles.ts +1 -7
- package/src/components/form/Switch/Switch.tsx +7 -13
- package/src/components/form/Textarea/Textarea.styles.ts +4 -4
- package/src/components/form/Textarea/Textarea.tsx +7 -1
- package/src/components/form/Textarea/Textarea.types.ts +4 -1
- package/src/components/form/TimePicker/TimePicker.styles.ts +8 -12
- package/src/components/form/TimePicker/TimePicker.tsx +122 -100
- package/src/components/form/TimePicker/TimePicker.types.ts +2 -2
- package/src/components/form/TimePicker/index.ts +1 -1
- package/src/components/form/Transfer/Transfer.styles.ts +3 -15
- package/src/components/form/Transfer/Transfer.tsx +146 -134
- package/src/components/form/Transfer/Transfer.types.ts +34 -26
- package/src/components/form/Transfer/components/TransferItem.tsx +55 -62
- package/src/components/form/Transfer/components/TransferList.tsx +212 -199
- package/src/components/form/Transfer/components/TransferOperations.tsx +52 -55
- package/src/components/form/Transfer/components/TransferPagination.tsx +115 -111
- package/src/components/form/Transfer/components/TransferSearch.tsx +52 -55
- package/src/components/form/Transfer/hooks/useTransferData.ts +91 -81
- package/src/components/form/Transfer/hooks/useTransferState.ts +22 -16
- package/src/components/form/Transfer/index.ts +2 -8
- package/src/components/form/Upload/Upload.styles.ts +21 -21
- package/src/components/form/Upload/Upload.tsx +189 -142
- package/src/components/form/Upload/Upload.types.ts +31 -31
- package/src/components/form/Upload/index.tsx +1 -1
- package/src/components/form/index.tsx +60 -29
- package/src/components/index.tsx +0 -1
- package/src/components/layout/Affix/Affix.styles.ts +16 -11
- package/src/components/layout/Affix/Affix.tsx +67 -75
- package/src/components/layout/Affix/Affix.types.ts +18 -18
- package/src/components/layout/Affix/index.tsx +1 -1
- package/src/components/layout/Col/Col.styles.ts +17 -17
- package/src/components/layout/Col/Col.test.tsx +7 -5
- package/src/components/layout/Col/Col.tsx +3 -21
- package/src/components/layout/Col/Col.types.ts +1 -1
- package/src/components/layout/Container/Container.styles.ts +3 -1
- package/src/components/layout/Container/Container.tsx +2 -11
- package/src/components/layout/Grid/Grid.tsx +3 -53
- package/src/components/layout/Layout/Content.tsx +24 -32
- package/src/components/layout/Layout/Footer.tsx +24 -32
- package/src/components/layout/Layout/Header.tsx +24 -32
- package/src/components/layout/Layout/Layout.styles.ts +17 -17
- package/src/components/layout/Layout/Layout.tsx +14 -25
- package/src/components/layout/Layout/Layout.types.ts +29 -29
- package/src/components/layout/Layout/Sider.tsx +44 -56
- package/src/components/layout/Layout/index.tsx +16 -2
- package/src/components/layout/Row/Row.tsx +15 -43
- package/src/components/layout/Space/Space.tsx +3 -11
- package/src/components/layout/Space/Space.types.ts +1 -1
- package/src/components/layout/index.tsx +29 -19
- package/src/components/navigation/Menu/Menu.constants.ts +69 -0
- package/src/components/navigation/Menu/Menu.stories.tsx +107 -0
- package/src/components/navigation/Menu/Menu.styles.ts +25 -37
- package/src/components/navigation/Menu/Menu.tsx +8 -11
- package/src/components/navigation/Menu/Menu.types.ts +2 -2
- package/src/components/navigation/Menu/Menu.utils.ts +17 -17
- package/src/components/navigation/Menu/MenuItem.tsx +9 -11
- package/src/components/navigation/Menu/SubMenu.tsx +8 -6
- package/src/components/navigation/Menu/index.tsx +4 -69
- package/src/components/navigation/NavBar/NavBar.styles.ts +1 -1
- package/src/components/navigation/NavBar/NavBar.tsx +7 -10
- package/src/components/navigation/NavBar/NavBar.types.ts +3 -3
- package/src/components/navigation/NavBar/index.tsx +1 -1
- package/src/components/navigation/Pagination/Pagination.test.tsx +2 -3
- package/src/components/navigation/Pagination/Pagination.tsx +3 -3
- package/src/components/navigation/Pagination/Pagination.types.ts +3 -2
- package/src/components/navigation/Pagination/index.ts +9 -3
- package/src/components/navigation/Steps/Step.tsx +24 -44
- package/src/components/navigation/Steps/Steps.styles.ts +28 -13
- package/src/components/navigation/Steps/Steps.test.tsx +2 -0
- package/src/components/navigation/Steps/Steps.tsx +88 -89
- package/src/components/navigation/Steps/Steps.types.ts +30 -30
- package/src/components/navigation/Steps/index.tsx +1 -1
- package/src/components/navigation/Tabs/Tabs.test.tsx +3 -2
- package/src/components/navigation/Tabs/Tabs.types.ts +4 -3
- package/src/components/navigation/index.tsx +21 -16
- package/src/constants/index.ts +1 -1
- package/src/hooks/index.ts +52 -102
- package/src/hooks/types.ts +4 -5
- package/src/hooks/useAsync.ts +46 -47
- package/src/hooks/useClickOutside.ts +52 -0
- package/src/hooks/useCounter.ts +87 -0
- package/src/hooks/useDebounce.ts +150 -0
- package/src/hooks/useDeepCompareEffect.ts +88 -0
- package/src/hooks/useEventListener.ts +77 -0
- package/src/hooks/useMediaQuery.ts +75 -0
- package/src/hooks/useMutation.ts +233 -0
- package/src/hooks/usePerformance.ts +1 -64
- package/src/hooks/usePlatform.ts +3 -1
- package/src/hooks/usePrevious.ts +25 -0
- package/src/hooks/useRequest.ts +12 -7
- package/src/hooks/useStateManagement.ts +1 -1
- package/src/hooks/useStorage.ts +169 -0
- package/src/hooks/useStyle.ts +8 -2
- package/src/hooks/useToggle.ts +54 -0
- package/src/index.ts +34 -9
- package/src/theme/ThemeProvider.tsx +3 -7
- package/src/theme/ThemeProvider.types.ts +1 -1
- package/src/theme/defaults.ts +1 -1
- package/src/theme/design-system.ts +2 -2
- package/src/theme/design-tokens.ts +85 -99
- package/src/theme/generated/dark-theme.scss +1 -1
- package/src/theme/generated/tokens.scss +82 -18
- package/src/theme/index.ts +8 -29
- package/src/theme/responsive.tsx +36 -34
- package/src/theme/styles.ts +1 -1
- package/src/theme/useThemeUtils.ts +43 -43
- package/src/theme/utils.ts +32 -32
- package/src/theme/variables.ts +70 -51
- package/src/types/accessibility.ts +36 -37
- package/src/types/button.ts +25 -27
- package/src/types/component-props.ts +6 -1
- package/src/types/glob.d.ts +4 -0
- package/src/types/index.ts +2 -2
- package/src/types/standardized-components.ts +9 -3
- package/src/types/utils.ts +13 -23
- package/src/utils/__tests__/responsiveUtils.test.ts +5 -4
- package/src/utils/abort-controller.ts +48 -0
- package/src/utils/cache.ts +2 -6
- package/src/utils/createNamespace.ts +4 -4
- package/src/utils/environment.ts +26 -6
- package/src/utils/error-handler.ts +2 -2
- package/src/utils/errorLogger.ts +16 -20
- package/src/utils/formatUtils.ts +38 -70
- package/src/utils/http/error-codes.ts +314 -0
- package/src/utils/http/http-client.test.ts +63 -0
- package/src/utils/{network → http}/http-client.ts +45 -35
- package/src/utils/http/request-cache.ts +127 -0
- package/src/utils/http/request.ts +954 -0
- package/src/utils/http/taro-adapter.test.ts +74 -0
- package/src/utils/http/taro-adapter.ts +24 -0
- package/src/utils/http/types.ts +414 -0
- package/src/utils/http/web-adapter.ts +33 -0
- package/src/utils/index.ts +5 -8
- package/src/utils/inputValidator.ts +17 -14
- package/src/utils/performance/performance.ts +60 -71
- package/src/utils/responsiveUtils.ts +7 -16
- package/src/utils/rtl-support.ts +29 -19
- package/src/utils/security/api-security.ts +47 -39
- package/src/utils/securityHeaders.ts +61 -67
- package/src/utils/typeHelpers.ts +10 -10
- package/src/utils/types/dataProcessing.ts +93 -92
- package/src/utils/types/typeHelpers.ts +31 -21
- package/src/utils/xssProtection.ts +96 -48
- package/dist/js/index-6NJ3A1Dn.js.map +0 -1
- package/dist/js/index-DffLRSro.js.map +0 -1
- package/src/components/form/Input/Input.enhanced.tsx +0 -732
- package/src/components/navigation/Menu/__tests__/Menu.test.tsx +0 -687
- package/src/components/navigation/Tree/Tree.styles.ts +0 -553
- package/src/components/navigation/Tree/Tree.test.basic.tsx +0 -7
- package/src/components/navigation/Tree/Tree.test.functional.tsx +0 -496
- package/src/components/navigation/Tree/Tree.test.import.check.tsx +0 -6
- package/src/components/navigation/Tree/Tree.test.import.tsx +0 -6
- package/src/components/navigation/Tree/Tree.test.minimal.tsx +0 -5
- package/src/components/navigation/Tree/Tree.test.simple.tsx +0 -30
- package/src/components/navigation/Tree/Tree.test.tsx +0 -908
- package/src/components/navigation/Tree/Tree.test.working.tsx +0 -673
- package/src/components/navigation/Tree/Tree.tsx +0 -600
- package/src/components/navigation/Tree/Tree.types.ts +0 -909
- package/src/components/navigation/Tree/Tree.utils.ts +0 -452
- package/src/components/navigation/Tree/index.ts +0 -33
- package/src/components/navigation/Tree/index.tsx +0 -23
- 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
|
// 所有函数已在文件开头单独导出
|
package/src/hooks/usePlatform.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/hooks/useRequest.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
import { httpClient,
|
|
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?:
|
|
8
|
-
service?: ((client:
|
|
9
|
-
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>(
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
+
}
|
package/src/hooks/useStyle.ts
CHANGED
|
@@ -137,7 +137,10 @@ export const useStyle = () => {
|
|
|
137
137
|
* @param baseStyle 基础样式
|
|
138
138
|
* @returns 包含激活效果的样式对象
|
|
139
139
|
*/
|
|
140
|
-
const active = (
|
|
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 = (
|
|
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
|
+
}
|