@gateweb/react-utils 1.6.0 → 1.7.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.
@@ -438,6 +438,40 @@ declare const pickByValue: <T extends object, K extends any[]>(object: T, ...val
438
438
  *
439
439
  */
440
440
  declare const deepMerge: <T extends object, U extends object>(target: T, source: U) => T & U;
441
+ /**
442
+ * a utility type to make all properties of an object required
443
+ *
444
+ * @param T - the object type
445
+ * @param K - the keys to make required
446
+ * @param RemoveUndefined - whether to remove undefined from the type
447
+ *
448
+ * @example
449
+ *
450
+ * type A = { a?: number; b?: string | undefined; c?: boolean };
451
+ * // Even though b is required, it can be undefined
452
+ * type B = RequiredBy<A, 'a' | 'b'>; // { a: number; b: string | undefined; c?: boolean
453
+ * type C = RequiredBy<A, 'a' | 'b', true>; // { a: number; b: string; c?: boolean }
454
+ */
455
+ type RequiredBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
456
+ [P in K]-?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
457
+ };
458
+ /**
459
+ * a utility type to make all properties of an object optional
460
+ *
461
+ * @param T - the object type
462
+ * @param K - the keys to make optional
463
+ * @param RemoveUndefined - whether to remove undefined from the type
464
+ *
465
+ * @example
466
+ *
467
+ * type A = { a: number; b: string | undefined; c: boolean };
468
+ * // Even though b is optional, it can be undefined
469
+ * type B = PartialBy<A, 'a' | 'b'>; // { a?: number; b?: string | undefined; c: boolean }
470
+ * type C = PartialBy<A, 'a' | 'b', true>; // { a?: number; b?: string; c: boolean }
471
+ */
472
+ type PartialBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
473
+ [P in K]?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
474
+ };
441
475
 
442
476
  /**
443
477
  * debounce function
@@ -703,6 +737,56 @@ declare const isTWMobile: () => RegExp;
703
737
  */
704
738
  declare const isTWPhone: () => RegExp;
705
739
 
740
+ type TQueryProps<Q> = {
741
+ /**
742
+ * the query object
743
+ */
744
+ query: Partial<Q>;
745
+ };
746
+ type TQueryState<Q> = {
747
+ /**
748
+ * trigger the change of query
749
+ *
750
+ * @param query - the new query
751
+ */
752
+ changeQuery: (query: TQueryProps<Q>['query']) => void;
753
+ } & TQueryProps<Q>;
754
+ type TInitialProps<Q> = Partial<TQueryProps<Q> & {
755
+ /**
756
+ * handle the change of query when calling `changeQuery`
757
+ *
758
+ * @param preQuery - the previous query
759
+ * @param newQuery - the new query
760
+ * @returns the custom new query
761
+ */
762
+ handleChangeQuery: (preQuery: TQueryProps<Q>['query'], newQuery: TQueryProps<Q>['query']) => TQueryProps<Q>['query'];
763
+ }>;
764
+ /**
765
+ * Provider to provide the store to the context
766
+ */
767
+ declare const QueryProvider: <Q>({ children, query, handleChangeQuery, }: React.PropsWithChildren<TInitialProps<Q>>) => React.JSX.Element;
768
+ /**
769
+ * hook to get the store from the context
770
+ *
771
+ * because we want the return type of `selector` to be inferred by ts, we use HOF to implement the hook
772
+ *
773
+ * so you should use it like this:
774
+ *
775
+ * ```tsx
776
+ * const useQuery = useQueryContext<MyObject>(); // => will return the store hook
777
+ * const result = useQuery(q => q.query); // => will return the query object
778
+ * ```
779
+ *
780
+ * @example
781
+ *
782
+ * ```tsx
783
+ * const result1 = useQueryContext<MyObject>()(q => '1234');
784
+ * const result2 = useQueryContext<MyObject>()(q => q.changeQuery);
785
+ * const result3 = useQueryContext<MyObject>()(q => q.query);
786
+ * ```
787
+ */
788
+ declare const useQueryContext: <Q>() => <T>(selector: (state: TQueryState<Q>) => T, equalityFn?: (left: T, right: T) => boolean) => T;
789
+
706
790
  /**
707
791
  * 將數字轉換成金額千分位格式
708
792
  *
@@ -827,4 +911,5 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
827
911
  */
828
912
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
829
913
 
830
- export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useValue, validTaxId, validateDateString, validateFileType, wait };
914
+ export { QueryProvider, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useQueryContext, useValue, validTaxId, validateDateString, validateFileType, wait };
915
+ export type { PartialBy, RequiredBy, TCountdownActions };
package/dist/cjs/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
3
  var dayjs = require('dayjs');
4
- var useCountdownClient = require('./useCountdown-client-CNjGBIUB.js');
5
- var react = require('react');
4
+ var useCountdownClient = require('./useCountdown-client-uiqhgllY.js');
5
+ var React = require('react');
6
+ var queryStoreClient = require('./queryStore-client-q_SLGgYH.js');
6
7
  var downloadClient = require('./download-client-DKxkL92w.js');
7
8
  var webStorageClient = require('./webStorage-client-BGQKUfrO.js');
8
9
 
@@ -488,8 +489,8 @@ const transformObjectKey = (obj, transformFunName)=>{
488
489
  throw new Error('Either `value` or `defaultValue` must be provided.');
489
490
  }
490
491
  const isControlled = value !== undefined;
491
- const [internalValue, setInternalValue] = react.useState(defaultValue);
492
- const setValue = react.useCallback((newValue)=>{
492
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
493
+ const setValue = React.useCallback((newValue)=>{
493
494
  if (!isControlled) {
494
495
  setInternalValue(newValue);
495
496
  }
@@ -931,6 +932,8 @@ function mergeRefs(refs) {
931
932
  };
932
933
 
933
934
  exports.useCountdown = useCountdownClient.useCountdown;
935
+ exports.QueryProvider = queryStoreClient.QueryProvider;
936
+ exports.useQueryContext = queryStoreClient.useQueryContext;
934
937
  exports.downloadFile = downloadClient.downloadFile;
935
938
  exports.getLocalStorage = webStorageClient.getLocalStorage;
936
939
  exports.setLocalStorage = webStorageClient.setLocalStorage;
@@ -0,0 +1,77 @@
1
+ 'use client';
2
+ var React = require('react');
3
+ var zustand = require('zustand');
4
+ var traditional = require('zustand/traditional');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React__default = /*#__PURE__*/_interopDefault(React);
9
+
10
+ const createQueryStore = ({ query, handleChangeQuery })=>zustand.createStore()((set)=>({
11
+ query: {
12
+ ...query
13
+ },
14
+ changeQuery: (newQuery)=>{
15
+ set((pre)=>{
16
+ if (handleChangeQuery) {
17
+ return {
18
+ query: handleChangeQuery(pre.query, newQuery)
19
+ };
20
+ }
21
+ return {
22
+ query: {
23
+ ...pre.query,
24
+ ...newQuery
25
+ }
26
+ };
27
+ });
28
+ }
29
+ }));
30
+ const QueryContext = /*#__PURE__*/ React.createContext(null);
31
+ /**
32
+ * Provider to provide the store to the context
33
+ */ const QueryProvider = ({ children, query, handleChangeQuery })=>{
34
+ const storeRef = React.useRef(null);
35
+ if (!storeRef.current) {
36
+ storeRef.current = createQueryStore({
37
+ query,
38
+ handleChangeQuery
39
+ });
40
+ }
41
+ return /*#__PURE__*/ React__default.default.createElement(QueryContext.Provider, {
42
+ value: storeRef.current
43
+ }, children);
44
+ };
45
+ /**
46
+ * hook to get the store from the context
47
+ *
48
+ * because we want the return type of `selector` to be inferred by ts, we use HOF to implement the hook
49
+ *
50
+ * so you should use it like this:
51
+ *
52
+ * ```tsx
53
+ * const useQuery = useQueryContext<MyObject>(); // => will return the store hook
54
+ * const result = useQuery(q => q.query); // => will return the query object
55
+ * ```
56
+ *
57
+ * @example
58
+ *
59
+ * ```tsx
60
+ * const result1 = useQueryContext<MyObject>()(q => '1234');
61
+ * const result2 = useQueryContext<MyObject>()(q => q.changeQuery);
62
+ * const result3 = useQueryContext<MyObject>()(q => q.query);
63
+ * ```
64
+ */ const useQueryContext = ()=>{
65
+ const store = React.useContext(QueryContext);
66
+ if (!store) throw new Error('Missing QueryContext.Provider in the tree');
67
+ /**
68
+ * the hook to get the store
69
+ *
70
+ * @param selector - the selector to get the state from the store
71
+ * @param equalityFn - the equality function to compare the previous and next state, if it returns `true`, the component will not re-render
72
+ */ const useStore = (selector, equalityFn)=>traditional.useStoreWithEqualityFn(store, selector, equalityFn);
73
+ return useStore;
74
+ };
75
+
76
+ exports.QueryProvider = QueryProvider;
77
+ exports.useQueryContext = useQueryContext;
@@ -88,6 +88,8 @@ type Entries<T> = {
88
88
  *
89
89
  * @template T - The object type to transform into keys.
90
90
  *
91
+ * @deprecated Use `MapToType` instead.
92
+ *
91
93
  * @example
92
94
  *
93
95
  * type Example = { a: number; b: string };
@@ -171,5 +173,19 @@ type DeepPartial<T> = (T extends (infer U)[] ? DeepPartial<U>[] : {
171
173
  type TChangeKeyType<T, K extends keyof T, V> = Omit<T, K> & {
172
174
  [P in K]: V;
173
175
  };
176
+ /**
177
+ * A utility type that transforms an object type `T` into another object type where each value type is replaced with type `A`.
178
+ *
179
+ * @template T - The object type to transform into keys.
180
+ *
181
+ * @example
182
+ *
183
+ * type Example = { a: number; b: string };
184
+ * type ExampleToBoolean = MapToType<Example, boolean>;
185
+ * // Result: ExampleToBoolean is { a: boolean; b: boolean; }
186
+ */
187
+ type MapToType<T extends Record<any, any>, A = any> = {
188
+ [K in keyof T]: A;
189
+ };
174
190
 
175
- export type { AtLeastOne, DeepPartial, Entries, MapToString, OnlyOne, PopArgs, PushArgs, ShiftArgs, TChangeKeyType, TExtractValueType, UnshiftArgs };
191
+ export type { AtLeastOne, DeepPartial, Entries, MapToString, MapToType, OnlyOne, PopArgs, PushArgs, ShiftArgs, TChangeKeyType, TExtractValueType, UnshiftArgs };
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- var react = require('react');
2
+ var React = require('react');
3
3
 
4
4
  /**
5
5
  * 倒數計時器
@@ -11,17 +11,17 @@ var react = require('react');
11
11
  * @param initialCountdown 倒數計時器初始值
12
12
  * @param enableReinitialize 允許重設初始值
13
13
  */ const useCountdown = (initialCountdown, enableReinitialize = false)=>{
14
- const [countdown, setCountdown] = react.useState(initialCountdown);
15
- const [isCounting, setIsCounting] = react.useState(false);
16
- const initialValues = react.useRef(initialCountdown);
17
- const isMounted = react.useRef(false);
18
- react.useEffect(()=>{
14
+ const [countdown, setCountdown] = React.useState(initialCountdown);
15
+ const [isCounting, setIsCounting] = React.useState(false);
16
+ const initialValues = React.useRef(initialCountdown);
17
+ const isMounted = React.useRef(false);
18
+ React.useEffect(()=>{
19
19
  isMounted.current = true;
20
20
  return ()=>{
21
21
  isMounted.current = false;
22
22
  };
23
23
  }, []);
24
- react.useEffect(()=>{
24
+ React.useEffect(()=>{
25
25
  if (isMounted.current && initialValues.current !== initialCountdown && enableReinitialize) {
26
26
  initialValues.current = initialCountdown;
27
27
  setCountdown(initialCountdown);
@@ -30,7 +30,7 @@ var react = require('react');
30
30
  initialCountdown,
31
31
  enableReinitialize
32
32
  ]);
33
- react.useEffect(()=>{
33
+ React.useEffect(()=>{
34
34
  let timer;
35
35
  if (isCounting && countdown > 0) {
36
36
  timer = setTimeout(()=>{
@@ -438,6 +438,40 @@ declare const pickByValue: <T extends object, K extends any[]>(object: T, ...val
438
438
  *
439
439
  */
440
440
  declare const deepMerge: <T extends object, U extends object>(target: T, source: U) => T & U;
441
+ /**
442
+ * a utility type to make all properties of an object required
443
+ *
444
+ * @param T - the object type
445
+ * @param K - the keys to make required
446
+ * @param RemoveUndefined - whether to remove undefined from the type
447
+ *
448
+ * @example
449
+ *
450
+ * type A = { a?: number; b?: string | undefined; c?: boolean };
451
+ * // Even though b is required, it can be undefined
452
+ * type B = RequiredBy<A, 'a' | 'b'>; // { a: number; b: string | undefined; c?: boolean
453
+ * type C = RequiredBy<A, 'a' | 'b', true>; // { a: number; b: string; c?: boolean }
454
+ */
455
+ type RequiredBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
456
+ [P in K]-?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
457
+ };
458
+ /**
459
+ * a utility type to make all properties of an object optional
460
+ *
461
+ * @param T - the object type
462
+ * @param K - the keys to make optional
463
+ * @param RemoveUndefined - whether to remove undefined from the type
464
+ *
465
+ * @example
466
+ *
467
+ * type A = { a: number; b: string | undefined; c: boolean };
468
+ * // Even though b is optional, it can be undefined
469
+ * type B = PartialBy<A, 'a' | 'b'>; // { a?: number; b?: string | undefined; c: boolean }
470
+ * type C = PartialBy<A, 'a' | 'b', true>; // { a?: number; b?: string; c: boolean }
471
+ */
472
+ type PartialBy<T, K extends keyof T, RemoveUndefined extends boolean = false> = Omit<T, K> & {
473
+ [P in K]?: RemoveUndefined extends true ? Exclude<T[P], undefined> : T[P];
474
+ };
441
475
 
442
476
  /**
443
477
  * debounce function
@@ -703,6 +737,56 @@ declare const isTWMobile: () => RegExp;
703
737
  */
704
738
  declare const isTWPhone: () => RegExp;
705
739
 
740
+ type TQueryProps<Q> = {
741
+ /**
742
+ * the query object
743
+ */
744
+ query: Partial<Q>;
745
+ };
746
+ type TQueryState<Q> = {
747
+ /**
748
+ * trigger the change of query
749
+ *
750
+ * @param query - the new query
751
+ */
752
+ changeQuery: (query: TQueryProps<Q>['query']) => void;
753
+ } & TQueryProps<Q>;
754
+ type TInitialProps<Q> = Partial<TQueryProps<Q> & {
755
+ /**
756
+ * handle the change of query when calling `changeQuery`
757
+ *
758
+ * @param preQuery - the previous query
759
+ * @param newQuery - the new query
760
+ * @returns the custom new query
761
+ */
762
+ handleChangeQuery: (preQuery: TQueryProps<Q>['query'], newQuery: TQueryProps<Q>['query']) => TQueryProps<Q>['query'];
763
+ }>;
764
+ /**
765
+ * Provider to provide the store to the context
766
+ */
767
+ declare const QueryProvider: <Q>({ children, query, handleChangeQuery, }: React.PropsWithChildren<TInitialProps<Q>>) => React.JSX.Element;
768
+ /**
769
+ * hook to get the store from the context
770
+ *
771
+ * because we want the return type of `selector` to be inferred by ts, we use HOF to implement the hook
772
+ *
773
+ * so you should use it like this:
774
+ *
775
+ * ```tsx
776
+ * const useQuery = useQueryContext<MyObject>(); // => will return the store hook
777
+ * const result = useQuery(q => q.query); // => will return the query object
778
+ * ```
779
+ *
780
+ * @example
781
+ *
782
+ * ```tsx
783
+ * const result1 = useQueryContext<MyObject>()(q => '1234');
784
+ * const result2 = useQueryContext<MyObject>()(q => q.changeQuery);
785
+ * const result3 = useQueryContext<MyObject>()(q => q.query);
786
+ * ```
787
+ */
788
+ declare const useQueryContext: <Q>() => <T>(selector: (state: TQueryState<Q>) => T, equalityFn?: (left: T, right: T) => boolean) => T;
789
+
706
790
  /**
707
791
  * 將數字轉換成金額千分位格式
708
792
  *
@@ -827,4 +911,5 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
827
911
  */
828
912
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
829
913
 
830
- export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useValue, validTaxId, validateDateString, validateFileType, wait };
914
+ export { QueryProvider, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useQueryContext, useValue, validTaxId, validateDateString, validateFileType, wait };
915
+ export type { PartialBy, RequiredBy, TCountdownActions };
package/dist/es/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import dayjs from 'dayjs';
2
2
  export { u as useCountdown } from './useCountdown-client-t52WIHfq.mjs';
3
3
  import { useState, useCallback } from 'react';
4
+ export { Q as QueryProvider, u as useQueryContext } from './queryStore-client-CFQTVwrg.mjs';
4
5
  export { d as downloadFile } from './download-client-CnaJ0p_f.mjs';
5
6
  export { g as getLocalStorage, s as setLocalStorage } from './webStorage-client-Pd-loNCg.mjs';
6
7
 
@@ -0,0 +1,72 @@
1
+ 'use client';
2
+ import React, { useRef, createContext, useContext } from 'react';
3
+ import { createStore } from 'zustand';
4
+ import { useStoreWithEqualityFn } from 'zustand/traditional';
5
+
6
+ const createQueryStore = ({ query, handleChangeQuery })=>createStore()((set)=>({
7
+ query: {
8
+ ...query
9
+ },
10
+ changeQuery: (newQuery)=>{
11
+ set((pre)=>{
12
+ if (handleChangeQuery) {
13
+ return {
14
+ query: handleChangeQuery(pre.query, newQuery)
15
+ };
16
+ }
17
+ return {
18
+ query: {
19
+ ...pre.query,
20
+ ...newQuery
21
+ }
22
+ };
23
+ });
24
+ }
25
+ }));
26
+ const QueryContext = /*#__PURE__*/ createContext(null);
27
+ /**
28
+ * Provider to provide the store to the context
29
+ */ const QueryProvider = ({ children, query, handleChangeQuery })=>{
30
+ const storeRef = useRef(null);
31
+ if (!storeRef.current) {
32
+ storeRef.current = createQueryStore({
33
+ query,
34
+ handleChangeQuery
35
+ });
36
+ }
37
+ return /*#__PURE__*/ React.createElement(QueryContext.Provider, {
38
+ value: storeRef.current
39
+ }, children);
40
+ };
41
+ /**
42
+ * hook to get the store from the context
43
+ *
44
+ * because we want the return type of `selector` to be inferred by ts, we use HOF to implement the hook
45
+ *
46
+ * so you should use it like this:
47
+ *
48
+ * ```tsx
49
+ * const useQuery = useQueryContext<MyObject>(); // => will return the store hook
50
+ * const result = useQuery(q => q.query); // => will return the query object
51
+ * ```
52
+ *
53
+ * @example
54
+ *
55
+ * ```tsx
56
+ * const result1 = useQueryContext<MyObject>()(q => '1234');
57
+ * const result2 = useQueryContext<MyObject>()(q => q.changeQuery);
58
+ * const result3 = useQueryContext<MyObject>()(q => q.query);
59
+ * ```
60
+ */ const useQueryContext = ()=>{
61
+ const store = useContext(QueryContext);
62
+ if (!store) throw new Error('Missing QueryContext.Provider in the tree');
63
+ /**
64
+ * the hook to get the store
65
+ *
66
+ * @param selector - the selector to get the state from the store
67
+ * @param equalityFn - the equality function to compare the previous and next state, if it returns `true`, the component will not re-render
68
+ */ const useStore = (selector, equalityFn)=>useStoreWithEqualityFn(store, selector, equalityFn);
69
+ return useStore;
70
+ };
71
+
72
+ export { QueryProvider as Q, useQueryContext as u };
@@ -88,6 +88,8 @@ type Entries<T> = {
88
88
  *
89
89
  * @template T - The object type to transform into keys.
90
90
  *
91
+ * @deprecated Use `MapToType` instead.
92
+ *
91
93
  * @example
92
94
  *
93
95
  * type Example = { a: number; b: string };
@@ -171,5 +173,19 @@ type DeepPartial<T> = (T extends (infer U)[] ? DeepPartial<U>[] : {
171
173
  type TChangeKeyType<T, K extends keyof T, V> = Omit<T, K> & {
172
174
  [P in K]: V;
173
175
  };
176
+ /**
177
+ * A utility type that transforms an object type `T` into another object type where each value type is replaced with type `A`.
178
+ *
179
+ * @template T - The object type to transform into keys.
180
+ *
181
+ * @example
182
+ *
183
+ * type Example = { a: number; b: string };
184
+ * type ExampleToBoolean = MapToType<Example, boolean>;
185
+ * // Result: ExampleToBoolean is { a: boolean; b: boolean; }
186
+ */
187
+ type MapToType<T extends Record<any, any>, A = any> = {
188
+ [K in keyof T]: A;
189
+ };
174
190
 
175
- export type { AtLeastOne, DeepPartial, Entries, MapToString, OnlyOne, PopArgs, PushArgs, ShiftArgs, TChangeKeyType, TExtractValueType, UnshiftArgs };
191
+ export type { AtLeastOne, DeepPartial, Entries, MapToString, MapToType, OnlyOne, PopArgs, PushArgs, ShiftArgs, TChangeKeyType, TExtractValueType, UnshiftArgs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gateweb/react-utils",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "React Utils for GateWeb",
5
5
  "homepage": "https://github.com/GatewebSolutions/react-utils",
6
6
  "files": [
@@ -37,7 +37,9 @@
37
37
  "dependencies": {
38
38
  "dayjs": "^1.11.13",
39
39
  "react": "^19.0.0",
40
- "react-dom": "^19.0.0"
40
+ "react-dom": "^19.0.0",
41
+ "use-sync-external-store": "^1.5.0",
42
+ "zustand": "^5.0.3"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@commitlint/cli": "^19.5.0",