@applicaster/zapp-react-native-utils 15.1.4 → 16.0.0-alpha.1042942411
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -6
- package/actionUtils/index.ts +7 -0
- package/actionsExecutor/ActionExecutor.ts +8 -10
- package/actionsExecutor/ActionExecutorContext.tsx +45 -340
- package/actionsExecutor/actions/appRestart.ts +24 -0
- package/actionsExecutor/actions/confirmDialog.ts +53 -0
- package/actionsExecutor/actions/index.ts +30 -0
- package/actionsExecutor/actions/localStorageRemove.ts +27 -0
- package/actionsExecutor/actions/localStorageSet.ts +28 -0
- package/actionsExecutor/actions/localStorageToggleFlag.ts +28 -0
- package/actionsExecutor/actions/navigateToScreen.ts +123 -0
- package/actionsExecutor/actions/refreshComponent.ts +79 -0
- package/actionsExecutor/actions/screenSetVariable.ts +35 -0
- package/actionsExecutor/actions/screenToggleFlag.ts +38 -0
- package/actionsExecutor/actions/sendCloudEvent.ts +88 -0
- package/actionsExecutor/actions/sessionStorageRemove.ts +19 -0
- package/actionsExecutor/actions/sessionStorageSet.ts +20 -0
- package/actionsExecutor/actions/sessionStorageToggleFlag.ts +15 -0
- package/actionsExecutor/actions/showToast.ts +31 -0
- package/actionsExecutor/actions/switchLayout.ts +40 -0
- package/actionsExecutor/feedDecorator.ts +6 -6
- package/actionsExecutor/types.ts +59 -0
- package/adsUtils/__tests__/createVMAP.test.ts +419 -0
- package/adsUtils/index.ts +2 -2
- package/analyticsUtils/README.md +1 -1
- package/appDataUtils/__tests__/urlScheme.test.ts +678 -0
- package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +0 -188
- package/appUtils/HooksManager/__tests__/hooksManager.test.js +16 -2
- package/appUtils/HooksManager/index.ts +12 -18
- package/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
- package/appUtils/accessibilityManager/const.ts +4 -0
- package/appUtils/accessibilityManager/utils.ts +0 -1
- package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
- package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
- package/appUtils/contextKeysManager/contextResolver.ts +51 -22
- package/appUtils/contextKeysManager/index.ts +65 -10
- package/appUtils/contextKeysManager/utils/index.ts +38 -25
- package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +3 -0
- package/appUtils/focusManager/index.ios.ts +43 -4
- package/appUtils/focusManager/treeDataStructure/Tree/__tests__/Tree.test.js +46 -0
- package/appUtils/focusManager/treeDataStructure/Tree/index.js +18 -18
- package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
- package/appUtils/focusManagerAux/utils/index.ts +11 -3
- package/appUtils/focusManagerAux/utils/utils.ios.ts +202 -3
- package/appUtils/keyCodes/keys/keys.web.ts +1 -4
- package/appUtils/orientationHelper.ts +2 -4
- package/appUtils/platform/platformUtils.ts +12 -1
- package/appUtils/playerManager/player.ts +4 -0
- package/appUtils/playerManager/playerNative.ts +30 -21
- package/appUtils/playerManager/usePlayerState.tsx +14 -2
- package/bottomSheet/__tests__/scrollContext.test.tsx +35 -0
- package/bottomSheet/index.ts +17 -0
- package/cloudEventsUtils/__tests__/index.test.ts +529 -0
- package/cloudEventsUtils/index.ts +65 -1
- package/componentsUtils/index.ts +8 -0
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
- package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +207 -0
- package/errorUtils/__tests__/GeneralError.test.ts +97 -0
- package/errorUtils/__tests__/HttpStatusCode.test.ts +344 -0
- package/errorUtils/__tests__/MissingPluginError.test.ts +113 -0
- package/errorUtils/__tests__/NetworkError.test.ts +202 -0
- package/errorUtils/__tests__/getParsedResponse.test.ts +188 -0
- package/errorUtils/__tests__/invariant.test.ts +112 -0
- package/focusManager/aux/index.ts +1 -1
- package/headersUtils/__tests__/headersUtils.test.js +11 -1
- package/headersUtils/index.ts +2 -1
- package/manifestUtils/_internals/__tests__/index.test.js +41 -0
- package/manifestUtils/_internals/index.js +33 -0
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +35 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +63 -5
- package/manifestUtils/index.js +3 -1
- package/manifestUtils/keys.js +236 -0
- package/manifestUtils/mobileAction/button/__tests__/mobileActionButton.test.js +168 -0
- package/manifestUtils/mobileAction/button/index.js +156 -0
- package/manifestUtils/mobileAction/container/__tests__/mobileActionButtonsContainer.test.js +102 -0
- package/manifestUtils/mobileAction/container/index.js +75 -0
- package/manifestUtils/mobileAction/groups/__tests__/buildMobileActionButtonGroups.test.js +127 -0
- package/manifestUtils/mobileAction/groups/defaults.js +78 -0
- package/manifestUtils/mobileAction/groups/index.js +80 -0
- package/manifestUtils/tvAction/container/index.js +1 -1
- package/numberUtils/__tests__/isMinusZero.test.ts +20 -0
- package/numberUtils/__tests__/isZero.test.ts +27 -0
- package/numberUtils/__tests__/requireNumber.test.ts +50 -0
- package/numberUtils/__tests__/toNumber.test.ts +54 -0
- package/numberUtils/__tests__/toNumberWithDefault.test.ts +64 -0
- package/numberUtils/__tests__/toNumberWithDefaultZero.test.ts +48 -0
- package/numberUtils/__tests__/toPositiveNumber.test.ts +193 -0
- package/numberUtils/index.ts +46 -5
- package/package.json +4 -4
- package/pluginUtils/index.ts +4 -0
- package/reactHooks/actions/index.ts +51 -1
- package/reactHooks/advertising/index.ts +2 -2
- package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +537 -0
- package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
- package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
- package/reactHooks/cell-click/__tests__/index.test.js +1 -3
- package/reactHooks/cell-click/index.ts +15 -7
- package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
- package/reactHooks/connection/__tests__/index.test.js +1 -1
- package/reactHooks/debugging/__tests__/index.test.js +4 -4
- package/reactHooks/dev/__tests__/useReRenderLog.test.ts +188 -0
- package/reactHooks/device/useIsTablet.tsx +14 -19
- package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
- package/reactHooks/feed/__mocks__/useMarkPipesDataStale.ts +4 -0
- package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
- package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
- package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +4 -1
- package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
- package/reactHooks/feed/__tests__/useInflatedUrl.test.tsx +26 -1
- package/reactHooks/feed/index.ts +5 -3
- package/reactHooks/feed/useBatchLoading.ts +17 -3
- package/reactHooks/feed/useEntryScreenId.ts +2 -2
- package/reactHooks/feed/{usePipesCacheReset.ts → useMarkPipesDataStale.ts} +14 -4
- package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
- package/reactHooks/layout/__tests__/index.test.tsx +1 -1
- package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
- package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
- package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
- package/reactHooks/navigation/__tests__/index.test.tsx +2 -4
- package/reactHooks/navigation/index.ts +7 -6
- package/reactHooks/navigation/useRoute.ts +8 -6
- package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
- package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
- package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
- package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
- package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
- package/reactHooks/resolvers/useCellResolver.ts +6 -2
- package/reactHooks/resolvers/useComponentResolver.ts +8 -2
- package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
- package/reactHooks/screen/__tests__/useIsStandaloneFullscreen.test.ts +114 -0
- package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
- package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +12 -4
- package/reactHooks/screen/useTargetScreenData.ts +4 -2
- package/reactHooks/state/useComponentScreenState.ts +1 -1
- package/reactHooks/state/useRivers.ts +1 -1
- package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +580 -0
- package/reactHooks/usePluginConfiguration.ts +2 -2
- package/reactHooks/utils/__tests__/index.test.js +1 -1
- package/reactHooks/utils/index.ts +3 -2
- package/rectUtils/__tests__/index.test.ts +549 -0
- package/rectUtils/index.ts +2 -2
- package/refreshUtils/RefreshCoordinator/__tests__/refreshCoordinator.test.ts +206 -0
- package/refreshUtils/RefreshCoordinator/index.ts +245 -0
- package/refreshUtils/RefreshCoordinator/utils/__tests__/getDataRefreshConfig.test.ts +104 -0
- package/refreshUtils/RefreshCoordinator/utils/index.ts +29 -0
- package/riverComponetsMeasurementProvider/index.tsx +1 -1
- package/screenPickerUtils/__tests__/index.test.ts +333 -0
- package/screenState/__tests__/index.test.ts +1 -1
- package/screenUtils/index.ts +3 -0
- package/searchUtils/const.ts +7 -0
- package/searchUtils/index.ts +3 -0
- package/stringUtils/__tests__/stringUtils.test.js +42 -0
- package/stringUtils/index.ts +3 -3
- package/testUtils/index.tsx +30 -21
- package/time/__tests__/BackgroundTimer.test.ts +156 -0
- package/time/__tests__/Timer.test.ts +236 -0
- package/typeGuards/__tests__/isString.test.ts +21 -0
- package/typeGuards/index.ts +4 -0
- package/uiActionsRegistrator/index.ts +203 -0
- package/utils/__tests__/mergeRight.test.ts +48 -0
- package/utils/__tests__/path.test.ts +7 -0
- package/utils/__tests__/selectors.test.ts +124 -0
- package/utils/index.ts +13 -0
- package/utils/mergeRight.ts +5 -0
- package/utils/path.ts +6 -3
- package/utils/pathOr.ts +5 -1
- package/utils/selectors.ts +46 -0
- package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +1 -1
- package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
- package/zappFrameworkUtils/loginPluginUtils.ts +1 -1
- package/reactHooks/componentsMap/index.ts +0 -55
- package/reactHooks/feed/__mocks__/usePipesCacheReset.ts +0 -1
- package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +0 -75
- package/reactHooks/feed/useFeedRefresh.tsx +0 -65
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { toNumberWithDefault } from "..";
|
|
2
|
+
|
|
3
|
+
describe("toNumberWithDefault", () => {
|
|
4
|
+
const DEFAULT = 5;
|
|
5
|
+
|
|
6
|
+
it("return number if input is number", () => {
|
|
7
|
+
const inputs = [-1, 0, 1, 100, 0.2];
|
|
8
|
+
expect.assertions(inputs.length);
|
|
9
|
+
|
|
10
|
+
inputs.forEach((input) => {
|
|
11
|
+
const output = toNumberWithDefault(DEFAULT, input);
|
|
12
|
+
expect(output).toBe(input);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("return number if input is string as number", () => {
|
|
17
|
+
const inputs = ["-1", "0", "1", "100", "0.2"];
|
|
18
|
+
expect.assertions(inputs.length);
|
|
19
|
+
|
|
20
|
+
inputs.forEach((input) => {
|
|
21
|
+
const output = toNumberWithDefault(DEFAULT, input);
|
|
22
|
+
expect(output).toBe(Number(input));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("return default if input is not a number", () => {
|
|
27
|
+
const inputs = [
|
|
28
|
+
"vfdvf",
|
|
29
|
+
"5n",
|
|
30
|
+
"-5n",
|
|
31
|
+
null,
|
|
32
|
+
undefined,
|
|
33
|
+
NaN,
|
|
34
|
+
"",
|
|
35
|
+
{},
|
|
36
|
+
{ test: 1 },
|
|
37
|
+
[],
|
|
38
|
+
[1],
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
expect.assertions(inputs.length);
|
|
42
|
+
|
|
43
|
+
inputs.forEach((input) => {
|
|
44
|
+
const output = toNumberWithDefault(DEFAULT, input);
|
|
45
|
+
expect(output).toBe(DEFAULT);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("BigInt support", () => {
|
|
50
|
+
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
51
|
+
|
|
52
|
+
if (isBigIntSupported) {
|
|
53
|
+
it("converts BigInt to number when BigInt is supported", () => {
|
|
54
|
+
expect(toNumberWithDefault(DEFAULT, BigInt(5))).toBe(5);
|
|
55
|
+
expect(toNumberWithDefault(DEFAULT, BigInt(0))).toBe(0);
|
|
56
|
+
expect(toNumberWithDefault(DEFAULT, BigInt(-10))).toBe(-10);
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
it("skips BigInt tests when BigInt is not supported", () => {
|
|
60
|
+
expect(typeof BigInt).toBe("undefined");
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { toNumberWithDefaultZero } from "..";
|
|
2
|
+
|
|
3
|
+
const DEFAULT = 0;
|
|
4
|
+
|
|
5
|
+
describe("toNumberWithDefaultZero", () => {
|
|
6
|
+
it("return number if input is number", () => {
|
|
7
|
+
const inputs = [-1, 0, 1, 100, 0.2];
|
|
8
|
+
expect.assertions(inputs.length);
|
|
9
|
+
|
|
10
|
+
inputs.forEach((input) => {
|
|
11
|
+
const output = toNumberWithDefaultZero(input);
|
|
12
|
+
expect(output).toBe(input);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("return number if input is string as number", () => {
|
|
17
|
+
const inputs = ["-1", "0", "1", "100", "0.2"];
|
|
18
|
+
expect.assertions(inputs.length);
|
|
19
|
+
|
|
20
|
+
inputs.forEach((input) => {
|
|
21
|
+
const output = toNumberWithDefaultZero(input);
|
|
22
|
+
expect(output).toBe(Number(input));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("return zero if input is not a number", () => {
|
|
27
|
+
const inputs = [
|
|
28
|
+
"vfdvf",
|
|
29
|
+
"5n",
|
|
30
|
+
"-5n",
|
|
31
|
+
null,
|
|
32
|
+
undefined,
|
|
33
|
+
NaN,
|
|
34
|
+
"",
|
|
35
|
+
{},
|
|
36
|
+
{ test: 1 },
|
|
37
|
+
[],
|
|
38
|
+
[1],
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
expect.assertions(inputs.length);
|
|
42
|
+
|
|
43
|
+
inputs.forEach((input) => {
|
|
44
|
+
const output = toNumberWithDefaultZero(input);
|
|
45
|
+
expect(output).toBe(DEFAULT);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { toPositiveNumber } from "..";
|
|
2
|
+
|
|
3
|
+
describe("toPositiveNumber", () => {
|
|
4
|
+
describe("valid positive numbers", () => {
|
|
5
|
+
it("returns the number for positive integers", () => {
|
|
6
|
+
expect(toPositiveNumber(5)).toBe(5);
|
|
7
|
+
expect(toPositiveNumber(1000)).toBe(1000);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("returns the number for positive floats", () => {
|
|
11
|
+
expect(toPositiveNumber(0.1)).toBe(0.1);
|
|
12
|
+
expect(toPositiveNumber(3.14159)).toBe(3.14159);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("returns the number for very small positive numbers", () => {
|
|
16
|
+
expect(toPositiveNumber(1e-300)).toBe(1e-300);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("returns the number for very large positive numbers", () => {
|
|
20
|
+
expect(toPositiveNumber(1e300)).toBe(1e300);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("returns Infinity for positive infinity", () => {
|
|
24
|
+
expect(toPositiveNumber(Infinity)).toBe(Infinity);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("converts valid positive strings to numbers", () => {
|
|
28
|
+
expect(toPositiveNumber("5")).toBe(5);
|
|
29
|
+
expect(toPositiveNumber("3.14")).toBe(3.14);
|
|
30
|
+
expect(toPositiveNumber(" 100 ")).toBe(100);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("converts boolean true to undefined", () => {
|
|
34
|
+
expect(toPositiveNumber(true)).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("converts single-element arrays to undefined", () => {
|
|
38
|
+
expect(toPositiveNumber([5])).toBeUndefined();
|
|
39
|
+
expect(toPositiveNumber(["10"])).toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("invalid cases (return undefined)", () => {
|
|
44
|
+
describe("zero values", () => {
|
|
45
|
+
it("returns undefined for zero", () => {
|
|
46
|
+
expect(toPositiveNumber(0)).toBeUndefined();
|
|
47
|
+
expect(toPositiveNumber(-0)).toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("returns undefined for string zero", () => {
|
|
51
|
+
expect(toPositiveNumber("0")).toBeUndefined();
|
|
52
|
+
expect(toPositiveNumber(" 0 ")).toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns undefined for boolean false", () => {
|
|
56
|
+
expect(toPositiveNumber(false)).toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("returns undefined for empty arrays", () => {
|
|
60
|
+
expect(toPositiveNumber([])).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns undefined for empty strings", () => {
|
|
64
|
+
expect(toPositiveNumber("")).toBeUndefined();
|
|
65
|
+
expect(toPositiveNumber(" ")).toBeUndefined();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("negative values", () => {
|
|
70
|
+
it("returns undefined for negative numbers", () => {
|
|
71
|
+
expect(toPositiveNumber(-5)).toBeUndefined();
|
|
72
|
+
expect(toPositiveNumber(-0.1)).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("returns undefined for negative strings", () => {
|
|
76
|
+
expect(toPositiveNumber("-5")).toBeUndefined();
|
|
77
|
+
expect(toPositiveNumber(" -10 ")).toBeUndefined();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("returns undefined for negative infinity", () => {
|
|
81
|
+
expect(toPositiveNumber(-Infinity)).toBeUndefined();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("non-convertible values", () => {
|
|
86
|
+
it("returns undefined for null", () => {
|
|
87
|
+
expect(toPositiveNumber(null)).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("returns undefined for undefined", () => {
|
|
91
|
+
expect(toPositiveNumber(undefined)).toBeUndefined();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns undefined for objects", () => {
|
|
95
|
+
expect(toPositiveNumber({})).toBeUndefined();
|
|
96
|
+
expect(toPositiveNumber({ a: 1 })).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("returns undefined for multi-element arrays", () => {
|
|
100
|
+
expect(toPositiveNumber([1, 2])).toBeUndefined();
|
|
101
|
+
expect(toPositiveNumber(["a", "b"])).toBeUndefined();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("returns undefined for non-numeric strings", () => {
|
|
105
|
+
expect(toPositiveNumber("abc")).toBeUndefined();
|
|
106
|
+
expect(toPositiveNumber("5px")).toBeUndefined();
|
|
107
|
+
expect(toPositiveNumber("123.45.67")).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("returns undefined for NaN", () => {
|
|
111
|
+
expect(toPositiveNumber(NaN)).toBeUndefined();
|
|
112
|
+
expect(toPositiveNumber(Number("abc"))).toBeUndefined();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe("special cases", () => {
|
|
118
|
+
it("handles exponential notation correctly", () => {
|
|
119
|
+
expect(toPositiveNumber("1e5")).toBe(100000);
|
|
120
|
+
expect(toPositiveNumber("1e-5")).toBe(0.00001);
|
|
121
|
+
expect(toPositiveNumber("-1e5")).toBeUndefined();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("preserves precision for decimal numbers", () => {
|
|
125
|
+
expect(toPositiveNumber(0.1 + 0.2)).toBeCloseTo(0.3);
|
|
126
|
+
expect(toPositiveNumber("0.1")).toBe(0.1);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("handles numeric strings with leading zeros", () => {
|
|
130
|
+
expect(toPositiveNumber("005")).toBe(5);
|
|
131
|
+
expect(toPositiveNumber("0.5")).toBe(0.5);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("returns undefined for numeric strings with trailing non-numeric characters", () => {
|
|
135
|
+
expect(toPositiveNumber("5px")).toBeUndefined();
|
|
136
|
+
expect(toPositiveNumber("10%")).toBeUndefined();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("handles scientific notation correctly", () => {
|
|
140
|
+
expect(toPositiveNumber("1.5e2")).toBe(150);
|
|
141
|
+
expect(toPositiveNumber("-2.5e3")).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe("type conversion behavior", () => {
|
|
146
|
+
it("converts Date objects correctly", () => {
|
|
147
|
+
const date = new Date(2026, 1, 17);
|
|
148
|
+
expect(toPositiveNumber(date)).toBeUndefined();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("converts functions to NaN (returns undefined)", () => {
|
|
152
|
+
expect(toPositiveNumber(() => {})).toBeUndefined();
|
|
153
|
+
expect(toPositiveNumber(Math.sqrt)).toBeUndefined();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("handles Symbol values", () => {
|
|
157
|
+
expect(toPositiveNumber(Symbol("test"))).toBeUndefined();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("BigInt support", () => {
|
|
162
|
+
// Conditional test based on BigInt availability
|
|
163
|
+
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
164
|
+
|
|
165
|
+
if (isBigIntSupported) {
|
|
166
|
+
it("converts positive BigInt values to numbers when BigInt is supported", () => {
|
|
167
|
+
expect(toPositiveNumber(BigInt(5))).toBe(5);
|
|
168
|
+
expect(toPositiveNumber(BigInt(100))).toBe(100);
|
|
169
|
+
expect(toPositiveNumber(BigInt(1000))).toBe(1000);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("returns undefined for zero BigInt", () => {
|
|
173
|
+
expect(toPositiveNumber(BigInt(0))).toBeUndefined();
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("returns undefined for negative BigInt values", () => {
|
|
177
|
+
expect(toPositiveNumber(BigInt(-5))).toBeUndefined();
|
|
178
|
+
expect(toPositiveNumber(BigInt(-100))).toBeUndefined();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("handles large positive BigInt values", () => {
|
|
182
|
+
const largeBigInt = BigInt(Number.MAX_SAFE_INTEGER);
|
|
183
|
+
const result = toPositiveNumber(largeBigInt);
|
|
184
|
+
expect(result).toBe(Number(largeBigInt));
|
|
185
|
+
});
|
|
186
|
+
} else {
|
|
187
|
+
it("skips BigInt tests when BigInt is not supported", () => {
|
|
188
|
+
// Placeholder test to indicate BigInt is not available
|
|
189
|
+
expect(typeof BigInt).toBe("undefined");
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
package/numberUtils/index.ts
CHANGED
|
@@ -1,14 +1,37 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { isNil } from "@applicaster/zapp-react-native-utils/utils";
|
|
2
|
+
|
|
2
3
|
import { logger } from "@applicaster/zapp-react-native-utils/logger";
|
|
3
4
|
|
|
4
5
|
const numberUtilsLogger = logger?.addSubsystem("NumberUtils");
|
|
5
6
|
|
|
7
|
+
/** Matches Ramda isEmpty: "" / [] / {} are empty; numbers and bigints are not. */
|
|
8
|
+
const isEmpty = (value: unknown): boolean => {
|
|
9
|
+
if (typeof value === "string" || Array.isArray(value)) {
|
|
10
|
+
return value.length === 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (typeof value === "object" && value !== null) {
|
|
14
|
+
return Object.keys(value).length === 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return false;
|
|
18
|
+
};
|
|
19
|
+
|
|
6
20
|
export const toNumber = (value: unknown): number | undefined => {
|
|
7
|
-
if (
|
|
21
|
+
if (isNil(value) || isEmpty(value)) {
|
|
8
22
|
return undefined;
|
|
9
23
|
}
|
|
10
24
|
|
|
11
|
-
|
|
25
|
+
// Feature-detect BigInt support to avoid ReferenceError on older runtimes
|
|
26
|
+
const isBigIntSupported = typeof BigInt !== "undefined";
|
|
27
|
+
const isBigIntValue = isBigIntSupported && typeof value === "bigint";
|
|
28
|
+
|
|
29
|
+
if (
|
|
30
|
+
typeof value === "number" ||
|
|
31
|
+
isBigIntValue ||
|
|
32
|
+
typeof value === "string" ||
|
|
33
|
+
value instanceof String
|
|
34
|
+
) {
|
|
12
35
|
const numberOrNan = Number(value);
|
|
13
36
|
|
|
14
37
|
return Number.isNaN(numberOrNan) ? undefined : numberOrNan;
|
|
@@ -55,7 +78,7 @@ export const toFiniteNumberWithDefault = (
|
|
|
55
78
|
export const isLikeNumber = (value: unknown): boolean => {
|
|
56
79
|
const possibleNumber = toNumber(value);
|
|
57
80
|
|
|
58
|
-
if (
|
|
81
|
+
if (isNil(possibleNumber)) {
|
|
59
82
|
return false;
|
|
60
83
|
}
|
|
61
84
|
|
|
@@ -69,13 +92,31 @@ export const isMinusZero = (value: number) => {
|
|
|
69
92
|
return 1 / value === -Infinity;
|
|
70
93
|
};
|
|
71
94
|
|
|
95
|
+
export const toPositiveNumber = (value: unknown): number | undefined => {
|
|
96
|
+
const possibleNumber = toNumber(value);
|
|
97
|
+
|
|
98
|
+
if (isNil(possibleNumber)) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (possibleNumber < 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isZero(possibleNumber)) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return possibleNumber;
|
|
111
|
+
};
|
|
112
|
+
|
|
72
113
|
export const toPositiveNumberWithDefault = (
|
|
73
114
|
defaultValue: number,
|
|
74
115
|
value: unknown
|
|
75
116
|
): number => {
|
|
76
117
|
const possibleNumber = toNumber(value);
|
|
77
118
|
|
|
78
|
-
if (
|
|
119
|
+
if (isNil(possibleNumber)) {
|
|
79
120
|
return defaultValue;
|
|
80
121
|
}
|
|
81
122
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "16.0.0-alpha.1042942411",
|
|
4
4
|
"description": "Applicaster Zapp React Native utilities package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@applicaster/applicaster-types": "
|
|
30
|
+
"@applicaster/applicaster-types": "16.0.0-alpha.1042942411",
|
|
31
31
|
"buffer": "^5.2.1",
|
|
32
32
|
"camelize": "^1.0.0",
|
|
33
33
|
"dayjs": "^1.11.10",
|
|
34
|
+
"handlebars": "4.7.9",
|
|
34
35
|
"memoizee": "0.4.15",
|
|
35
|
-
"prop-types": "^15.0.0"
|
|
36
|
-
"react-native-handlebars": "^5.0.0-alpha.1"
|
|
36
|
+
"prop-types": "^15.0.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@applicaster/zapp-pipes-v2-client": "*",
|
package/pluginUtils/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { deprecationMessage } from "../appUtils";
|
|
|
6
6
|
|
|
7
7
|
import { pluginUtilsLogger } from "./logger";
|
|
8
8
|
import { platformSelect } from "../reactUtils";
|
|
9
|
+
import { get } from "../utils";
|
|
9
10
|
|
|
10
11
|
type PluginModule = any;
|
|
11
12
|
type Plugin = {
|
|
@@ -253,3 +254,6 @@ const getPluginType = R.pathOr("unknown_plugin_type", [
|
|
|
253
254
|
|
|
254
255
|
export const isPlayerPlugin = (routeState): boolean =>
|
|
255
256
|
getPluginType(routeState) === "player";
|
|
257
|
+
|
|
258
|
+
export const getPluginModuleUrlScheme = (plugin) =>
|
|
259
|
+
get(plugin, ["module", "urlScheme"]);
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/// <reference types="@applicaster/applicaster-types" />
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
|
-
import { Context, useContext, useState } from "react";
|
|
3
|
+
import { Context, useCallback, useContext, useEffect, useState } from "react";
|
|
4
4
|
import { ActionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ActionsContext";
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
observeEntryState,
|
|
8
|
+
RegisteredActionValue,
|
|
9
|
+
} from "../../uiActionsRegistrator";
|
|
6
10
|
import { reactHooksLogger } from "../logger";
|
|
7
11
|
|
|
8
12
|
const logger = reactHooksLogger.addSubsystem("actions");
|
|
@@ -46,3 +50,49 @@ export function useActions<T = unknown>(plugId: string): any {
|
|
|
46
50
|
|
|
47
51
|
return context;
|
|
48
52
|
}
|
|
53
|
+
|
|
54
|
+
export type UseEntryActionState = {
|
|
55
|
+
state: CellActionEntryState | undefined;
|
|
56
|
+
invokeAction: (options?: InvokeArgsOptions) => void;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Subscribes a component to a single action's state for a given `entry`.
|
|
61
|
+
*
|
|
62
|
+
* It observes state changes reactively via `observeEntryState` (which is backed
|
|
63
|
+
* by the action's `addListener`), seeds the initial value synchronously from
|
|
64
|
+
* `initialEntryState`, and returns a memoized `invokeAction` that forwards
|
|
65
|
+
* optimistic `updateState` updates back into local state.
|
|
66
|
+
*
|
|
67
|
+
* This is the single, unified way to drive an action button - it works the same
|
|
68
|
+
* for registry actions, legacy context-provider actions and entry actions.
|
|
69
|
+
*/
|
|
70
|
+
export function useEntryActionState(
|
|
71
|
+
action: RegisteredActionValue | undefined,
|
|
72
|
+
entry: ZappEntry | ZappFeed
|
|
73
|
+
): UseEntryActionState {
|
|
74
|
+
const [state, setState] = useState<CellActionEntryState | undefined>(() =>
|
|
75
|
+
action?.initialEntryState?.(entry)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const entryId = (entry as ZappEntry)?.id;
|
|
79
|
+
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (!action) return undefined;
|
|
82
|
+
|
|
83
|
+
const subscription = observeEntryState(action, entry).subscribe(setState);
|
|
84
|
+
|
|
85
|
+
return () => subscription.unsubscribe();
|
|
86
|
+
// eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
|
|
87
|
+
}, [action, entryId]);
|
|
88
|
+
|
|
89
|
+
const invokeAction = useCallback(
|
|
90
|
+
(options: InvokeArgsOptions = {}) => {
|
|
91
|
+
action?.invokeAction?.(entry, { updateState: setState, ...options });
|
|
92
|
+
},
|
|
93
|
+
// eslint-disable-next-line @wogns3623/better-exhaustive-deps/exhaustive-deps
|
|
94
|
+
[action, entryId]
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return { state, invokeAction };
|
|
98
|
+
}
|
|
@@ -3,7 +3,7 @@ import { View } from "react-native";
|
|
|
3
3
|
import * as R from "ramda";
|
|
4
4
|
|
|
5
5
|
import { useNavigation } from "../navigation";
|
|
6
|
-
import {
|
|
6
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux/hooks";
|
|
7
7
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
8
8
|
import { dismissModal, openModal } from "../../modalState";
|
|
9
9
|
|
|
@@ -16,7 +16,7 @@ const ModalContainer = platformSelect({
|
|
|
16
16
|
|
|
17
17
|
export function useAdvertisingInterstitial() {
|
|
18
18
|
const { screenData, currentRoute } = useNavigation();
|
|
19
|
-
const
|
|
19
|
+
const plugins = usePlugins();
|
|
20
20
|
|
|
21
21
|
return useEffect(() => {
|
|
22
22
|
// TODD: typing problem: fix any type
|