@developer_tribe/react-builder 0.1.0 → 0.1.2

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 (107) hide show
  1. package/package.json +4 -2
  2. package/scripts/build-components.js +550 -0
  3. package/scripts/prebuild.js +11 -0
  4. package/src/AttributesEditor.tsx +107 -0
  5. package/src/RenderMainNode.tsx +37 -0
  6. package/src/RenderPage.tsx +61 -0
  7. package/src/assets/devices.json +730 -0
  8. package/src/assets/samples/carousel-sample.json +108 -0
  9. package/src/assets/samples/getSamples.ts +28 -0
  10. package/src/assets/samples/simple-1.json +46 -0
  11. package/src/assets/samples/simple-2.json +233 -0
  12. package/src/assets/samples/vpn-onboard-1.json +799 -0
  13. package/src/assets/samples/vpn-onboard-2.json +790 -0
  14. package/src/assets/samples/vpn-onboard-3.json +803 -0
  15. package/src/assets/samples/vpn-onboard-4.json +804 -0
  16. package/src/build-components/Button/Button.tsx +13 -0
  17. package/src/build-components/Button/ButtonProps.generated.ts +21 -0
  18. package/src/build-components/Button/ButtonProps.ts +3 -0
  19. package/src/build-components/Button/pattern.json +25 -0
  20. package/src/build-components/Carousel/Carousel.tsx +27 -0
  21. package/src/build-components/Carousel/CarouselProps.generated.ts +6 -0
  22. package/src/build-components/Carousel/CarouselProps.ts +3 -0
  23. package/src/build-components/Carousel/pattern.json +9 -0
  24. package/src/build-components/CarouselButtons/CarouselButtons.tsx +47 -0
  25. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +9 -0
  26. package/src/build-components/CarouselButtons/CarouselButtonsProps.ts +3 -0
  27. package/src/build-components/CarouselButtons/pattern.json +12 -0
  28. package/src/build-components/CarouselDots/CarouselDots.tsx +40 -0
  29. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +14 -0
  30. package/src/build-components/CarouselDots/CarouselDotsProps.ts +3 -0
  31. package/src/build-components/CarouselDots/pattern.json +18 -0
  32. package/src/build-components/CarouselItem/CarouselItem.tsx +18 -0
  33. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +6 -0
  34. package/src/build-components/CarouselItem/CarouselItemProps.ts +3 -0
  35. package/src/build-components/CarouselItem/pattern.json +9 -0
  36. package/src/build-components/CarouselProvider/CarouselProvider.tsx +26 -0
  37. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +6 -0
  38. package/src/build-components/CarouselProvider/CarouselProviderProps.ts +3 -0
  39. package/src/build-components/CarouselProvider/pattern.json +9 -0
  40. package/src/build-components/Image/Image.tsx +35 -0
  41. package/src/build-components/Image/ImageProps.generated.ts +12 -0
  42. package/src/build-components/Image/ImageProps.ts +3 -0
  43. package/src/build-components/Image/pattern.json +15 -0
  44. package/src/build-components/Onboard/Onboard.tsx +14 -0
  45. package/src/build-components/Onboard/OnboardProps.generated.ts +6 -0
  46. package/src/build-components/Onboard/OnboardProps.ts +3 -0
  47. package/src/build-components/Onboard/pattern.json +9 -0
  48. package/src/build-components/OnboardBoardTitle/OnboardBoardTitle.tsx +28 -0
  49. package/src/build-components/OnboardBoardTitle/OnboardBoardTitleProps.generated.ts +21 -0
  50. package/src/build-components/OnboardBoardTitle/OnboardBoardTitleProps.ts +4 -0
  51. package/src/build-components/OnboardBoardTitle/pattern.json +25 -0
  52. package/src/build-components/OnboardButton/OnboardButton.tsx +59 -0
  53. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +13 -0
  54. package/src/build-components/OnboardButton/OnboardButtonProps.ts +3 -0
  55. package/src/build-components/OnboardButton/pattern.json +16 -0
  56. package/src/build-components/OnboardButtons/OnboardButtons.tsx +76 -0
  57. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +12 -0
  58. package/src/build-components/OnboardButtons/OnboardButtonsProps.ts +3 -0
  59. package/src/build-components/OnboardButtons/pattern.json +15 -0
  60. package/src/build-components/OnboardExpandingDot/OnboardExpandingDot.tsx +14 -0
  61. package/src/build-components/OnboardExpandingDot/OnboardExpandingDotProps.generated.ts +14 -0
  62. package/src/build-components/OnboardExpandingDot/OnboardExpandingDotProps.ts +4 -0
  63. package/src/build-components/OnboardExpandingDot/pattern.json +18 -0
  64. package/src/build-components/OnboardFooter/OnboardFooter.tsx +13 -0
  65. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +24 -0
  66. package/src/build-components/OnboardFooter/OnboardFooterProps.ts +3 -0
  67. package/src/build-components/OnboardFooter/pattern.json +28 -0
  68. package/src/build-components/OnboardImage/OnboardImage.tsx +14 -0
  69. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +12 -0
  70. package/src/build-components/OnboardImage/OnboardImageProps.ts +3 -0
  71. package/src/build-components/OnboardImage/pattern.json +15 -0
  72. package/src/build-components/OnboardItem/OnboardItem.tsx +29 -0
  73. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +6 -0
  74. package/src/build-components/OnboardItem/OnboardItemProps.ts +3 -0
  75. package/src/build-components/OnboardItem/pattern.json +9 -0
  76. package/src/build-components/OnboardProvider/OnboardProvider.tsx +65 -0
  77. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +6 -0
  78. package/src/build-components/OnboardProvider/OnboardProviderProps.ts +3 -0
  79. package/src/build-components/OnboardProvider/pattern.json +9 -0
  80. package/src/build-components/OnboardSubtitle/OnboardSubtitle.tsx +28 -0
  81. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +21 -0
  82. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.ts +3 -0
  83. package/src/build-components/OnboardSubtitle/pattern.json +25 -0
  84. package/src/build-components/RenderNode.generated.tsx +97 -0
  85. package/src/build-components/Text/Text.tsx +23 -0
  86. package/src/build-components/Text/TextProps.generated.ts +21 -0
  87. package/src/build-components/Text/TextProps.ts +3 -0
  88. package/src/build-components/Text/pattern.json +26 -0
  89. package/src/build-components/View/View.tsx +62 -0
  90. package/src/build-components/View/ViewProps.generated.ts +24 -0
  91. package/src/build-components/View/ViewProps.ts +3 -0
  92. package/src/build-components/View/pattern.json +28 -0
  93. package/src/build-components/other.ts +6 -0
  94. package/src/index.ts +24 -0
  95. package/src/styles/index.scss +114 -0
  96. package/src/types/Device.ts +12 -0
  97. package/src/types/Node.ts +19 -0
  98. package/src/types/PreviewConfig.ts +19 -0
  99. package/src/types/Project.ts +11 -0
  100. package/src/types/TargetedScreenSize.ts +4 -0
  101. package/src/utils/analyseNode.ts +77 -0
  102. package/src/utils/generateRandomKeyForNode.ts +3 -0
  103. package/src/utils/getDevices.ts +6 -0
  104. package/src/utils/isCarousel.ts +36 -0
  105. package/src/utils/isOnboard.ts +54 -0
  106. package/src/utils/novaToJson.ts +254 -0
  107. package/src/utils/patterns.ts +63 -0
@@ -0,0 +1,254 @@
1
+ import { Node, NodeData } from '../types/Node';
2
+ import { Project, ProjectBase } from '../types/Project';
3
+
4
+ export function novaToJson(nova: ProjectBase<unknown>): Node {
5
+ const layout = (nova.data as any).data?.layout;
6
+ console.info('layout', layout);
7
+ if (layout === 'onboard-layout') {
8
+ return onboardNovaToJson(nova);
9
+ }
10
+ return null;
11
+ }
12
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ function onboardNovaToJson(nova: ProjectBase<unknown>): Node {
14
+ const attributes =
15
+ (nova?.data as any)?.data?.attributes ||
16
+ (nova?.data as any)?.attributes ||
17
+ {};
18
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const generalComponents = (attributes?.general_components || []) as any[];
20
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ const pages = (attributes?.data || []) as any[];
22
+
23
+ const dotsNode = mapDotsFromGeneralComponents(generalComponents);
24
+ const footerNode = mapFooterFromGeneralComponents(generalComponents);
25
+ const { carouselNode, providerLevelButtons } = buildCarouselFromPages(pages);
26
+
27
+ const providerNode: NodeData = {
28
+ type: 'OnboardProvider',
29
+ children: [
30
+ carouselNode,
31
+ // Place dots above buttons in visual order
32
+ ...(dotsNode ? [dotsNode] : []),
33
+ ...(providerLevelButtons.length ? providerLevelButtons : []),
34
+ ...(footerNode ? [footerNode] : []),
35
+ ],
36
+ attributes: {
37
+ theme: (nova?.data as any)?.theme,
38
+ },
39
+ };
40
+
41
+ return providerNode;
42
+ }
43
+ N;
44
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ function buildCarouselFromPages(pages: any[]): {
46
+ carouselNode: NodeData;
47
+ providerLevelButtons: Node[];
48
+ } {
49
+ const simplePages = pages.filter(
50
+ (p) => p?.layout === 'simple-onboard-layout',
51
+ );
52
+ const pageKeyToIndex = new Map<string, number>();
53
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ simplePages.forEach((p: any, idx: number) => {
55
+ const key = p?.attributes?.key;
56
+ if (typeof key === 'string') pageKeyToIndex.set(key, idx);
57
+ });
58
+
59
+ const providerLevelButtons: Node[] = [];
60
+ const items: Node[] = simplePages.map((page) =>
61
+ buildCarouselItem(page, pageKeyToIndex, providerLevelButtons),
62
+ );
63
+
64
+ const carouselNode: NodeData = {
65
+ type: 'Onboard',
66
+ children: items as unknown as Node,
67
+ };
68
+
69
+ return { carouselNode, providerLevelButtons };
70
+ }
71
+
72
+ function buildCarouselItem(
73
+ page: any,
74
+ pageKeyToIndex: Map<string, number>,
75
+ providerLevelButtons: Node[],
76
+ ): NodeData {
77
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ const components = (page?.attributes?.components || []) as any[];
79
+ const children: Node[] = [];
80
+
81
+ for (const comp of components) {
82
+ if (comp?.layout === 'title-layout') {
83
+ const title = comp?.attributes?.title_localization_key || '';
84
+ const color = comp?.attributes?.title_color || undefined;
85
+ children.push({
86
+ type: 'OnboardBoardTitle',
87
+ attributes: color ? { color } : undefined,
88
+ children: title,
89
+ });
90
+ } else if (comp?.layout === 'subtitle-layout') {
91
+ const subtitle = comp?.attributes?.subtitle_localization_key || '';
92
+ const color = comp?.attributes?.subtitle_color || undefined;
93
+ children.push({
94
+ type: 'OnboardSubtitle',
95
+ attributes: color ? { color } : undefined,
96
+ children: subtitle,
97
+ });
98
+ } else if (comp?.layout === 'image-layout') {
99
+ const src = comp?.attributes?.image || comp?.attributes?.src || '';
100
+ const rawHeight =
101
+ comp?.attributes?.height ??
102
+ comp?.attributes?.ios_height ??
103
+ comp?.attributes?.android_height;
104
+ const height =
105
+ typeof rawHeight === 'string'
106
+ ? Number.parseInt(rawHeight, 10)
107
+ : typeof rawHeight === 'number'
108
+ ? rawHeight
109
+ : undefined;
110
+
111
+ if (src) {
112
+ children.push({
113
+ type: 'OnboardImage',
114
+ attributes: {
115
+ src,
116
+ ...(height ? { height } : {}),
117
+ resizeMode: 'contain',
118
+ },
119
+ children: undefined as unknown as Node,
120
+ } as unknown as NodeData);
121
+ }
122
+ } else if (comp?.layout === 'Buttons') {
123
+ const direction = comp?.attributes?.buttons_direction;
124
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
125
+ const buttons = (comp?.attributes?.buttons || []) as any[];
126
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
127
+ const buttonNodes: Node[] = [];
128
+ for (const btn of buttons) {
129
+ const attrs = btn?.attributes || {};
130
+ const labelKey = attrs?.button_text_localization_key || '';
131
+ const buttonTextColor = attrs?.button_text_color;
132
+ const buttonBackgroundColor = attrs?.button_background_color;
133
+ const flex = attrs?.flex ? Number(attrs.flex) : undefined;
134
+
135
+ // Find first Navigate event and map to target index
136
+ let targetIndex: number | undefined = undefined;
137
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
138
+ const actions = (attrs?.actions || []) as any[];
139
+ const normalizedEvents: {
140
+ type: 'Permission' | 'Navigate';
141
+ permission?: string;
142
+ next_page_key?: string;
143
+ }[] = [];
144
+ for (const action of actions) {
145
+ //@eslint-disable-next-line @typescript-eslint/no-explicit-any
146
+ const events = (action?.attributes?.events || []) as any[];
147
+ for (const e of events) {
148
+ if (e?.layout === 'Permission') {
149
+ const permission = e?.attributes?.permission as
150
+ | string
151
+ | undefined;
152
+ normalizedEvents.push({ type: 'Permission', permission });
153
+ } else if (e?.layout === 'Navigate') {
154
+ const nextKey = e?.attributes?.next_page_key as
155
+ | string
156
+ | undefined;
157
+ normalizedEvents.push({
158
+ type: 'Navigate',
159
+ next_page_key: nextKey,
160
+ });
161
+ if (typeof nextKey === 'string' && pageKeyToIndex.has(nextKey)) {
162
+ targetIndex = pageKeyToIndex.get(nextKey)!;
163
+ }
164
+ }
165
+ }
166
+ }
167
+
168
+ buttonNodes.push({
169
+ type: 'OnboardButton',
170
+ attributes: {
171
+ labelKey,
172
+ ...(typeof buttonTextColor === 'string'
173
+ ? { button_text_color: buttonTextColor }
174
+ : {}),
175
+ ...(typeof buttonBackgroundColor === 'string'
176
+ ? { button_background_color: buttonBackgroundColor }
177
+ : {}),
178
+ ...(typeof flex === 'number' ? { flex } : {}),
179
+ ...(typeof targetIndex === 'number' ? { targetIndex } : {}),
180
+ ...(normalizedEvents.length ? { events: normalizedEvents } : {}),
181
+ },
182
+ children: undefined as unknown as Node,
183
+ } as unknown as NodeData);
184
+ }
185
+
186
+ if (buttonNodes.length > 0) {
187
+ // Place buttons inside the page (OnboardItem) instead of provider level
188
+ children.push({
189
+ type: 'OnboardButtons',
190
+ attributes: {
191
+ ...(direction ? { buttons_direction: direction } : {}),
192
+ },
193
+ children: buttonNodes as unknown as Node,
194
+ } as unknown as NodeData);
195
+ }
196
+ }
197
+ }
198
+
199
+ const pageKeyAttr = page?.attributes?.key;
200
+ const resolvedKey =
201
+ (typeof pageKeyAttr === 'string' && pageKeyAttr) ||
202
+ (typeof page?.key === 'string' ? page.key : undefined);
203
+
204
+ return {
205
+ type: 'OnboardItem',
206
+ ...(resolvedKey ? { key: resolvedKey } : {}),
207
+ children,
208
+ };
209
+ }
210
+
211
+ function mapDotsFromGeneralComponents(generalComponents: any[]): Node | null {
212
+ const dots = generalComponents.find((gc) => gc?.layout === 'dots-layout');
213
+ if (!dots) return null;
214
+ const dotArray = dots?.attributes?.dot || [];
215
+ const dotType = dotArray?.[0]?.layout as
216
+ | 'expanding_dot'
217
+ | 'normal_dot'
218
+ | 'scaling_dot'
219
+ | 'sliding_border'
220
+ | 'sliding_dot'
221
+ | 'liquid_like';
222
+ return {
223
+ type: 'OnboardExpandingDot',
224
+ attributes: dotType ? { dotType } : undefined,
225
+ children: undefined as unknown as Node,
226
+ } as unknown as NodeData;
227
+ }
228
+
229
+ function mapFooterFromGeneralComponents(generalComponents: any[]): Node | null {
230
+ const footer = generalComponents.find((gc) => gc?.layout === 'footer-layout');
231
+ if (!footer) return null;
232
+ const texts = (footer?.attributes?.texts || []) as any[];
233
+ const children: Node[] = [];
234
+
235
+ for (const t of texts) {
236
+ if (t?.layout === 'Text') {
237
+ const textKey = t?.attributes?.text_localization_key || '';
238
+ const color = t?.attributes?.text_color || undefined;
239
+ children.push({
240
+ type: 'text',
241
+ attributes: color ? { color } : undefined,
242
+ children: textKey,
243
+ });
244
+ }
245
+ }
246
+
247
+ if (children.length === 0) return null;
248
+
249
+ return {
250
+ type: 'view',
251
+ attributes: { gap: 8 },
252
+ children,
253
+ } as NodeData;
254
+ }
@@ -0,0 +1,63 @@
1
+ import imagePattern from '../build-components/Image/pattern.json';
2
+ import textPattern from '../build-components/Text/pattern.json';
3
+ import buttonPattern from '../build-components/Button/pattern.json';
4
+ import viewPattern from '../build-components/View/pattern.json';
5
+ import carouselPattern from '../build-components/Carousel/pattern.json';
6
+ import carouselButtonsPattern from '../build-components/CarouselButtons/pattern.json';
7
+ import carouselDotsPattern from '../build-components/CarouselDots/pattern.json';
8
+ import carouselItemPattern from '../build-components/CarouselItem/pattern.json';
9
+ import carouselProviderPattern from '../build-components/CarouselProvider/pattern.json';
10
+ import onboardPattern from '../build-components/Onboard/pattern.json';
11
+ import onboardProviderPattern from '../build-components/OnboardProvider/pattern.json';
12
+ import onboardItemPattern from '../build-components/OnboardItem/pattern.json';
13
+ import onboardImagePattern from '../build-components/OnboardImage/pattern.json';
14
+ import onboardButtonsPattern from '../build-components/OnboardButtons/pattern.json';
15
+ import onboardButtonPattern from '../build-components/OnboardButton/pattern.json';
16
+ import onboardBoardTitlePattern from '../build-components/OnboardBoardTitle/pattern.json';
17
+ import onboardSubtitlePattern from '../build-components/OnboardSubtitle/pattern.json';
18
+ import onboardFooterPattern from '../build-components/OnboardFooter/pattern.json';
19
+ import onboardExpandingDotPattern from '../build-components/OnboardExpandingDot/pattern.json';
20
+
21
+ type Pattern = {
22
+ schemaVersion: number;
23
+ allowUnknownAttributes: boolean;
24
+ pattern: {
25
+ type: string;
26
+ children: unknown;
27
+ attributes: Record<string, string | string[]>;
28
+ };
29
+ };
30
+
31
+ const patterns: Pattern[] = [
32
+ imagePattern as Pattern,
33
+ textPattern as Pattern,
34
+ buttonPattern as Pattern,
35
+ viewPattern as Pattern,
36
+ carouselPattern as Pattern,
37
+ carouselButtonsPattern as Pattern,
38
+ carouselDotsPattern as Pattern,
39
+ carouselItemPattern as Pattern,
40
+ carouselProviderPattern as Pattern,
41
+ onboardPattern as Pattern,
42
+ onboardProviderPattern as Pattern,
43
+ onboardItemPattern as Pattern,
44
+ onboardImagePattern as Pattern,
45
+ onboardButtonsPattern as Pattern,
46
+ onboardButtonPattern as Pattern,
47
+ onboardBoardTitlePattern as Pattern,
48
+ onboardSubtitlePattern as Pattern,
49
+ onboardFooterPattern as Pattern,
50
+ onboardExpandingDotPattern as Pattern,
51
+ ];
52
+
53
+ export function getPatternByType(type?: string | null) {
54
+ if (!type) return undefined;
55
+ return patterns.find((p) => p.pattern.type === type);
56
+ }
57
+
58
+ export function getAttributeSchema(
59
+ type?: string | null,
60
+ ): Record<string, string | string[]> | undefined {
61
+ const p = getPatternByType(type);
62
+ return p?.pattern.attributes;
63
+ }