@gateweb/react-utils 1.10.0 → 1.11.0

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.
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  import { AtLeastOne } from './types.js';
3
3
  export * from './types.js';
4
4
 
@@ -404,6 +404,7 @@ declare const extractEnumLikeObject: <T extends Record<string, { [P in K]: any;
404
404
  *
405
405
  * @param obj 要處理的物件
406
406
  * @param name 生成的 enum 名稱
407
+ * @param scene 要使用的條件 (參考 example)
407
408
  *
408
409
  * @example
409
410
  *
@@ -974,6 +975,43 @@ declare const QueryProvider: <Q>({ children, query, handleChangeQuery, }: React.
974
975
  */
975
976
  declare const useQueryContext: <Q>() => <T>(selector: (state: TQueryState<Q>) => T, equalityFn?: (left: T, right: T) => boolean) => T;
976
977
 
978
+ /**
979
+ * Creates a strongly-typed React Context and Provider pair for data sharing.
980
+ *
981
+ * This utility helps you avoid prop drilling by providing a reusable way to define
982
+ * context with strict type inference. It returns a custom hook for consuming the context
983
+ * and a Provider component for supplying context values.
984
+ *
985
+ * @template T - The value type for the context.
986
+ * @returns {Object} An object containing:
987
+ * - useDataContext: A custom hook to access the context value. Throws an error if used outside the provider.
988
+ * - DataProvider: A Provider component to wrap your component tree and supply the context value.
989
+ *
990
+ * @example
991
+ * // Example usage:
992
+ * const { useDataContext, DataProvider } = createDataContext<{ count: number }>();
993
+ *
994
+ * function Counter() {
995
+ * const { count } = useDataContext();
996
+ * return <span>{count}</span>;
997
+ * }
998
+ *
999
+ * function App() {
1000
+ * return (
1001
+ * <DataProvider value={{ count: 42 }}>
1002
+ * <Counter />
1003
+ * </DataProvider>
1004
+ * );
1005
+ * }
1006
+ */
1007
+ declare const createDataContext: <T>() => {
1008
+ readonly useDataContext: () => T & ({} | null);
1009
+ readonly DataProvider: ({ children, value }: {
1010
+ children: ReactNode;
1011
+ value: T;
1012
+ }) => React.JSX.Element;
1013
+ };
1014
+
977
1015
  type TCountdownActions = {
978
1016
  /** 目前秒數 */
979
1017
  countdown: number;
@@ -1107,4 +1145,4 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
1107
1145
  */
1108
1146
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
1109
1147
 
1110
- export { ByteSize, type PartialBy, QueryProvider, type RequiredBy, type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, convertBytes, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isEqual, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, maskString, mergeRefs, objectToSearchParams, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, searchParamsToObject, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useQueryContext, useValue, validTaxId, validateDateString, validateFileType, wait };
1148
+ export { ByteSize, type PartialBy, QueryProvider, type RequiredBy, type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, convertBytes, createDataContext, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isEqual, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, maskString, mergeRefs, objectToSearchParams, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, searchParamsToObject, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useQueryContext, useValue, validTaxId, validateDateString, validateFileType, wait };
package/dist/cjs/index.js CHANGED
@@ -2,14 +2,15 @@ Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
3
  var dayjs = require('dayjs');
4
4
  var queryStoreClient = require('./queryStore-client-q_SLGgYH.js');
5
- var useCountdownClient = require('./useCountdown-client-uiqhgllY.js');
6
5
  var React = require('react');
6
+ var useCountdownClient = require('./useCountdown-client-uiqhgllY.js');
7
7
  var downloadClient = require('./download-client-DKxkL92w.js');
8
8
  var webStorageClient = require('./webStorage-client-BGQKUfrO.js');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
12
  var dayjs__default = /*#__PURE__*/_interopDefault(dayjs);
13
+ var React__default = /*#__PURE__*/_interopDefault(React);
13
14
 
14
15
  const FILE_SIZE_UNITS$1 = [
15
16
  'Bytes',
@@ -1043,6 +1044,57 @@ const FILE_SIZE_UNITS = [
1043
1044
  return dayjs__default.default(dateString, format, true).isValid();
1044
1045
  };
1045
1046
 
1047
+ /**
1048
+ * Creates a strongly-typed React Context and Provider pair for data sharing.
1049
+ *
1050
+ * This utility helps you avoid prop drilling by providing a reusable way to define
1051
+ * context with strict type inference. It returns a custom hook for consuming the context
1052
+ * and a Provider component for supplying context values.
1053
+ *
1054
+ * @template T - The value type for the context.
1055
+ * @returns {Object} An object containing:
1056
+ * - useDataContext: A custom hook to access the context value. Throws an error if used outside the provider.
1057
+ * - DataProvider: A Provider component to wrap your component tree and supply the context value.
1058
+ *
1059
+ * @example
1060
+ * // Example usage:
1061
+ * const { useDataContext, DataProvider } = createDataContext<{ count: number }>();
1062
+ *
1063
+ * function Counter() {
1064
+ * const { count } = useDataContext();
1065
+ * return <span>{count}</span>;
1066
+ * }
1067
+ *
1068
+ * function App() {
1069
+ * return (
1070
+ * <DataProvider value={{ count: 42 }}>
1071
+ * <Counter />
1072
+ * </DataProvider>
1073
+ * );
1074
+ * }
1075
+ */ const createDataContext = ()=>{
1076
+ const Context = /*#__PURE__*/ React.createContext(undefined);
1077
+ const useDataContext = ()=>{
1078
+ const context = React.useContext(Context);
1079
+ if (context === undefined) {
1080
+ throw new Error(`useDataContext must be used within a DataProvider`);
1081
+ }
1082
+ return context;
1083
+ };
1084
+ const DataProvider = ({ children, value })=>{
1085
+ const memoized = React.useMemo(()=>value, [
1086
+ value
1087
+ ]);
1088
+ return /*#__PURE__*/ React__default.default.createElement(Context.Provider, {
1089
+ value: memoized
1090
+ }, children);
1091
+ };
1092
+ return {
1093
+ useDataContext,
1094
+ DataProvider
1095
+ };
1096
+ };
1097
+
1046
1098
  /**
1047
1099
  * A hook to manage a value.
1048
1100
  *
@@ -1180,6 +1232,7 @@ exports.camelCase2SnakeCase = camelCase2SnakeCase;
1180
1232
  exports.camelString2PascalString = camelString2PascalString;
1181
1233
  exports.camelString2SnakeString = camelString2SnakeString;
1182
1234
  exports.convertBytes = convertBytes;
1235
+ exports.createDataContext = createDataContext;
1183
1236
  exports.createEnumLikeObject = createEnumLikeObject;
1184
1237
  exports.debounce = debounce;
1185
1238
  exports.deepMerge = deepMerge;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  import { AtLeastOne } from './types.mjs';
3
3
  export * from './types.mjs';
4
4
 
@@ -404,6 +404,7 @@ declare const extractEnumLikeObject: <T extends Record<string, { [P in K]: any;
404
404
  *
405
405
  * @param obj 要處理的物件
406
406
  * @param name 生成的 enum 名稱
407
+ * @param scene 要使用的條件 (參考 example)
407
408
  *
408
409
  * @example
409
410
  *
@@ -974,6 +975,43 @@ declare const QueryProvider: <Q>({ children, query, handleChangeQuery, }: React.
974
975
  */
975
976
  declare const useQueryContext: <Q>() => <T>(selector: (state: TQueryState<Q>) => T, equalityFn?: (left: T, right: T) => boolean) => T;
976
977
 
978
+ /**
979
+ * Creates a strongly-typed React Context and Provider pair for data sharing.
980
+ *
981
+ * This utility helps you avoid prop drilling by providing a reusable way to define
982
+ * context with strict type inference. It returns a custom hook for consuming the context
983
+ * and a Provider component for supplying context values.
984
+ *
985
+ * @template T - The value type for the context.
986
+ * @returns {Object} An object containing:
987
+ * - useDataContext: A custom hook to access the context value. Throws an error if used outside the provider.
988
+ * - DataProvider: A Provider component to wrap your component tree and supply the context value.
989
+ *
990
+ * @example
991
+ * // Example usage:
992
+ * const { useDataContext, DataProvider } = createDataContext<{ count: number }>();
993
+ *
994
+ * function Counter() {
995
+ * const { count } = useDataContext();
996
+ * return <span>{count}</span>;
997
+ * }
998
+ *
999
+ * function App() {
1000
+ * return (
1001
+ * <DataProvider value={{ count: 42 }}>
1002
+ * <Counter />
1003
+ * </DataProvider>
1004
+ * );
1005
+ * }
1006
+ */
1007
+ declare const createDataContext: <T>() => {
1008
+ readonly useDataContext: () => T & ({} | null);
1009
+ readonly DataProvider: ({ children, value }: {
1010
+ children: ReactNode;
1011
+ value: T;
1012
+ }) => React.JSX.Element;
1013
+ };
1014
+
977
1015
  type TCountdownActions = {
978
1016
  /** 目前秒數 */
979
1017
  countdown: number;
@@ -1107,4 +1145,4 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
1107
1145
  */
1108
1146
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
1109
1147
 
1110
- export { ByteSize, type PartialBy, QueryProvider, type RequiredBy, type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, convertBytes, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isEqual, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, maskString, mergeRefs, objectToSearchParams, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, searchParamsToObject, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useQueryContext, useValue, validTaxId, validateDateString, validateFileType, wait };
1148
+ export { ByteSize, type PartialBy, QueryProvider, type RequiredBy, type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, convertBytes, createDataContext, createEnumLikeObject, debounce, deepMerge, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isEqual, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, maskString, mergeRefs, objectToSearchParams, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, searchParamsToObject, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, useQueryContext, useValue, validTaxId, validateDateString, validateFileType, wait };
package/dist/es/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import dayjs from 'dayjs';
2
2
  export { Q as QueryProvider, u as useQueryContext } from './queryStore-client-vG-bXFYm.mjs';
3
+ import React, { useContext, useMemo, createContext, useState, useCallback } from 'react';
3
4
  export { u as useCountdown } from './useCountdown-client-t52WIHfq.mjs';
4
- import { useState, useCallback } from 'react';
5
5
  export { d as downloadFile } from './download-client-CnaJ0p_f.mjs';
6
6
  export { g as getLocalStorage, s as setLocalStorage } from './webStorage-client-Pd-loNCg.mjs';
7
7
 
@@ -1037,6 +1037,57 @@ const FILE_SIZE_UNITS = [
1037
1037
  return dayjs(dateString, format, true).isValid();
1038
1038
  };
1039
1039
 
1040
+ /**
1041
+ * Creates a strongly-typed React Context and Provider pair for data sharing.
1042
+ *
1043
+ * This utility helps you avoid prop drilling by providing a reusable way to define
1044
+ * context with strict type inference. It returns a custom hook for consuming the context
1045
+ * and a Provider component for supplying context values.
1046
+ *
1047
+ * @template T - The value type for the context.
1048
+ * @returns {Object} An object containing:
1049
+ * - useDataContext: A custom hook to access the context value. Throws an error if used outside the provider.
1050
+ * - DataProvider: A Provider component to wrap your component tree and supply the context value.
1051
+ *
1052
+ * @example
1053
+ * // Example usage:
1054
+ * const { useDataContext, DataProvider } = createDataContext<{ count: number }>();
1055
+ *
1056
+ * function Counter() {
1057
+ * const { count } = useDataContext();
1058
+ * return <span>{count}</span>;
1059
+ * }
1060
+ *
1061
+ * function App() {
1062
+ * return (
1063
+ * <DataProvider value={{ count: 42 }}>
1064
+ * <Counter />
1065
+ * </DataProvider>
1066
+ * );
1067
+ * }
1068
+ */ const createDataContext = ()=>{
1069
+ const Context = /*#__PURE__*/ createContext(undefined);
1070
+ const useDataContext = ()=>{
1071
+ const context = useContext(Context);
1072
+ if (context === undefined) {
1073
+ throw new Error(`useDataContext must be used within a DataProvider`);
1074
+ }
1075
+ return context;
1076
+ };
1077
+ const DataProvider = ({ children, value })=>{
1078
+ const memoized = useMemo(()=>value, [
1079
+ value
1080
+ ]);
1081
+ return /*#__PURE__*/ React.createElement(Context.Provider, {
1082
+ value: memoized
1083
+ }, children);
1084
+ };
1085
+ return {
1086
+ useDataContext,
1087
+ DataProvider
1088
+ };
1089
+ };
1090
+
1040
1091
  /**
1041
1092
  * A hook to manage a value.
1042
1093
  *
@@ -1161,4 +1212,4 @@ function mergeRefs(refs) {
1161
1212
  return dayjs(endMonth, 'YYYYMM').subtract(1911, 'year').format('YYYYMM').substring(1);
1162
1213
  };
1163
1214
 
1164
- export { ByteSize, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, convertBytes, createEnumLikeObject, debounce, deepMerge, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isEqual, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, maskString, mergeRefs, objectToSearchParams, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, searchParamsToObject, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useValue, validTaxId, validateDateString, validateFileType, wait };
1215
+ export { ByteSize, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, convertBytes, createDataContext, createEnumLikeObject, debounce, deepMerge, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isEqual, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, maskString, mergeRefs, objectToSearchParams, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, searchParamsToObject, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useValue, validTaxId, validateDateString, validateFileType, wait };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gateweb/react-utils",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "React Utils for GateWeb",
5
5
  "homepage": "https://github.com/GatewebSolutions/react-utils",
6
6
  "files": [
@@ -45,6 +45,7 @@
45
45
  "@commitlint/cli": "^19.5.0",
46
46
  "@commitlint/config-conventional": "^19.5.0",
47
47
  "@gateweb/eslint-config-gateweb": "^1.0.6",
48
+ "@testing-library/jest-dom": "^6.6.3",
48
49
  "@testing-library/react": "^16.2.0",
49
50
  "@types/jest": "^29.5.13",
50
51
  "@types/node": "^22.7.7",