@developer_tribe/react-builder 1.0.7 → 1.0.9

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 (217) hide show
  1. package/dist/build-components/BIcon/BIconProps.generated.d.ts +3 -0
  2. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +1 -0
  3. package/dist/build-components/Button/ButtonProps.generated.d.ts +1 -0
  4. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +5 -0
  5. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +1 -0
  6. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +1 -0
  7. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +1 -0
  8. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +1 -0
  9. package/dist/build-components/Image/ImageProps.generated.d.ts +1 -0
  10. package/dist/build-components/Main/MainProps.generated.d.ts +1 -1
  11. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +1 -0
  12. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +1 -0
  13. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +1 -0
  14. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +1 -0
  15. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +3 -0
  16. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +1 -0
  17. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +1 -0
  18. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +3 -0
  19. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +3 -0
  20. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +3 -0
  21. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +1 -1
  22. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +3 -1
  23. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +1 -1
  24. package/dist/build-components/PaywallProvider/PaywallContext.d.ts +12 -0
  25. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +1 -1
  26. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +1 -0
  27. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +1 -1
  28. package/dist/build-components/Text/TextProps.generated.d.ts +3 -0
  29. package/dist/build-components/View/ViewProps.generated.d.ts +1 -0
  30. package/dist/build-components/patterns.generated.d.ts +372 -374
  31. package/dist/components/BuilderProvider.d.ts +2 -0
  32. package/dist/components/ParamsProvider.d.ts +5 -0
  33. package/dist/components/RenderErrorBoundary.d.ts +28 -0
  34. package/dist/hooks/useSyncHtmlThemeClass.d.ts +7 -0
  35. package/dist/index.cjs.js +5 -5
  36. package/dist/index.cjs.js.map +1 -1
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.esm.js +3 -3
  39. package/dist/index.esm.js.map +1 -1
  40. package/dist/index.native.cjs.js +4 -4
  41. package/dist/index.native.cjs.js.map +1 -1
  42. package/dist/index.native.d.ts +1 -0
  43. package/dist/index.native.esm.js +4 -4
  44. package/dist/index.native.esm.js.map +1 -1
  45. package/dist/migrations/migratePipe.d.ts +14 -0
  46. package/dist/migrations/migrations/1.1.0_normalize_style_attributes.d.ts +2 -0
  47. package/dist/migrations/semver.d.ts +8 -0
  48. package/dist/migrations/types.d.ts +8 -0
  49. package/dist/mockOS/components/SubscriptionModal.d.ts +7 -0
  50. package/dist/mockOS/context/MockOSContextBase.d.ts +1 -0
  51. package/dist/mockOS/hooks/useMockIap.d.ts +3 -0
  52. package/dist/mockOS/index.d.ts +4 -0
  53. package/dist/mockOS/managers/mockOSIapManager.d.ts +6 -0
  54. package/dist/mockOS/managers/subscriptionManager.d.ts +10 -0
  55. package/dist/pages/ProjectDebug.d.ts +14 -0
  56. package/dist/pages/ProjectMigrationPage.d.ts +23 -0
  57. package/dist/pages/ProjectValidationPage.d.ts +15 -0
  58. package/dist/styles.css +1 -1
  59. package/dist/types/Device.d.ts +5 -0
  60. package/dist/utils/__special_exceptions.d.ts +7 -0
  61. package/dist/utils/getImage.d.ts +23 -0
  62. package/dist/utils/pasteNode.d.ts +15 -0
  63. package/dist/utils/patterns.d.ts +1 -2
  64. package/package.json +6 -2
  65. package/scripts/migrate-patterns-to-v2.mjs +131 -0
  66. package/scripts/migrate-samples-to-current.ts +79 -0
  67. package/scripts/prebuild/utils/createGeneratedProps.js +4 -5
  68. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +32 -21
  69. package/scripts/prebuild/utils/validatePatternJson.js +12 -10
  70. package/src/.DS_Store +0 -0
  71. package/src/AttributesEditor.tsx +41 -11
  72. package/src/RenderPage.tsx +55 -0
  73. package/src/assets/.DS_Store +0 -0
  74. package/src/assets/devices.json +91 -0
  75. package/src/assets/samples/carousel-sample.json +141 -29
  76. package/src/assets/samples/getSamples.ts +9 -0
  77. package/src/assets/samples/paywall-1.json +119 -71
  78. package/src/assets/samples/simple-1.json +28 -16
  79. package/src/assets/samples/simple-2.json +157 -82
  80. package/src/assets/samples/unmigrated-builder1.json +42 -0
  81. package/src/assets/samples/unvalidated-builder1.json +49 -0
  82. package/src/assets/samples/unvalidated-crash1.json +19 -0
  83. package/src/assets/samples/unvalidated-crashcomponent1.json +16 -0
  84. package/src/assets/samples/vpn-onboard-1.json +91 -51
  85. package/src/assets/samples/vpn-onboard-2.json +318 -278
  86. package/src/assets/samples/vpn-onboard-3.json +286 -252
  87. package/src/assets/samples/vpn-onboard-4.json +286 -252
  88. package/src/assets/samples/vpn-onboard-5.json +434 -374
  89. package/src/assets/samples/vpn-onboard-6.json +290 -250
  90. package/src/attributes-editor/Field.tsx +1 -1
  91. package/src/attributes-editor/LayoutPreviewPicker.tsx +5 -2
  92. package/src/build-components/BIcon/BIconProps.generated.ts +3 -0
  93. package/src/build-components/BIcon/pattern.json +12 -9
  94. package/src/build-components/BackgroundImage/BackgroundImage.tsx +3 -1
  95. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +1 -0
  96. package/src/build-components/BackgroundImage/pattern.json +25 -16
  97. package/src/build-components/Button/Button.tsx +26 -3
  98. package/src/build-components/Button/ButtonProps.generated.ts +1 -0
  99. package/src/build-components/Button/pattern.json +10 -6
  100. package/src/build-components/Carousel/CarouselProps.generated.ts +5 -0
  101. package/src/build-components/Carousel/pattern.json +19 -8
  102. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +1 -0
  103. package/src/build-components/CarouselButtons/pattern.json +11 -5
  104. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +1 -0
  105. package/src/build-components/CarouselDots/pattern.json +5 -4
  106. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +1 -0
  107. package/src/build-components/CarouselItem/pattern.json +5 -4
  108. package/src/build-components/CarouselProvider/CarouselProvider.tsx +44 -2
  109. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +1 -0
  110. package/src/build-components/Image/Image.tsx +2 -1
  111. package/src/build-components/Image/ImageProps.generated.ts +1 -0
  112. package/src/build-components/Image/pattern.json +11 -5
  113. package/src/build-components/Main/MainProps.generated.ts +1 -1
  114. package/src/build-components/Main/pattern.json +12 -9
  115. package/src/build-components/Onboard/OnboardProps.generated.ts +1 -0
  116. package/src/build-components/Onboard/pattern.json +14 -9
  117. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +1 -0
  118. package/src/build-components/OnboardButton/pattern.json +5 -4
  119. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +1 -0
  120. package/src/build-components/OnboardButtons/pattern.json +5 -4
  121. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +1 -0
  122. package/src/build-components/OnboardDot/pattern.json +5 -4
  123. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +3 -0
  124. package/src/build-components/OnboardFooter/pattern.json +8 -5
  125. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +1 -0
  126. package/src/build-components/OnboardImage/pattern.json +7 -4
  127. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +1 -0
  128. package/src/build-components/OnboardItem/pattern.json +18 -9
  129. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +3 -0
  130. package/src/build-components/OnboardProvider/pattern.json +21 -6
  131. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +3 -0
  132. package/src/build-components/OnboardSubtitle/pattern.json +10 -6
  133. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +3 -0
  134. package/src/build-components/OnboardTitle/pattern.json +11 -7
  135. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +1 -1
  136. package/src/build-components/PaywallBackground/pattern.json +5 -4
  137. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +6 -1
  138. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +3 -1
  139. package/src/build-components/PaywallCloseButton/pattern.json +15 -12
  140. package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +0 -1
  141. package/src/build-components/PaywallOptions/PaywallOptions.tsx +3 -2
  142. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +1 -1
  143. package/src/build-components/PaywallOptions/pattern.json +14 -11
  144. package/src/build-components/PaywallProvider/PaywallContext.ts +25 -0
  145. package/src/build-components/PaywallProvider/PaywallProvider.tsx +102 -5
  146. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +1 -1
  147. package/src/build-components/PaywallProvider/pattern.json +11 -8
  148. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +7 -0
  149. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +1 -0
  150. package/src/build-components/PaywallSubscribeButton/pattern.json +16 -13
  151. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +1 -1
  152. package/src/build-components/RadioButton/pattern.json +5 -4
  153. package/src/build-components/Text/Text.tsx +107 -4
  154. package/src/build-components/Text/TextProps.generated.ts +3 -0
  155. package/src/build-components/Text/pattern.json +19 -4
  156. package/src/build-components/View/ViewProps.generated.ts +1 -0
  157. package/src/build-components/View/pattern.json +28 -13
  158. package/src/build-components/other.tsx +15 -0
  159. package/src/build-components/patterns.generated.ts +340 -235
  160. package/src/build-components/useNode.ts +22 -3
  161. package/src/components/BottomBar.tsx +45 -45
  162. package/src/components/Builder.tsx +20 -6
  163. package/src/components/BuilderButton.tsx +75 -38
  164. package/src/components/BuilderProvider.tsx +22 -2
  165. package/src/components/DeviceButton.tsx +12 -5
  166. package/src/components/EditorHeader.tsx +296 -38
  167. package/src/components/ParamsProvider.tsx +7 -0
  168. package/src/components/RenderErrorBoundary.tsx +200 -0
  169. package/src/hooks/useParams.ts +5 -1
  170. package/src/hooks/useSyncHtmlThemeClass.ts +19 -0
  171. package/src/index.native.ts +7 -0
  172. package/src/index.ts +8 -0
  173. package/src/migrations/migratePipe.ts +59 -0
  174. package/src/migrations/migrations/1.1.0_normalize_style_attributes.ts +80 -0
  175. package/src/migrations/semver.ts +24 -0
  176. package/src/migrations/types.ts +9 -0
  177. package/src/mockOS/components/PermissionModal.tsx +3 -2
  178. package/src/mockOS/components/SubscriptionModal.tsx +400 -0
  179. package/src/mockOS/context/MockOSContext.tsx +61 -10
  180. package/src/mockOS/context/MockOSContextBase.ts +1 -0
  181. package/src/mockOS/hooks/useMockIap.ts +11 -0
  182. package/src/mockOS/index.ts +7 -0
  183. package/src/mockOS/managers/mockOSIapManager.ts +10 -0
  184. package/src/mockOS/managers/subscriptionManager.ts +36 -0
  185. package/src/modals/IconPickerModal.tsx +1 -1
  186. package/src/pages/ProjectDebug.tsx +331 -0
  187. package/src/pages/ProjectMigrationPage.tsx +92 -0
  188. package/src/pages/ProjectPage.tsx +318 -166
  189. package/src/pages/ProjectValidationPage.tsx +54 -0
  190. package/src/styles/base/_global.scss +58 -11
  191. package/src/styles/components/_attributes-editor.scss +1 -1
  192. package/src/styles/components/_bottom-bar.scss +7 -4
  193. package/src/styles/components/_editor-shell.scss +126 -4
  194. package/src/styles/components/_mockos-router.scss +3 -2
  195. package/src/styles/components/_ui-components.scss +10 -5
  196. package/src/styles/foundation/_colors.scss +78 -11
  197. package/src/styles/foundation/_mixins.scss +4 -1
  198. package/src/styles/foundation/_sizes.scss +4 -2
  199. package/src/styles/index.scss +1 -0
  200. package/src/styles/layout/_builder.scss +61 -0
  201. package/src/styles/layout/_project-validation.scss +214 -0
  202. package/src/styles/modals/_add-component.scss +4 -2
  203. package/src/styles/modals/_color-modal.scss +4 -2
  204. package/src/styles/modals/_modal-shell.scss +3 -1
  205. package/src/types/Device.ts +5 -0
  206. package/src/utils/__special_exceptions.ts +88 -0
  207. package/src/utils/analyseNode.ts +8 -2
  208. package/src/utils/analyseNodeByPatterns.ts +43 -9
  209. package/src/utils/extractTextStyle.ts +19 -6
  210. package/src/utils/extractViewStyle.ts +68 -59
  211. package/src/utils/getImage.ts +76 -0
  212. package/src/utils/novaToJson.ts +2 -1
  213. package/src/utils/pasteNode.ts +172 -0
  214. package/src/utils/patterns.ts +4 -3
  215. package/dist/android.svg +0 -43
  216. package/dist/apple.svg +0 -16
  217. package/dist/background.jpg +0 -0
@@ -1,6 +1,5 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "BIcon",
6
5
  "children": "never",
@@ -9,18 +8,15 @@
9
8
  "iconType": "iconType",
10
9
  "size": "number",
11
10
  "strokeWidth": "number"
12
- },
13
- "defaults": {
14
- "iconType": "activity",
15
- "fontSize": "16",
16
- "strokeWidth": 1.5
17
11
  }
18
12
  },
19
13
  "meta": {
20
- "desiredParent": ["all"],
14
+ "desiredParent": [
15
+ "all"
16
+ ],
21
17
  "label": "BIcon",
22
18
  "description": "Renders an icon from the icon set.",
23
- "attributes": {
19
+ "styles": {
24
20
  "iconType": {
25
21
  "label": "Icon",
26
22
  "description": "Which icon to render.",
@@ -43,5 +39,12 @@
43
39
  "sort": 3
44
40
  }
45
41
  }
42
+ },
43
+ "defaults": {
44
+ "iconType": "activity",
45
+ "strokeWidth": 1.5,
46
+ "style": {
47
+ "fontSize": "16"
48
+ }
46
49
  }
47
50
  }
@@ -3,6 +3,7 @@ import type { BackgroundImageComponentProps } from './BackgroundImageProps.gener
3
3
  import useNode from '../useNode';
4
4
  import { useRenderStore } from '../../store';
5
5
  import { extractViewStyle } from '../../utils/extractViewStyle';
6
+ import { resolveImageSrc } from '../../utils/getImage';
6
7
  import { useLogRender } from '../../utils/useLogRender';
7
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
9
  import { useMergedStyle } from '../../utils/useMergedStyle';
@@ -36,7 +37,8 @@ function BackgroundImage({ node }: BackgroundImageComponentProps) {
36
37
  };
37
38
 
38
39
  if (attrs?.src) {
39
- style.backgroundImage = `url(${attrs.src})`;
40
+ const resolved = resolveImageSrc(attrs.src);
41
+ if (resolved) style.backgroundImage = `url(${resolved})`;
40
42
  }
41
43
 
42
44
  switch (attrs?.resizeMode) {
@@ -22,6 +22,7 @@ export type ResizeModeOptionType = 'cover' | 'contain' | 'stretch' | 'center';
22
22
  export interface BackgroundImagePropsGenerated {
23
23
  child: string;
24
24
  attributes: {
25
+ style?: Record<string, unknown>;
25
26
  scrollable?: boolean;
26
27
  flexDirection?: FlexDirectionOptionType;
27
28
  alignItems?: AlignItemsOptionType;
@@ -1,31 +1,27 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "BackgroundImage",
6
5
  "children": "never",
7
6
  "extends": "View",
8
7
  "attributes": {
9
8
  "src": "string",
10
- "resizeMode": ["cover", "contain", "stretch", "center"]
11
- },
12
- "defaults": {
13
- "resizeMode": "cover",
14
- "width": "100%",
15
- "height": "100%",
16
- "position": "absolute",
17
- "top": 0,
18
- "left": 0,
19
- "right": 0,
20
- "bottom": 0,
21
- "zIndex": 0
9
+ "resizeMode": [
10
+ "cover",
11
+ "contain",
12
+ "stretch",
13
+ "center"
14
+ ]
22
15
  }
23
16
  },
24
17
  "meta": {
25
- "desiredParent": ["all", "background"],
18
+ "desiredParent": [
19
+ "all",
20
+ "background"
21
+ ],
26
22
  "label": "Background Image",
27
23
  "description": "Background image.",
28
- "attributes": {
24
+ "styles": {
29
25
  "src": {
30
26
  "label": "Src",
31
27
  "description": "Image source URL.",
@@ -41,5 +37,18 @@
41
37
  "sort": 4
42
38
  }
43
39
  }
40
+ },
41
+ "defaults": {
42
+ "resizeMode": "cover",
43
+ "style": {
44
+ "width": "100%",
45
+ "height": "100%",
46
+ "position": "absolute",
47
+ "top": 0,
48
+ "left": 0,
49
+ "right": 0,
50
+ "bottom": 0,
51
+ "zIndex": 0
52
+ }
44
53
  }
45
54
  }
@@ -4,8 +4,10 @@ import useNode from '../useNode';
4
4
  import { useRenderStore } from '../../store';
5
5
  import { useLogRender } from '../../utils/useLogRender';
6
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
7
+ import { extractTextStyle } from '../../utils/extractTextStyle';
7
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
9
  import { useMergedStyle } from '../../utils/useMergedStyle';
10
+ import { useLocalize } from '../../hooks/useLocalize';
9
11
 
10
12
  function Button({ node }: ButtonComponentProps) {
11
13
  useLogRender('Button');
@@ -21,10 +23,23 @@ function Button({ node }: ButtonComponentProps) {
21
23
  projectColors: s.projectColors,
22
24
  }),
23
25
  );
26
+ const localize = useLocalize();
24
27
  const baseStyle = useMemo(
25
28
  () => extractViewStyle(node, { appConfig, projectColors }),
26
29
  [node, appConfig, projectColors],
27
30
  );
31
+ const textStyle = useMemo(() => {
32
+ const combined = extractTextStyle(node as any, {
33
+ appConfig,
34
+ projectColors,
35
+ });
36
+ return {
37
+ color: combined.color,
38
+ fontSize: combined.fontSize,
39
+ fontWeight: combined.fontWeight,
40
+ textAlign: combined.textAlign,
41
+ } as React.CSSProperties;
42
+ }, [node, appConfig, projectColors]);
28
43
  const buttonDefaults = useMemo(() => {
29
44
  const hasExplicitBackground =
30
45
  node?.attributes?.backgroundColor !== undefined &&
@@ -32,6 +47,7 @@ function Button({ node }: ButtonComponentProps) {
32
47
  String(node?.attributes?.backgroundColor).trim() !== '';
33
48
  return {
34
49
  cursor: 'pointer',
50
+ textDecoration: 'none',
35
51
  ...(hasExplicitBackground
36
52
  ? undefined
37
53
  : { backgroundColor: 'transparent' }),
@@ -44,14 +60,21 @@ function Button({ node }: ButtonComponentProps) {
44
60
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
45
61
  );
46
62
 
63
+ const label =
64
+ typeof node.children === 'string' && node.children.trim().length > 0
65
+ ? node.children
66
+ : 'Button';
67
+
47
68
  return (
48
- <div
69
+ <a
49
70
  attribute-name={attributeName}
50
71
  attribute-key={attributeKey}
72
+ href="#"
73
+ onClick={(e) => e.preventDefault()}
51
74
  style={style}
52
75
  >
53
- {String(node?.type ?? 'button')}
54
- </div>
76
+ <span style={textStyle}>{localize(label)}</span>
77
+ </a>
55
78
  );
56
79
  }
57
80
 
@@ -33,6 +33,7 @@ export type FontWeightOptionType =
33
33
  export interface ButtonPropsGenerated {
34
34
  child: string;
35
35
  attributes: {
36
+ style?: Record<string, unknown>;
36
37
  scrollable?: boolean;
37
38
  flexDirection?: FlexDirectionOptionType;
38
39
  alignItems?: AlignItemsOptionType;
@@ -1,6 +1,5 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "Button",
6
5
  "children": "string",
@@ -21,16 +20,13 @@
21
20
  "800",
22
21
  "900"
23
22
  ]
24
- },
25
- "defaults": {
26
- "backgroundColor": "transparent"
27
23
  }
28
24
  },
29
25
  "meta": {
30
26
  "desiredParent": ["all"],
31
27
  "label": "Button",
32
28
  "description": "Simple action button.",
33
- "attributes": {
29
+ "styles": {
34
30
  "color": {
35
31
  "label": "Color",
36
32
  "description": "Text color of the button.",
@@ -53,5 +49,13 @@
53
49
  "sort": 3
54
50
  }
55
51
  }
52
+ },
53
+ "defaults": {
54
+ "style": {
55
+ "display": "flex",
56
+ "alignItems": "center",
57
+ "justifyContent": "center",
58
+ "backgroundColor": "transparent"
59
+ }
56
60
  }
57
61
  }
@@ -17,10 +17,12 @@ export type JustifyContentOptionType =
17
17
  | 'space-around'
18
18
  | 'space-evenly';
19
19
  export type PositionOptionType = 'relative' | 'absolute';
20
+ export type AlignOptionType = 'start' | 'center' | 'end';
20
21
 
21
22
  export interface CarouselPropsGenerated {
22
23
  child: string;
23
24
  attributes: {
25
+ style?: Record<string, unknown>;
24
26
  scrollable?: boolean;
25
27
  flexDirection?: FlexDirectionOptionType;
26
28
  alignItems?: AlignItemsOptionType;
@@ -54,6 +56,9 @@ export interface CarouselPropsGenerated {
54
56
  left?: string;
55
57
  right?: string;
56
58
  zIndex?: number;
59
+ loop?: boolean;
60
+ dragFree?: boolean;
61
+ align?: AlignOptionType;
57
62
  };
58
63
  }
59
64
 
@@ -1,19 +1,30 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "extends": "View",
6
5
  "type": "Carousel",
7
- "children": "CarouselItem",
8
- "attributes": {},
9
- "defaults": {
10
- "flexDirection": "row"
6
+ "children": "node",
7
+ "attributes": {
8
+ "loop": "boolean",
9
+ "dragFree": "boolean",
10
+ "align": [
11
+ "start",
12
+ "center",
13
+ "end"
14
+ ]
11
15
  }
12
16
  },
13
17
  "meta": {
14
- "desiredParent": ["=CarouselProvider"],
18
+ "desiredParent": [
19
+ "=CarouselProvider"
20
+ ],
15
21
  "label": "Carousel",
16
22
  "description": "Container for carousel items.",
17
- "attributes": {}
23
+ "styles": {}
24
+ },
25
+ "defaults": {
26
+ "style": {
27
+ "flexDirection": "row"
28
+ }
18
29
  }
19
30
  }
@@ -25,6 +25,7 @@ export type ButtonTypeOptionType =
25
25
  export interface CarouselButtonsPropsGenerated {
26
26
  child: string;
27
27
  attributes: {
28
+ style?: Record<string, unknown>;
28
29
  scrollable?: boolean;
29
30
  flexDirection?: FlexDirectionOptionType;
30
31
  alignItems?: AlignItemsOptionType;
@@ -1,20 +1,26 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "CarouselButtons",
6
5
  "children": "never",
7
6
  "extends": "View",
8
7
  "attributes": {
9
- "buttonType": ["previous_button", "next_button", "skip_button"],
8
+ "buttonType": [
9
+ "previous_button",
10
+ "next_button",
11
+ "skip_button"
12
+ ],
10
13
  "skipNumber": "number"
11
14
  }
12
15
  },
13
16
  "meta": {
14
- "desiredParent": [">OnboardProvider", ">CarouselProvider"],
17
+ "desiredParent": [
18
+ ">OnboardProvider",
19
+ ">CarouselProvider"
20
+ ],
15
21
  "label": "Carousel Buttons",
16
22
  "description": "Renders built-in carousel buttons.",
17
- "attributes": {
23
+ "styles": {
18
24
  "buttonType": {
19
25
  "label": "Button Type",
20
26
  "description": "Which carousel button to show.",
@@ -28,6 +28,7 @@ export type DotTypeOptionType =
28
28
  export interface CarouselDotsPropsGenerated {
29
29
  child: string;
30
30
  attributes: {
31
+ style?: Record<string, unknown>;
31
32
  scrollable?: boolean;
32
33
  flexDirection?: FlexDirectionOptionType;
33
34
  alignItems?: AlignItemsOptionType;
@@ -1,6 +1,5 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "CarouselDots",
6
5
  "children": "never",
@@ -17,10 +16,12 @@
17
16
  }
18
17
  },
19
18
  "meta": {
20
- "desiredParent": [">CarouselProvider"],
19
+ "desiredParent": [
20
+ ">CarouselProvider"
21
+ ],
21
22
  "label": "Carousel Dots",
22
23
  "description": "Renders page indicator dots.",
23
- "attributes": {
24
+ "styles": {
24
25
  "dotType": {
25
26
  "label": "Dot Type",
26
27
  "description": "Style used for the dots.",
@@ -21,6 +21,7 @@ export type PositionOptionType = 'relative' | 'absolute';
21
21
  export interface CarouselItemPropsGenerated {
22
22
  child: string;
23
23
  attributes: {
24
+ style?: Record<string, unknown>;
24
25
  scrollable?: boolean;
25
26
  flexDirection?: FlexDirectionOptionType;
26
27
  alignItems?: AlignItemsOptionType;
@@ -1,6 +1,5 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "CarouselItem",
6
5
  "children": "node",
@@ -8,9 +7,11 @@
8
7
  "attributes": {}
9
8
  },
10
9
  "meta": {
11
- "desiredParent": ["=Carousel"],
10
+ "desiredParent": [
11
+ "=Carousel"
12
+ ],
12
13
  "label": "Carousel Item",
13
14
  "description": "Single slide inside a carousel.",
14
- "attributes": {}
15
+ "styles": {}
15
16
  }
16
17
  }
@@ -5,6 +5,8 @@ import useEmblaCarousel from 'embla-carousel-react';
5
5
  import useNode from '../useNode';
6
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
7
7
  import { useRenderStore } from '../../store';
8
+ import { isCarousel } from '../../utils/isCarousel';
9
+ import type { Node, NodeData } from '../../types/Node';
8
10
 
9
11
  export const carouselContext = createContext<any>(undefined);
10
12
  function CarouselProvider({ node }: CarouselProviderComponentProps) {
@@ -22,6 +24,38 @@ function CarouselProvider({ node }: CarouselProviderComponentProps) {
22
24
  () => extractViewStyle(node, { appConfig, projectColors }),
23
25
  [node, appConfig, projectColors],
24
26
  );
27
+
28
+ const { carouselChild, otherChildren } = useMemo(() => {
29
+ const children = node.children as Node;
30
+
31
+ if (!children) {
32
+ return {
33
+ carouselChild: null as NodeData | null,
34
+ otherChildren: [] as Node[],
35
+ };
36
+ }
37
+
38
+ if (Array.isArray(children)) {
39
+ const idx = children.findIndex((c) => isCarousel(c));
40
+ const carousel = idx >= 0 ? (children[idx] as NodeData) : null;
41
+ const rest = idx >= 0 ? children.filter((_, i) => i !== idx) : children;
42
+ return { carouselChild: carousel, otherChildren: rest };
43
+ }
44
+
45
+ if (isCarousel(children)) {
46
+ return {
47
+ carouselChild: children as NodeData,
48
+ otherChildren: [] as Node[],
49
+ };
50
+ }
51
+
52
+ // Non-carousel single child (e.g. dots/buttons): treat as "other" so we don't mount embla with an invalid DOM.
53
+ return {
54
+ carouselChild: null as NodeData | null,
55
+ otherChildren: [children],
56
+ };
57
+ }, [node.children]);
58
+
25
59
  return (
26
60
  <carouselContext.Provider value={emblaApi}>
27
61
  <div
@@ -31,10 +65,18 @@ function CarouselProvider({ node }: CarouselProviderComponentProps) {
31
65
  style={viewStyle}
32
66
  >
33
67
  <div className="embla">
34
- <div className="embla__viewport" ref={emblaRef}>
35
- {node.children && <RenderNode node={node.children} />}
68
+ <div
69
+ className="embla__viewport"
70
+ ref={carouselChild ? emblaRef : undefined}
71
+ >
72
+ {carouselChild ? <RenderNode node={carouselChild} /> : null}
36
73
  </div>
37
74
  </div>
75
+ {otherChildren.length > 0
76
+ ? otherChildren.map((child, index) => (
77
+ <RenderNode key={index} node={child} />
78
+ ))
79
+ : null}
38
80
  </div>
39
81
  </carouselContext.Provider>
40
82
  );
@@ -21,6 +21,7 @@ export type PositionOptionType = 'relative' | 'absolute';
21
21
  export interface CarouselProviderPropsGenerated {
22
22
  child: string;
23
23
  attributes: {
24
+ style?: Record<string, unknown>;
24
25
  scrollable?: boolean;
25
26
  flexDirection?: FlexDirectionOptionType;
26
27
  alignItems?: AlignItemsOptionType;
@@ -3,6 +3,7 @@ import type { ImageComponentProps } from './ImageProps.generated';
3
3
  import useNode from '../useNode';
4
4
  import { useRenderStore } from '../../store';
5
5
  import { extractImageStyle } from '../../utils/extractImageStyle';
6
+ import { resolveImageSrc } from '../../utils/getImage';
6
7
  import { useLogRender } from '../../utils/useLogRender';
7
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
9
  import { useMergedStyle } from '../../utils/useMergedStyle';
@@ -36,7 +37,7 @@ function Image({ node }: ImageComponentProps) {
36
37
  key={node.key + (node.attributes?.src ?? '-')}
37
38
  attribute-name={attributeName}
38
39
  attribute-key={attributeKey}
39
- src={node.attributes?.src}
40
+ src={resolveImageSrc(node.attributes?.src)}
40
41
  style={style}
41
42
  alt=""
42
43
  />
@@ -22,6 +22,7 @@ export type ResizeModeOptionType = 'cover' | 'contain' | 'stretch' | 'center';
22
22
  export interface ImagePropsGenerated {
23
23
  child: string;
24
24
  attributes: {
25
+ style?: Record<string, unknown>;
25
26
  scrollable?: boolean;
26
27
  flexDirection?: FlexDirectionOptionType;
27
28
  alignItems?: AlignItemsOptionType;
@@ -1,6 +1,5 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "Image",
6
5
  "children": "never",
@@ -9,14 +8,21 @@
9
8
  "src": "string",
10
9
  "width": "size",
11
10
  "height": "size",
12
- "resizeMode": ["cover", "contain", "stretch", "center"]
11
+ "resizeMode": [
12
+ "cover",
13
+ "contain",
14
+ "stretch",
15
+ "center"
16
+ ]
13
17
  }
14
18
  },
15
19
  "meta": {
16
- "desiredParent": ["all"],
20
+ "desiredParent": [
21
+ "all"
22
+ ],
17
23
  "label": "Image",
18
24
  "description": "Shows an image or graphic.",
19
- "attributes": {
25
+ "styles": {
20
26
  "src": {
21
27
  "label": "Src",
22
28
  "description": "Image source URL.",
@@ -21,6 +21,7 @@ export type PositionOptionType = 'relative' | 'absolute';
21
21
  export interface MainPropsGenerated {
22
22
  child: string;
23
23
  attributes: {
24
+ style?: Record<string, unknown>;
24
25
  scrollable?: boolean;
25
26
  flexDirection?: FlexDirectionOptionType;
26
27
  alignItems?: AlignItemsOptionType;
@@ -55,7 +56,6 @@ export interface MainPropsGenerated {
55
56
  right?: string;
56
57
  zIndex?: number;
57
58
  useSafeAreaView?: boolean;
58
- [key: string]: string | number | boolean | undefined;
59
59
  };
60
60
  }
61
61
 
@@ -1,9 +1,8 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": true,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "Main",
6
- "children": ["node", "array"],
5
+ "children": "node",
7
6
  "extends": "View",
8
7
  "attributes": {
9
8
  "useSafeAreaView": "boolean"
@@ -11,17 +10,21 @@
11
10
  },
12
11
  "defaults": {
13
12
  "useSafeAreaView": true,
14
- "width": "100%",
15
- "height": "100%",
16
- "flex": 1,
17
- "position": "relative"
13
+ "style": {
14
+ "width": "100%",
15
+ "height": "100%",
16
+ "flex": 1,
17
+ "position": "relative"
18
+ }
18
19
  },
19
20
  "meta": {
20
- "desiredParent": ["root"],
21
+ "desiredParent": [
22
+ "root"
23
+ ],
21
24
  "label": "Main",
22
25
  "description": "Top-level screen wrapper (safe area, base layout).",
23
26
  "hideAllAttributes": true,
24
- "attributes": {
27
+ "styles": {
25
28
  "useSafeAreaView": {
26
29
  "label": "Use Safe Area View",
27
30
  "description": "Wraps content with a safe-area-aware container (when supported by the target).",
@@ -21,6 +21,7 @@ export type PositionOptionType = 'relative' | 'absolute';
21
21
  export interface OnboardPropsGenerated {
22
22
  child: string;
23
23
  attributes: {
24
+ style?: Record<string, unknown>;
24
25
  scrollable?: boolean;
25
26
  flexDirection?: FlexDirectionOptionType;
26
27
  alignItems?: AlignItemsOptionType;
@@ -1,20 +1,25 @@
1
1
  {
2
- "schemaVersion": 1,
3
- "allowUnknownAttributes": false,
2
+ "schemaVersion": 2,
4
3
  "pattern": {
5
4
  "type": "Onboard",
6
5
  "children": "node",
7
6
  "extends": "View",
8
- "attributes": {},
9
- "defaults": {
10
- "flexDirection": "row"
11
- }
7
+ "attributes": {}
12
8
  },
13
9
  "meta": {
14
- "desiredParent": ["=OnboardProvider"],
15
- "desiredChildren": ["=OnboardItem"],
10
+ "desiredParent": [
11
+ "=OnboardProvider"
12
+ ],
13
+ "desiredChildren": [
14
+ "=OnboardItem"
15
+ ],
16
16
  "label": "Onboard",
17
17
  "description": "Wraps the onboarding flow.",
18
- "attributes": {}
18
+ "styles": {}
19
+ },
20
+ "defaults": {
21
+ "style": {
22
+ "flexDirection": "row"
23
+ }
19
24
  }
20
25
  }
@@ -36,6 +36,7 @@ export interface EventObjectGenerated {
36
36
  export interface OnboardButtonPropsGenerated {
37
37
  child: string;
38
38
  attributes: {
39
+ style?: Record<string, unknown>;
39
40
  scrollable?: boolean;
40
41
  flexDirection?: FlexDirectionOptionType;
41
42
  alignItems?: AlignItemsOptionType;