@developer_tribe/react-builder 1.2.22 → 1.2.24
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/dist/attribute-analyser/style/native/useExtractImageStyle.d.ts +6 -6
- package/dist/attribute-analyser/style/native/useExtractTextStyle.d.ts +6 -4
- package/dist/attribute-analyser/style/native/useExtractViewStyle.d.ts +5 -3
- package/dist/build-components/Image/ImageProps.generated.d.ts +2 -4
- package/dist/build-components/NavigationBarColor/NavigationBarColor.d.ts +5 -0
- package/dist/build-components/NavigationBarColor/NavigationBarColorProps.generated.d.ts +54 -0
- package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +1 -3
- package/dist/build-components/Separator/Separator.d.ts +5 -0
- package/dist/build-components/Separator/SeparatorProps.generated.d.ts +21 -0
- package/dist/build-components/StatusBarColor/StatusBarColor.d.ts +5 -0
- package/dist/build-components/StatusBarColor/StatusBarColorProps.generated.d.ts +54 -0
- package/dist/build-components/index.d.ts +4 -1
- package/dist/build-components/patterns.generated.d.ts +2111 -1251
- package/dist/components/AttributesEditorPanel.d.ts +1 -1
- package/dist/components/BuilderProvider.d.ts +1 -1
- package/dist/index.cjs.js +4 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +6 -6
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +4 -4
- package/dist/index.web.esm.js.map +1 -1
- package/dist/store.d.ts +4 -0
- package/dist/styles.css +1 -1
- package/dist/utils/attributeStyle.d.ts +21 -0
- package/dist/utils/extractImageStyle.d.ts +1 -1
- package/dist/utils/extractViewStyle/extractViewStyleNative.d.ts +1 -1
- package/package.json +7 -2
- package/src/DeviceMockFrame.tsx +8 -2
- package/src/assets/meta.json +1 -1
- package/src/assets/samples/paywall-1.json +44 -39
- package/src/assets/samples/paywall-2.json +44 -25
- package/src/assets/samples/paywall-app-delete-offer.json +40 -21
- package/src/assets/samples/paywall-app-open-offer.json +40 -21
- package/src/assets/samples/paywall-back-offer.json +40 -21
- package/src/assets/samples/paywall-notification-offer.json +40 -21
- package/src/assets/samples/vpn-onboard-1.json +84 -39
- package/src/assets/samples/vpn-onboard-2.json +85 -40
- package/src/assets/samples/vpn-onboard-3.json +84 -39
- package/src/assets/samples/vpn-onboard-4.json +84 -39
- package/src/assets/samples/vpn-onboard-5.json +102 -55
- package/src/assets/samples/vpn-onboard-6.json +87 -38
- package/src/attribute-analyser/style/native/useExtractImageStyle.ts +31 -25
- package/src/attribute-analyser/style/native/useExtractTextStyle.ts +26 -11
- package/src/attribute-analyser/style/native/useExtractViewStyle.ts +21 -11
- package/src/attributes-editor/useAttributesEditorModel.ts +23 -17
- package/src/build-components/BackgroundImage/pattern.json +9 -7
- package/src/build-components/CarouselDots/CarouselDots.tsx +12 -11
- package/src/build-components/CarouselProvider/CarouselProvider.tsx +3 -1
- package/src/build-components/Image/ImageProps.generated.ts +2 -4
- package/src/build-components/Image/pattern.json +15 -25
- package/src/build-components/NavigationBarColor/NavigationBarColor.tsx +39 -0
- package/src/build-components/NavigationBarColor/NavigationBarColorProps.generated.ts +71 -0
- package/src/build-components/NavigationBarColor/pattern.json +34 -0
- package/src/build-components/OnboardButton/OnboardButton.tsx +19 -5
- package/src/build-components/OnboardButtons/OnboardButtons.tsx +8 -10
- package/src/build-components/OnboardDot/OnboardDot.tsx +12 -10
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +15 -4
- package/src/build-components/OnboardImage/OnboardImage.tsx +1 -1
- package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +1 -3
- package/src/build-components/OnboardProvider/OnboardProvider.tsx +3 -1
- package/src/build-components/RenderNode.generated.tsx +15 -0
- package/src/build-components/Separator/Separator.tsx +41 -0
- package/src/build-components/Separator/SeparatorProps.generated.ts +26 -0
- package/src/build-components/Separator/pattern.json +59 -0
- package/src/build-components/StatusBarColor/StatusBarColor.tsx +39 -0
- package/src/build-components/StatusBarColor/StatusBarColorProps.generated.ts +71 -0
- package/src/build-components/StatusBarColor/pattern.json +34 -0
- package/src/build-components/Text/pattern.json +45 -38
- package/src/build-components/index.ts +15 -0
- package/src/build-components/patterns.generated.ts +2153 -1272
- package/src/build-components/useNode.ts +24 -25
- package/src/components/AttributesEditorPanel.tsx +4 -5
- package/src/components/Builder.tsx +1 -2
- package/src/components/BuilderProvider.tsx +43 -6
- package/src/components/JsonTextEditor.tsx +2 -2
- package/src/components/LoadingComponent.tsx +1 -1
- package/src/components/RenderErrorBoundary.tsx +1 -3
- package/src/index.ts +3 -0
- package/src/migrations/migrations/1.1.2_extract_component_attributes_from_style.ts +3 -3
- package/src/modals/BenefitPresetsModal.tsx +1 -1
- package/src/modals/ProductPresetsModal.tsx +1 -1
- package/src/pages/DebugJsonPage.tsx +7 -4
- package/src/pages/ProjectDebug.tsx +1 -1
- package/src/pages/ProjectPage.tsx +31 -32
- package/src/pages/ProjectValidationPage.tsx +2 -2
- package/src/store.ts +13 -0
- package/src/styles/layout/_builder.scss +6 -0
- package/src/utils/__special_exceptions.ts +5 -5
- package/src/utils/analyseNode.ts +2 -2
- package/src/utils/analyseNodeByPatterns.ts +10 -9
- package/src/utils/analyseNodeStructural.ts +1 -1
- package/src/utils/attributeStyle.ts +104 -0
- package/src/utils/extractImageStyle.ts +17 -13
- package/src/utils/extractTextStyle/extractTextStyle.ts +7 -7
- package/src/utils/extractTextStyle/extractTextStyleNative.ts +10 -10
- package/src/utils/extractViewStyle/extractViewStyle.ts +8 -11
- package/src/utils/extractViewStyle/extractViewStyleNative.ts +19 -19
- package/src/utils/loadFontFamily.ts +14 -19
- package/src/utils/logRenderStore.ts +5 -4
- package/src/utils/nodeTree.ts +1 -1
- package/src/utils/patterns.ts +26 -31
- package/src/utils/repairNodeKeys.ts +5 -7
- package/src/utils/wrapNodeInMain.ts +3 -3
|
@@ -9,7 +9,9 @@ import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtra
|
|
|
9
9
|
export const carouselContext = createContext<any>(undefined);
|
|
10
10
|
function CarouselProvider({ node }: CarouselProviderComponentProps) {
|
|
11
11
|
node = useNode(node);
|
|
12
|
-
const [emblaRef, emblaApi] = useEmblaCarousel(
|
|
12
|
+
const [emblaRef, emblaApi] = useEmblaCarousel(
|
|
13
|
+
node.attributes as Parameters<typeof useEmblaCarousel>[0],
|
|
14
|
+
);
|
|
13
15
|
const generatedId = useId();
|
|
14
16
|
const attributeName = node.sourceType ?? node.type ?? 'carouselProvider';
|
|
15
17
|
const attributeKey = node.key ?? generatedId;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import type { NodeData } from '../../types/Node';
|
|
4
4
|
|
|
5
|
-
export type ResizeModeOptionType = 'cover' | 'contain' | 'stretch' | 'center';
|
|
6
5
|
export type FlexDirectionOptionType = 'row' | 'column';
|
|
7
6
|
export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
8
7
|
export type AlignItemsOptionType =
|
|
@@ -19,6 +18,7 @@ export type JustifyContentOptionType =
|
|
|
19
18
|
| 'space-around'
|
|
20
19
|
| 'space-evenly';
|
|
21
20
|
export type PositionOptionType = 'relative' | 'absolute';
|
|
21
|
+
export type ResizeModeOptionType = 'cover' | 'contain' | 'stretch' | 'center';
|
|
22
22
|
|
|
23
23
|
export interface ImageStyleGenerated {
|
|
24
24
|
flexDirection?: FlexDirectionOptionType;
|
|
@@ -55,6 +55,7 @@ export interface ImageStyleGenerated {
|
|
|
55
55
|
left?: string;
|
|
56
56
|
right?: string;
|
|
57
57
|
zIndex?: number;
|
|
58
|
+
resizeMode?: ResizeModeOptionType;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
export interface ImagePropsGenerated {
|
|
@@ -65,9 +66,6 @@ export interface ImagePropsGenerated {
|
|
|
65
66
|
title?: string;
|
|
66
67
|
description?: string;
|
|
67
68
|
src?: string;
|
|
68
|
-
width?: string;
|
|
69
|
-
height?: string;
|
|
70
|
-
resizeMode?: ResizeModeOptionType;
|
|
71
69
|
};
|
|
72
70
|
}
|
|
73
71
|
|
|
@@ -8,16 +8,27 @@
|
|
|
8
8
|
"title": "title",
|
|
9
9
|
"description": "description",
|
|
10
10
|
"src": "string",
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"style": {
|
|
12
|
+
"resizeMode": ["cover", "contain", "stretch", "center"]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"defaults": {
|
|
16
|
+
"resizeMode": "contain"
|
|
14
17
|
}
|
|
15
18
|
},
|
|
16
19
|
"meta": {
|
|
17
20
|
"desiredParent": ["all"],
|
|
18
21
|
"label": "Image",
|
|
19
22
|
"description": "Shows an image or graphic.",
|
|
20
|
-
"styles": {
|
|
23
|
+
"styles": {
|
|
24
|
+
"resizeMode": {
|
|
25
|
+
"label": "Resize Mode",
|
|
26
|
+
"description": "How the image fits the frame.",
|
|
27
|
+
"category": "style",
|
|
28
|
+
"specialCategory": null,
|
|
29
|
+
"sort": 4
|
|
30
|
+
}
|
|
31
|
+
},
|
|
21
32
|
"attributes": {
|
|
22
33
|
"src": {
|
|
23
34
|
"label": "Src",
|
|
@@ -25,27 +36,6 @@
|
|
|
25
36
|
"category": "other",
|
|
26
37
|
"specialCategory": null,
|
|
27
38
|
"sort": 1
|
|
28
|
-
},
|
|
29
|
-
"width": {
|
|
30
|
-
"label": "Width",
|
|
31
|
-
"description": "Image width.",
|
|
32
|
-
"category": "container",
|
|
33
|
-
"specialCategory": null,
|
|
34
|
-
"sort": 2
|
|
35
|
-
},
|
|
36
|
-
"height": {
|
|
37
|
-
"label": "Height",
|
|
38
|
-
"description": "Image height.",
|
|
39
|
-
"category": "container",
|
|
40
|
-
"specialCategory": null,
|
|
41
|
-
"sort": 3
|
|
42
|
-
},
|
|
43
|
-
"resizeMode": {
|
|
44
|
-
"label": "Resize Mode",
|
|
45
|
-
"description": "How the image fits the frame.",
|
|
46
|
-
"category": "other",
|
|
47
|
-
"specialCategory": null,
|
|
48
|
-
"sort": 4
|
|
49
39
|
}
|
|
50
40
|
}
|
|
51
41
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import type { NavigationBarColorComponentProps } from './NavigationBarColorProps.generated';
|
|
3
|
+
import useNode from '../useNode';
|
|
4
|
+
import { useBuilderParams } from '../../components/BuilderProvider';
|
|
5
|
+
import { parseColor } from '../../utils/parseColor';
|
|
6
|
+
import { getStyleBag } from '../../utils/attributeStyle';
|
|
7
|
+
import { useLogRender } from '../../utils/useLogRender';
|
|
8
|
+
import { useRenderStore } from '../../store';
|
|
9
|
+
|
|
10
|
+
function NavigationBarColor({ node }: NavigationBarColorComponentProps) {
|
|
11
|
+
useLogRender('NavigationBarColor');
|
|
12
|
+
node = useNode(node);
|
|
13
|
+
|
|
14
|
+
const { appConfig, projectColors } = useBuilderParams();
|
|
15
|
+
const setNavBarOverrideColor = useRenderStore(
|
|
16
|
+
(s) => s.setNavBarOverrideColor,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const rawBg = getStyleBag(node.attributes)?.backgroundColor as
|
|
20
|
+
| string
|
|
21
|
+
| undefined;
|
|
22
|
+
const resolvedColor = parseColor(rawBg, {
|
|
23
|
+
projectColors,
|
|
24
|
+
theme: appConfig?.theme,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (resolvedColor) {
|
|
29
|
+
setNavBarOverrideColor(resolvedColor);
|
|
30
|
+
}
|
|
31
|
+
return () => {
|
|
32
|
+
setNavBarOverrideColor(null);
|
|
33
|
+
};
|
|
34
|
+
}, [resolvedColor, setNavBarOverrideColor]);
|
|
35
|
+
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default React.memo(NavigationBarColor);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
2
|
+
|
|
3
|
+
import type { NodeData } from '../../types/Node';
|
|
4
|
+
|
|
5
|
+
export type FlexDirectionOptionType = 'row' | 'column';
|
|
6
|
+
export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
7
|
+
export type AlignItemsOptionType =
|
|
8
|
+
| 'flex-start'
|
|
9
|
+
| 'center'
|
|
10
|
+
| 'flex-end'
|
|
11
|
+
| 'stretch'
|
|
12
|
+
| 'baseline';
|
|
13
|
+
export type JustifyContentOptionType =
|
|
14
|
+
| 'flex-start'
|
|
15
|
+
| 'center'
|
|
16
|
+
| 'flex-end'
|
|
17
|
+
| 'space-between'
|
|
18
|
+
| 'space-around'
|
|
19
|
+
| 'space-evenly';
|
|
20
|
+
export type PositionOptionType = 'relative' | 'absolute';
|
|
21
|
+
|
|
22
|
+
export interface NavigationBarColorStyleGenerated {
|
|
23
|
+
flexDirection?: FlexDirectionOptionType;
|
|
24
|
+
flexWrap?: FlexWrapOptionType;
|
|
25
|
+
alignItems?: AlignItemsOptionType;
|
|
26
|
+
justifyContent?: JustifyContentOptionType;
|
|
27
|
+
gap?: string;
|
|
28
|
+
padding?: string;
|
|
29
|
+
paddingHorizontal?: string;
|
|
30
|
+
paddingVertical?: string;
|
|
31
|
+
paddingTop?: string;
|
|
32
|
+
paddingBottom?: string;
|
|
33
|
+
paddingLeft?: string;
|
|
34
|
+
paddingRight?: string;
|
|
35
|
+
margin?: string;
|
|
36
|
+
marginHorizontal?: string;
|
|
37
|
+
marginVertical?: string;
|
|
38
|
+
marginTop?: string;
|
|
39
|
+
marginBottom?: string;
|
|
40
|
+
marginLeft?: string;
|
|
41
|
+
marginRight?: string;
|
|
42
|
+
backgroundColor?: string;
|
|
43
|
+
borderRadius?: string;
|
|
44
|
+
width?: string;
|
|
45
|
+
minWidth?: string;
|
|
46
|
+
maxWidth?: string;
|
|
47
|
+
height?: string;
|
|
48
|
+
minHeight?: string;
|
|
49
|
+
maxHeight?: string;
|
|
50
|
+
flex?: number;
|
|
51
|
+
position?: PositionOptionType;
|
|
52
|
+
top?: string;
|
|
53
|
+
bottom?: string;
|
|
54
|
+
left?: string;
|
|
55
|
+
right?: string;
|
|
56
|
+
zIndex?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface NavigationBarColorPropsGenerated {
|
|
60
|
+
child: string;
|
|
61
|
+
attributes: {
|
|
62
|
+
style?: NavigationBarColorStyleGenerated;
|
|
63
|
+
scrollable?: boolean;
|
|
64
|
+
title?: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface NavigationBarColorComponentProps {
|
|
70
|
+
node: NodeData<NavigationBarColorPropsGenerated['attributes']>;
|
|
71
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 2,
|
|
3
|
+
"pattern": {
|
|
4
|
+
"type": "NavigationBarColor",
|
|
5
|
+
"children": "never",
|
|
6
|
+
"extends": "View",
|
|
7
|
+
"attributes": {
|
|
8
|
+
"title": "title",
|
|
9
|
+
"description": "description",
|
|
10
|
+
"style": {
|
|
11
|
+
"backgroundColor": "color"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"meta": {
|
|
16
|
+
"desiredParent": ["all"],
|
|
17
|
+
"label": "Navigation Bar Color",
|
|
18
|
+
"description": "Sets the OS navigation bar background color.",
|
|
19
|
+
"styles": {
|
|
20
|
+
"backgroundColor": {
|
|
21
|
+
"label": "Background Color",
|
|
22
|
+
"description": "Navigation bar background color.",
|
|
23
|
+
"category": "style",
|
|
24
|
+
"specialCategory": null,
|
|
25
|
+
"sort": 1
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"defaults": {
|
|
30
|
+
"style": {
|
|
31
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -10,13 +10,16 @@ import { useLogRender } from '../../utils/useLogRender';
|
|
|
10
10
|
import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
|
|
11
11
|
import { useMockOSContext, useMockPermission } from '../../mockOS';
|
|
12
12
|
import { useLocalize } from '../../hooks/useLocalize';
|
|
13
|
+
import { parseColor } from '../../utils/parseColor';
|
|
14
|
+
import { getStyleBag, toAttributeRecord } from '../../utils/attributeStyle';
|
|
13
15
|
|
|
14
16
|
function OnboardButton({ node }: OnboardButtonComponentProps) {
|
|
15
17
|
useLogRender('OnboardButton');
|
|
16
18
|
node = useNode(node);
|
|
17
19
|
const attributeName = node.sourceType ?? node.type ?? 'OnboardButton';
|
|
18
20
|
const { emblaApi } = useContext(onboardContext) ?? {};
|
|
19
|
-
const { appConfig } = useBuilderParams();
|
|
21
|
+
const { appConfig, projectColors } = useBuilderParams();
|
|
22
|
+
const theme = appConfig?.theme;
|
|
20
23
|
|
|
21
24
|
const context = useMockOSContext();
|
|
22
25
|
const mockPermissionManager = useMockPermission(context);
|
|
@@ -25,14 +28,25 @@ function OnboardButton({ node }: OnboardButtonComponentProps) {
|
|
|
25
28
|
const attributeKey = node.key ?? generatedId;
|
|
26
29
|
|
|
27
30
|
const attrs = node.attributes;
|
|
28
|
-
const
|
|
31
|
+
const attrRecord = toAttributeRecord(attrs);
|
|
32
|
+
const styleBag = getStyleBag(attrs);
|
|
29
33
|
const labelRaw = attrs?.labelKey ?? '';
|
|
30
34
|
const localize = useLocalize({ appConfig });
|
|
31
35
|
const label = localize(labelRaw);
|
|
32
36
|
|
|
33
|
-
const flex = styleBag?.flex ?? 1;
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
const flex = (attrRecord.flex ?? styleBag?.flex ?? 1) as number;
|
|
38
|
+
|
|
39
|
+
// The editor saves color attrs inside `styles` (meta category === 'style'),
|
|
40
|
+
// but legacy JSON may have them at the top level.
|
|
41
|
+
const rawTextColor = (attrRecord.button_text_color ??
|
|
42
|
+
styleBag?.button_text_color) as string | undefined;
|
|
43
|
+
const rawBgColor = (attrRecord.button_background_color ??
|
|
44
|
+
styleBag?.button_background_color) as string | undefined;
|
|
45
|
+
|
|
46
|
+
const textColor =
|
|
47
|
+
parseColor(rawTextColor, { projectColors, theme }) ?? '#FFFFFF';
|
|
48
|
+
const backgroundColor =
|
|
49
|
+
parseColor(rawBgColor, { projectColors, theme }) ?? '#0066FF';
|
|
36
50
|
const viewStyle = useExtractViewStyle(node);
|
|
37
51
|
|
|
38
52
|
const handleClick = () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
|
|
2
|
-
import type { Node } from '../../types/Node';
|
|
2
|
+
import type { Node, NodeData } from '../../types/Node';
|
|
3
3
|
import type { OnboardButtonsComponentProps } from './OnboardButtonsProps.generated';
|
|
4
4
|
import { onboardContext } from '../OnboardProvider/OnboardProvider';
|
|
5
5
|
import RenderNode from '../RenderNode.generated';
|
|
@@ -9,6 +9,7 @@ import { useLogRender } from '../../utils/useLogRender';
|
|
|
9
9
|
import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
|
|
10
10
|
import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
|
|
11
11
|
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
12
|
+
import { getStyleBag, toAttributeRecord } from '../../utils/attributeStyle';
|
|
12
13
|
|
|
13
14
|
function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
14
15
|
useLogRender('OnboardButtons');
|
|
@@ -28,13 +29,10 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
|
28
29
|
}
|
|
29
30
|
}, [ctx.selectedIndex]);
|
|
30
31
|
|
|
31
|
-
const
|
|
32
|
-
const styleBag = attributes
|
|
33
|
-
| Record<string, unknown>
|
|
34
|
-
| undefined;
|
|
32
|
+
const attrRecord = toAttributeRecord(node.attributes);
|
|
33
|
+
const styleBag = getStyleBag(node.attributes);
|
|
35
34
|
const direction =
|
|
36
|
-
(
|
|
37
|
-
'column'
|
|
35
|
+
(attrRecord.buttons_direction ?? styleBag?.buttons_direction) === 'column'
|
|
38
36
|
? 'column'
|
|
39
37
|
: 'row';
|
|
40
38
|
|
|
@@ -62,9 +60,9 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
|
62
60
|
const generatedId = useId();
|
|
63
61
|
|
|
64
62
|
// New condition logic: hide when condition is carousel-index and does not match
|
|
65
|
-
const condition =
|
|
63
|
+
const condition = attrRecord.condition ?? styleBag?.condition;
|
|
66
64
|
const conditionVariable =
|
|
67
|
-
|
|
65
|
+
attrRecord.conditionVariable ?? styleBag?.conditionVariable;
|
|
68
66
|
const shouldHide =
|
|
69
67
|
condition === 'carousel-index' &&
|
|
70
68
|
typeof conditionVariable === 'number' &&
|
|
@@ -81,7 +79,7 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
|
81
79
|
style={{ ...viewStyle, boxSizing: 'border-box' }}
|
|
82
80
|
>
|
|
83
81
|
{children.map((child, idx) => (
|
|
84
|
-
<RenderNode key={(child as
|
|
82
|
+
<RenderNode key={(child as NodeData)?.key ?? idx} node={child} />
|
|
85
83
|
))}
|
|
86
84
|
</div>
|
|
87
85
|
);
|
|
@@ -10,6 +10,7 @@ import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
|
10
10
|
import { parseColor } from '../../utils/parseColor';
|
|
11
11
|
import { parseSize } from '../../size-matters';
|
|
12
12
|
import { defaultAppConfig } from '../../types/PreviewConfig';
|
|
13
|
+
import { getStyleBag, toAttributeRecord } from '../../utils/attributeStyle';
|
|
13
14
|
|
|
14
15
|
function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
15
16
|
useLogRender('OnboardDot');
|
|
@@ -20,12 +21,12 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
|
20
21
|
const attributeName = node.type ?? 'OnboardDot';
|
|
21
22
|
const attributeKey = node.key ?? generatedId;
|
|
22
23
|
const attrs = node.attributes;
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
((attrs as any)?.style as Record<string, unknown> | undefined) ??
|
|
26
|
-
undefined;
|
|
24
|
+
const attrRecord = toAttributeRecord(attrs);
|
|
25
|
+
const stylesBag = getStyleBag(attrs);
|
|
27
26
|
const dotType =
|
|
28
|
-
(stylesBag?.dotType as
|
|
27
|
+
(stylesBag?.dotType as string | undefined) ??
|
|
28
|
+
(attrRecord.dotType as string | undefined) ??
|
|
29
|
+
'normal_dot';
|
|
29
30
|
const GHOST_DOT_DARK_COLOR = '#E4E5E7';
|
|
30
31
|
const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
|
|
31
32
|
const {
|
|
@@ -43,14 +44,14 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
|
43
44
|
: GHOST_DOT_LIGHT_COLOR;
|
|
44
45
|
const inactiveDotOpacity =
|
|
45
46
|
(stylesBag?.inactive_dot_opacity as number | undefined) ??
|
|
46
|
-
(
|
|
47
|
+
(attrRecord.inactive_dot_opacity as number | undefined) ??
|
|
47
48
|
0.3;
|
|
48
49
|
const inactiveDotColorOverride =
|
|
49
50
|
(stylesBag?.inactive_dot_color as string | undefined) ??
|
|
50
|
-
(
|
|
51
|
+
(attrRecord.inactive_dot_color as string | undefined);
|
|
51
52
|
const activeDotColor =
|
|
52
53
|
(stylesBag?.active_dot_color as string | undefined) ??
|
|
53
|
-
(
|
|
54
|
+
(attrRecord.active_dot_color as string | undefined);
|
|
54
55
|
const resolvedActiveDotColor = useMemo(
|
|
55
56
|
() => parseColor(activeDotColor, { theme: appConfig.theme, projectColors }),
|
|
56
57
|
[activeDotColor, appConfig.theme, projectColors],
|
|
@@ -83,7 +84,8 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
|
83
84
|
isSelected ? SELECTED_OUTLINE_STYLE : undefined,
|
|
84
85
|
);
|
|
85
86
|
const dotThicknessRaw =
|
|
86
|
-
(stylesBag?.dot_thickness as
|
|
87
|
+
(stylesBag?.dot_thickness as string | number | undefined) ??
|
|
88
|
+
(attrRecord.dot_thickness as string | number | undefined);
|
|
87
89
|
const dotSizeCss = useMemo((): string => {
|
|
88
90
|
const parsed = parseSize(dotThicknessRaw);
|
|
89
91
|
if (parsed === undefined) return '10px';
|
|
@@ -100,7 +102,7 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
|
100
102
|
const n = Number.isFinite(px) ? px : 10;
|
|
101
103
|
return `${Math.max(0, n / 3)}px`;
|
|
102
104
|
}, [dotSizeCss]);
|
|
103
|
-
const gapValue =
|
|
105
|
+
const gapValue = style.gap ?? dotGapCss;
|
|
104
106
|
const containerStyle = useMergedStyle(style, {
|
|
105
107
|
display: 'flex',
|
|
106
108
|
flexWrap: 'wrap',
|
|
@@ -9,6 +9,7 @@ import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
|
|
|
9
9
|
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
10
10
|
import { defaultAppConfig } from '../../types/PreviewConfig';
|
|
11
11
|
import { parseColor } from '../../utils/parseColor';
|
|
12
|
+
import { getStyleBag, toAttributeRecord } from '../../utils/attributeStyle';
|
|
12
13
|
|
|
13
14
|
type Segment =
|
|
14
15
|
| { type: 'text'; value: string }
|
|
@@ -107,26 +108,36 @@ function OnboardFooter({ node }: OnboardFooterComponentProps) {
|
|
|
107
108
|
key ? (localication?.[defaultLanguage ?? 'en']?.[key] ?? key) : '';
|
|
108
109
|
|
|
109
110
|
const attrs = node?.attributes;
|
|
111
|
+
const attrRecord = toAttributeRecord(attrs);
|
|
112
|
+
const styleBag = getStyleBag(attrs);
|
|
110
113
|
const text = t(attrs?.textLocalizationKey);
|
|
111
114
|
const textStyle = useExtractTextStyle(node, true);
|
|
112
115
|
const viewStyle = useExtractViewStyle(node);
|
|
113
116
|
|
|
117
|
+
// Read linked-word colors from both top-level attributes and the styles bag.
|
|
118
|
+
// The editor saves them inside `styles` (meta category === 'style'),
|
|
119
|
+
// but legacy JSON may have them at the top level.
|
|
120
|
+
const rawFirstColor = (attrRecord.linkedWordFirstColor ??
|
|
121
|
+
styleBag?.linkedWordFirstColor) as string | undefined;
|
|
122
|
+
const rawSecondColor = (attrRecord.linkedWordSecondColor ??
|
|
123
|
+
styleBag?.linkedWordSecondColor) as string | undefined;
|
|
124
|
+
|
|
114
125
|
// Parse colors for linked words
|
|
115
126
|
const parsedFirstColor = useMemo(
|
|
116
127
|
() =>
|
|
117
|
-
parseColor(
|
|
128
|
+
parseColor(rawFirstColor, {
|
|
118
129
|
projectColors,
|
|
119
130
|
theme,
|
|
120
131
|
}),
|
|
121
|
-
[
|
|
132
|
+
[rawFirstColor, projectColors, theme],
|
|
122
133
|
);
|
|
123
134
|
const parsedSecondColor = useMemo(
|
|
124
135
|
() =>
|
|
125
|
-
parseColor(
|
|
136
|
+
parseColor(rawSecondColor, {
|
|
126
137
|
projectColors,
|
|
127
138
|
theme,
|
|
128
139
|
}),
|
|
129
|
-
[
|
|
140
|
+
[rawSecondColor, projectColors, theme],
|
|
130
141
|
);
|
|
131
142
|
|
|
132
143
|
const mergedTextStyle = useMergedStyle(textStyle, {
|
|
@@ -21,6 +21,7 @@ export type JustifyContentOptionType =
|
|
|
21
21
|
export type PositionOptionType = 'relative' | 'absolute';
|
|
22
22
|
|
|
23
23
|
export interface OnboardImageStyleGenerated {
|
|
24
|
+
resizeMode?: ResizeModeOptionType;
|
|
24
25
|
flexDirection?: FlexDirectionOptionType;
|
|
25
26
|
flexWrap?: FlexWrapOptionType;
|
|
26
27
|
alignItems?: AlignItemsOptionType;
|
|
@@ -64,9 +65,6 @@ export interface OnboardImagePropsGenerated {
|
|
|
64
65
|
title?: string;
|
|
65
66
|
description?: string;
|
|
66
67
|
src?: string;
|
|
67
|
-
width?: string;
|
|
68
|
-
height?: string;
|
|
69
|
-
resizeMode?: ResizeModeOptionType;
|
|
70
68
|
scrollable?: boolean;
|
|
71
69
|
video_url?: string;
|
|
72
70
|
lottie?: string;
|
|
@@ -20,7 +20,9 @@ function OnboardProvider({ node }: OnboardProviderComponentProps) {
|
|
|
20
20
|
node = useNode(node);
|
|
21
21
|
const generatedId = useId();
|
|
22
22
|
const attributeName = node.sourceType ?? node.type ?? 'OnboardProvider';
|
|
23
|
-
const [emblaRef, emblaApi] = useEmblaCarousel(
|
|
23
|
+
const [emblaRef, emblaApi] = useEmblaCarousel(
|
|
24
|
+
node.attributes as Parameters<typeof useEmblaCarousel>[0],
|
|
25
|
+
);
|
|
24
26
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
25
27
|
const attributeKey = node.key ?? generatedId;
|
|
26
28
|
|
|
@@ -25,6 +25,7 @@ import type { CountDownComponentProps } from './CountDown/CountDownProps.generat
|
|
|
25
25
|
import type { CounterComponentProps } from './Counter/CounterProps.generated';
|
|
26
26
|
import type { ImageComponentProps } from './Image/ImageProps.generated';
|
|
27
27
|
import type { MainComponentProps } from './Main/MainProps.generated';
|
|
28
|
+
import type { NavigationBarColorComponentProps } from './NavigationBarColor/NavigationBarColorProps.generated';
|
|
28
29
|
import type { OnboardComponentProps } from './Onboard/OnboardProps.generated';
|
|
29
30
|
import type { OnboardButtonComponentProps } from './OnboardButton/OnboardButtonProps.generated';
|
|
30
31
|
import type { OnboardButtonsComponentProps } from './OnboardButtons/OnboardButtonsProps.generated';
|
|
@@ -42,6 +43,8 @@ import type { PaywallOptionsComponentProps } from './PaywallOptions/PaywallOptio
|
|
|
42
43
|
import type { PaywallProviderComponentProps } from './PaywallProvider/PaywallProviderProps.generated';
|
|
43
44
|
import type { PaywallSubscribeButtonComponentProps } from './PaywallSubscribeButton/PaywallSubscribeButtonProps.generated';
|
|
44
45
|
import type { RadioButtonComponentProps } from './RadioButton/RadioButtonProps.generated';
|
|
46
|
+
import type { SeparatorComponentProps } from './Separator/SeparatorProps.generated';
|
|
47
|
+
import type { StatusBarColorComponentProps } from './StatusBarColor/StatusBarColorProps.generated';
|
|
45
48
|
import type { TextComponentProps } from './Text/TextProps.generated';
|
|
46
49
|
import type { ViewComponentProps } from './View/ViewProps.generated';
|
|
47
50
|
import BIcon from './BIcon/BIcon';
|
|
@@ -56,6 +59,7 @@ import { CountDown } from './CountDown/CountDown';
|
|
|
56
59
|
import { Counter } from './Counter/Counter';
|
|
57
60
|
import Image from './Image/Image';
|
|
58
61
|
import Main from './Main/Main';
|
|
62
|
+
import NavigationBarColor from './NavigationBarColor/NavigationBarColor';
|
|
59
63
|
import Onboard from './Onboard/Onboard';
|
|
60
64
|
import OnboardButton from './OnboardButton/OnboardButton';
|
|
61
65
|
import OnboardButtons from './OnboardButtons/OnboardButtons';
|
|
@@ -73,6 +77,8 @@ import PaywallOptions from './PaywallOptions/PaywallOptions';
|
|
|
73
77
|
import PaywallProvider from './PaywallProvider/PaywallProvider';
|
|
74
78
|
import PaywallSubscribeButton from './PaywallSubscribeButton/PaywallSubscribeButton';
|
|
75
79
|
import RadioButton from './RadioButton/RadioButton';
|
|
80
|
+
import Separator from './Separator/Separator';
|
|
81
|
+
import StatusBarColor from './StatusBarColor/StatusBarColor';
|
|
76
82
|
import Text from './Text/Text';
|
|
77
83
|
import View from './View/View';
|
|
78
84
|
|
|
@@ -89,6 +95,7 @@ type BuilderNode =
|
|
|
89
95
|
| (CounterComponentProps['node'] & { type: 'Counter' })
|
|
90
96
|
| (ImageComponentProps['node'] & { type: 'Image' })
|
|
91
97
|
| (MainComponentProps['node'] & { type: 'Main' })
|
|
98
|
+
| (NavigationBarColorComponentProps['node'] & { type: 'NavigationBarColor' })
|
|
92
99
|
| (OnboardComponentProps['node'] & { type: 'Onboard' })
|
|
93
100
|
| (OnboardButtonComponentProps['node'] & { type: 'OnboardButton' })
|
|
94
101
|
| (OnboardButtonsComponentProps['node'] & { type: 'OnboardButtons' })
|
|
@@ -108,6 +115,8 @@ type BuilderNode =
|
|
|
108
115
|
type: 'PaywallSubscribeButton';
|
|
109
116
|
})
|
|
110
117
|
| (RadioButtonComponentProps['node'] & { type: 'RadioButton' })
|
|
118
|
+
| (SeparatorComponentProps['node'] & { type: 'Separator' })
|
|
119
|
+
| (StatusBarColorComponentProps['node'] & { type: 'StatusBarColor' })
|
|
111
120
|
| (TextComponentProps['node'] & { type: 'Text' })
|
|
112
121
|
| (ViewComponentProps['node'] & { type: 'View' });
|
|
113
122
|
|
|
@@ -165,6 +174,8 @@ function RenderNode({ node }: { node: Node }) {
|
|
|
165
174
|
return <Image node={normalizedNode} />;
|
|
166
175
|
case 'Main':
|
|
167
176
|
return <Main node={normalizedNode} />;
|
|
177
|
+
case 'NavigationBarColor':
|
|
178
|
+
return <NavigationBarColor node={normalizedNode} />;
|
|
168
179
|
case 'Onboard':
|
|
169
180
|
return <Onboard node={normalizedNode} />;
|
|
170
181
|
case 'OnboardButton':
|
|
@@ -199,6 +210,10 @@ function RenderNode({ node }: { node: Node }) {
|
|
|
199
210
|
return <PaywallSubscribeButton node={normalizedNode} />;
|
|
200
211
|
case 'RadioButton':
|
|
201
212
|
return <RadioButton node={normalizedNode} />;
|
|
213
|
+
case 'Separator':
|
|
214
|
+
return <Separator node={normalizedNode} />;
|
|
215
|
+
case 'StatusBarColor':
|
|
216
|
+
return <StatusBarColor node={normalizedNode} />;
|
|
202
217
|
case 'Text':
|
|
203
218
|
return <Text node={normalizedNode} />;
|
|
204
219
|
case 'View':
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { useId } from 'react';
|
|
2
|
+
import type { SeparatorComponentProps } from './SeparatorProps.generated';
|
|
3
|
+
import useNode from '../useNode';
|
|
4
|
+
import { useBuilderParams } from '../../components/BuilderProvider';
|
|
5
|
+
import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
|
|
6
|
+
import { useLogRender } from '../../utils/useLogRender';
|
|
7
|
+
import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
|
|
8
|
+
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
9
|
+
|
|
10
|
+
function Separator({ node }: SeparatorComponentProps) {
|
|
11
|
+
useLogRender('Separator');
|
|
12
|
+
node = useNode(node);
|
|
13
|
+
|
|
14
|
+
const generatedId = useId();
|
|
15
|
+
const attributeName = node.sourceType ?? node.type ?? 'Separator';
|
|
16
|
+
const attributeKey = node.key ?? generatedId;
|
|
17
|
+
|
|
18
|
+
const { previewMode, selectedKey } = useBuilderParams();
|
|
19
|
+
|
|
20
|
+
const baseStyle = useExtractViewStyle(node);
|
|
21
|
+
|
|
22
|
+
const isSelected = isNodeSelected({
|
|
23
|
+
previewMode: !!previewMode,
|
|
24
|
+
current: selectedKey ? { key: selectedKey } : undefined,
|
|
25
|
+
node,
|
|
26
|
+
});
|
|
27
|
+
const style = useMergedStyle(
|
|
28
|
+
baseStyle,
|
|
29
|
+
isSelected ? SELECTED_OUTLINE_STYLE : undefined,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
attribute-name={attributeName}
|
|
35
|
+
attribute-key={attributeKey}
|
|
36
|
+
style={style}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default React.memo(Separator);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
2
|
+
|
|
3
|
+
import type { NodeData } from '../../types/Node';
|
|
4
|
+
|
|
5
|
+
export interface SeparatorStyleGenerated {
|
|
6
|
+
backgroundColor?: string;
|
|
7
|
+
width?: string;
|
|
8
|
+
height?: string;
|
|
9
|
+
marginHorizontal?: string;
|
|
10
|
+
marginVertical?: string;
|
|
11
|
+
marginTop?: string;
|
|
12
|
+
marginBottom?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SeparatorPropsGenerated {
|
|
16
|
+
child: string;
|
|
17
|
+
attributes: {
|
|
18
|
+
style?: SeparatorStyleGenerated;
|
|
19
|
+
title?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SeparatorComponentProps {
|
|
25
|
+
node: NodeData<SeparatorPropsGenerated['attributes']>;
|
|
26
|
+
}
|