@developer_tribe/react-builder 1.0.8 → 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 (216) 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/Builder.tsx +20 -6
  162. package/src/components/BuilderButton.tsx +75 -38
  163. package/src/components/BuilderProvider.tsx +22 -2
  164. package/src/components/DeviceButton.tsx +12 -5
  165. package/src/components/EditorHeader.tsx +296 -38
  166. package/src/components/ParamsProvider.tsx +7 -0
  167. package/src/components/RenderErrorBoundary.tsx +200 -0
  168. package/src/hooks/useParams.ts +5 -1
  169. package/src/hooks/useSyncHtmlThemeClass.ts +19 -0
  170. package/src/index.native.ts +7 -0
  171. package/src/index.ts +8 -0
  172. package/src/migrations/migratePipe.ts +59 -0
  173. package/src/migrations/migrations/1.1.0_normalize_style_attributes.ts +80 -0
  174. package/src/migrations/semver.ts +24 -0
  175. package/src/migrations/types.ts +9 -0
  176. package/src/mockOS/components/PermissionModal.tsx +3 -2
  177. package/src/mockOS/components/SubscriptionModal.tsx +400 -0
  178. package/src/mockOS/context/MockOSContext.tsx +61 -10
  179. package/src/mockOS/context/MockOSContextBase.ts +1 -0
  180. package/src/mockOS/hooks/useMockIap.ts +11 -0
  181. package/src/mockOS/index.ts +7 -0
  182. package/src/mockOS/managers/mockOSIapManager.ts +10 -0
  183. package/src/mockOS/managers/subscriptionManager.ts +36 -0
  184. package/src/modals/IconPickerModal.tsx +1 -1
  185. package/src/pages/ProjectDebug.tsx +331 -0
  186. package/src/pages/ProjectMigrationPage.tsx +92 -0
  187. package/src/pages/ProjectPage.tsx +313 -161
  188. package/src/pages/ProjectValidationPage.tsx +54 -0
  189. package/src/styles/base/_global.scss +58 -11
  190. package/src/styles/components/_attributes-editor.scss +1 -1
  191. package/src/styles/components/_bottom-bar.scss +7 -4
  192. package/src/styles/components/_editor-shell.scss +126 -4
  193. package/src/styles/components/_mockos-router.scss +3 -2
  194. package/src/styles/components/_ui-components.scss +10 -5
  195. package/src/styles/foundation/_colors.scss +78 -11
  196. package/src/styles/foundation/_mixins.scss +4 -1
  197. package/src/styles/foundation/_sizes.scss +4 -2
  198. package/src/styles/index.scss +1 -0
  199. package/src/styles/layout/_builder.scss +61 -0
  200. package/src/styles/layout/_project-validation.scss +214 -0
  201. package/src/styles/modals/_add-component.scss +4 -2
  202. package/src/styles/modals/_color-modal.scss +4 -2
  203. package/src/styles/modals/_modal-shell.scss +3 -1
  204. package/src/types/Device.ts +5 -0
  205. package/src/utils/__special_exceptions.ts +88 -0
  206. package/src/utils/analyseNode.ts +8 -2
  207. package/src/utils/analyseNodeByPatterns.ts +43 -9
  208. package/src/utils/extractTextStyle.ts +19 -6
  209. package/src/utils/extractViewStyle.ts +68 -59
  210. package/src/utils/getImage.ts +76 -0
  211. package/src/utils/novaToJson.ts +2 -1
  212. package/src/utils/pasteNode.ts +172 -0
  213. package/src/utils/patterns.ts +4 -3
  214. package/dist/android.svg +0 -43
  215. package/dist/apple.svg +0 -16
  216. package/dist/background.jpg +0 -0
@@ -15,7 +15,18 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
15
15
  options: ExtractViewStyleOptions = {},
16
16
  ) {
17
17
  const attributes = node.attributes;
18
- const scrollable = attributes?.scrollable ?? false;
18
+ const styleBag = (attributes as any)?.style as
19
+ | Record<string, unknown>
20
+ | undefined;
21
+ const get = <K extends keyof ViewPropsGenerated['attributes']>(
22
+ key: K,
23
+ ): ViewPropsGenerated['attributes'][K] | undefined => {
24
+ const direct = (attributes as any)?.[key];
25
+ if (direct !== undefined && direct !== null) return direct;
26
+ return styleBag?.[key as unknown as string] as any;
27
+ };
28
+
29
+ const scrollable = (get('scrollable') as any) ?? false;
19
30
  const style: React.CSSProperties = {
20
31
  display: 'flex',
21
32
  flexDirection: 'column',
@@ -29,7 +40,7 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
29
40
  // Important for flex children: allow the element to shrink so overflow scroll can work.
30
41
  style.minWidth = 0;
31
42
  style.minHeight = 0;
32
- if (attributes.flexDirection === 'row') {
43
+ if (get('flexDirection') === 'row') {
33
44
  style.overflowX = 'auto';
34
45
  style.overflowY = 'hidden';
35
46
  style.maxWidth = '100%';
@@ -41,13 +52,15 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
41
52
  style.maxWidth = '100%';
42
53
  }
43
54
  }
44
- if (attributes.flexDirection) style.flexDirection = attributes.flexDirection;
45
- if (attributes.alignItems)
46
- style.alignItems =
47
- attributes.alignItems as React.CSSProperties['alignItems'];
48
- if (attributes.justifyContent)
55
+ const flexDirection = get('flexDirection');
56
+ if (flexDirection) style.flexDirection = flexDirection as any;
57
+ const alignItems = get('alignItems');
58
+ if (alignItems)
59
+ style.alignItems = alignItems as React.CSSProperties['alignItems'];
60
+ const justifyContent = get('justifyContent');
61
+ if (justifyContent)
49
62
  style.justifyContent =
50
- attributes.justifyContent as React.CSSProperties['justifyContent'];
63
+ justifyContent as React.CSSProperties['justifyContent'];
51
64
  const setParsedSize = <K extends keyof React.CSSProperties>(
52
65
  property: K,
53
66
  rawValue: string | number | undefined,
@@ -57,80 +70,76 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
57
70
  style[property] = parsed as React.CSSProperties[K];
58
71
  };
59
72
 
60
- setParsedSize('gap', attributes.gap);
61
- setParsedSize('padding', attributes.padding);
62
- setParsedSize('margin', attributes.margin);
73
+ setParsedSize('gap', get('gap') as any);
74
+ setParsedSize('padding', get('padding') as any);
75
+ setParsedSize('margin', get('margin') as any);
63
76
 
64
- if (!isEmptySizeValue(attributes.paddingHorizontal)) {
65
- const parsed = parseSize(attributes.paddingHorizontal);
77
+ const paddingHorizontal = get('paddingHorizontal') as any;
78
+ if (!isEmptySizeValue(paddingHorizontal)) {
79
+ const parsed = parseSize(paddingHorizontal);
66
80
  style.paddingLeft = parsed as React.CSSProperties['paddingLeft'];
67
81
  style.paddingRight = parsed as React.CSSProperties['paddingRight'];
68
82
  }
69
- if (!isEmptySizeValue(attributes.paddingVertical)) {
70
- const parsed = parseSize(attributes.paddingVertical);
83
+ const paddingVertical = get('paddingVertical') as any;
84
+ if (!isEmptySizeValue(paddingVertical)) {
85
+ const parsed = parseSize(paddingVertical);
71
86
  style.paddingTop = parsed as React.CSSProperties['paddingTop'];
72
87
  style.paddingBottom = parsed as React.CSSProperties['paddingBottom'];
73
88
  }
74
89
 
75
90
  // Explicit per-side paddings should override paddingHorizontal/paddingVertical.
76
- setParsedSize('paddingTop', attributes.paddingTop);
77
- setParsedSize('paddingBottom', attributes.paddingBottom);
78
- setParsedSize('paddingLeft', attributes.paddingLeft);
79
- setParsedSize('paddingRight', attributes.paddingRight);
91
+ setParsedSize('paddingTop', get('paddingTop') as any);
92
+ setParsedSize('paddingBottom', get('paddingBottom') as any);
93
+ setParsedSize('paddingLeft', get('paddingLeft') as any);
94
+ setParsedSize('paddingRight', get('paddingRight') as any);
80
95
 
81
- const marginHorizontalRaw = (attributes as Record<string, unknown>)
82
- .marginHorizontal as string | number | undefined;
96
+ const marginHorizontalRaw =
97
+ ((attributes as Record<string, unknown>).marginHorizontal as
98
+ | string
99
+ | number
100
+ | undefined) ?? (styleBag?.marginHorizontal as any);
83
101
  if (!isEmptySizeValue(marginHorizontalRaw)) {
84
102
  const parsed = parseSize(marginHorizontalRaw);
85
103
  style.marginLeft = parsed as React.CSSProperties['marginLeft'];
86
104
  style.marginRight = parsed as React.CSSProperties['marginRight'];
87
105
  }
88
106
 
89
- if (!isEmptySizeValue(attributes.marginVertical)) {
90
- const parsed = parseSize(attributes.marginVertical);
107
+ const marginVertical = get('marginVertical') as any;
108
+ if (!isEmptySizeValue(marginVertical)) {
109
+ const parsed = parseSize(marginVertical);
91
110
  style.marginTop = parsed as React.CSSProperties['marginTop'];
92
111
  style.marginBottom = parsed as React.CSSProperties['marginBottom'];
93
112
  }
94
113
 
95
- setParsedSize('marginTop', attributes.marginTop);
96
- setParsedSize('marginBottom', attributes.marginBottom);
97
- setParsedSize('marginLeft', attributes.marginLeft);
98
- setParsedSize('marginRight', attributes.marginRight);
99
- if (attributes.backgroundColor) {
114
+ setParsedSize('marginTop', get('marginTop') as any);
115
+ setParsedSize('marginBottom', get('marginBottom') as any);
116
+ setParsedSize('marginLeft', get('marginLeft') as any);
117
+ setParsedSize('marginRight', get('marginRight') as any);
118
+ const backgroundColor = get('backgroundColor') as any;
119
+ if (backgroundColor) {
100
120
  style.backgroundColor =
101
- parseColor(attributes.backgroundColor, {
121
+ parseColor(backgroundColor, {
102
122
  projectColors: options.projectColors,
103
123
  appConfig: options.appConfig,
104
- }) ?? attributes.backgroundColor;
124
+ }) ?? backgroundColor;
105
125
  }
106
- setParsedSize('borderRadius', attributes.borderRadius);
107
- setParsedSize('width', attributes.width);
108
- setParsedSize(
109
- 'minWidth',
110
- (attributes as ViewPropsGenerated['attributes']).minWidth,
111
- );
112
- setParsedSize(
113
- 'maxWidth',
114
- (attributes as ViewPropsGenerated['attributes']).maxWidth,
115
- );
116
- setParsedSize('height', attributes.height);
117
- setParsedSize(
118
- 'minHeight',
119
- (attributes as ViewPropsGenerated['attributes']).minHeight,
120
- );
121
- setParsedSize(
122
- 'maxHeight',
123
- (attributes as ViewPropsGenerated['attributes']).maxHeight,
124
- );
125
- if (attributes.flex !== undefined)
126
- style.flex = attributes.flex as React.CSSProperties['flex'];
127
- if (attributes.position)
128
- style.position = attributes.position as React.CSSProperties['position'];
129
- setParsedSize('top', attributes.top);
130
- setParsedSize('bottom', attributes.bottom);
131
- setParsedSize('left', attributes.left);
132
- setParsedSize('right', attributes.right);
133
- if (attributes.zIndex !== undefined)
134
- style.zIndex = attributes.zIndex as React.CSSProperties['zIndex'];
126
+ setParsedSize('borderRadius', get('borderRadius') as any);
127
+ setParsedSize('width', get('width') as any);
128
+ setParsedSize('minWidth', get('minWidth') as any);
129
+ setParsedSize('maxWidth', get('maxWidth') as any);
130
+ setParsedSize('height', get('height') as any);
131
+ setParsedSize('minHeight', get('minHeight') as any);
132
+ setParsedSize('maxHeight', get('maxHeight') as any);
133
+ const flex = get('flex') as any;
134
+ if (flex !== undefined) style.flex = flex as React.CSSProperties['flex'];
135
+ const position = get('position') as any;
136
+ if (position) style.position = position as React.CSSProperties['position'];
137
+ setParsedSize('top', get('top') as any);
138
+ setParsedSize('bottom', get('bottom') as any);
139
+ setParsedSize('left', get('left') as any);
140
+ setParsedSize('right', get('right') as any);
141
+ const zIndex = get('zIndex') as any;
142
+ if (zIndex !== undefined)
143
+ style.zIndex = zIndex as React.CSSProperties['zIndex'];
135
144
  return style;
136
145
  }
@@ -0,0 +1,76 @@
1
+ export const TRIBE_ASSETS_BASE_URL =
2
+ 'https://tribemarketing.s3.eu-central-1.amazonaws.com/tribehub-assets/';
3
+
4
+ export enum TribeAssetName {
5
+ Android = 'android.svg',
6
+ Apple = 'apple.svg',
7
+ Background = 'background.jpg',
8
+ }
9
+
10
+ function normalizeAssetName(name: string): string {
11
+ const trimmed = name.trim().replace(/^\/+/, '');
12
+
13
+ // Common typos / aliases
14
+ if (trimmed === 'backgorund.jpg') return 'background.jpg';
15
+ if (trimmed === 'ios.svg') return 'apple.svg';
16
+
17
+ return trimmed;
18
+ }
19
+
20
+ function encodePath(path: string): string {
21
+ // Encode each segment but keep `/` separators intact.
22
+ return path
23
+ .split('/')
24
+ .filter(Boolean)
25
+ .map((seg) => encodeURIComponent(seg))
26
+ .join('/');
27
+ }
28
+
29
+ /**
30
+ * Returns a full CDN URL for a given asset name/path.
31
+ *
32
+ * Examples:
33
+ * - getImage(TribeAssetName.Android)
34
+ * - getImage(TribeAssetName.Apple) // also accepts 'ios.svg' via parseTribeAssetName/resolveImageSrc
35
+ * - getImage(TribeAssetName.Background) // also accepts 'backgorund.jpg' via parseTribeAssetName/resolveImageSrc
36
+ */
37
+ export function getImage(name: TribeAssetName): string {
38
+ const normalized = normalizeAssetName(name);
39
+ const base = TRIBE_ASSETS_BASE_URL.endsWith('/')
40
+ ? TRIBE_ASSETS_BASE_URL
41
+ : `${TRIBE_ASSETS_BASE_URL}/`;
42
+
43
+ return `${base}${encodePath(normalized)}`;
44
+ }
45
+
46
+ export function parseTribeAssetName(name: string): TribeAssetName | null {
47
+ const normalized = normalizeAssetName(name);
48
+ switch (normalized) {
49
+ case TribeAssetName.Android:
50
+ return TribeAssetName.Android;
51
+ case TribeAssetName.Apple:
52
+ return TribeAssetName.Apple;
53
+ case TribeAssetName.Background:
54
+ return TribeAssetName.Background;
55
+ default:
56
+ return null;
57
+ }
58
+ }
59
+
60
+ function isAbsoluteUrl(src: string): boolean {
61
+ // Covers http(s), data, blob, and protocol-relative URLs.
62
+ return /^(https?:)?\/\//.test(src) || /^(data|blob):/.test(src);
63
+ }
64
+
65
+ /**
66
+ * Resolves a `src` value into a usable URL:
67
+ * - Absolute URLs are returned unchanged
68
+ * - Known tribe asset names (or aliases) are converted via `getImage`
69
+ * - Unknown relative strings are returned unchanged
70
+ */
71
+ export function resolveImageSrc(src?: string | null): string | undefined {
72
+ if (!src) return undefined;
73
+ if (isAbsoluteUrl(src)) return src;
74
+ const parsed = parseTribeAssetName(src);
75
+ return parsed ? getImage(parsed) : src;
76
+ }
@@ -539,7 +539,8 @@ function mapFooterFromGeneralComponents(generalComponents: any[]): Node | null {
539
539
 
540
540
  const attributes: Record<string, unknown> = { gap: 8 };
541
541
  if (baseTextKey) attributes.textLocalizationKey = baseTextKey;
542
- if (baseTextColor) attributes.textColor = baseTextColor;
542
+ // OnboardFooter extends Text, so the canonical text color attribute is `color`.
543
+ if (baseTextColor) attributes.color = baseTextColor;
543
544
  const first = linkedWords[0];
544
545
  const second = linkedWords[1];
545
546
  if (first) {
@@ -0,0 +1,172 @@
1
+ import type { Node, NodeData } from '../types/Node';
2
+ import {
3
+ isNodeArray,
4
+ isNodeNullOrUndefined,
5
+ isNodeString,
6
+ } from './analyseNode';
7
+ import { getPatternByType } from './patterns';
8
+
9
+ export type PasteIntoChildrenResult =
10
+ | {
11
+ ok: true;
12
+ nextRoot: Node;
13
+ pastedNode: Node;
14
+ }
15
+ | {
16
+ ok: false;
17
+ nextRoot: Node;
18
+ reason: string;
19
+ };
20
+
21
+ function isNodeData(node: Node): node is NodeData {
22
+ return (
23
+ node !== null &&
24
+ node !== undefined &&
25
+ typeof node === 'object' &&
26
+ !Array.isArray(node)
27
+ );
28
+ }
29
+
30
+ function appendChild(children: Node, childToAppend: Node): Node {
31
+ if (Array.isArray(children)) {
32
+ return [...children, childToAppend];
33
+ }
34
+ if (
35
+ children === null ||
36
+ children === undefined ||
37
+ typeof children === 'string'
38
+ ) {
39
+ return [childToAppend];
40
+ }
41
+ return [children as Node, childToAppend];
42
+ }
43
+
44
+ function replaceNode(root: Node, target: Node, next: Node): Node {
45
+ if (root === target) return next;
46
+ if (root === null || root === undefined) return root;
47
+ if (typeof root === 'string') return root;
48
+ if (Array.isArray(root)) {
49
+ let changed = false;
50
+ const arr = root.map((item) => {
51
+ const r = replaceNode(item, target, next);
52
+ if (r !== item) changed = true;
53
+ return r;
54
+ });
55
+ return changed ? arr : root;
56
+ }
57
+ const data = root as NodeData;
58
+ const prev = data.children as Node;
59
+ if (!prev) return root;
60
+ const replaced = Array.isArray(prev)
61
+ ? (prev as Node[]).map((c) => replaceNode(c, target, next))
62
+ : replaceNode(prev as Node, target, next);
63
+ if (replaced !== prev) {
64
+ return { ...data, children: replaced } as Node;
65
+ }
66
+ return root;
67
+ }
68
+
69
+ export function canPasteIntoChildren(
70
+ target: Node,
71
+ pastedNode: Node,
72
+ ): {
73
+ ok: boolean;
74
+ reason?: string;
75
+ } {
76
+ if (isNodeNullOrUndefined(target)) {
77
+ return { ok: false, reason: 'Select a node to paste into.' };
78
+ }
79
+ if (isNodeString(target)) {
80
+ return { ok: false, reason: 'Select a component node to paste into.' };
81
+ }
82
+ if (!isNodeData(pastedNode)) {
83
+ return { ok: false, reason: 'Only component nodes can be pasted.' };
84
+ }
85
+ const childType = pastedNode.type;
86
+ if (!childType) {
87
+ return { ok: false, reason: 'Pasted node has no type.' };
88
+ }
89
+
90
+ // Collections behave like generic containers.
91
+ if (isNodeArray(target)) return { ok: true };
92
+
93
+ if (!isNodeData(target)) {
94
+ return { ok: false, reason: 'Select a component node to paste into.' };
95
+ }
96
+
97
+ const parentType = target.type;
98
+ if (!parentType) {
99
+ return { ok: false, reason: 'Target node has no type.' };
100
+ }
101
+
102
+ // Special rule: limit OnboardButtons to OnboardButton only
103
+ if (parentType === 'OnboardButtons' && childType !== 'OnboardButton') {
104
+ return {
105
+ ok: false,
106
+ reason: 'OnboardButtons can only contain OnboardButton.',
107
+ };
108
+ }
109
+
110
+ const childrenSchema = getPatternByType(parentType)?.pattern
111
+ ?.children as unknown;
112
+ if (!childrenSchema) {
113
+ return { ok: false, reason: `${parentType} does not accept children.` };
114
+ }
115
+ if (childrenSchema === 'never' || childrenSchema === 'string') {
116
+ return { ok: false, reason: `${parentType} does not accept child nodes.` };
117
+ }
118
+ if (
119
+ childrenSchema === 'node' ||
120
+ (Array.isArray(childrenSchema) &&
121
+ (childrenSchema as unknown[]).includes('node'))
122
+ ) {
123
+ return { ok: true };
124
+ }
125
+ if (typeof childrenSchema === 'string') {
126
+ return childType === childrenSchema
127
+ ? { ok: true }
128
+ : {
129
+ ok: false,
130
+ reason: `${parentType} only accepts ${childrenSchema} children.`,
131
+ };
132
+ }
133
+ return { ok: false, reason: `${parentType} does not accept this child.` };
134
+ }
135
+
136
+ export function pasteIntoChildren(
137
+ root: Node,
138
+ target: Node,
139
+ pastedNode: Node,
140
+ ): PasteIntoChildrenResult {
141
+ const can = canPasteIntoChildren(target, pastedNode);
142
+ if (!can.ok) {
143
+ return {
144
+ ok: false,
145
+ nextRoot: root,
146
+ reason: can.reason ?? 'Cannot paste into this node.',
147
+ };
148
+ }
149
+
150
+ // Paste into collection (root arrays / array nodes).
151
+ if (isNodeArray(target)) {
152
+ const nextList = [...(target as Node[]), pastedNode];
153
+ const nextRoot = replaceNode(root, target, nextList);
154
+ return { ok: true, nextRoot, pastedNode };
155
+ }
156
+
157
+ // Paste into component node children.
158
+ if (!isNodeData(target)) {
159
+ return {
160
+ ok: false,
161
+ nextRoot: root,
162
+ reason: 'Select a component node to paste into.',
163
+ };
164
+ }
165
+
166
+ const nextTarget: NodeData = {
167
+ ...(target as NodeData),
168
+ children: appendChild((target as NodeData).children as Node, pastedNode),
169
+ };
170
+ const nextRoot = replaceNode(root, target, nextTarget as Node);
171
+ return { ok: true, nextRoot, pastedNode };
172
+ }
@@ -29,6 +29,9 @@ export type SpecialCategoryMeta = {
29
29
  type PatternMeta = {
30
30
  label?: string;
31
31
  description?: string;
32
+ // schemaVersion >= 2 uses `styles` (formerly `attributes`)
33
+ styles?: Record<string, AttributeMeta>;
34
+ // backwards-compat for schemaVersion 1 patterns
32
35
  attributes?: Record<string, AttributeMeta>;
33
36
  specialCategories?: Record<string, SpecialCategoryMeta>;
34
37
  desiredParent?: string[];
@@ -40,8 +43,6 @@ type PatternMeta = {
40
43
 
41
44
  type Pattern = {
42
45
  schemaVersion: number;
43
- allowUnknownAttributes: boolean;
44
- extends: string;
45
46
  pattern: {
46
47
  type: string;
47
48
  children: unknown;
@@ -122,7 +123,7 @@ export function getAttributeMeta(
122
123
  type?: string | null,
123
124
  ): Record<string, AttributeMeta> | undefined {
124
125
  const p = getPatternByType(type);
125
- return p?.meta?.attributes;
126
+ return p?.meta?.styles ?? p?.meta?.attributes;
126
127
  }
127
128
 
128
129
  /** Returns defaults block (if any) for a given component type */
package/dist/android.svg DELETED
@@ -1,43 +0,0 @@
1
- <?xml version="1.0" encoding="iso-8859-1"?>
2
- <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
3
- <svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
4
- viewBox="0 0 502.857 502.857" xml:space="preserve">
5
- <g>
6
- <path style="fill:#57C927;" d="M115.428,155.433v217.664c0,17,10.208,30.336,27.704,30.336h22.84c-0.784,0-2.544,5.768-2.544,8.6
7
- v61.648c0,16.112,15.448,29.176,32,29.176c16.56,0,32-13.064,32-29.176v-61.648c0-2.832-3.088-8.6-3.848-8.6h55.712
8
- c-0.76,0-3.864,5.768-3.864,8.6v61.648c0,16.112,15.416,29.176,31.968,29.176c16.592,0,32.032-13.064,32.032-29.176v-61.648
9
- c0-2.832-1.752-8.6-2.536-8.6h22.872c17.496,0,27.664-13.336,27.664-30.336V155.433H113.596H115.428z"/>
10
- <path style="fill:#57C927;" d="M59.428,158.977c-16.568,0-32,13.072-32,29.176v124.92c0,16.112,15.432,29.176,32,29.176
11
- c16.56,0,32-13.064,32-29.176V188.161C91.428,172.049,75.988,158.977,59.428,158.977z"/>
12
- <path style="fill:#57C927;" d="M320.3,42.057l5.584-8.192l5.592-8.096l12.456-18.2c1.56-2.256,0.912-5.264-1.384-6.744
13
- c-2.272-1.512-5.416-0.88-6.904,1.36l-19.016,27.704l-5.72,8.344c-18.072-6.832-38.208-10.64-59.48-10.64
14
- c-21.224,0-41.4,3.816-59.472,10.64l-5.688-8.336l-5.624-8.184l-13.36-19.512c-1.544-2.248-4.648-2.84-6.952-1.36
15
- c-2.28,1.488-2.912,4.496-1.392,6.744l12.448,18.208l5.592,8.104l5.616,8.168c-42.432,19.24-71.144,57.368-71.144,97.368h279.96
16
- C391.412,99.433,362.708,61.305,320.3,42.057z M191.436,100.593c-8.312,0-15.008-6.536-15.008-14.608s6.696-14.576,15.008-14.576
17
- c8.288,0,15,6.504,15,14.576S199.732,100.593,191.436,100.593z M311.436,100.593c-8.304,0-15.016-6.536-15.016-14.608
18
- s6.712-14.576,15.016-14.576c8.288,0,15,6.504,15,14.576S319.724,100.593,311.436,100.593z"/>
19
- </g>
20
- <path style="fill:#1CB71C;" d="M60.852,224.193c-12.472,0-25.424-11.768-33.424-30.432v119.32c0,16.112,15.432,29.176,32,29.176
21
- c16.56,0,32-13.064,32-29.176V199.985C83.428,214.977,71.86,224.193,60.852,224.193z"/>
22
- <path style="fill:#57C927;" d="M443.428,158.977c-16.568,0-32,13.072-32,29.176v124.92c0,16.112,15.432,29.176,32,29.176
23
- c16.56,0,32-13.064,32-29.176V188.161C475.428,172.049,459.988,158.977,443.428,158.977z"/>
24
- <g>
25
- <path style="fill:#1CB71C;" d="M444.852,224.193c-12.472,0-25.424-11.768-33.424-30.432v119.32c0,16.112,15.432,29.176,32,29.176
26
- c16.56,0,32-13.064,32-29.176V199.985C467.428,214.977,455.86,224.193,444.852,224.193z"/>
27
- <path style="fill:#1CB71C;" d="M251.428,179.337c-63.28,0-120-7.32-136-17.712v211.472c0,17,10.208,30.336,27.704,30.336h22.84
28
- c-0.784,0-2.544,5.768-2.544,8.6v61.648c0,16.112,15.448,29.176,32,29.176c16.56,0,32-13.064,32-29.176v-61.648
29
- c0-2.832-3.088-8.6-3.848-8.6h55.712c-0.76,0-3.864,5.768-3.864,8.6v61.648c0,16.112,15.416,29.176,31.968,29.176
30
- c16.592,0,32.032-13.064,32.032-29.176v-61.648c0-2.832-1.752-8.6-2.536-8.6h22.872c17.496,0,27.664-13.336,27.664-30.336v-211.48
31
- C371.428,172.009,314.716,179.337,251.428,179.337z"/>
32
- <path style="fill:#1CB71C;" d="M326.436,85.977c0,8.072-6.712,14.608-15,14.608c-8.304,0-15.016-6.536-15.016-14.608
33
- c0-4.376,2.008-8.24,5.136-10.912c-15.816-2.64-32.64-4.088-50.128-4.088s-34.304,1.448-50.128,4.088
34
- c3.136,2.664,5.144,6.536,5.144,10.912c0,8.072-6.712,14.608-15,14.608c-8.312,0-15.008-6.536-15.008-14.608
35
- c0-2.064,0.456-4.024,1.248-5.808c-23.984,6.304-44.592,15.504-60.144,26.808c-3.92,10.296-6.088,24.456-6.088,32.456h279.96
36
- c0-8-2.168-22.152-6.08-32.44c-15.544-11.32-36.16-20.536-60.128-26.84C325.988,81.937,326.436,83.921,326.436,85.977z"/>
37
- </g>
38
- <path style="fill:#049E42;" d="M251.428,262.817c-53.896,0-104-10.632-136-28.056v138.336c0,17,10.208,30.336,27.704,30.336h22.84
39
- c-0.784,0-2.544,5.768-2.544,8.6v61.648c0,16.112,15.448,29.176,32,29.176c16.56,0,32-13.064,32-29.176v-61.648
40
- c0-2.832-3.088-8.6-3.848-8.6h55.712c-0.76,0-3.864,5.768-3.864,8.6v61.648c0,16.112,15.416,29.176,31.968,29.176
41
- c16.592,0,32.032-13.064,32.032-29.176v-61.648c0-2.832-1.752-8.6-2.536-8.6h22.872c17.496,0,27.664-13.336,27.664-30.336V234.761
42
- C355.428,252.193,305.324,262.817,251.428,262.817z"/>
43
- </svg>
package/dist/apple.svg DELETED
@@ -1,16 +0,0 @@
1
- <?xml version="1.0" encoding="iso-8859-1"?>
2
- <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
3
- <svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
4
- viewBox="0 0 496.412 496.412" xml:space="preserve">
5
- <path d="M317.222,80.584C333.414,59.696,345.686,30.152,341.246,0c-26.472,1.84-57.384,18.768-75.432,40.832
6
- c-16.456,20-29.976,49.728-24.688,78.608C270.054,120.344,299.91,103.008,317.222,80.584z"/>
7
- <path style="fill:#1B546B;" d="M445.838,166.544c-25.4-31.872-61.12-50.344-94.848-50.344c-44.512,0-63.352,21.312-94.264,21.312
8
- c-31.896,0-56.12-21.248-94.624-21.248c-37.832,0-78.112,23.12-103.64,62.64C22.574,234.576,28.694,339.2,86.894,428.336
9
- c20.808,31.904,48.592,67.744,84.952,68.072c32.36,0.32,41.488-20.752,85.336-20.992c43.832-0.256,52.16,21.264,84.456,20.896
10
- c36.384-0.288,65.712-40.016,86.512-71.92c14.912-22.848,20.48-34.376,32.056-60.184
11
- C376.014,332.184,362.518,212.488,445.838,166.544z"/>
12
- <path d="M394.774,228.08c-63.632,51.52-153.592,83.712-253.44,83.712c-35.776,0-70.288-4.144-102.768-11.808
13
- c5.496,41.808,21.16,86.736,48.336,128.344c20.808,31.904,48.592,67.744,84.952,68.072c32.36,0.32,41.488-20.752,85.336-20.992
14
- c43.832-0.256,52.16,21.264,84.456,20.896c36.384-0.288,65.712-40.016,86.512-71.92c14.912-22.848,20.48-34.376,32.056-60.184
15
- C402.966,342.44,378.454,280.176,394.774,228.08z"/>
16
- </svg>
Binary file