@applicaster/zapp-react-native-ui-components 16.0.0-alpha.1011304583 → 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/Components/MasterCell/DefaultComponents/ActionButton.tsx +27 -59
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +47 -21
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +34 -6
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +217 -46
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +46 -109
- package/Components/MasterCell/DefaultComponents/Button.tsx +50 -43
- package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/__snapshots__/index.test.tsx.snap +18 -0
- package/Components/MasterCell/DefaultComponents/CellBadge/__tests__/index.test.tsx +90 -0
- package/Components/MasterCell/DefaultComponents/CellBadge/index.tsx +13 -14
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +29 -9
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +46 -50
- package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +47 -39
- package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +19 -6
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +4 -0
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +45 -15
- package/Components/MasterCell/DefaultComponents/UIKitAdapters/Badge.tsx +49 -0
- package/Components/MasterCell/DefaultComponents/__tests__/ActionButton.test.tsx +122 -0
- package/Components/MasterCell/DefaultComponents/__tests__/Button.test.tsx +186 -0
- package/Components/MasterCell/DefaultComponents/__tests__/DynamicBadge.test.tsx +156 -0
- package/Components/MasterCell/DefaultComponents/__tests__/__snapshots__/ActionButton.test.tsx.snap +60 -0
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +196 -67
- package/Components/MasterCell/DefaultComponents/index.ts +4 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +154 -100
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +15 -4
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +56 -22
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +6 -4
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +3 -1
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +35 -26
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +15 -4
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +23 -16
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +8 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +2 -2
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/insertButtonsBetweenLabels.test.ts +45 -13
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +2 -2
- package/Components/MasterCell/contexts/PressedStateContext.ts +3 -0
- package/Components/MasterCell/elementMapper.tsx +2 -0
- package/Components/MasterCell/hooks/index.ts +2 -0
- package/Components/MasterCell/hooks/usePressedState.ts +4 -0
- package/Components/ModalComponent/AudioPlayer/Components/Action.tsx +332 -0
- package/Components/ModalComponent/AudioPlayer/Components/Button.tsx +402 -0
- package/Components/ModalComponent/AudioPlayer/Components/Header.tsx +811 -0
- package/Components/ModalComponent/AudioPlayer/Components/Input.tsx +671 -0
- package/Components/ModalComponent/AudioPlayer/Components/Item.tsx +878 -0
- package/Components/ModalComponent/AudioPlayer/Components/index.ts +9 -0
- package/Components/ModalComponent/BottomSheetDragArea.tsx +33 -0
- package/Components/ModalComponent/BottomSheetModalContent.tsx +49 -26
- package/Components/ModalComponent/__tests__/BottomSheetDragArea.test.tsx +74 -0
- package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +4 -85
- package/Components/OfflineHandler/__tests__/index.test.tsx +78 -18
- package/Components/OfflineHandler/hooks.ts +123 -0
- package/Components/OfflineHandler/index.tsx +51 -73
- package/Components/OfflineHandler/utils/index.ts +1 -13
- package/Components/PreloaderWrapper/index.tsx +1 -1
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +2 -0
- package/Components/ScreenFeedLoader/ScreenFeedLoader.tsx +5 -3
- package/Components/ScreenResolverFeedProvider/ScreenResolverFeedProvider.tsx +1 -1
- package/Components/TopCutoffOverlay/index.tsx +2 -2
- package/Components/Transitioner/Transitioner.tsx +28 -17
- package/package.json +5 -5
- package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +0 -112
- package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +0 -107
- package/Components/OfflineHandler/NotificationView/NotificationView.tsx +0 -153
- package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -66
- package/Components/OfflineHandler/NotificationView/utils.ts +0 -34
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import React, { useCallback, useEffect } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { ViewStyle } from "react-native";
|
|
3
|
+
import {
|
|
4
|
+
ActionButton as UIKitActionButton,
|
|
5
|
+
ActionButtonProps,
|
|
6
|
+
} from "@applicaster/uikit/lib/components/uikit/action-button";
|
|
3
7
|
|
|
4
8
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
5
|
-
|
|
6
9
|
import Image from "./Image";
|
|
10
|
+
|
|
7
11
|
type Props = {
|
|
8
12
|
item: ZappEntry | ZappFeed;
|
|
9
13
|
flavour?: "flavour_1" | "flavour_2";
|
|
@@ -28,30 +32,6 @@ type Props = {
|
|
|
28
32
|
extraProps?: Record<string, any>;
|
|
29
33
|
};
|
|
30
34
|
|
|
31
|
-
function isStringAsset(asset) {
|
|
32
|
-
return typeof asset === "string" || Array.isArray(asset);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function getAssetValue(asset, flavour, fallbackAsset = null) {
|
|
36
|
-
if (!asset) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (typeof asset === "string") return fallbackAsset || asset;
|
|
41
|
-
|
|
42
|
-
if (Array.isArray(asset)) {
|
|
43
|
-
const flavourIndex = Number(flavour.replace("flavour_", ""));
|
|
44
|
-
|
|
45
|
-
if (flavour && flavourIndex > -1) {
|
|
46
|
-
return fallbackAsset || asset[flavourIndex - 1];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return fallbackAsset || asset[0];
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return asset.src || fallbackAsset;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
35
|
export const ActionButton = React.memo(function ActionButtonComponent(
|
|
56
36
|
props: Props
|
|
57
37
|
) {
|
|
@@ -93,44 +73,32 @@ export const ActionButton = React.memo(function ActionButtonComponent(
|
|
|
93
73
|
}, [item?.id, setActionState, actionContext]);
|
|
94
74
|
|
|
95
75
|
if (actionDisabled || !actionContext) return null;
|
|
96
|
-
|
|
76
|
+
|
|
77
|
+
const resolvedAssetComponent = actionState?.asset;
|
|
97
78
|
|
|
98
79
|
// Default state is not yet ready
|
|
99
|
-
if (!
|
|
80
|
+
if (!resolvedAssetComponent) return null;
|
|
100
81
|
|
|
101
82
|
return (
|
|
102
|
-
<
|
|
103
|
-
|
|
83
|
+
<UIKitActionButton
|
|
84
|
+
id={`action-button-${item.id}`}
|
|
85
|
+
item={item}
|
|
86
|
+
action={action}
|
|
87
|
+
asset={asset}
|
|
88
|
+
flavour={flavour}
|
|
89
|
+
cellUUID={cellUUID}
|
|
90
|
+
extraProps={props?.extraProps}
|
|
91
|
+
show={!!resolvedAssetComponent}
|
|
92
|
+
AssetComponent={resolvedAssetComponent}
|
|
93
|
+
ImageComponent={Image}
|
|
104
94
|
onPress={onPress}
|
|
105
|
-
testID={props?.testID
|
|
106
|
-
accessibilityLabel={props?.accessibilityLabel
|
|
95
|
+
testID={props?.testID}
|
|
96
|
+
accessibilityLabel={props?.accessibilityLabel}
|
|
107
97
|
accessibilityHint={props?.accessibilityHint}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
fadeDuration={0}
|
|
114
|
-
style={asset?.style || props?.style}
|
|
115
|
-
uri={getAssetValue(
|
|
116
|
-
actionState.asset,
|
|
117
|
-
flavour,
|
|
118
|
-
actionState.state === 1 ? asset?.src.active : asset?.src.inactive
|
|
119
|
-
)}
|
|
120
|
-
{...asset?.props}
|
|
121
|
-
/>
|
|
122
|
-
) : (
|
|
123
|
-
<AssetComponent
|
|
124
|
-
flavour={flavour}
|
|
125
|
-
asset={getAssetValue(
|
|
126
|
-
asset,
|
|
127
|
-
flavour,
|
|
128
|
-
actionState.state === 1 ? asset?.src.active : asset?.src.inactive
|
|
129
|
-
)}
|
|
130
|
-
cellUUID={cellUUID}
|
|
131
|
-
{...(props?.extraProps ?? {})}
|
|
132
|
-
/>
|
|
133
|
-
)}
|
|
134
|
-
</TouchableOpacity>
|
|
98
|
+
style={props?.style as ActionButtonProps["style"]}
|
|
99
|
+
fallbackSrc={
|
|
100
|
+
actionState.state === 1 ? asset?.src.active : asset?.src.inactive
|
|
101
|
+
}
|
|
102
|
+
/>
|
|
135
103
|
);
|
|
136
104
|
});
|
package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts
CHANGED
|
@@ -6,28 +6,54 @@ import {
|
|
|
6
6
|
describe("ActionButtonsCore placement", () => {
|
|
7
7
|
const buttons = { type: "View", name: "buttons" };
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
{ name: "
|
|
11
|
-
{ name: "
|
|
12
|
-
{ name: "
|
|
9
|
+
const slots = [
|
|
10
|
+
{ name: "text_label_1", element: { type: "View", id: "label_1" } },
|
|
11
|
+
{ name: "text_label_2", element: { type: "View", id: "label_2" } },
|
|
12
|
+
{ name: "text_label_3", element: { type: "View", id: "label_3" } },
|
|
13
13
|
];
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
{ name: "below_label_1" },
|
|
17
|
-
{ name: "below_label_2" },
|
|
18
|
-
{ name: "below_label_3" },
|
|
19
|
-
];
|
|
15
|
+
const labels = slots.map((slot) => slot.element);
|
|
20
16
|
|
|
21
17
|
it("inserts buttons after the matching label", () => {
|
|
22
18
|
expect(
|
|
23
|
-
insertBetweenLabels({ position: "
|
|
24
|
-
).toEqual([
|
|
19
|
+
insertBetweenLabels({ position: "below_text_label_2" }, buttons, slots)
|
|
20
|
+
).toEqual([labels[0], labels[1], buttons, labels[2]]);
|
|
25
21
|
});
|
|
26
22
|
|
|
27
23
|
it("inserts buttons before the matching label", () => {
|
|
28
24
|
expect(
|
|
29
|
-
insertBetweenLabels({ position: "
|
|
30
|
-
).toEqual([
|
|
25
|
+
insertBetweenLabels({ position: "above_text_label_2" }, buttons, slots)
|
|
26
|
+
).toEqual([labels[0], buttons, labels[1], labels[2]]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("inserts buttons after the matching label on a plain name match", () => {
|
|
30
|
+
expect(
|
|
31
|
+
insertBetweenLabels({ position: "text_label_2" }, buttons, slots)
|
|
32
|
+
).toEqual([labels[0], labels[1], buttons, labels[2]]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("keeps the slot when its label is empty (null element)", () => {
|
|
36
|
+
const slotsWithEmpty = [
|
|
37
|
+
{ name: "text_label_1", element: { id: "label_1" } },
|
|
38
|
+
{ name: "text_label_2", element: null },
|
|
39
|
+
{ name: "text_label_3", element: { id: "label_3" } },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
expect(
|
|
43
|
+
insertBetweenLabels(
|
|
44
|
+
{ position: "above_text_label_2" },
|
|
45
|
+
buttons,
|
|
46
|
+
slotsWithEmpty
|
|
47
|
+
)
|
|
48
|
+
).toEqual([{ id: "label_1" }, buttons, { id: "label_3" }]);
|
|
49
|
+
|
|
50
|
+
expect(
|
|
51
|
+
insertBetweenLabels(
|
|
52
|
+
{ position: "below_text_label_2" },
|
|
53
|
+
buttons,
|
|
54
|
+
slotsWithEmpty
|
|
55
|
+
)
|
|
56
|
+
).toEqual([{ id: "label_1" }, buttons, { id: "label_3" }]);
|
|
31
57
|
});
|
|
32
58
|
|
|
33
59
|
it("prepends buttons only when on_top is allowed", () => {
|
|
@@ -35,17 +61,17 @@ describe("ActionButtonsCore placement", () => {
|
|
|
35
61
|
insertBetweenLabels(
|
|
36
62
|
{ position: "on_top", allowOnTop: true },
|
|
37
63
|
buttons,
|
|
38
|
-
|
|
64
|
+
slots
|
|
39
65
|
)
|
|
40
|
-
).toEqual([buttons, ...
|
|
66
|
+
).toEqual([buttons, ...labels]);
|
|
41
67
|
|
|
42
68
|
expect(
|
|
43
69
|
insertBetweenLabels(
|
|
44
70
|
{ position: "on_top", allowOnTop: false },
|
|
45
71
|
buttons,
|
|
46
|
-
|
|
72
|
+
slots
|
|
47
73
|
)
|
|
48
|
-
).toEqual(
|
|
74
|
+
).toEqual(labels);
|
|
49
75
|
});
|
|
50
76
|
|
|
51
77
|
it("appends buttons when appendWhenMissing is enabled", () => {
|
|
@@ -53,9 +79,9 @@ describe("ActionButtonsCore placement", () => {
|
|
|
53
79
|
insertBetweenLabels(
|
|
54
80
|
{ position: "unknown", appendWhenMissing: true },
|
|
55
81
|
buttons,
|
|
56
|
-
|
|
82
|
+
slots
|
|
57
83
|
)
|
|
58
|
-
).toEqual([...
|
|
84
|
+
).toEqual([...labels, buttons]);
|
|
59
85
|
});
|
|
60
86
|
|
|
61
87
|
it("returns labels unchanged when appendWhenMissing is disabled", () => {
|
|
@@ -63,9 +89,9 @@ describe("ActionButtonsCore placement", () => {
|
|
|
63
89
|
insertBetweenLabels(
|
|
64
90
|
{ position: "unknown", appendWhenMissing: false },
|
|
65
91
|
buttons,
|
|
66
|
-
|
|
92
|
+
slots
|
|
67
93
|
)
|
|
68
|
-
).toEqual(
|
|
94
|
+
).toEqual(labels);
|
|
69
95
|
});
|
|
70
96
|
|
|
71
97
|
const labelContainers = [
|
|
@@ -17,6 +17,11 @@ type InsertOptions = {
|
|
|
17
17
|
appendWhenMissing?: boolean;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
type Slot = {
|
|
21
|
+
name: string;
|
|
22
|
+
element?: unknown;
|
|
23
|
+
};
|
|
24
|
+
|
|
20
25
|
const hasLabelName = (value: unknown): value is Label =>
|
|
21
26
|
!!value &&
|
|
22
27
|
typeof value === "object" &&
|
|
@@ -100,8 +105,14 @@ const containsNestedLabel = (
|
|
|
100
105
|
export const insertBetweenLabels = (
|
|
101
106
|
{ position, allowOnTop = false, appendWhenMissing = false }: InsertOptions,
|
|
102
107
|
buttons: unknown,
|
|
103
|
-
|
|
108
|
+
slots: Slot[] = []
|
|
104
109
|
) => {
|
|
110
|
+
// Slots are defined by the canonical label list, so an empty (null) label
|
|
111
|
+
// still keeps its position — buttons placed above/below it survive.
|
|
112
|
+
const labels = slots
|
|
113
|
+
.map((slot) => slot.element)
|
|
114
|
+
.filter((element) => element != null);
|
|
115
|
+
|
|
105
116
|
if (buttons == null) {
|
|
106
117
|
return labels;
|
|
107
118
|
}
|
|
@@ -110,14 +121,31 @@ export const insertBetweenLabels = (
|
|
|
110
121
|
return [buttons, ...labels];
|
|
111
122
|
}
|
|
112
123
|
|
|
113
|
-
|
|
114
|
-
const
|
|
124
|
+
let inserted = false;
|
|
125
|
+
const result: unknown[] = [];
|
|
126
|
+
|
|
127
|
+
for (const { name, element } of slots) {
|
|
128
|
+
if (position === `above_${name}`) {
|
|
129
|
+
result.push(buttons);
|
|
130
|
+
inserted = true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (element != null) {
|
|
134
|
+
result.push(element);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Insert after on `below_*` or a plain label-name match.
|
|
138
|
+
if (position === `below_${name}` || position === name) {
|
|
139
|
+
result.push(buttons);
|
|
140
|
+
inserted = true;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
115
143
|
|
|
116
|
-
if (!inserted
|
|
117
|
-
return [...labels, buttons];
|
|
144
|
+
if (!inserted) {
|
|
145
|
+
return appendWhenMissing ? [...labels, buttons] : labels;
|
|
118
146
|
}
|
|
119
147
|
|
|
120
|
-
return
|
|
148
|
+
return result;
|
|
121
149
|
};
|
|
122
150
|
|
|
123
151
|
export const insertBetweenLabelContainers = (
|
package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx
CHANGED
|
@@ -1,26 +1,85 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "../index";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
jest.mock("@applicaster/zapp-react-native-utils/numberUtils", () => ({
|
|
11
|
-
toNumberWithDefaultZero: jest.fn((value) => Number(value) || 0),
|
|
12
|
-
}));
|
|
2
|
+
import { render, waitFor } from "@testing-library/react-native";
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
|
+
|
|
5
|
+
import { BorderContainerView, getBorderPadding } from "../index";
|
|
6
|
+
import { ImageBorderContainer } from "../../ImageBorderContainer";
|
|
7
|
+
import { MeasurementPortalContext } from "../../../../MeasurmentsPortal/MeasurementsPortal";
|
|
8
|
+
|
|
9
|
+
const mockAddHeading = jest.fn();
|
|
13
10
|
|
|
14
11
|
jest.mock(
|
|
15
12
|
"@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks",
|
|
16
13
|
() => ({
|
|
17
14
|
useAccessibilityManager: jest.fn(() => ({
|
|
18
|
-
addHeading:
|
|
15
|
+
addHeading: mockAddHeading,
|
|
19
16
|
})),
|
|
20
17
|
})
|
|
21
18
|
);
|
|
22
19
|
|
|
20
|
+
const createMockValue = () => {
|
|
21
|
+
const values = {
|
|
22
|
+
cell_padding_top: 1,
|
|
23
|
+
cell_padding_left: 2,
|
|
24
|
+
cell_padding_right: 3,
|
|
25
|
+
cell_padding_bottom: 4,
|
|
26
|
+
image_border_size: 5,
|
|
27
|
+
image_focused_border_color: "red",
|
|
28
|
+
image_selected_border_color: "blue",
|
|
29
|
+
image_focused_selected_border_color: "green",
|
|
30
|
+
image_border_color: "black",
|
|
31
|
+
image_corner_radius: 10,
|
|
32
|
+
image_border_position: "outside",
|
|
33
|
+
image_border_padding_top: 6,
|
|
34
|
+
image_border_padding_right: 7,
|
|
35
|
+
image_border_padding_bottom: 8,
|
|
36
|
+
image_border_padding_left: 9,
|
|
37
|
+
image_margin_top: 11,
|
|
38
|
+
image_margin_left: 12,
|
|
39
|
+
image_margin_right: 13,
|
|
40
|
+
image_margin_bottom: 14,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (key) => values[key] || 0;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const renderBorderContainer = (
|
|
47
|
+
overrideProps: Partial<any> = {},
|
|
48
|
+
measurementValue: React.ContextType<typeof MeasurementPortalContext> = null
|
|
49
|
+
) => {
|
|
50
|
+
const props = {
|
|
51
|
+
style: {
|
|
52
|
+
borderWidth: 4,
|
|
53
|
+
borderColor: "red",
|
|
54
|
+
borderRadius: 8,
|
|
55
|
+
backgroundColor: "navy",
|
|
56
|
+
},
|
|
57
|
+
testID: "border-container",
|
|
58
|
+
borderPosition: "outside" as const,
|
|
59
|
+
borderPaddingTop: 1,
|
|
60
|
+
borderPaddingRight: 2,
|
|
61
|
+
borderPaddingBottom: 3,
|
|
62
|
+
borderPaddingLeft: 4,
|
|
63
|
+
hasFocusableInside: jest.fn(() => false),
|
|
64
|
+
entry: { id: "test-entry", title: "Test title" } as ZappEntry,
|
|
65
|
+
state: "focused" as CellState,
|
|
66
|
+
hasTextLabels: false,
|
|
67
|
+
children: <View testID="child" />,
|
|
68
|
+
...overrideProps,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return render(
|
|
72
|
+
<MeasurementPortalContext.Provider value={measurementValue}>
|
|
73
|
+
<BorderContainerView {...props} />
|
|
74
|
+
</MeasurementPortalContext.Provider>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
23
78
|
describe("BorderContainerView", () => {
|
|
79
|
+
beforeEach(() => {
|
|
80
|
+
jest.clearAllMocks();
|
|
81
|
+
});
|
|
82
|
+
|
|
24
83
|
describe("getBorderPadding", () => {
|
|
25
84
|
it("returns 0 for inside", () => {
|
|
26
85
|
expect(getBorderPadding("inside", 10)).toBe(0);
|
|
@@ -35,47 +94,159 @@ describe("BorderContainerView", () => {
|
|
|
35
94
|
});
|
|
36
95
|
|
|
37
96
|
it("returns borderWidth for invalid position", () => {
|
|
38
|
-
// @ts-ignore
|
|
97
|
+
// @ts-ignore preserve current fallback semantics
|
|
39
98
|
expect(getBorderPadding("other_value", 10)).toBe(10);
|
|
40
99
|
});
|
|
41
100
|
});
|
|
42
101
|
|
|
43
|
-
it("
|
|
44
|
-
const style =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
102
|
+
it("extracts explicit border props from flattened style while preserving root style", () => {
|
|
103
|
+
const style = [
|
|
104
|
+
{ backgroundColor: "purple", shadowOpacity: 0.6 },
|
|
105
|
+
{ borderWidth: "6", borderColor: "orange", borderRadius: 12 },
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const { getByTestId } = renderBorderContainer({
|
|
109
|
+
style,
|
|
110
|
+
borderPaddingTop: 1,
|
|
111
|
+
borderPaddingRight: 2,
|
|
112
|
+
borderPaddingBottom: 3,
|
|
113
|
+
borderPaddingLeft: 4,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const root = getByTestId("border-container");
|
|
117
|
+
const overlay = root.children[0] as any;
|
|
118
|
+
const overlayHost = overlay.children[0] as any;
|
|
119
|
+
const child = root.children[1] as any;
|
|
120
|
+
|
|
121
|
+
expect(child.props.testID).toBe("child");
|
|
122
|
+
|
|
123
|
+
const flattenedRootStyle = StyleSheet.flatten(root.props.style);
|
|
124
|
+
expect(flattenedRootStyle.backgroundColor).toBe("purple");
|
|
125
|
+
expect(flattenedRootStyle.shadowOpacity).toBe(0.6);
|
|
126
|
+
expect(flattenedRootStyle.borderRadius).toBe(12);
|
|
127
|
+
|
|
128
|
+
expect(overlay.props.borderWidth).toBe(6);
|
|
129
|
+
expect(overlay.props.borderColor).toBe("orange");
|
|
130
|
+
expect(overlay.props.borderRadius).toBe(12);
|
|
131
|
+
|
|
132
|
+
const flattenedOverlayStyle = StyleSheet.flatten(overlayHost.props.style);
|
|
133
|
+
expect(flattenedOverlayStyle.borderWidth).toBe(6);
|
|
134
|
+
expect(flattenedOverlayStyle.borderColor).toBe("orange");
|
|
135
|
+
expect(flattenedOverlayStyle.top).toBe(-7);
|
|
136
|
+
expect(flattenedOverlayStyle.right).toBe(-8);
|
|
137
|
+
expect(flattenedOverlayStyle.bottom).toBe(-9);
|
|
138
|
+
expect(flattenedOverlayStyle.left).toBe(-10);
|
|
139
|
+
expect(flattenedOverlayStyle.borderTopLeftRadius).toBe(19);
|
|
140
|
+
expect(flattenedOverlayStyle.borderTopRightRadius).toBe(19);
|
|
141
|
+
expect(flattenedOverlayStyle.borderBottomLeftRadius).toBe(21);
|
|
142
|
+
expect(flattenedOverlayStyle.borderBottomRightRadius).toBe(20);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("renders no overlay when borderPosition is missing", () => {
|
|
146
|
+
const { getByTestId } = renderBorderContainer({
|
|
147
|
+
borderPosition: null,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const root = getByTestId("border-container");
|
|
151
|
+
|
|
152
|
+
expect(root.children).toHaveLength(2);
|
|
153
|
+
expect((root.children[0] as any).children).toHaveLength(0);
|
|
154
|
+
expect((root.children[1] as any).props.testID).toBe("child");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("preserves root pointerEvents defaults and caller overrides", () => {
|
|
158
|
+
const defaultRender = renderBorderContainer();
|
|
159
|
+
|
|
160
|
+
expect(
|
|
161
|
+
defaultRender.getByTestId("border-container").props.pointerEvents
|
|
162
|
+
).toBe("box-none");
|
|
163
|
+
|
|
164
|
+
const overrideRender = renderBorderContainer({
|
|
165
|
+
pointerEvents: "none",
|
|
166
|
+
testID: "override-border-container",
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
expect(
|
|
170
|
+
overrideRender.getByTestId("override-border-container").props
|
|
171
|
+
.pointerEvents
|
|
172
|
+
).toBe("none");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("keeps the heading announcement logic in the QuickBrick wrapper", async () => {
|
|
176
|
+
renderBorderContainer({
|
|
177
|
+
entry: { id: "entry-1", title: "Hero title" } as ZappEntry,
|
|
178
|
+
state: "focused",
|
|
179
|
+
hasTextLabels: false,
|
|
180
|
+
hasFocusableInside: jest.fn(() => false),
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await waitFor(() => {
|
|
184
|
+
expect(mockAddHeading).toHaveBeenCalledWith("Hero title");
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("suppresses the heading announcement while measurement is in progress", async () => {
|
|
189
|
+
renderBorderContainer(
|
|
190
|
+
{
|
|
191
|
+
entry: { id: "entry-1", title: "Hero title" } as ZappEntry,
|
|
192
|
+
},
|
|
193
|
+
{ measuringInProgress: true }
|
|
73
194
|
);
|
|
74
195
|
|
|
75
|
-
|
|
196
|
+
await waitFor(() => {
|
|
197
|
+
expect(mockAddHeading).not.toHaveBeenCalled();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("stays compatible with the ImageBorderContainer caller path", () => {
|
|
202
|
+
const imageBorderConfig = ImageBorderContainer({
|
|
203
|
+
value: createMockValue(),
|
|
204
|
+
state: "default",
|
|
205
|
+
imageStyles: {
|
|
206
|
+
width: 100,
|
|
207
|
+
height: 60,
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const { getByTestId } = renderBorderContainer({
|
|
212
|
+
style: imageBorderConfig.style,
|
|
213
|
+
pointerEvents: imageBorderConfig.additionalProps.pointerEvents,
|
|
214
|
+
borderPosition: imageBorderConfig.additionalProps.borderPosition,
|
|
215
|
+
borderPaddingTop: imageBorderConfig.additionalProps.borderPaddingTop,
|
|
216
|
+
borderPaddingRight: imageBorderConfig.additionalProps.borderPaddingRight,
|
|
217
|
+
borderPaddingBottom:
|
|
218
|
+
imageBorderConfig.additionalProps.borderPaddingBottom,
|
|
219
|
+
borderPaddingLeft: imageBorderConfig.additionalProps.borderPaddingLeft,
|
|
220
|
+
children: <View testID="image-border-child" />,
|
|
221
|
+
state: null,
|
|
222
|
+
hasTextLabels: true,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const root = getByTestId("border-container");
|
|
226
|
+
const overlay = root.children[0] as any;
|
|
227
|
+
const overlayHost = overlay.children[0] as any;
|
|
228
|
+
const child = root.children[1] as any;
|
|
229
|
+
|
|
230
|
+
expect(root.props.pointerEvents).toBe("none");
|
|
231
|
+
expect(child.props.testID).toBe("image-border-child");
|
|
232
|
+
|
|
233
|
+
const flattenedRootStyle = StyleSheet.flatten(root.props.style);
|
|
234
|
+
expect(flattenedRootStyle.borderRadius).toBe(10);
|
|
235
|
+
expect(flattenedRootStyle.marginTop).toBe(12);
|
|
236
|
+
expect(flattenedRootStyle.marginLeft).toBe(14);
|
|
237
|
+
expect(flattenedRootStyle.marginRight).toBe(16);
|
|
238
|
+
expect(flattenedRootStyle.marginBottom).toBe(18);
|
|
76
239
|
|
|
77
|
-
expect(
|
|
240
|
+
expect(overlay.props.borderWidth).toBe(5);
|
|
241
|
+
expect(overlay.props.borderColor).toBe("black");
|
|
242
|
+
expect(overlay.props.borderRadius).toBe(10);
|
|
78
243
|
|
|
79
|
-
|
|
244
|
+
const flattenedOverlayStyle = StyleSheet.flatten(overlayHost.props.style);
|
|
245
|
+
expect(flattenedOverlayStyle.borderWidth).toBe(5);
|
|
246
|
+
expect(flattenedOverlayStyle.borderColor).toBe("black");
|
|
247
|
+
expect(flattenedOverlayStyle.borderTopLeftRadius).toBe(21);
|
|
248
|
+
expect(flattenedOverlayStyle.borderTopRightRadius).toBe(21);
|
|
249
|
+
expect(flattenedOverlayStyle.borderBottomLeftRadius).toBe(23);
|
|
250
|
+
expect(flattenedOverlayStyle.borderBottomRightRadius).toBe(22);
|
|
80
251
|
});
|
|
81
252
|
});
|