@applicaster/zapp-react-native-ui-components 15.0.0-rc.144 → 15.0.0-rc.145
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/FocusableGroup/index.tsx +3 -2
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +5 -0
- package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
- package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tv.android.tsx +58 -0
- package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
- package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
- package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
- package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
- package/Components/MasterCell/DefaultComponents/PressableView.tsx +7 -234
- package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +11 -0
- package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
- package/Components/MasterCell/DefaultComponents/index.ts +7 -3
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +135 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +20 -29
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +22 -0
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +67 -69
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +21 -16
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +207 -9
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +56 -55
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +137 -16
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +49 -31
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +165 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +24 -21
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +24 -12
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +62 -0
- package/Components/MasterCell/MappingFunctions/index.js +3 -2
- package/Components/MasterCell/README.md +4 -0
- package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
- package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
- package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
- package/Components/MasterCell/dataAdapter.ts +4 -1
- package/Components/MasterCell/elementMapper.tsx +51 -7
- package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
- package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
- package/Components/MasterCell/utils/index.ts +85 -15
- package/Components/Navigator/StackNavigator.tsx +6 -0
- package/Components/ScreenRevealManager/withScreenRevealManager.tsx +4 -1
- package/package.json +5 -5
- package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ButtonContainerView.ts +0 -23
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
- package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@testing-library/react-native";
|
|
3
|
+
|
|
4
|
+
import { defaultComponents } from "../index";
|
|
5
|
+
import { elementMapper } from "../../elementMapper";
|
|
6
|
+
|
|
7
|
+
const WrapperProbe = jest.fn(({ children }) => <>{children}</>);
|
|
8
|
+
const LeafProbe = jest.fn(() => null);
|
|
9
|
+
|
|
10
|
+
const components = {
|
|
11
|
+
...defaultComponents,
|
|
12
|
+
View: WrapperProbe,
|
|
13
|
+
Text: LeafProbe,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const entry = { id: "entry-1" };
|
|
17
|
+
const item = { id: "item-1" };
|
|
18
|
+
|
|
19
|
+
const renderNode = (node) =>
|
|
20
|
+
render(
|
|
21
|
+
<React.Fragment>{elementMapper(components)(node as never)}</React.Fragment>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
describe("DataProvider", () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("injects resolved runtime props under dataProviderProps into the direct child and its direct children only", () => {
|
|
30
|
+
renderNode({
|
|
31
|
+
type: "DataProvider",
|
|
32
|
+
props: { _dataKey: "entry", entry },
|
|
33
|
+
elements: [
|
|
34
|
+
{
|
|
35
|
+
type: "View",
|
|
36
|
+
props: {},
|
|
37
|
+
elements: [
|
|
38
|
+
{
|
|
39
|
+
type: "View",
|
|
40
|
+
props: {},
|
|
41
|
+
elements: [{ type: "Text", props: {} }],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
expect(WrapperProbe).toHaveBeenNthCalledWith(
|
|
49
|
+
1,
|
|
50
|
+
expect.objectContaining({
|
|
51
|
+
dataProviderProps: expect.objectContaining({ entry }),
|
|
52
|
+
}),
|
|
53
|
+
expect.anything()
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(WrapperProbe).toHaveBeenNthCalledWith(
|
|
57
|
+
2,
|
|
58
|
+
expect.objectContaining({
|
|
59
|
+
dataProviderProps: expect.objectContaining({ entry }),
|
|
60
|
+
}),
|
|
61
|
+
expect.anything()
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
expect(LeafProbe).toHaveBeenCalledWith(
|
|
65
|
+
expect.not.objectContaining({
|
|
66
|
+
dataProviderProps: expect.anything(),
|
|
67
|
+
}),
|
|
68
|
+
expect.anything()
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("derives the namespaced values from the resolved runtime props", () => {
|
|
73
|
+
renderNode({
|
|
74
|
+
type: "DataProvider",
|
|
75
|
+
props: { _dataKey: "item", item },
|
|
76
|
+
elements: [
|
|
77
|
+
{
|
|
78
|
+
type: "View",
|
|
79
|
+
props: {},
|
|
80
|
+
elements: [{ type: "View", props: {} }],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(WrapperProbe).toHaveBeenNthCalledWith(
|
|
86
|
+
1,
|
|
87
|
+
expect.objectContaining({
|
|
88
|
+
dataProviderProps: expect.objectContaining({ item }),
|
|
89
|
+
}),
|
|
90
|
+
expect.anything()
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
expect(WrapperProbe).toHaveBeenNthCalledWith(
|
|
94
|
+
2,
|
|
95
|
+
expect.objectContaining({
|
|
96
|
+
dataProviderProps: expect.objectContaining({ item }),
|
|
97
|
+
}),
|
|
98
|
+
expect.anything()
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("does not overwrite explicit dataProviderProps on the direct child", () => {
|
|
103
|
+
const explicitEntry = { id: "explicit" };
|
|
104
|
+
|
|
105
|
+
renderNode({
|
|
106
|
+
type: "DataProvider",
|
|
107
|
+
props: { _dataKey: "entry", entry },
|
|
108
|
+
elements: [
|
|
109
|
+
{
|
|
110
|
+
type: "View",
|
|
111
|
+
props: {
|
|
112
|
+
dataProviderProps: {
|
|
113
|
+
entry: explicitEntry,
|
|
114
|
+
source: "child",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
elements: [{ type: "View", props: {} }],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
expect(WrapperProbe).toHaveBeenNthCalledWith(
|
|
123
|
+
1,
|
|
124
|
+
expect.objectContaining({
|
|
125
|
+
dataProviderProps: expect.objectContaining({
|
|
126
|
+
entry: explicitEntry,
|
|
127
|
+
source: "child",
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
130
|
+
expect.anything()
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(WrapperProbe).toHaveBeenNthCalledWith(
|
|
134
|
+
2,
|
|
135
|
+
expect.objectContaining({
|
|
136
|
+
dataProviderProps: expect.objectContaining({ entry }),
|
|
137
|
+
}),
|
|
138
|
+
expect.anything()
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -6,17 +6,19 @@ import PureImage from "./Image";
|
|
|
6
6
|
import { CollapsibleTextContainer } from "../SharedUI/CollapsibleTextContainer/CollapsibleTextContainer";
|
|
7
7
|
import { Toggle } from "./Toggle";
|
|
8
8
|
import { Button } from "./Button";
|
|
9
|
-
import { FocusableView } from "./FocusableView";
|
|
10
9
|
import ProgressBar from "../SharedUI/ProgressBar/ProgressBar";
|
|
11
10
|
import { LiveImage } from "./LiveImage";
|
|
12
11
|
import { DynamicBadge } from "./DynamicBadge";
|
|
13
12
|
import { SecondaryImage } from "./SecondaryImage/Image";
|
|
14
13
|
import { BorderContainerView } from "./BorderContainerView";
|
|
15
14
|
import { CellBadge } from "./CellBadge";
|
|
15
|
+
import { DataProvider } from "./DataProvider";
|
|
16
16
|
import { TvActionButtons } from "./tv/TvActionButtons";
|
|
17
|
-
import {
|
|
17
|
+
import { TvActionButton } from "./tv/TvActionButtons/TvActionButton";
|
|
18
|
+
import { ButtonContainerView } from "./ButtonContainerView";
|
|
18
19
|
import { ImageBorderContainer } from "./ImageBorderContainer";
|
|
19
20
|
import { PressableView } from "./PressableView";
|
|
21
|
+
import { ActionButton as MobileActionButton } from "./mobile/MobileActionButtons/ActionButton";
|
|
20
22
|
|
|
21
23
|
export const defaultComponents = {
|
|
22
24
|
View,
|
|
@@ -27,7 +29,6 @@ export const defaultComponents = {
|
|
|
27
29
|
Image,
|
|
28
30
|
PureImage,
|
|
29
31
|
ButtonContainerView,
|
|
30
|
-
FocusableView,
|
|
31
32
|
ProgressBar,
|
|
32
33
|
Toggle,
|
|
33
34
|
LiveImage,
|
|
@@ -36,5 +37,8 @@ export const defaultComponents = {
|
|
|
36
37
|
DynamicBadge,
|
|
37
38
|
SecondaryImage,
|
|
38
39
|
TvActionButtons,
|
|
40
|
+
TvActionButton,
|
|
41
|
+
MobileActionButton,
|
|
39
42
|
CellBadge,
|
|
43
|
+
DataProvider,
|
|
40
44
|
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { PressableView } from "../../PressableView";
|
|
3
|
+
|
|
4
|
+
import { ActionButtonController } from "../../ActionButtonsCore/components";
|
|
5
|
+
|
|
6
|
+
import { masterCellLogger } from "../../../logger";
|
|
7
|
+
import { resolveLabelText, selectByAssetFlavour } from "./utils";
|
|
8
|
+
|
|
9
|
+
type ChildElementProps = {
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
mobileActionRole?: "asset" | "label" | "label_container";
|
|
12
|
+
uri?: string;
|
|
13
|
+
asset?: React.ReactNode;
|
|
14
|
+
state?: "default" | "focused";
|
|
15
|
+
entry?: any;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const isValidElement = (
|
|
19
|
+
child: React.ReactNode
|
|
20
|
+
): child is React.ReactElement<ChildElementProps> =>
|
|
21
|
+
React.isValidElement(child);
|
|
22
|
+
|
|
23
|
+
export const ActionButton = ({ style, children, action, entry, ...props }) => {
|
|
24
|
+
return (
|
|
25
|
+
<ActionButtonController
|
|
26
|
+
action={action}
|
|
27
|
+
entry={entry}
|
|
28
|
+
onMissingActionContext={(identifier) => {
|
|
29
|
+
masterCellLogger.warning(
|
|
30
|
+
`You're missing an action plugin(${identifier || action?.identifier}) required by your mobile action button.`
|
|
31
|
+
);
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
{({ actionContext, actionState, isActive, onPress }) => {
|
|
35
|
+
const supportsEntryState =
|
|
36
|
+
typeof actionContext?.initialEntryState === "function";
|
|
37
|
+
|
|
38
|
+
const shouldRenderAsset = Boolean(
|
|
39
|
+
supportsEntryState ? actionState?.mobileButtonAssets : false
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const shouldRenderLabel = Boolean(
|
|
43
|
+
supportsEntryState && resolveLabelText(actionState?.label)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const _cloneChildrenWithState = (
|
|
47
|
+
nodes?: React.ReactNode
|
|
48
|
+
): React.ReactNode => {
|
|
49
|
+
return React.Children.map(nodes, (child) => {
|
|
50
|
+
if (!isValidElement(child)) {
|
|
51
|
+
return child;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const role = child.props.mobileActionRole;
|
|
55
|
+
|
|
56
|
+
const nextChildren = _cloneChildrenWithState(child.props.children);
|
|
57
|
+
|
|
58
|
+
// Prevents of the asset rendering when the action doesn't provide asset for current entry state
|
|
59
|
+
if (role === "asset" && !shouldRenderAsset) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Prevents of the label rendering when the action doesn't provide label for current entry state.
|
|
64
|
+
// Also prevents of the label container when it doesn't have children to avoid unnecessary empty space.
|
|
65
|
+
if (role === "label" && !shouldRenderLabel) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Prevents of the label container rendering when it doesn't have children to avoid unnecessary empty space.
|
|
70
|
+
if (
|
|
71
|
+
role === "label_container" &&
|
|
72
|
+
React.Children.count(nextChildren) === 0
|
|
73
|
+
) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const nextProps: Partial<ChildElementProps> = {};
|
|
78
|
+
|
|
79
|
+
// Inject asset or uri to Asset component with role asset
|
|
80
|
+
if (role === "asset") {
|
|
81
|
+
const resolvedAsset = selectByAssetFlavour(
|
|
82
|
+
actionState,
|
|
83
|
+
action.flavour,
|
|
84
|
+
isActive
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
if (typeof resolvedAsset === "function") {
|
|
88
|
+
const AssetComponent =
|
|
89
|
+
resolvedAsset as CellActionAssetComponent;
|
|
90
|
+
|
|
91
|
+
nextProps.asset = (
|
|
92
|
+
<AssetComponent
|
|
93
|
+
flavour={action.flavour || "flavour_1"}
|
|
94
|
+
width={action.width}
|
|
95
|
+
height={action.height}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
} else {
|
|
99
|
+
nextProps.uri = resolvedAsset;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Inject state and entry to Text component with role label
|
|
104
|
+
if (role === "label") {
|
|
105
|
+
nextProps.state = isActive ? "focused" : "default";
|
|
106
|
+
nextProps.entry = entry;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (nextChildren !== child.props.children) {
|
|
110
|
+
nextProps.children = nextChildren;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return React.cloneElement(child, nextProps);
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
if (!shouldRenderAsset && !shouldRenderLabel) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<PressableView
|
|
123
|
+
testID={props.testID || `${entry?.id}`}
|
|
124
|
+
style={isActive ? { ...style, ...props.focusedStyles } : style}
|
|
125
|
+
onPress={onPress}
|
|
126
|
+
accessibilityLabel={props.accessibilityLabel || `${entry?.id}`}
|
|
127
|
+
accessibilityHint={props.accessibilityHint}
|
|
128
|
+
>
|
|
129
|
+
{_cloneChildrenWithState(children)}
|
|
130
|
+
</PressableView>
|
|
131
|
+
);
|
|
132
|
+
}}
|
|
133
|
+
</ActionButtonController>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
@@ -1,40 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssetComponent } from "./AssetComponent";
|
|
2
2
|
|
|
3
3
|
type Props = {
|
|
4
|
-
prefix: string;
|
|
5
|
-
value: Function;
|
|
6
4
|
testID?: string;
|
|
5
|
+
style?: Record<string, unknown>;
|
|
7
6
|
};
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
type AssetNode = {
|
|
9
|
+
type: "ReactComponent";
|
|
10
|
+
style?: Record<string, unknown>;
|
|
11
|
+
additionalProps: {
|
|
12
|
+
component: typeof AssetComponent;
|
|
13
|
+
requiresCellUUID: true;
|
|
14
|
+
renderChildren: false;
|
|
15
|
+
mobileActionRole: "asset";
|
|
16
|
+
testID?: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
14
19
|
|
|
20
|
+
/** Asset used in conjunction with ActionButton inside mobile action buttons, uri is provided by ActionButton */
|
|
21
|
+
export const Asset = ({ testID, style }: Props): AssetNode => {
|
|
15
22
|
return {
|
|
16
|
-
type: "
|
|
17
|
-
style
|
|
18
|
-
width: toNumberWithDefaultZero(value(`${prefix}_asset_width`)),
|
|
19
|
-
height: toNumberWithDefaultZero(value(`${prefix}_asset_height`)),
|
|
20
|
-
marginTop: toNumberWithDefaultZero(value(`${prefix}_asset_margin_top`)),
|
|
21
|
-
marginRight: toNumberWithDefaultZero(
|
|
22
|
-
value(`${prefix}_asset_margin_right`)
|
|
23
|
-
),
|
|
24
|
-
marginBottom: toNumberWithDefaultZero(
|
|
25
|
-
value(`${prefix}_asset_margin_bottom`)
|
|
26
|
-
),
|
|
27
|
-
marginLeft: toNumberWithDefaultZero(value(`${prefix}_asset_margin_left`)),
|
|
28
|
-
backgroundColor: "transparent",
|
|
29
|
-
},
|
|
30
|
-
data: [
|
|
31
|
-
{
|
|
32
|
-
func: (entry) => entry,
|
|
33
|
-
args: [],
|
|
34
|
-
propName: "entry",
|
|
35
|
-
},
|
|
36
|
-
],
|
|
23
|
+
type: "ReactComponent",
|
|
24
|
+
style,
|
|
37
25
|
additionalProps: {
|
|
26
|
+
component: AssetComponent,
|
|
27
|
+
requiresCellUUID: true,
|
|
28
|
+
renderChildren: false,
|
|
38
29
|
mobileActionRole: "asset",
|
|
39
30
|
testID: testID ? `${testID}-asset` : undefined,
|
|
40
31
|
},
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { ImageContainer } from "../../ImageContainer";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
style?: Record<string, unknown>;
|
|
7
|
+
uri?: string;
|
|
8
|
+
asset?: React.ReactNode;
|
|
9
|
+
testID?: string;
|
|
10
|
+
cellUUID?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const AssetComponent = (props: Props & Record<string, unknown>) => {
|
|
14
|
+
return props.asset && React.isValidElement(props.asset) ? (
|
|
15
|
+
<View style={props.style} testID={props.testID}>
|
|
16
|
+
{React.cloneElement(props.asset, { cellUUID: props.cellUUID })}
|
|
17
|
+
</View>
|
|
18
|
+
) : (
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
<ImageContainer {...props} uri={props.uri} />
|
|
21
|
+
);
|
|
22
|
+
};
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
toNumberWithDefault,
|
|
3
|
-
toNumberWithDefaultZero,
|
|
4
|
-
} from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
1
|
+
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
5
2
|
import { compact } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
6
3
|
|
|
7
4
|
import { Asset } from "./Asset";
|
|
8
|
-
import { Spacer } from "./Spacer";
|
|
9
5
|
import { TextLabelsContainer } from "./TextLabelsContainer";
|
|
10
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
getAssetStyles,
|
|
8
|
+
getContentDirection,
|
|
9
|
+
getContentsAlignment,
|
|
10
|
+
getPressableStyles,
|
|
11
|
+
getTextLabelStyles,
|
|
12
|
+
} from "./utils";
|
|
11
13
|
|
|
12
|
-
const displayModeStyle = (
|
|
13
|
-
const mode = value(
|
|
14
|
+
const displayModeStyle = (value) => {
|
|
15
|
+
const mode = value("display_mode") || "dynamic";
|
|
14
16
|
|
|
15
17
|
if (mode === "fixed") {
|
|
16
18
|
return {
|
|
17
|
-
width: toNumberWithDefault(140, value(
|
|
19
|
+
width: toNumberWithDefault(140, value("width")),
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -42,86 +44,82 @@ export const Button = ({
|
|
|
42
44
|
specificPrefix,
|
|
43
45
|
spacingStyle,
|
|
44
46
|
}: Props) => {
|
|
45
|
-
|
|
47
|
+
// Retrives values depending to the slot
|
|
48
|
+
const getSlotBasedValue = (property: string) =>
|
|
49
|
+
value(`${specificPrefix}_${property}`);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Retrieves values depending to the independ_style toggle:
|
|
53
|
+
* (e.g for button value button_2_label_enabled returns button_1_label_enabled when independent_style: false)
|
|
54
|
+
*/
|
|
55
|
+
const getValue = (property: string) => value(`${stylePrefix}_${property}`);
|
|
56
|
+
|
|
57
|
+
const assetEnabled = getValue("asset_enabled");
|
|
58
|
+
const labelEnabled = getValue("label_enabled");
|
|
59
|
+
|
|
60
|
+
if (!getSlotBasedValue("button_enabled")) {
|
|
46
61
|
return null;
|
|
47
62
|
}
|
|
48
63
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const actionAssetFlavour = value(`${stylePrefix}_action_asset_flavour`);
|
|
64
|
+
if (!assetEnabled && !labelEnabled) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
53
67
|
|
|
54
|
-
const
|
|
55
|
-
|
|
68
|
+
const testID = `mobile_action_button_${index + 1}`;
|
|
69
|
+
const actionIdentifier = getSlotBasedValue("assign_action");
|
|
70
|
+
const assetAlignment = getValue("asset_alignment") || "left";
|
|
71
|
+
const actionAssetFlavour = getValue("action_asset_flavour");
|
|
72
|
+
const contentsAlignment = getValue("contents_alignment") || "center";
|
|
56
73
|
|
|
57
74
|
return {
|
|
58
|
-
type: "
|
|
75
|
+
type: "MobileActionButton",
|
|
59
76
|
style: {
|
|
60
77
|
flexDirection: getContentDirection(assetAlignment),
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
value(`${stylePrefix}_margin_right`)
|
|
67
|
-
),
|
|
68
|
-
marginBottom: toNumberWithDefaultZero(
|
|
69
|
-
value(`${stylePrefix}_margin_bottom`)
|
|
70
|
-
),
|
|
71
|
-
marginLeft: toNumberWithDefaultZero(value(`${stylePrefix}_margin_left`)),
|
|
72
|
-
|
|
73
|
-
paddingTop: toNumberWithDefaultZero(value(`${stylePrefix}_padding_top`)),
|
|
74
|
-
paddingRight: toNumberWithDefaultZero(
|
|
75
|
-
value(`${stylePrefix}_padding_right`)
|
|
76
|
-
),
|
|
77
|
-
paddingBottom: toNumberWithDefaultZero(
|
|
78
|
-
value(`${stylePrefix}_padding_bottom`)
|
|
79
|
-
),
|
|
80
|
-
paddingLeft: toNumberWithDefaultZero(
|
|
81
|
-
value(`${stylePrefix}_padding_left`)
|
|
82
|
-
),
|
|
83
|
-
|
|
84
|
-
borderWidth: toNumberWithDefaultZero(value(`${stylePrefix}_border_size`)),
|
|
85
|
-
borderRadius: toNumberWithDefaultZero(
|
|
86
|
-
value(`${stylePrefix}_corner_radius`)
|
|
87
|
-
),
|
|
88
|
-
borderColor: value(`${stylePrefix}_border_color`),
|
|
89
|
-
backgroundColor: value(`${stylePrefix}_background_color`),
|
|
90
|
-
|
|
91
|
-
...displayModeStyle({ value, prefix: stylePrefix }),
|
|
78
|
+
alignContent: "center",
|
|
79
|
+
alignItems: getContentsAlignment(contentsAlignment, assetAlignment),
|
|
80
|
+
justifyContent: getContentsAlignment(contentsAlignment, assetAlignment),
|
|
81
|
+
...getPressableStyles(getValue),
|
|
82
|
+
...displayModeStyle(getValue),
|
|
92
83
|
...spacingStyle,
|
|
93
84
|
},
|
|
94
85
|
additionalProps: {
|
|
95
86
|
action: {
|
|
96
87
|
identifier: actionIdentifier,
|
|
97
88
|
flavour: actionAssetFlavour,
|
|
89
|
+
width: toNumberWithDefault(24, getValue("asset_width")),
|
|
90
|
+
height: toNumberWithDefault(24, getValue("asset_height")),
|
|
98
91
|
},
|
|
99
92
|
focusedStyles: {
|
|
100
|
-
backgroundColor:
|
|
101
|
-
borderColor:
|
|
93
|
+
backgroundColor: getValue("focused_background_color"),
|
|
94
|
+
borderColor: getValue("focused_border_color"),
|
|
102
95
|
},
|
|
103
96
|
testID,
|
|
104
97
|
},
|
|
105
98
|
elements: compact([
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
99
|
+
assetEnabled
|
|
100
|
+
? Asset({
|
|
101
|
+
style: getAssetStyles(getValue),
|
|
102
|
+
testID,
|
|
103
|
+
})
|
|
104
|
+
: null,
|
|
105
|
+
|
|
106
|
+
labelEnabled
|
|
107
|
+
? TextLabelsContainer({
|
|
108
|
+
style: getTextLabelStyles(getValue),
|
|
109
|
+
extraProps: {
|
|
110
|
+
normalStyles: {
|
|
111
|
+
color: getValue("font_color"),
|
|
112
|
+
},
|
|
113
|
+
focusedStyles: {
|
|
114
|
+
color: getValue("focused_font_color"),
|
|
115
|
+
},
|
|
116
|
+
transformText: getValue("text_transform") || "default",
|
|
117
|
+
numberOfLines: getValue("number_of_lines"),
|
|
118
|
+
},
|
|
119
|
+
actionIdentifier,
|
|
120
|
+
testID,
|
|
121
|
+
})
|
|
122
|
+
: null,
|
|
118
123
|
]),
|
|
119
|
-
data: [
|
|
120
|
-
{
|
|
121
|
-
func: (x) => x,
|
|
122
|
-
args: [],
|
|
123
|
-
propName: "item",
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
124
|
};
|
|
127
125
|
};
|
package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
|
-
import { compact } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
2
|
-
|
|
3
|
-
import { TextLabel } from "./TextLabel";
|
|
4
|
-
|
|
5
1
|
type Props = {
|
|
6
|
-
prefix: string;
|
|
7
|
-
value: Function;
|
|
8
2
|
actionIdentifier: string;
|
|
9
3
|
testID?: string;
|
|
4
|
+
style?: object;
|
|
5
|
+
labelEnabled?: boolean;
|
|
6
|
+
extraProps?: object;
|
|
10
7
|
};
|
|
11
8
|
|
|
12
9
|
export const TextLabelsContainer = ({
|
|
13
|
-
prefix,
|
|
14
|
-
value,
|
|
15
10
|
actionIdentifier,
|
|
16
11
|
testID,
|
|
12
|
+
style,
|
|
13
|
+
extraProps,
|
|
17
14
|
}: Props) => {
|
|
18
15
|
return {
|
|
19
16
|
type: "View",
|
|
20
17
|
additionalProps: {
|
|
21
18
|
mobileActionRole: "label_container",
|
|
22
19
|
},
|
|
23
|
-
elements:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
elements: [
|
|
21
|
+
{
|
|
22
|
+
type: "Text",
|
|
23
|
+
style: style,
|
|
24
|
+
additionalProps: {
|
|
25
|
+
label: {
|
|
26
|
+
context: actionIdentifier,
|
|
27
|
+
name: "label_1",
|
|
28
|
+
},
|
|
29
|
+
state: "default",
|
|
30
|
+
mobileActionRole: "label",
|
|
31
|
+
testID: testID ? `${testID}-label` : undefined,
|
|
32
|
+
...extraProps,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
31
36
|
};
|
|
32
37
|
};
|