@trackunit/react-core-hooks 1.7.94 → 1.7.96
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/index.cjs.js +8 -340
- package/index.esm.js +10 -336
- package/package.json +3 -7
- package/src/index.d.ts +1 -7
- package/src/subscription/UserSubscriptionProvider.d.ts +4 -4
- package/src/encoding/useCustomEncoding.d.ts +0 -13
- package/src/localStorage/initLocalStorageState.d.ts +0 -9
- package/src/localStorage/setLocalStorage.d.ts +0 -11
- package/src/localStorage/types.d.ts +0 -27
- package/src/localStorage/useLocalStorage.d.ts +0 -10
- package/src/localStorage/useLocalStorageEffect.d.ts +0 -11
- package/src/localStorage/useLocalStorageReducer.d.ts +0 -12
- package/src/localStorage/validateState.d.ts +0 -13
- package/src/usePrevious.d.ts +0 -8
- package/src/useTextSearch.d.ts +0 -13
- package/src/useWatch.d.ts +0 -20
- /package/src/{filter-bar → filterBar}/FilterBarProvider.d.ts +0 -0
package/index.cjs.js
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
-
var fflate = require('fflate');
|
|
6
5
|
var irisAppRuntimeCore = require('@trackunit/iris-app-runtime-core');
|
|
7
|
-
var sharedUtils = require('@trackunit/shared-utils');
|
|
8
|
-
var esToolkit = require('es-toolkit');
|
|
9
6
|
|
|
10
7
|
const AnalyticsContext = react.createContext(null);
|
|
11
8
|
const AnalyticsContextProvider = AnalyticsContext.Provider; // easy import
|
|
@@ -114,106 +111,6 @@ const useConfirmationDialog = () => {
|
|
|
114
111
|
return confirmationDialogContext;
|
|
115
112
|
};
|
|
116
113
|
|
|
117
|
-
/**
|
|
118
|
-
* Base64URL encode bytes to a URL-safe string
|
|
119
|
-
*/
|
|
120
|
-
const b64urlEncode = (bytes) => {
|
|
121
|
-
let bin = "";
|
|
122
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
123
|
-
bin += String.fromCharCode(bytes[i] ?? 0);
|
|
124
|
-
}
|
|
125
|
-
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
126
|
-
};
|
|
127
|
-
/**
|
|
128
|
-
* Base64URL decode a URL-safe string to bytes
|
|
129
|
-
*/
|
|
130
|
-
const b64urlDecode = (s) => {
|
|
131
|
-
s = s.replace(/-/g, "+").replace(/_/g, "/");
|
|
132
|
-
s += "===".slice((s.length + 3) % 4);
|
|
133
|
-
const bin = atob(s);
|
|
134
|
-
const out = new Uint8Array(bin.length);
|
|
135
|
-
for (let i = 0; i < bin.length; i++) {
|
|
136
|
-
out[i] = bin.charCodeAt(i);
|
|
137
|
-
}
|
|
138
|
-
return out;
|
|
139
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* React hook for safe base64 encoding/decoding with UTF-8 support and compression
|
|
142
|
-
*
|
|
143
|
-
* This hook provides callbacks for safely encoding and decoding objects/strings to/from base64
|
|
144
|
-
* with proper Unicode character support (including Japanese, Chinese, etc.) and automatic
|
|
145
|
-
* compression for better performance with large objects.
|
|
146
|
-
*
|
|
147
|
-
* @returns { { encode: (input: unknown) => string, decode: (str: string) => JSON | string } } Object containing encode and decode callback functions
|
|
148
|
-
*/
|
|
149
|
-
const useCustomEncoding = () => {
|
|
150
|
-
/**
|
|
151
|
-
* Safely encode an object or string with compression and UTF-8 support
|
|
152
|
-
*
|
|
153
|
-
* This function compresses objects before encoding for better performance,
|
|
154
|
-
* and properly handles Unicode characters (including Japanese, Chinese, etc.).
|
|
155
|
-
*
|
|
156
|
-
* @param input - The object or string to encode
|
|
157
|
-
* @returns The compressed and encoded string
|
|
158
|
-
*/
|
|
159
|
-
const encode = react.useCallback((input) => {
|
|
160
|
-
try {
|
|
161
|
-
// If it's already a string, use it directly; otherwise stringify the object
|
|
162
|
-
const json = typeof input === "string" ? input : JSON.stringify(input);
|
|
163
|
-
const textInput = new TextEncoder().encode(json);
|
|
164
|
-
// Use fflate for synchronous gzip compression
|
|
165
|
-
const compressed = fflate.gzipSync(textInput);
|
|
166
|
-
return b64urlEncode(compressed);
|
|
167
|
-
}
|
|
168
|
-
catch (error) {
|
|
169
|
-
return "";
|
|
170
|
-
}
|
|
171
|
-
}, []);
|
|
172
|
-
/**
|
|
173
|
-
* Safely decode a compressed and encoded string back to its original form
|
|
174
|
-
*
|
|
175
|
-
* This function decompresses and decodes strings, properly handling Unicode characters
|
|
176
|
-
* and returning the original object or string.
|
|
177
|
-
*
|
|
178
|
-
* @param str - The compressed and encoded string to decode
|
|
179
|
-
* @returns The decoded object or string, or null if decoding fails
|
|
180
|
-
*/
|
|
181
|
-
const decode = react.useCallback((str) => {
|
|
182
|
-
try {
|
|
183
|
-
// Try to decode as compressed data first
|
|
184
|
-
try {
|
|
185
|
-
const bytes = b64urlDecode(str);
|
|
186
|
-
const decompressed = fflate.gunzipSync(bytes);
|
|
187
|
-
const json = new TextDecoder().decode(decompressed);
|
|
188
|
-
// Try to parse as JSON first (for objects)
|
|
189
|
-
try {
|
|
190
|
-
return JSON.parse(json);
|
|
191
|
-
}
|
|
192
|
-
catch (_) {
|
|
193
|
-
// If JSON parsing fails, return the string as-is
|
|
194
|
-
return json;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
catch (_) {
|
|
198
|
-
// If compression decoding fails, fall back to regular decoding
|
|
199
|
-
}
|
|
200
|
-
// Fallback: use regular base64 decoding
|
|
201
|
-
const decoded = decodeURIComponent(escape(atob(str)));
|
|
202
|
-
try {
|
|
203
|
-
return JSON.parse(decoded);
|
|
204
|
-
}
|
|
205
|
-
catch (_) {
|
|
206
|
-
// If JSON parsing fails, return the string as-is
|
|
207
|
-
return decoded;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
catch (error) {
|
|
211
|
-
return "";
|
|
212
|
-
}
|
|
213
|
-
}, []);
|
|
214
|
-
return react.useMemo(() => ({ encode, decode }), [encode, decode]);
|
|
215
|
-
};
|
|
216
|
-
|
|
217
114
|
const EnvironmentContext = react.createContext(null);
|
|
218
115
|
/**
|
|
219
116
|
* This is a provider for the EnvironmentContext.
|
|
@@ -512,174 +409,6 @@ const useIrisAppImage = () => {
|
|
|
512
409
|
};
|
|
513
410
|
};
|
|
514
411
|
|
|
515
|
-
/**
|
|
516
|
-
* The usePrevious hook is a useful tool for tracking the previous value of a variable in a functional component. This can be particularly handy in scenarios where it is necessary to compare the current value with the previous one, such as triggering actions or rendering based on changes.
|
|
517
|
-
*
|
|
518
|
-
* @example
|
|
519
|
-
* const [color, setColor] = React.useState(getRandomColor());
|
|
520
|
-
const previousColor = usePrevious(color);
|
|
521
|
-
*/
|
|
522
|
-
const usePrevious = (value) => {
|
|
523
|
-
const ref = react.useRef(undefined);
|
|
524
|
-
react.useEffect(() => {
|
|
525
|
-
ref.current = value;
|
|
526
|
-
}, [value]);
|
|
527
|
-
const wrapper = react.useMemo(() => ({
|
|
528
|
-
get previous() {
|
|
529
|
-
return ref.current;
|
|
530
|
-
},
|
|
531
|
-
}), []);
|
|
532
|
-
return wrapper.previous;
|
|
533
|
-
};
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Validates the state object using a Zod schema.
|
|
537
|
-
*
|
|
538
|
-
* @template TState - The type of the state.
|
|
539
|
-
* @param {ValidateStateOptions<TState>} params - The parameters for the validateState function.
|
|
540
|
-
*/
|
|
541
|
-
const validateState = ({ state, schema, onValidationFailed, onValidationSuccessful, defaultState, }) => {
|
|
542
|
-
try {
|
|
543
|
-
const parsedState = schema.parse(state);
|
|
544
|
-
onValidationSuccessful?.(parsedState);
|
|
545
|
-
return parsedState;
|
|
546
|
-
}
|
|
547
|
-
catch (error) {
|
|
548
|
-
// eslint-disable-next-line no-console
|
|
549
|
-
console.error("Failed to parse and validate the state from local storage.", error);
|
|
550
|
-
onValidationFailed?.(error);
|
|
551
|
-
return defaultState;
|
|
552
|
-
}
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* Initializes the state from local storage, parsing and validating it if a Zod schema is provided.
|
|
557
|
-
*
|
|
558
|
-
* @template TState - The type of the state stored in local storage.
|
|
559
|
-
* @param {Omit<LocalStorageParams<TState>, "state">} params - The parameters for initializing the local storage state.
|
|
560
|
-
* @returns {TState} - The initialized state.
|
|
561
|
-
*/
|
|
562
|
-
const initLocalStorageState = ({ key, defaultState, schema, }) => {
|
|
563
|
-
const localStorageItem = localStorage.getItem(key);
|
|
564
|
-
if (!localStorageItem) {
|
|
565
|
-
return defaultState;
|
|
566
|
-
}
|
|
567
|
-
const localStorageItemJSON = JSON.parse(localStorageItem);
|
|
568
|
-
if (!schema) {
|
|
569
|
-
return localStorageItemJSON;
|
|
570
|
-
}
|
|
571
|
-
return validateState({ state: localStorageItemJSON, defaultState, schema });
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
/**
|
|
575
|
-
* Sets a value in the local storage with the specified key.
|
|
576
|
-
* Thin wrapper around localStorage.setItem() that is slightly more type safe
|
|
577
|
-
* Stringifies value automatically.
|
|
578
|
-
* Useful if you for some reason can't use the useLocalStorage hook for React lifecycle reasons
|
|
579
|
-
*
|
|
580
|
-
* @template TValue - The type of value to be stored.
|
|
581
|
-
* @param {string} key - The key under which to store the value.
|
|
582
|
-
* @param {TValue} value - The value to store in the local storage.
|
|
583
|
-
*/
|
|
584
|
-
const setLocalStorage = (key, value) => {
|
|
585
|
-
localStorage.setItem(key, JSON.stringify(value));
|
|
586
|
-
};
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Custom hook for synchronizing a state variable with local storage,
|
|
590
|
-
* with optional schema validation and callbacks.
|
|
591
|
-
*
|
|
592
|
-
* @template TState - The type of the state variable.
|
|
593
|
-
* @param {LocalStorageParams<TState> & LocalStorageCallbacks & { state: TState }} params - The parameters for the useLocalStorageEffect hook.
|
|
594
|
-
*/
|
|
595
|
-
const useLocalStorageEffect = ({ key, state, defaultState, schema, onValidationFailed, onValidationSuccessful, }) => {
|
|
596
|
-
const prevState = usePrevious(state);
|
|
597
|
-
react.useEffect(() => {
|
|
598
|
-
if (JSON.stringify(prevState) === JSON.stringify(state)) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
if (schema) {
|
|
602
|
-
validateState({
|
|
603
|
-
state,
|
|
604
|
-
schema,
|
|
605
|
-
defaultState,
|
|
606
|
-
onValidationFailed: error => {
|
|
607
|
-
// eslint-disable-next-line no-console
|
|
608
|
-
console.error(`State validation failed. Resetting local storage to default state: ${defaultState}.`, error);
|
|
609
|
-
localStorage.removeItem(key);
|
|
610
|
-
onValidationFailed?.(error);
|
|
611
|
-
},
|
|
612
|
-
onValidationSuccessful: data => {
|
|
613
|
-
setLocalStorage(key, data);
|
|
614
|
-
onValidationSuccessful?.(data);
|
|
615
|
-
},
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
const stringifiedState = JSON.stringify(state);
|
|
620
|
-
localStorage.setItem(key, stringifiedState);
|
|
621
|
-
}
|
|
622
|
-
}, [state, key, schema, defaultState, prevState, onValidationFailed, onValidationSuccessful]);
|
|
623
|
-
};
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* Works like a normal useState, but saves to local storage and has optional schema validation.
|
|
627
|
-
*
|
|
628
|
-
* @template TState - The type of the value stored in local storage.
|
|
629
|
-
* @param {Omit<LocalStorageParams<TState>, "state"> & LocalStorageCallbacks} options - The options for useLocalStorage.
|
|
630
|
-
* @returns {[TState, Dispatch<SetStateAction<TState>>, () => void]} - A tuple containing the current value, a function to update the value, and a function to remove the value from local storage.
|
|
631
|
-
*/
|
|
632
|
-
const useLocalStorage = ({ key, defaultState, schema, onValidationFailed, onValidationSuccessful, }) => {
|
|
633
|
-
if (!key) {
|
|
634
|
-
throw new Error("useLocalStorage key must be defined");
|
|
635
|
-
}
|
|
636
|
-
const defaultStateRef = react.useRef(defaultState);
|
|
637
|
-
react.useEffect(() => {
|
|
638
|
-
defaultStateRef.current = defaultState;
|
|
639
|
-
}, [defaultState]);
|
|
640
|
-
const schemaRef = react.useRef(schema);
|
|
641
|
-
react.useEffect(() => {
|
|
642
|
-
schemaRef.current = schema;
|
|
643
|
-
}, [schema]);
|
|
644
|
-
const [state, setState] = react.useState(initLocalStorageState({ key, defaultState: defaultStateRef.current, schema: schemaRef.current }));
|
|
645
|
-
const prevKey = usePrevious(key);
|
|
646
|
-
react.useEffect(() => {
|
|
647
|
-
if (key !== prevKey) {
|
|
648
|
-
setState(initLocalStorageState({ key, defaultState: defaultStateRef.current, schema: schemaRef.current }));
|
|
649
|
-
}
|
|
650
|
-
}, [key, prevKey, schema]);
|
|
651
|
-
const localStorageProps = react.useMemo(() => ({
|
|
652
|
-
key,
|
|
653
|
-
state,
|
|
654
|
-
defaultState: defaultStateRef.current,
|
|
655
|
-
schema: schemaRef.current,
|
|
656
|
-
onValidationFailed,
|
|
657
|
-
onValidationSuccessful,
|
|
658
|
-
}), [key, state, onValidationFailed, onValidationSuccessful]);
|
|
659
|
-
useLocalStorageEffect(localStorageProps);
|
|
660
|
-
const reset = react.useCallback(() => {
|
|
661
|
-
setState(defaultStateRef.current);
|
|
662
|
-
}, []);
|
|
663
|
-
return react.useMemo(() => [state, setState, reset], [state, setState, reset]);
|
|
664
|
-
};
|
|
665
|
-
|
|
666
|
-
/**
|
|
667
|
-
* Works like a normal useReducer, but saves to local storage and has optional schema validation.
|
|
668
|
-
*
|
|
669
|
-
* @template TState - The type of the state.
|
|
670
|
-
* @template TAction - The type of the action.
|
|
671
|
-
* @param {LocalStorageParams<TState> & LocalStorageCallbacks} params - The parameters for the useLocalStorageReducer function.
|
|
672
|
-
* @returns {[TState, Dispatch<TAction>]} - A tuple containing the state and the dispatch function.
|
|
673
|
-
*/
|
|
674
|
-
const useLocalStorageReducer = ({ key, defaultState, reducer, schema, onValidationFailed, onValidationSuccessful, }) => {
|
|
675
|
-
if (!key) {
|
|
676
|
-
throw new Error("useLocalStorage key may not be falsy");
|
|
677
|
-
}
|
|
678
|
-
const [state, dispatch] = react.useReducer(reducer, defaultState, () => initLocalStorageState({ key, defaultState, schema }));
|
|
679
|
-
useLocalStorageEffect({ key, state, defaultState, schema, onValidationFailed, onValidationSuccessful });
|
|
680
|
-
return [state, dispatch];
|
|
681
|
-
};
|
|
682
|
-
|
|
683
412
|
const ModalDialogContext = react.createContext(null);
|
|
684
413
|
/**
|
|
685
414
|
* This is a provider for the ModalDialogContext.
|
|
@@ -810,7 +539,7 @@ const useAssetRuntime = () => {
|
|
|
810
539
|
setError(new Error("Failed to get asset info"));
|
|
811
540
|
}
|
|
812
541
|
};
|
|
813
|
-
getAssetInfo();
|
|
542
|
+
void getAssetInfo();
|
|
814
543
|
}, []);
|
|
815
544
|
return { assetInfo, loading, error };
|
|
816
545
|
};
|
|
@@ -849,7 +578,7 @@ const useCustomerRuntime = () => {
|
|
|
849
578
|
setError(new Error("Failed to get customer info"));
|
|
850
579
|
}
|
|
851
580
|
};
|
|
852
|
-
getCustomerInfo();
|
|
581
|
+
void getCustomerInfo();
|
|
853
582
|
}, []);
|
|
854
583
|
return { customerInfo, loading, error };
|
|
855
584
|
};
|
|
@@ -888,7 +617,7 @@ const useEventRuntime = () => {
|
|
|
888
617
|
setError(new Error("Failed to get event info"));
|
|
889
618
|
}
|
|
890
619
|
};
|
|
891
|
-
getEventInfo();
|
|
620
|
+
void getEventInfo();
|
|
892
621
|
}, []);
|
|
893
622
|
return { eventInfo, loading, error };
|
|
894
623
|
};
|
|
@@ -926,7 +655,7 @@ const useIrisAppName = () => {
|
|
|
926
655
|
setError(new Error("Failed to get iris app name"));
|
|
927
656
|
}
|
|
928
657
|
};
|
|
929
|
-
getAppName();
|
|
658
|
+
void getAppName();
|
|
930
659
|
}, []);
|
|
931
660
|
return { appName, loading, error };
|
|
932
661
|
};
|
|
@@ -951,7 +680,7 @@ const useIrisAppId = () => {
|
|
|
951
680
|
const [loading, setLoading] = react.useState(true);
|
|
952
681
|
const [error, setError] = react.useState();
|
|
953
682
|
react.useEffect(() => {
|
|
954
|
-
const
|
|
683
|
+
const getData = async () => {
|
|
955
684
|
setLoading(true);
|
|
956
685
|
try {
|
|
957
686
|
const updatedAppName = await irisAppRuntimeCore.ParamsRuntime.getAppName();
|
|
@@ -964,7 +693,7 @@ const useIrisAppId = () => {
|
|
|
964
693
|
setError(new Error("Failed to get iris app name"));
|
|
965
694
|
}
|
|
966
695
|
};
|
|
967
|
-
|
|
696
|
+
void getData();
|
|
968
697
|
}, []);
|
|
969
698
|
return { irisAppId, loading, error };
|
|
970
699
|
};
|
|
@@ -1003,7 +732,7 @@ const useSiteRuntime = () => {
|
|
|
1003
732
|
setError(new Error("Failed to get site info"));
|
|
1004
733
|
}
|
|
1005
734
|
};
|
|
1006
|
-
getSiteInfo();
|
|
735
|
+
void getSiteInfo();
|
|
1007
736
|
}, []);
|
|
1008
737
|
return { siteInfo, loading, error };
|
|
1009
738
|
};
|
|
@@ -1024,7 +753,7 @@ const UserSubscriptionProvider = (props) => {
|
|
|
1024
753
|
* const { numberOfDaysWithAccessToHistoricalData, packageType } = useUserSubscription();
|
|
1025
754
|
* // use it for something
|
|
1026
755
|
* const data = fetchData(numberOfDaysWithAccessToHistoricalData)
|
|
1027
|
-
* @see {
|
|
756
|
+
* @see { UserSubscription}
|
|
1028
757
|
*/
|
|
1029
758
|
const useUserSubscription = () => {
|
|
1030
759
|
const context = react.useContext(UserSubscriptionContext);
|
|
@@ -1213,61 +942,6 @@ const useCurrentUser = () => {
|
|
|
1213
942
|
return context;
|
|
1214
943
|
};
|
|
1215
944
|
|
|
1216
|
-
/**
|
|
1217
|
-
* Hook for filtering a list of items by text search, client side search in a list.
|
|
1218
|
-
*
|
|
1219
|
-
* @template TSearchableItem
|
|
1220
|
-
* @param items The list of items to filter.
|
|
1221
|
-
* @param props The properties to search in each item.
|
|
1222
|
-
* @returns {[TSearchableItem[], string, Dispatch<string>]} A tuple with the filtered items, the search text and a setter for the search text.
|
|
1223
|
-
* @example
|
|
1224
|
-
* const [result, searchText, setSearchText] = useTextSearch(items, item => [item.name, item.description]);
|
|
1225
|
-
*/
|
|
1226
|
-
function useTextSearch(items, props) {
|
|
1227
|
-
const [searchText, setSearchText] = react.useState("");
|
|
1228
|
-
const result = react.useMemo(() => {
|
|
1229
|
-
if (!searchText) {
|
|
1230
|
-
return items;
|
|
1231
|
-
}
|
|
1232
|
-
return sharedUtils.filterByMultiple(items, props, searchText);
|
|
1233
|
-
}, [items, props, searchText]);
|
|
1234
|
-
return react.useMemo(() => [result, searchText, setSearchText], [result, searchText, setSearchText]);
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
const UNINITIALIZED = Symbol("UNINITIALIZED");
|
|
1238
|
-
/**
|
|
1239
|
-
* Hook to watch for changes in a value and react to them.
|
|
1240
|
-
* Uses deep equality comparison via es-toolkit's isEqual.
|
|
1241
|
-
*
|
|
1242
|
-
* @param props - The hook properties
|
|
1243
|
-
* @param props.value - The value to watch for changes
|
|
1244
|
-
* @param props.onChange - Function to call when the value changes
|
|
1245
|
-
* @param props.immediate - Whether to run the callback immediately on mount (default: false)
|
|
1246
|
-
* @param props.skip - Whether to skip watching for changes (default: false)
|
|
1247
|
-
*/
|
|
1248
|
-
const useWatch = ({ value, onChange, immediate = false, skip = false }) => {
|
|
1249
|
-
const prevValue = react.useRef(UNINITIALIZED);
|
|
1250
|
-
const onChangeRef = react.useRef(onChange);
|
|
1251
|
-
// Update the ref whenever onChange changes
|
|
1252
|
-
react.useEffect(() => {
|
|
1253
|
-
onChangeRef.current = onChange;
|
|
1254
|
-
}, [onChange]);
|
|
1255
|
-
react.useEffect(() => {
|
|
1256
|
-
if (skip) {
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
const prev = prevValue.current;
|
|
1260
|
-
const hasChanged = prev === UNINITIALIZED ? false : !esToolkit.isEqual(value, prev);
|
|
1261
|
-
if (immediate && prev === UNINITIALIZED) {
|
|
1262
|
-
onChangeRef.current(value, null);
|
|
1263
|
-
}
|
|
1264
|
-
else if (hasChanged && prev !== UNINITIALIZED) {
|
|
1265
|
-
onChangeRef.current(value, prev);
|
|
1266
|
-
}
|
|
1267
|
-
prevValue.current = value;
|
|
1268
|
-
}, [value, immediate, skip]);
|
|
1269
|
-
};
|
|
1270
|
-
|
|
1271
945
|
const WidgetConfigContext = react.createContext(null);
|
|
1272
946
|
/**
|
|
1273
947
|
* This is a hook to use the WidgetConfigProvider.
|
|
@@ -1401,7 +1075,6 @@ exports.useCurrentUser = useCurrentUser;
|
|
|
1401
1075
|
exports.useCurrentUserLanguage = useCurrentUserLanguage;
|
|
1402
1076
|
exports.useCurrentUserSystemOfMeasurement = useCurrentUserSystemOfMeasurement;
|
|
1403
1077
|
exports.useCurrentUserTimeZonePreference = useCurrentUserTimeZonePreference;
|
|
1404
|
-
exports.useCustomEncoding = useCustomEncoding;
|
|
1405
1078
|
exports.useCustomerRuntime = useCustomerRuntime;
|
|
1406
1079
|
exports.useEnvironment = useEnvironment;
|
|
1407
1080
|
exports.useErrorHandler = useErrorHandler;
|
|
@@ -1416,18 +1089,13 @@ exports.useImageUploader = useImageUploader;
|
|
|
1416
1089
|
exports.useIrisAppId = useIrisAppId;
|
|
1417
1090
|
exports.useIrisAppImage = useIrisAppImage;
|
|
1418
1091
|
exports.useIrisAppName = useIrisAppName;
|
|
1419
|
-
exports.useLocalStorage = useLocalStorage;
|
|
1420
|
-
exports.useLocalStorageReducer = useLocalStorageReducer;
|
|
1421
1092
|
exports.useModalDialogContext = useModalDialogContext;
|
|
1422
1093
|
exports.useNavigateInHost = useNavigateInHost;
|
|
1423
1094
|
exports.useOemBrandingContext = useOemBrandingContext;
|
|
1424
|
-
exports.usePrevious = usePrevious;
|
|
1425
1095
|
exports.useSiteRuntime = useSiteRuntime;
|
|
1426
|
-
exports.useTextSearch = useTextSearch;
|
|
1427
1096
|
exports.useTimeRange = useTimeRange;
|
|
1428
1097
|
exports.useToast = useToast;
|
|
1429
1098
|
exports.useToken = useToken;
|
|
1430
1099
|
exports.useUserSubscription = useUserSubscription;
|
|
1431
|
-
exports.useWatch = useWatch;
|
|
1432
1100
|
exports.useWidgetConfig = useWidgetConfig;
|
|
1433
1101
|
exports.useWidgetConfigAsync = useWidgetConfigAsync;
|
package/index.esm.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { createContext, useContext, useMemo,
|
|
1
|
+
import { createContext, useContext, useMemo, useState, useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { gzipSync, gunzipSync } from 'fflate';
|
|
4
3
|
import { AssetRuntime, CustomerRuntime, EventRuntime, ParamsRuntime, SiteRuntime, WidgetConfigRuntime } from '@trackunit/iris-app-runtime-core';
|
|
5
|
-
import { filterByMultiple } from '@trackunit/shared-utils';
|
|
6
|
-
import { isEqual } from 'es-toolkit';
|
|
7
4
|
|
|
8
5
|
const AnalyticsContext = createContext(null);
|
|
9
6
|
const AnalyticsContextProvider = AnalyticsContext.Provider; // easy import
|
|
@@ -112,106 +109,6 @@ const useConfirmationDialog = () => {
|
|
|
112
109
|
return confirmationDialogContext;
|
|
113
110
|
};
|
|
114
111
|
|
|
115
|
-
/**
|
|
116
|
-
* Base64URL encode bytes to a URL-safe string
|
|
117
|
-
*/
|
|
118
|
-
const b64urlEncode = (bytes) => {
|
|
119
|
-
let bin = "";
|
|
120
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
121
|
-
bin += String.fromCharCode(bytes[i] ?? 0);
|
|
122
|
-
}
|
|
123
|
-
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* Base64URL decode a URL-safe string to bytes
|
|
127
|
-
*/
|
|
128
|
-
const b64urlDecode = (s) => {
|
|
129
|
-
s = s.replace(/-/g, "+").replace(/_/g, "/");
|
|
130
|
-
s += "===".slice((s.length + 3) % 4);
|
|
131
|
-
const bin = atob(s);
|
|
132
|
-
const out = new Uint8Array(bin.length);
|
|
133
|
-
for (let i = 0; i < bin.length; i++) {
|
|
134
|
-
out[i] = bin.charCodeAt(i);
|
|
135
|
-
}
|
|
136
|
-
return out;
|
|
137
|
-
};
|
|
138
|
-
/**
|
|
139
|
-
* React hook for safe base64 encoding/decoding with UTF-8 support and compression
|
|
140
|
-
*
|
|
141
|
-
* This hook provides callbacks for safely encoding and decoding objects/strings to/from base64
|
|
142
|
-
* with proper Unicode character support (including Japanese, Chinese, etc.) and automatic
|
|
143
|
-
* compression for better performance with large objects.
|
|
144
|
-
*
|
|
145
|
-
* @returns { { encode: (input: unknown) => string, decode: (str: string) => JSON | string } } Object containing encode and decode callback functions
|
|
146
|
-
*/
|
|
147
|
-
const useCustomEncoding = () => {
|
|
148
|
-
/**
|
|
149
|
-
* Safely encode an object or string with compression and UTF-8 support
|
|
150
|
-
*
|
|
151
|
-
* This function compresses objects before encoding for better performance,
|
|
152
|
-
* and properly handles Unicode characters (including Japanese, Chinese, etc.).
|
|
153
|
-
*
|
|
154
|
-
* @param input - The object or string to encode
|
|
155
|
-
* @returns The compressed and encoded string
|
|
156
|
-
*/
|
|
157
|
-
const encode = useCallback((input) => {
|
|
158
|
-
try {
|
|
159
|
-
// If it's already a string, use it directly; otherwise stringify the object
|
|
160
|
-
const json = typeof input === "string" ? input : JSON.stringify(input);
|
|
161
|
-
const textInput = new TextEncoder().encode(json);
|
|
162
|
-
// Use fflate for synchronous gzip compression
|
|
163
|
-
const compressed = gzipSync(textInput);
|
|
164
|
-
return b64urlEncode(compressed);
|
|
165
|
-
}
|
|
166
|
-
catch (error) {
|
|
167
|
-
return "";
|
|
168
|
-
}
|
|
169
|
-
}, []);
|
|
170
|
-
/**
|
|
171
|
-
* Safely decode a compressed and encoded string back to its original form
|
|
172
|
-
*
|
|
173
|
-
* This function decompresses and decodes strings, properly handling Unicode characters
|
|
174
|
-
* and returning the original object or string.
|
|
175
|
-
*
|
|
176
|
-
* @param str - The compressed and encoded string to decode
|
|
177
|
-
* @returns The decoded object or string, or null if decoding fails
|
|
178
|
-
*/
|
|
179
|
-
const decode = useCallback((str) => {
|
|
180
|
-
try {
|
|
181
|
-
// Try to decode as compressed data first
|
|
182
|
-
try {
|
|
183
|
-
const bytes = b64urlDecode(str);
|
|
184
|
-
const decompressed = gunzipSync(bytes);
|
|
185
|
-
const json = new TextDecoder().decode(decompressed);
|
|
186
|
-
// Try to parse as JSON first (for objects)
|
|
187
|
-
try {
|
|
188
|
-
return JSON.parse(json);
|
|
189
|
-
}
|
|
190
|
-
catch (_) {
|
|
191
|
-
// If JSON parsing fails, return the string as-is
|
|
192
|
-
return json;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
catch (_) {
|
|
196
|
-
// If compression decoding fails, fall back to regular decoding
|
|
197
|
-
}
|
|
198
|
-
// Fallback: use regular base64 decoding
|
|
199
|
-
const decoded = decodeURIComponent(escape(atob(str)));
|
|
200
|
-
try {
|
|
201
|
-
return JSON.parse(decoded);
|
|
202
|
-
}
|
|
203
|
-
catch (_) {
|
|
204
|
-
// If JSON parsing fails, return the string as-is
|
|
205
|
-
return decoded;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
catch (error) {
|
|
209
|
-
return "";
|
|
210
|
-
}
|
|
211
|
-
}, []);
|
|
212
|
-
return useMemo(() => ({ encode, decode }), [encode, decode]);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
112
|
const EnvironmentContext = createContext(null);
|
|
216
113
|
/**
|
|
217
114
|
* This is a provider for the EnvironmentContext.
|
|
@@ -510,174 +407,6 @@ const useIrisAppImage = () => {
|
|
|
510
407
|
};
|
|
511
408
|
};
|
|
512
409
|
|
|
513
|
-
/**
|
|
514
|
-
* The usePrevious hook is a useful tool for tracking the previous value of a variable in a functional component. This can be particularly handy in scenarios where it is necessary to compare the current value with the previous one, such as triggering actions or rendering based on changes.
|
|
515
|
-
*
|
|
516
|
-
* @example
|
|
517
|
-
* const [color, setColor] = React.useState(getRandomColor());
|
|
518
|
-
const previousColor = usePrevious(color);
|
|
519
|
-
*/
|
|
520
|
-
const usePrevious = (value) => {
|
|
521
|
-
const ref = useRef(undefined);
|
|
522
|
-
useEffect(() => {
|
|
523
|
-
ref.current = value;
|
|
524
|
-
}, [value]);
|
|
525
|
-
const wrapper = useMemo(() => ({
|
|
526
|
-
get previous() {
|
|
527
|
-
return ref.current;
|
|
528
|
-
},
|
|
529
|
-
}), []);
|
|
530
|
-
return wrapper.previous;
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Validates the state object using a Zod schema.
|
|
535
|
-
*
|
|
536
|
-
* @template TState - The type of the state.
|
|
537
|
-
* @param {ValidateStateOptions<TState>} params - The parameters for the validateState function.
|
|
538
|
-
*/
|
|
539
|
-
const validateState = ({ state, schema, onValidationFailed, onValidationSuccessful, defaultState, }) => {
|
|
540
|
-
try {
|
|
541
|
-
const parsedState = schema.parse(state);
|
|
542
|
-
onValidationSuccessful?.(parsedState);
|
|
543
|
-
return parsedState;
|
|
544
|
-
}
|
|
545
|
-
catch (error) {
|
|
546
|
-
// eslint-disable-next-line no-console
|
|
547
|
-
console.error("Failed to parse and validate the state from local storage.", error);
|
|
548
|
-
onValidationFailed?.(error);
|
|
549
|
-
return defaultState;
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Initializes the state from local storage, parsing and validating it if a Zod schema is provided.
|
|
555
|
-
*
|
|
556
|
-
* @template TState - The type of the state stored in local storage.
|
|
557
|
-
* @param {Omit<LocalStorageParams<TState>, "state">} params - The parameters for initializing the local storage state.
|
|
558
|
-
* @returns {TState} - The initialized state.
|
|
559
|
-
*/
|
|
560
|
-
const initLocalStorageState = ({ key, defaultState, schema, }) => {
|
|
561
|
-
const localStorageItem = localStorage.getItem(key);
|
|
562
|
-
if (!localStorageItem) {
|
|
563
|
-
return defaultState;
|
|
564
|
-
}
|
|
565
|
-
const localStorageItemJSON = JSON.parse(localStorageItem);
|
|
566
|
-
if (!schema) {
|
|
567
|
-
return localStorageItemJSON;
|
|
568
|
-
}
|
|
569
|
-
return validateState({ state: localStorageItemJSON, defaultState, schema });
|
|
570
|
-
};
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* Sets a value in the local storage with the specified key.
|
|
574
|
-
* Thin wrapper around localStorage.setItem() that is slightly more type safe
|
|
575
|
-
* Stringifies value automatically.
|
|
576
|
-
* Useful if you for some reason can't use the useLocalStorage hook for React lifecycle reasons
|
|
577
|
-
*
|
|
578
|
-
* @template TValue - The type of value to be stored.
|
|
579
|
-
* @param {string} key - The key under which to store the value.
|
|
580
|
-
* @param {TValue} value - The value to store in the local storage.
|
|
581
|
-
*/
|
|
582
|
-
const setLocalStorage = (key, value) => {
|
|
583
|
-
localStorage.setItem(key, JSON.stringify(value));
|
|
584
|
-
};
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* Custom hook for synchronizing a state variable with local storage,
|
|
588
|
-
* with optional schema validation and callbacks.
|
|
589
|
-
*
|
|
590
|
-
* @template TState - The type of the state variable.
|
|
591
|
-
* @param {LocalStorageParams<TState> & LocalStorageCallbacks & { state: TState }} params - The parameters for the useLocalStorageEffect hook.
|
|
592
|
-
*/
|
|
593
|
-
const useLocalStorageEffect = ({ key, state, defaultState, schema, onValidationFailed, onValidationSuccessful, }) => {
|
|
594
|
-
const prevState = usePrevious(state);
|
|
595
|
-
useEffect(() => {
|
|
596
|
-
if (JSON.stringify(prevState) === JSON.stringify(state)) {
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
if (schema) {
|
|
600
|
-
validateState({
|
|
601
|
-
state,
|
|
602
|
-
schema,
|
|
603
|
-
defaultState,
|
|
604
|
-
onValidationFailed: error => {
|
|
605
|
-
// eslint-disable-next-line no-console
|
|
606
|
-
console.error(`State validation failed. Resetting local storage to default state: ${defaultState}.`, error);
|
|
607
|
-
localStorage.removeItem(key);
|
|
608
|
-
onValidationFailed?.(error);
|
|
609
|
-
},
|
|
610
|
-
onValidationSuccessful: data => {
|
|
611
|
-
setLocalStorage(key, data);
|
|
612
|
-
onValidationSuccessful?.(data);
|
|
613
|
-
},
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
else {
|
|
617
|
-
const stringifiedState = JSON.stringify(state);
|
|
618
|
-
localStorage.setItem(key, stringifiedState);
|
|
619
|
-
}
|
|
620
|
-
}, [state, key, schema, defaultState, prevState, onValidationFailed, onValidationSuccessful]);
|
|
621
|
-
};
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* Works like a normal useState, but saves to local storage and has optional schema validation.
|
|
625
|
-
*
|
|
626
|
-
* @template TState - The type of the value stored in local storage.
|
|
627
|
-
* @param {Omit<LocalStorageParams<TState>, "state"> & LocalStorageCallbacks} options - The options for useLocalStorage.
|
|
628
|
-
* @returns {[TState, Dispatch<SetStateAction<TState>>, () => void]} - A tuple containing the current value, a function to update the value, and a function to remove the value from local storage.
|
|
629
|
-
*/
|
|
630
|
-
const useLocalStorage = ({ key, defaultState, schema, onValidationFailed, onValidationSuccessful, }) => {
|
|
631
|
-
if (!key) {
|
|
632
|
-
throw new Error("useLocalStorage key must be defined");
|
|
633
|
-
}
|
|
634
|
-
const defaultStateRef = useRef(defaultState);
|
|
635
|
-
useEffect(() => {
|
|
636
|
-
defaultStateRef.current = defaultState;
|
|
637
|
-
}, [defaultState]);
|
|
638
|
-
const schemaRef = useRef(schema);
|
|
639
|
-
useEffect(() => {
|
|
640
|
-
schemaRef.current = schema;
|
|
641
|
-
}, [schema]);
|
|
642
|
-
const [state, setState] = useState(initLocalStorageState({ key, defaultState: defaultStateRef.current, schema: schemaRef.current }));
|
|
643
|
-
const prevKey = usePrevious(key);
|
|
644
|
-
useEffect(() => {
|
|
645
|
-
if (key !== prevKey) {
|
|
646
|
-
setState(initLocalStorageState({ key, defaultState: defaultStateRef.current, schema: schemaRef.current }));
|
|
647
|
-
}
|
|
648
|
-
}, [key, prevKey, schema]);
|
|
649
|
-
const localStorageProps = useMemo(() => ({
|
|
650
|
-
key,
|
|
651
|
-
state,
|
|
652
|
-
defaultState: defaultStateRef.current,
|
|
653
|
-
schema: schemaRef.current,
|
|
654
|
-
onValidationFailed,
|
|
655
|
-
onValidationSuccessful,
|
|
656
|
-
}), [key, state, onValidationFailed, onValidationSuccessful]);
|
|
657
|
-
useLocalStorageEffect(localStorageProps);
|
|
658
|
-
const reset = useCallback(() => {
|
|
659
|
-
setState(defaultStateRef.current);
|
|
660
|
-
}, []);
|
|
661
|
-
return useMemo(() => [state, setState, reset], [state, setState, reset]);
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* Works like a normal useReducer, but saves to local storage and has optional schema validation.
|
|
666
|
-
*
|
|
667
|
-
* @template TState - The type of the state.
|
|
668
|
-
* @template TAction - The type of the action.
|
|
669
|
-
* @param {LocalStorageParams<TState> & LocalStorageCallbacks} params - The parameters for the useLocalStorageReducer function.
|
|
670
|
-
* @returns {[TState, Dispatch<TAction>]} - A tuple containing the state and the dispatch function.
|
|
671
|
-
*/
|
|
672
|
-
const useLocalStorageReducer = ({ key, defaultState, reducer, schema, onValidationFailed, onValidationSuccessful, }) => {
|
|
673
|
-
if (!key) {
|
|
674
|
-
throw new Error("useLocalStorage key may not be falsy");
|
|
675
|
-
}
|
|
676
|
-
const [state, dispatch] = useReducer(reducer, defaultState, () => initLocalStorageState({ key, defaultState, schema }));
|
|
677
|
-
useLocalStorageEffect({ key, state, defaultState, schema, onValidationFailed, onValidationSuccessful });
|
|
678
|
-
return [state, dispatch];
|
|
679
|
-
};
|
|
680
|
-
|
|
681
410
|
const ModalDialogContext = createContext(null);
|
|
682
411
|
/**
|
|
683
412
|
* This is a provider for the ModalDialogContext.
|
|
@@ -808,7 +537,7 @@ const useAssetRuntime = () => {
|
|
|
808
537
|
setError(new Error("Failed to get asset info"));
|
|
809
538
|
}
|
|
810
539
|
};
|
|
811
|
-
getAssetInfo();
|
|
540
|
+
void getAssetInfo();
|
|
812
541
|
}, []);
|
|
813
542
|
return { assetInfo, loading, error };
|
|
814
543
|
};
|
|
@@ -847,7 +576,7 @@ const useCustomerRuntime = () => {
|
|
|
847
576
|
setError(new Error("Failed to get customer info"));
|
|
848
577
|
}
|
|
849
578
|
};
|
|
850
|
-
getCustomerInfo();
|
|
579
|
+
void getCustomerInfo();
|
|
851
580
|
}, []);
|
|
852
581
|
return { customerInfo, loading, error };
|
|
853
582
|
};
|
|
@@ -886,7 +615,7 @@ const useEventRuntime = () => {
|
|
|
886
615
|
setError(new Error("Failed to get event info"));
|
|
887
616
|
}
|
|
888
617
|
};
|
|
889
|
-
getEventInfo();
|
|
618
|
+
void getEventInfo();
|
|
890
619
|
}, []);
|
|
891
620
|
return { eventInfo, loading, error };
|
|
892
621
|
};
|
|
@@ -924,7 +653,7 @@ const useIrisAppName = () => {
|
|
|
924
653
|
setError(new Error("Failed to get iris app name"));
|
|
925
654
|
}
|
|
926
655
|
};
|
|
927
|
-
getAppName();
|
|
656
|
+
void getAppName();
|
|
928
657
|
}, []);
|
|
929
658
|
return { appName, loading, error };
|
|
930
659
|
};
|
|
@@ -949,7 +678,7 @@ const useIrisAppId = () => {
|
|
|
949
678
|
const [loading, setLoading] = useState(true);
|
|
950
679
|
const [error, setError] = useState();
|
|
951
680
|
useEffect(() => {
|
|
952
|
-
const
|
|
681
|
+
const getData = async () => {
|
|
953
682
|
setLoading(true);
|
|
954
683
|
try {
|
|
955
684
|
const updatedAppName = await ParamsRuntime.getAppName();
|
|
@@ -962,7 +691,7 @@ const useIrisAppId = () => {
|
|
|
962
691
|
setError(new Error("Failed to get iris app name"));
|
|
963
692
|
}
|
|
964
693
|
};
|
|
965
|
-
|
|
694
|
+
void getData();
|
|
966
695
|
}, []);
|
|
967
696
|
return { irisAppId, loading, error };
|
|
968
697
|
};
|
|
@@ -1001,7 +730,7 @@ const useSiteRuntime = () => {
|
|
|
1001
730
|
setError(new Error("Failed to get site info"));
|
|
1002
731
|
}
|
|
1003
732
|
};
|
|
1004
|
-
getSiteInfo();
|
|
733
|
+
void getSiteInfo();
|
|
1005
734
|
}, []);
|
|
1006
735
|
return { siteInfo, loading, error };
|
|
1007
736
|
};
|
|
@@ -1022,7 +751,7 @@ const UserSubscriptionProvider = (props) => {
|
|
|
1022
751
|
* const { numberOfDaysWithAccessToHistoricalData, packageType } = useUserSubscription();
|
|
1023
752
|
* // use it for something
|
|
1024
753
|
* const data = fetchData(numberOfDaysWithAccessToHistoricalData)
|
|
1025
|
-
* @see {
|
|
754
|
+
* @see { UserSubscription}
|
|
1026
755
|
*/
|
|
1027
756
|
const useUserSubscription = () => {
|
|
1028
757
|
const context = useContext(UserSubscriptionContext);
|
|
@@ -1211,61 +940,6 @@ const useCurrentUser = () => {
|
|
|
1211
940
|
return context;
|
|
1212
941
|
};
|
|
1213
942
|
|
|
1214
|
-
/**
|
|
1215
|
-
* Hook for filtering a list of items by text search, client side search in a list.
|
|
1216
|
-
*
|
|
1217
|
-
* @template TSearchableItem
|
|
1218
|
-
* @param items The list of items to filter.
|
|
1219
|
-
* @param props The properties to search in each item.
|
|
1220
|
-
* @returns {[TSearchableItem[], string, Dispatch<string>]} A tuple with the filtered items, the search text and a setter for the search text.
|
|
1221
|
-
* @example
|
|
1222
|
-
* const [result, searchText, setSearchText] = useTextSearch(items, item => [item.name, item.description]);
|
|
1223
|
-
*/
|
|
1224
|
-
function useTextSearch(items, props) {
|
|
1225
|
-
const [searchText, setSearchText] = useState("");
|
|
1226
|
-
const result = useMemo(() => {
|
|
1227
|
-
if (!searchText) {
|
|
1228
|
-
return items;
|
|
1229
|
-
}
|
|
1230
|
-
return filterByMultiple(items, props, searchText);
|
|
1231
|
-
}, [items, props, searchText]);
|
|
1232
|
-
return useMemo(() => [result, searchText, setSearchText], [result, searchText, setSearchText]);
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
const UNINITIALIZED = Symbol("UNINITIALIZED");
|
|
1236
|
-
/**
|
|
1237
|
-
* Hook to watch for changes in a value and react to them.
|
|
1238
|
-
* Uses deep equality comparison via es-toolkit's isEqual.
|
|
1239
|
-
*
|
|
1240
|
-
* @param props - The hook properties
|
|
1241
|
-
* @param props.value - The value to watch for changes
|
|
1242
|
-
* @param props.onChange - Function to call when the value changes
|
|
1243
|
-
* @param props.immediate - Whether to run the callback immediately on mount (default: false)
|
|
1244
|
-
* @param props.skip - Whether to skip watching for changes (default: false)
|
|
1245
|
-
*/
|
|
1246
|
-
const useWatch = ({ value, onChange, immediate = false, skip = false }) => {
|
|
1247
|
-
const prevValue = useRef(UNINITIALIZED);
|
|
1248
|
-
const onChangeRef = useRef(onChange);
|
|
1249
|
-
// Update the ref whenever onChange changes
|
|
1250
|
-
useEffect(() => {
|
|
1251
|
-
onChangeRef.current = onChange;
|
|
1252
|
-
}, [onChange]);
|
|
1253
|
-
useEffect(() => {
|
|
1254
|
-
if (skip) {
|
|
1255
|
-
return;
|
|
1256
|
-
}
|
|
1257
|
-
const prev = prevValue.current;
|
|
1258
|
-
const hasChanged = prev === UNINITIALIZED ? false : !isEqual(value, prev);
|
|
1259
|
-
if (immediate && prev === UNINITIALIZED) {
|
|
1260
|
-
onChangeRef.current(value, null);
|
|
1261
|
-
}
|
|
1262
|
-
else if (hasChanged && prev !== UNINITIALIZED) {
|
|
1263
|
-
onChangeRef.current(value, prev);
|
|
1264
|
-
}
|
|
1265
|
-
prevValue.current = value;
|
|
1266
|
-
}, [value, immediate, skip]);
|
|
1267
|
-
};
|
|
1268
|
-
|
|
1269
943
|
const WidgetConfigContext = createContext(null);
|
|
1270
944
|
/**
|
|
1271
945
|
* This is a hook to use the WidgetConfigProvider.
|
|
@@ -1369,4 +1043,4 @@ const useWidgetConfig = () => {
|
|
|
1369
1043
|
return result;
|
|
1370
1044
|
};
|
|
1371
1045
|
|
|
1372
|
-
export { AnalyticsContext, AnalyticsContextProvider, AssetSortingProvider, ConfirmationDialogProvider, CurrentUserPreferenceProvider, CurrentUserProvider, EnvironmentContextProvider, ErrorHandlingContext, ErrorHandlingContextProvider, ExportDataContext, FeatureFlagContextProvider, FilterBarProvider, ModalDialogContextProvider, NavigationContextProvider, OemBrandingContextProvider, TimeRangeProvider, ToastProvider, TokenProvider, UserSubscriptionProvider, WidgetConfigContext, WidgetConfigProvider, fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference,
|
|
1046
|
+
export { AnalyticsContext, AnalyticsContextProvider, AssetSortingProvider, ConfirmationDialogProvider, CurrentUserPreferenceProvider, CurrentUserProvider, EnvironmentContextProvider, ErrorHandlingContext, ErrorHandlingContextProvider, ExportDataContext, FeatureFlagContextProvider, FilterBarProvider, ModalDialogContextProvider, NavigationContextProvider, OemBrandingContextProvider, TimeRangeProvider, ToastProvider, TokenProvider, UserSubscriptionProvider, WidgetConfigContext, WidgetConfigProvider, fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useExportDataContext, useFeatureBranchQueryString, useFeatureFlags, useFilterBarContext, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useModalDialogContext, useNavigateInHost, useOemBrandingContext, useSiteRuntime, useTimeRange, useToast, useToken, useUserSubscription, useWidgetConfig, useWidgetConfigAsync };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-core-hooks",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.96",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -8,12 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"react": "19.0.0",
|
|
11
|
-
"
|
|
12
|
-
"@trackunit/iris-app-runtime-core": "1.
|
|
13
|
-
"@trackunit/shared-utils": "1.9.80",
|
|
14
|
-
"fflate": "^0.8.2",
|
|
15
|
-
"es-toolkit": "^1.39.10",
|
|
16
|
-
"@trackunit/iris-app-runtime-core-api": "1.7.90"
|
|
11
|
+
"@trackunit/iris-app-runtime-core": "1.8.92",
|
|
12
|
+
"@trackunit/iris-app-runtime-core-api": "1.7.92"
|
|
17
13
|
},
|
|
18
14
|
"module": "./index.esm.js",
|
|
19
15
|
"main": "./index.cjs.js",
|
package/src/index.d.ts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
export * from "./analytics/AnalyticsProvider";
|
|
2
2
|
export * from "./assetSorting/AssetSortingProvider";
|
|
3
3
|
export * from "./confirmationDialog/ConfirmationDialogProvider";
|
|
4
|
-
export * from "./encoding/useCustomEncoding";
|
|
5
4
|
export * from "./environment/EnvironmentContextProvider";
|
|
6
5
|
export * from "./errorHandling/ErrorHandlingProvider";
|
|
7
6
|
export * from "./exportData/ExportDataContextState";
|
|
8
7
|
export * from "./featureFlags/FeatureFlagContextProvider";
|
|
9
8
|
export * from "./fetchAssetBlobUrl";
|
|
10
|
-
export * from "./
|
|
9
|
+
export * from "./filterBar/FilterBarProvider";
|
|
11
10
|
export * from "./images/useImageUploader";
|
|
12
11
|
export * from "./images/useIrisAppImage";
|
|
13
|
-
export * from "./localStorage/useLocalStorage";
|
|
14
|
-
export * from "./localStorage/useLocalStorageReducer";
|
|
15
12
|
export * from "./modalDialog/ModalDialogProvider";
|
|
16
13
|
export * from "./navigation/NavigationContextProvider";
|
|
17
14
|
export * from "./oemBranding/OemBrandingContextProvider";
|
|
@@ -25,9 +22,6 @@ export * from "./timeRange/TimeRangeProvider";
|
|
|
25
22
|
export * from "./toast/ToastProvider";
|
|
26
23
|
export * from "./token/TokenProvider";
|
|
27
24
|
export * from "./useFeatureBranchQueryString";
|
|
28
|
-
export * from "./usePrevious";
|
|
29
25
|
export * from "./user/CurrentUserPreferenceProvider";
|
|
30
26
|
export * from "./user/CurrentUserProvider";
|
|
31
|
-
export * from "./useTextSearch";
|
|
32
|
-
export * from "./useWatch";
|
|
33
27
|
export * from "./widgetConfig/WidgetConfigProvider";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UserSubscription } from "@trackunit/iris-app-runtime-core-api";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
interface UserSubscriptionProviderProps {
|
|
4
|
-
value:
|
|
4
|
+
value: UserSubscription;
|
|
5
5
|
children?: ReactNode;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
@@ -17,7 +17,7 @@ export declare const UserSubscriptionProvider: (props: UserSubscriptionProviderP
|
|
|
17
17
|
* const { numberOfDaysWithAccessToHistoricalData, packageType } = useUserSubscription();
|
|
18
18
|
* // use it for something
|
|
19
19
|
* const data = fetchData(numberOfDaysWithAccessToHistoricalData)
|
|
20
|
-
* @see {
|
|
20
|
+
* @see { UserSubscription}
|
|
21
21
|
*/
|
|
22
|
-
export declare const useUserSubscription: () =>
|
|
22
|
+
export declare const useUserSubscription: () => UserSubscription;
|
|
23
23
|
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React hook for safe base64 encoding/decoding with UTF-8 support and compression
|
|
3
|
-
*
|
|
4
|
-
* This hook provides callbacks for safely encoding and decoding objects/strings to/from base64
|
|
5
|
-
* with proper Unicode character support (including Japanese, Chinese, etc.) and automatic
|
|
6
|
-
* compression for better performance with large objects.
|
|
7
|
-
*
|
|
8
|
-
* @returns { { encode: (input: unknown) => string, decode: (str: string) => JSON | string } } Object containing encode and decode callback functions
|
|
9
|
-
*/
|
|
10
|
-
export declare const useCustomEncoding: () => {
|
|
11
|
-
encode: (input: unknown) => string;
|
|
12
|
-
decode: (str: string) => JSON | string;
|
|
13
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { LocalStorageParams } from "./types";
|
|
2
|
-
/**
|
|
3
|
-
* Initializes the state from local storage, parsing and validating it if a Zod schema is provided.
|
|
4
|
-
*
|
|
5
|
-
* @template TState - The type of the state stored in local storage.
|
|
6
|
-
* @param {Omit<LocalStorageParams<TState>, "state">} params - The parameters for initializing the local storage state.
|
|
7
|
-
* @returns {TState} - The initialized state.
|
|
8
|
-
*/
|
|
9
|
-
export declare const initLocalStorageState: <TState>({ key, defaultState, schema, }: Omit<LocalStorageParams<TState>, "state">) => any;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sets a value in the local storage with the specified key.
|
|
3
|
-
* Thin wrapper around localStorage.setItem() that is slightly more type safe
|
|
4
|
-
* Stringifies value automatically.
|
|
5
|
-
* Useful if you for some reason can't use the useLocalStorage hook for React lifecycle reasons
|
|
6
|
-
*
|
|
7
|
-
* @template TValue - The type of value to be stored.
|
|
8
|
-
* @param {string} key - The key under which to store the value.
|
|
9
|
-
* @param {TValue} value - The value to store in the local storage.
|
|
10
|
-
*/
|
|
11
|
-
export declare const setLocalStorage: <TValue>(key: string, value: TValue) => void;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export interface LocalStorageParams<TState> {
|
|
3
|
-
/**
|
|
4
|
-
* The key used to store the value in local storage.
|
|
5
|
-
*/
|
|
6
|
-
key: string;
|
|
7
|
-
/**
|
|
8
|
-
* The default state value.
|
|
9
|
-
*/
|
|
10
|
-
defaultState: TState;
|
|
11
|
-
/**
|
|
12
|
-
* Optional schema for validating the state.
|
|
13
|
-
*/
|
|
14
|
-
schema?: z.Schema<TState>;
|
|
15
|
-
}
|
|
16
|
-
export interface LocalStorageCallbacks<TState> {
|
|
17
|
-
/**
|
|
18
|
-
* Optional callback function called when validation fails.
|
|
19
|
-
*
|
|
20
|
-
* @param error - The validation error object.
|
|
21
|
-
*/
|
|
22
|
-
onValidationFailed?: (error: unknown) => void;
|
|
23
|
-
/**
|
|
24
|
-
* Optional callback function called when validation succeeds.
|
|
25
|
-
*/
|
|
26
|
-
onValidationSuccessful?: (data: TState) => void;
|
|
27
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Dispatch, SetStateAction } from "react";
|
|
2
|
-
import { LocalStorageCallbacks, LocalStorageParams } from "./types";
|
|
3
|
-
/**
|
|
4
|
-
* Works like a normal useState, but saves to local storage and has optional schema validation.
|
|
5
|
-
*
|
|
6
|
-
* @template TState - The type of the value stored in local storage.
|
|
7
|
-
* @param {Omit<LocalStorageParams<TState>, "state"> & LocalStorageCallbacks} options - The options for useLocalStorage.
|
|
8
|
-
* @returns {[TState, Dispatch<SetStateAction<TState>>, () => void]} - A tuple containing the current value, a function to update the value, and a function to remove the value from local storage.
|
|
9
|
-
*/
|
|
10
|
-
export declare const useLocalStorage: <TState>({ key, defaultState, schema, onValidationFailed, onValidationSuccessful, }: LocalStorageParams<TState> & LocalStorageCallbacks<TState>) => readonly [TState, Dispatch<SetStateAction<TState>>, () => void];
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { LocalStorageCallbacks, LocalStorageParams } from "./types";
|
|
2
|
-
/**
|
|
3
|
-
* Custom hook for synchronizing a state variable with local storage,
|
|
4
|
-
* with optional schema validation and callbacks.
|
|
5
|
-
*
|
|
6
|
-
* @template TState - The type of the state variable.
|
|
7
|
-
* @param {LocalStorageParams<TState> & LocalStorageCallbacks & { state: TState }} params - The parameters for the useLocalStorageEffect hook.
|
|
8
|
-
*/
|
|
9
|
-
export declare const useLocalStorageEffect: <TState>({ key, state, defaultState, schema, onValidationFailed, onValidationSuccessful, }: LocalStorageParams<TState> & LocalStorageCallbacks<TState> & {
|
|
10
|
-
state: TState;
|
|
11
|
-
}) => void;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { LocalStorageCallbacks, LocalStorageParams } from "./types";
|
|
2
|
-
/**
|
|
3
|
-
* Works like a normal useReducer, but saves to local storage and has optional schema validation.
|
|
4
|
-
*
|
|
5
|
-
* @template TState - The type of the state.
|
|
6
|
-
* @template TAction - The type of the action.
|
|
7
|
-
* @param {LocalStorageParams<TState> & LocalStorageCallbacks} params - The parameters for the useLocalStorageReducer function.
|
|
8
|
-
* @returns {[TState, Dispatch<TAction>]} - A tuple containing the state and the dispatch function.
|
|
9
|
-
*/
|
|
10
|
-
export declare const useLocalStorageReducer: <TState, TAction>({ key, defaultState, reducer, schema, onValidationFailed, onValidationSuccessful, }: {
|
|
11
|
-
reducer: (state: TState, action: TAction) => TState;
|
|
12
|
-
} & LocalStorageParams<TState> & LocalStorageCallbacks<TState>) => readonly [TState, import("react").ActionDispatch<[action: TAction]>];
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { LocalStorageCallbacks, LocalStorageParams } from "./types";
|
|
2
|
-
type ValidateStateOptions<TState> = Required<Pick<LocalStorageParams<TState>, "schema">> & {
|
|
3
|
-
state: TState;
|
|
4
|
-
defaultState: TState;
|
|
5
|
-
} & LocalStorageCallbacks<TState>;
|
|
6
|
-
/**
|
|
7
|
-
* Validates the state object using a Zod schema.
|
|
8
|
-
*
|
|
9
|
-
* @template TState - The type of the state.
|
|
10
|
-
* @param {ValidateStateOptions<TState>} params - The parameters for the validateState function.
|
|
11
|
-
*/
|
|
12
|
-
export declare const validateState: <TState>({ state, schema, onValidationFailed, onValidationSuccessful, defaultState, }: ValidateStateOptions<TState>) => TState;
|
|
13
|
-
export {};
|
package/src/usePrevious.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The usePrevious hook is a useful tool for tracking the previous value of a variable in a functional component. This can be particularly handy in scenarios where it is necessary to compare the current value with the previous one, such as triggering actions or rendering based on changes.
|
|
3
|
-
*
|
|
4
|
-
* @example
|
|
5
|
-
* const [color, setColor] = React.useState(getRandomColor());
|
|
6
|
-
const previousColor = usePrevious(color);
|
|
7
|
-
*/
|
|
8
|
-
export declare const usePrevious: <TValue>(value: TValue) => TValue | undefined;
|
package/src/useTextSearch.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Maybe } from "@trackunit/shared-utils";
|
|
2
|
-
import { Dispatch } from "react";
|
|
3
|
-
/**
|
|
4
|
-
* Hook for filtering a list of items by text search, client side search in a list.
|
|
5
|
-
*
|
|
6
|
-
* @template TSearchableItem
|
|
7
|
-
* @param items The list of items to filter.
|
|
8
|
-
* @param props The properties to search in each item.
|
|
9
|
-
* @returns {[TSearchableItem[], string, Dispatch<string>]} A tuple with the filtered items, the search text and a setter for the search text.
|
|
10
|
-
* @example
|
|
11
|
-
* const [result, searchText, setSearchText] = useTextSearch(items, item => [item.name, item.description]);
|
|
12
|
-
*/
|
|
13
|
-
export declare function useTextSearch<TSearchableItem>(items: Array<TSearchableItem>, props: (item: TSearchableItem) => Array<Maybe<string> | undefined>): [Array<TSearchableItem>, string, Dispatch<string>];
|
package/src/useWatch.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
interface UseWatchOptions {
|
|
2
|
-
immediate?: boolean;
|
|
3
|
-
skip?: boolean;
|
|
4
|
-
}
|
|
5
|
-
interface UseWatchProps<TValue> extends UseWatchOptions {
|
|
6
|
-
value: TValue;
|
|
7
|
-
onChange: (value: TValue, prevValue: TValue | null) => void;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Hook to watch for changes in a value and react to them.
|
|
11
|
-
* Uses deep equality comparison via es-toolkit's isEqual.
|
|
12
|
-
*
|
|
13
|
-
* @param props - The hook properties
|
|
14
|
-
* @param props.value - The value to watch for changes
|
|
15
|
-
* @param props.onChange - Function to call when the value changes
|
|
16
|
-
* @param props.immediate - Whether to run the callback immediately on mount (default: false)
|
|
17
|
-
* @param props.skip - Whether to skip watching for changes (default: false)
|
|
18
|
-
*/
|
|
19
|
-
export declare const useWatch: <TValue>({ value, onChange, immediate, skip }: UseWatchProps<TValue>) => void;
|
|
20
|
-
export {};
|
|
File without changes
|