@developer_tribe/react-builder 1.2.21 → 1.2.23

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.
Files changed (100) hide show
  1. package/dist/attribute-analyser/style/native/useExtractImageStyle.d.ts +2 -2
  2. package/dist/build-components/Image/ImageProps.generated.d.ts +2 -4
  3. package/dist/build-components/NavigationBarColor/NavigationBarColor.d.ts +5 -0
  4. package/dist/build-components/NavigationBarColor/NavigationBarColorProps.generated.d.ts +54 -0
  5. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +1 -3
  6. package/dist/build-components/Separator/Separator.d.ts +5 -0
  7. package/dist/build-components/Separator/SeparatorProps.generated.d.ts +21 -0
  8. package/dist/build-components/StatusBarColor/StatusBarColor.d.ts +5 -0
  9. package/dist/build-components/StatusBarColor/StatusBarColorProps.generated.d.ts +54 -0
  10. package/dist/build-components/index.d.ts +4 -1
  11. package/dist/build-components/patterns.generated.d.ts +2105 -1253
  12. package/dist/components/AttributesEditorPanel.d.ts +1 -1
  13. package/dist/components/BuilderProvider.d.ts +1 -1
  14. package/dist/index.cjs.js +4 -4
  15. package/dist/index.cjs.js.map +1 -1
  16. package/dist/index.esm.js +4 -4
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.web.cjs.js +6 -6
  19. package/dist/index.web.cjs.js.map +1 -1
  20. package/dist/index.web.esm.js +4 -4
  21. package/dist/index.web.esm.js.map +1 -1
  22. package/dist/store.d.ts +4 -0
  23. package/dist/styles.css +1 -1
  24. package/dist/utils/attributeStyle.d.ts +9 -0
  25. package/dist/utils/extractImageStyle.d.ts +1 -1
  26. package/dist/utils/extractViewStyle/extractViewStyleNative.d.ts +1 -1
  27. package/package.json +2 -2
  28. package/src/DeviceMockFrame.tsx +8 -2
  29. package/src/assets/meta.json +1 -1
  30. package/src/assets/samples/paywall-1.json +39 -34
  31. package/src/assets/samples/paywall-2.json +39 -20
  32. package/src/assets/samples/paywall-app-delete-offer.json +40 -21
  33. package/src/assets/samples/paywall-app-open-offer.json +40 -21
  34. package/src/assets/samples/paywall-back-offer.json +40 -21
  35. package/src/assets/samples/paywall-notification-offer.json +40 -21
  36. package/src/assets/samples/vpn-onboard-1.json +84 -39
  37. package/src/assets/samples/vpn-onboard-2.json +85 -40
  38. package/src/assets/samples/vpn-onboard-3.json +84 -39
  39. package/src/assets/samples/vpn-onboard-4.json +84 -39
  40. package/src/assets/samples/vpn-onboard-5.json +102 -55
  41. package/src/assets/samples/vpn-onboard-6.json +87 -38
  42. package/src/attribute-analyser/style/native/useExtractImageStyle.ts +24 -22
  43. package/src/attribute-analyser/style/native/useExtractTextStyle.ts +9 -4
  44. package/src/attribute-analyser/style/native/useExtractViewStyle.ts +19 -7
  45. package/src/attributes-editor/useAttributesEditorModel.ts +23 -17
  46. package/src/build-components/BackgroundImage/pattern.json +9 -7
  47. package/src/build-components/CarouselDots/CarouselDots.tsx +12 -11
  48. package/src/build-components/CarouselProvider/CarouselProvider.tsx +3 -1
  49. package/src/build-components/Image/ImageProps.generated.ts +2 -4
  50. package/src/build-components/Image/pattern.json +12 -25
  51. package/src/build-components/NavigationBarColor/NavigationBarColor.tsx +39 -0
  52. package/src/build-components/NavigationBarColor/NavigationBarColorProps.generated.ts +71 -0
  53. package/src/build-components/NavigationBarColor/pattern.json +34 -0
  54. package/src/build-components/OnboardButtons/OnboardButtons.tsx +8 -10
  55. package/src/build-components/OnboardDot/OnboardDot.tsx +12 -10
  56. package/src/build-components/OnboardImage/OnboardImage.tsx +1 -1
  57. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +1 -3
  58. package/src/build-components/OnboardProvider/OnboardProvider.tsx +3 -1
  59. package/src/build-components/RenderNode.generated.tsx +15 -0
  60. package/src/build-components/Separator/Separator.tsx +41 -0
  61. package/src/build-components/Separator/SeparatorProps.generated.ts +26 -0
  62. package/src/build-components/Separator/pattern.json +59 -0
  63. package/src/build-components/StatusBarColor/StatusBarColor.tsx +39 -0
  64. package/src/build-components/StatusBarColor/StatusBarColorProps.generated.ts +71 -0
  65. package/src/build-components/StatusBarColor/pattern.json +34 -0
  66. package/src/build-components/Text/pattern.json +45 -38
  67. package/src/build-components/index.ts +15 -0
  68. package/src/build-components/patterns.generated.ts +2149 -1272
  69. package/src/build-components/useNode.ts +24 -25
  70. package/src/components/AttributesEditorPanel.tsx +4 -5
  71. package/src/components/Builder.tsx +1 -2
  72. package/src/components/BuilderProvider.tsx +40 -3
  73. package/src/components/JsonTextEditor.tsx +2 -2
  74. package/src/components/LoadingComponent.tsx +1 -1
  75. package/src/components/RenderErrorBoundary.tsx +1 -3
  76. package/src/migrations/migrations/1.1.2_extract_component_attributes_from_style.ts +3 -3
  77. package/src/modals/BenefitPresetsModal.tsx +1 -1
  78. package/src/modals/ProductPresetsModal.tsx +1 -1
  79. package/src/pages/DebugJsonPage.tsx +7 -4
  80. package/src/pages/ProjectDebug.tsx +1 -1
  81. package/src/pages/ProjectPage.tsx +31 -32
  82. package/src/pages/ProjectValidationPage.tsx +2 -2
  83. package/src/store.ts +13 -0
  84. package/src/styles/layout/_builder.scss +6 -0
  85. package/src/utils/__special_exceptions.ts +5 -5
  86. package/src/utils/analyseNode.ts +2 -2
  87. package/src/utils/analyseNodeByPatterns.ts +10 -9
  88. package/src/utils/analyseNodeStructural.ts +1 -1
  89. package/src/utils/attributeStyle.ts +26 -0
  90. package/src/utils/extractImageStyle.ts +17 -13
  91. package/src/utils/extractTextStyle/extractTextStyle.ts +7 -7
  92. package/src/utils/extractTextStyle/extractTextStyleNative.ts +10 -10
  93. package/src/utils/extractViewStyle/extractViewStyle.ts +8 -11
  94. package/src/utils/extractViewStyle/extractViewStyleNative.ts +19 -19
  95. package/src/utils/loadFontFamily.ts +14 -19
  96. package/src/utils/logRenderStore.ts +5 -4
  97. package/src/utils/nodeTree.ts +1 -1
  98. package/src/utils/patterns.ts +26 -31
  99. package/src/utils/repairNodeKeys.ts +5 -7
  100. package/src/utils/wrapNodeInMain.ts +3 -3
@@ -8,16 +8,24 @@
8
8
  "title": "title",
9
9
  "description": "description",
10
10
  "src": "string",
11
- "width": "size",
12
- "height": "size",
13
- "resizeMode": ["cover", "contain", "stretch", "center"]
11
+ "style": {
12
+ "resizeMode": ["cover", "contain", "stretch", "center"]
13
+ }
14
14
  }
15
15
  },
16
16
  "meta": {
17
17
  "desiredParent": ["all"],
18
18
  "label": "Image",
19
19
  "description": "Shows an image or graphic.",
20
- "styles": {},
20
+ "styles": {
21
+ "resizeMode": {
22
+ "label": "Resize Mode",
23
+ "description": "How the image fits the frame.",
24
+ "category": "style",
25
+ "specialCategory": null,
26
+ "sort": 4
27
+ }
28
+ },
21
29
  "attributes": {
22
30
  "src": {
23
31
  "label": "Src",
@@ -25,27 +33,6 @@
25
33
  "category": "other",
26
34
  "specialCategory": null,
27
35
  "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
36
  }
50
37
  }
51
38
  }
@@ -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
+ }
@@ -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 attributes = node.attributes as any;
32
- const styleBag = attributes?.style as Record<string, unknown> | undefined as
33
- | Record<string, unknown>
34
- | undefined;
32
+ const attrRecord = toAttributeRecord(node.attributes);
33
+ const styleBag = getStyleBag(node.attributes);
35
34
  const direction =
36
- (attributes?.buttons_direction ?? (styleBag as any)?.buttons_direction) ===
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 = attributes?.condition ?? (styleBag as any)?.condition;
63
+ const condition = attrRecord.condition ?? styleBag?.condition;
66
64
  const conditionVariable =
67
- attributes?.conditionVariable ?? (styleBag as any)?.conditionVariable;
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 any)?.key ?? idx} node={child} />
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 stylesBag =
24
- ((attrs as any)?.styles as Record<string, unknown> | undefined) ??
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 any) ?? (attrs as any)?.dotType ?? 'normal_dot';
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
- (attrs as any)?.inactive_dot_opacity ??
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
- (attrs as any)?.inactive_dot_color;
51
+ (attrRecord.inactive_dot_color as string | undefined);
51
52
  const activeDotColor =
52
53
  (stylesBag?.active_dot_color as string | undefined) ??
53
- (attrs as any)?.active_dot_color;
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 any) ?? (attrs as any)?.dot_thickness;
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 = (style as any)?.gap ?? dotGapCss;
105
+ const gapValue = style.gap ?? dotGapCss;
104
106
  const containerStyle = useMergedStyle(style, {
105
107
  display: 'flex',
106
108
  flexWrap: 'wrap',
@@ -70,7 +70,7 @@ function OnboardImage({ node }: OnboardImageComponentProps) {
70
70
  ...node,
71
71
  type: 'image',
72
72
  sourceType: attributeName,
73
- } as unknown as ImageComponentProps['node']
73
+ } as ImageComponentProps['node']
74
74
  }
75
75
  />
76
76
  );
@@ -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(node.attributes as any);
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
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "pattern": {
4
+ "type": "Separator",
5
+ "children": "never",
6
+ "attributes": {
7
+ "title": "title",
8
+ "description": "description",
9
+ "style": {
10
+ "backgroundColor": "color",
11
+ "width": "size",
12
+ "height": "size",
13
+ "marginHorizontal": "size",
14
+ "marginVertical": "size",
15
+ "marginTop": "size",
16
+ "marginBottom": "size"
17
+ }
18
+ }
19
+ },
20
+ "meta": {
21
+ "desiredParent": ["all"],
22
+ "label": "Separator",
23
+ "description": "Horizontal line separator.",
24
+ "styles": {
25
+ "backgroundColor": {
26
+ "label": "Color",
27
+ "description": "Separator line color.",
28
+ "category": "style",
29
+ "specialCategory": null,
30
+ "sort": 1
31
+ }
32
+ },
33
+ "attributes": {
34
+ "width": {
35
+ "label": "Width",
36
+ "description": "Separator width.",
37
+ "category": "container",
38
+ "specialCategory": null,
39
+ "sort": 1,
40
+ "preferredScale": "s"
41
+ },
42
+ "height": {
43
+ "label": "Height",
44
+ "description": "Separator thickness.",
45
+ "category": "container",
46
+ "specialCategory": null,
47
+ "sort": 2,
48
+ "preferredScale": "vs"
49
+ }
50
+ }
51
+ },
52
+ "defaults": {
53
+ "style": {
54
+ "width": "100%",
55
+ "height": 2,
56
+ "backgroundColor": "#000000"
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,39 @@
1
+ import React, { useEffect } from 'react';
2
+ import type { StatusBarColorComponentProps } from './StatusBarColorProps.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 StatusBarColor({ node }: StatusBarColorComponentProps) {
11
+ useLogRender('StatusBarColor');
12
+ node = useNode(node);
13
+
14
+ const { appConfig, projectColors } = useBuilderParams();
15
+ const setStatusBarOverrideColor = useRenderStore(
16
+ (s) => s.setStatusBarOverrideColor,
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
+ setStatusBarOverrideColor(resolvedColor);
30
+ }
31
+ return () => {
32
+ setStatusBarOverrideColor(null);
33
+ };
34
+ }, [resolvedColor, setStatusBarOverrideColor]);
35
+
36
+ return null;
37
+ }
38
+
39
+ export default React.memo(StatusBarColor);
@@ -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 StatusBarColorStyleGenerated {
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 StatusBarColorPropsGenerated {
60
+ child: string;
61
+ attributes: {
62
+ style?: StatusBarColorStyleGenerated;
63
+ scrollable?: boolean;
64
+ title?: string;
65
+ description?: string;
66
+ };
67
+ }
68
+
69
+ export interface StatusBarColorComponentProps {
70
+ node: NodeData<StatusBarColorPropsGenerated['attributes']>;
71
+ }