@trackunit/react-core-hooks 1.6.58 → 1.6.60

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 CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var react = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var fflate = require('fflate');
5
6
  var irisAppRuntimeCore = require('@trackunit/iris-app-runtime-core');
6
7
  var sharedUtils = require('@trackunit/shared-utils');
7
8
  var reactRouter = require('@tanstack/react-router');
@@ -113,6 +114,106 @@ const useConfirmationDialog = () => {
113
114
  return confirmationDialogContext;
114
115
  };
115
116
 
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 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
+
116
217
  const EnvironmentContext = react.createContext(null);
117
218
  /**
118
219
  * This is a provider for the EnvironmentContext.
@@ -1205,6 +1306,7 @@ exports.useCurrentUser = useCurrentUser;
1205
1306
  exports.useCurrentUserLanguage = useCurrentUserLanguage;
1206
1307
  exports.useCurrentUserSystemOfMeasurement = useCurrentUserSystemOfMeasurement;
1207
1308
  exports.useCurrentUserTimeZonePreference = useCurrentUserTimeZonePreference;
1309
+ exports.useCustomEncoding = useCustomEncoding;
1208
1310
  exports.useCustomerRuntime = useCustomerRuntime;
1209
1311
  exports.useEnvironment = useEnvironment;
1210
1312
  exports.useErrorHandler = useErrorHandler;
package/index.esm.js CHANGED
@@ -1,5 +1,6 @@
1
- import { createContext, useContext, useMemo, useState, useCallback, useRef, useEffect, useReducer } from 'react';
1
+ import { createContext, useContext, useMemo, useCallback, useState, useRef, useEffect, useReducer } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
+ import { gzipSync, gunzipSync } from 'fflate';
3
4
  import { AssetRuntime, CustomerRuntime, EventRuntime, ParamsRuntime, SiteRuntime, WidgetConfigRuntime } from '@trackunit/iris-app-runtime-core';
4
5
  import { filterByMultiple } from '@trackunit/shared-utils';
5
6
  import { useLocation } from '@tanstack/react-router';
@@ -111,6 +112,106 @@ const useConfirmationDialog = () => {
111
112
  return confirmationDialogContext;
112
113
  };
113
114
 
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 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
+
114
215
  const EnvironmentContext = createContext(null);
115
216
  /**
116
217
  * This is a provider for the EnvironmentContext.
@@ -1176,4 +1277,4 @@ const useWidgetConfig = () => {
1176
1277
  return result;
1177
1278
  };
1178
1279
 
1179
- export { AnalyticsContext, AnalyticsContextProvider, AssetSortingProvider, ConfirmationDialogProvider, CurrentUserPreferenceProvider, CurrentUserProvider, EnvironmentContextProvider, ErrorHandlingContext, ErrorHandlingContextProvider, FilterBarProvider, ModalDialogContextProvider, NavigationContextProvider, OemBrandingContextProvider, TimeRangeProvider, ToastProvider, TokenProvider, UserSubscriptionProvider, WidgetConfigProvider, fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useFeatureBranchQueryString, useFilterBarContext, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useLocalStorage, useLocalStorageReducer, useModalDialogContext, useNavigateInHost, useOemBrandingContext, usePrevious, useSiteRuntime, useTextSearch, useTimeRange, useToast, useToken, useUserSubscription, useWidgetConfig, useWidgetConfigAsync };
1280
+ export { AnalyticsContext, AnalyticsContextProvider, AssetSortingProvider, ConfirmationDialogProvider, CurrentUserPreferenceProvider, CurrentUserProvider, EnvironmentContextProvider, ErrorHandlingContext, ErrorHandlingContextProvider, FilterBarProvider, ModalDialogContextProvider, NavigationContextProvider, OemBrandingContextProvider, TimeRangeProvider, ToastProvider, TokenProvider, UserSubscriptionProvider, WidgetConfigProvider, fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomEncoding, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useFeatureBranchQueryString, useFilterBarContext, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useLocalStorage, useLocalStorageReducer, useModalDialogContext, useNavigateInHost, useOemBrandingContext, usePrevious, useSiteRuntime, useTextSearch, 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.6.58",
3
+ "version": "1.6.60",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -10,11 +10,12 @@
10
10
  "react": "19.0.0",
11
11
  "jest-fetch-mock": "^3.0.3",
12
12
  "zod": "^3.23.8",
13
- "@trackunit/react-core-contexts-api": "1.7.56",
14
- "@trackunit/iris-app-runtime-core": "1.7.57",
15
- "@trackunit/shared-utils": "1.8.55",
13
+ "@trackunit/react-core-contexts-api": "1.7.58",
14
+ "@trackunit/iris-app-runtime-core": "1.7.59",
15
+ "@trackunit/shared-utils": "1.8.57",
16
16
  "@tanstack/react-router": "1.114.29",
17
- "@trackunit/react-test-setup": "1.3.54"
17
+ "@trackunit/react-test-setup": "1.3.56",
18
+ "fflate": "^0.8.2"
18
19
  },
19
20
  "module": "./index.esm.js",
20
21
  "main": "./index.cjs.js",
@@ -0,0 +1,13 @@
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 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
+ };
package/src/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./analytics/AnalyticsProvider";
2
2
  export * from "./assetSorting/AssetSortingProvider";
3
3
  export * from "./confirmationDialog/ConfirmationDialogProvider";
4
+ export * from "./encoding/useCustomEncoding";
4
5
  export * from "./environment/EnvironmentContextProvider";
5
6
  export * from "./errorHandling/ErrorHandlingProvider";
6
7
  export * from "./fetchAssetBlobUrl";