@developer_tribe/react-builder 1.0.1 → 1.0.3

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 (218) hide show
  1. package/dist/AttributesEditor.d.ts +3 -1
  2. package/dist/DeviceMockFrame.d.ts +2 -1
  3. package/dist/RenderPage.d.ts +5 -3
  4. package/dist/attributes-editor/Field.d.ts +17 -0
  5. package/dist/attributes-editor/FieldInfoTooltip.d.ts +7 -0
  6. package/dist/attributes-editor/LayoutPreviewPicker.d.ts +12 -0
  7. package/dist/attributes-editor/SpecialCategorySection.d.ts +20 -0
  8. package/dist/attributes-editor/types.d.ts +14 -0
  9. package/dist/background.jpg +0 -0
  10. package/dist/build-components/BackgroundImage/BackgroundImage.d.ts +5 -0
  11. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +44 -0
  12. package/dist/build-components/Button/Button.d.ts +1 -1
  13. package/dist/build-components/Button/ButtonProps.generated.d.ts +33 -1
  14. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +34 -1
  15. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +32 -0
  16. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +32 -0
  17. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +34 -1
  18. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +34 -1
  19. package/dist/build-components/Image/ImageProps.generated.d.ts +32 -3
  20. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +34 -1
  21. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +32 -0
  22. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +32 -0
  23. package/dist/build-components/OnboardDot/OnboardDot.d.ts +1 -1
  24. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +29 -0
  25. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +11 -5
  26. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +32 -3
  27. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +31 -3
  28. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +32 -5
  29. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +11 -5
  30. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +11 -5
  31. package/dist/build-components/Text/TextProps.generated.d.ts +11 -5
  32. package/dist/build-components/View/ViewProps.generated.d.ts +10 -4
  33. package/dist/build-components/index.d.ts +2 -1
  34. package/dist/build-components/patterns.generated.d.ts +6288 -136
  35. package/dist/components/AttributesEditorPanel.d.ts +3 -4
  36. package/dist/components/Breadcrumb.d.ts +3 -1
  37. package/dist/components/Builder.d.ts +2 -1
  38. package/dist/components/BuilderButton.d.ts +9 -0
  39. package/dist/components/Checkbox.d.ts +17 -0
  40. package/dist/components/DeviceButton.d.ts +8 -0
  41. package/dist/components/DeviceNavigationBar.d.ts +10 -0
  42. package/dist/components/DeviceStatusBar.d.ts +9 -0
  43. package/dist/components/EditorHeader.d.ts +3 -8
  44. package/dist/index.cjs.js +5 -5
  45. package/dist/index.cjs.js.map +1 -1
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.esm.js +5 -5
  48. package/dist/index.esm.js.map +1 -1
  49. package/dist/mockOS/components/MockLaunchScreenComponent.d.ts +6 -0
  50. package/dist/mockOS/components/MockOSRouter.d.ts +8 -0
  51. package/dist/mockOS/components/PermissionModal.d.ts +9 -0
  52. package/dist/mockOS/context/MockOSContext.d.ts +36 -0
  53. package/dist/mockOS/hooks/useMockNavigation.d.ts +3 -0
  54. package/dist/mockOS/hooks/useMockPermission.d.ts +3 -0
  55. package/dist/mockOS/index.d.ts +9 -0
  56. package/dist/mockOS/managers/mockPermissionManager.d.ts +10 -0
  57. package/dist/mockOS/managers/navigationManager.d.ts +17 -0
  58. package/dist/modals/AddComponentModal.d.ts +8 -0
  59. package/dist/modals/ColorModal.d.ts +11 -0
  60. package/dist/modals/DeviceSelectorModal.d.ts +9 -0
  61. package/dist/modals/LocalicationModal.d.ts +8 -0
  62. package/dist/modals/Modal.d.ts +12 -0
  63. package/dist/modals/index.d.ts +5 -0
  64. package/dist/pages/ProjectPage.d.ts +3 -3
  65. package/dist/pages/tabs/BuilderPanel.d.ts +8 -0
  66. package/dist/pages/tabs/{DebugTab.d.ts → SideTool.d.ts} +2 -2
  67. package/dist/store.d.ts +7 -3
  68. package/dist/styles.css +1 -1
  69. package/dist/types/Project.d.ts +11 -0
  70. package/dist/utils/analyseNode.d.ts +1 -0
  71. package/dist/utils/extractTextStyle.d.ts +8 -1
  72. package/dist/utils/extractViewStyle.d.ts +8 -1
  73. package/dist/utils/parseColor.d.ts +7 -0
  74. package/dist/utils/patterns.d.ts +24 -0
  75. package/package.json +2 -1
  76. package/scripts/prebuild/utils/createGeneratedProps.js +11 -3
  77. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +45 -6
  78. package/scripts/prebuild/utils/validatePatternJson.js +13 -5
  79. package/src/AttributesEditor.tsx +493 -310
  80. package/src/DeviceMockFrame.tsx +21 -37
  81. package/src/RenderPage.tsx +86 -7
  82. package/src/assets/images/android.svg +42 -42
  83. package/src/assets/images/apple.svg +15 -15
  84. package/src/attributes-editor/Field.tsx +669 -0
  85. package/src/attributes-editor/FieldInfoTooltip.tsx +49 -0
  86. package/src/attributes-editor/LayoutPreviewPicker.tsx +199 -0
  87. package/src/attributes-editor/SpecialCategorySection.tsx +285 -0
  88. package/src/attributes-editor/types.ts +30 -0
  89. package/src/build-components/BackgroundImage/BackgroundImage.tsx +87 -0
  90. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +60 -0
  91. package/src/build-components/BackgroundImage/pattern.json +45 -0
  92. package/src/build-components/Button/Button.tsx +37 -2
  93. package/src/build-components/Button/ButtonProps.generated.ts +44 -1
  94. package/src/build-components/Button/pattern.json +31 -2
  95. package/src/build-components/Carousel/Carousel.tsx +39 -2
  96. package/src/build-components/Carousel/CarouselProps.generated.ts +46 -1
  97. package/src/build-components/Carousel/pattern.json +10 -0
  98. package/src/build-components/CarouselButtons/CarouselButtons.tsx +21 -2
  99. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +43 -0
  100. package/src/build-components/CarouselButtons/pattern.json +22 -0
  101. package/src/build-components/CarouselDots/CarouselDots.tsx +49 -8
  102. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +43 -0
  103. package/src/build-components/CarouselDots/pattern.json +15 -0
  104. package/src/build-components/CarouselItem/CarouselItem.tsx +21 -2
  105. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +46 -1
  106. package/src/build-components/CarouselItem/pattern.json +7 -0
  107. package/src/build-components/CarouselProvider/CarouselProvider.tsx +21 -2
  108. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +46 -1
  109. package/src/build-components/CarouselProvider/pattern.json +7 -0
  110. package/src/build-components/Image/Image.tsx +33 -2
  111. package/src/build-components/Image/ImageProps.generated.ts +43 -3
  112. package/src/build-components/Image/pattern.json +46 -3
  113. package/src/build-components/Onboard/Onboard.tsx +6 -1
  114. package/src/build-components/Onboard/OnboardProps.generated.ts +46 -1
  115. package/src/build-components/Onboard/pattern.json +11 -0
  116. package/src/build-components/OnboardButton/OnboardButton.tsx +54 -6
  117. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +43 -0
  118. package/src/build-components/OnboardButton/pattern.json +71 -5
  119. package/src/build-components/OnboardButtons/OnboardButtons.tsx +33 -11
  120. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +43 -0
  121. package/src/build-components/OnboardButtons/pattern.json +70 -4
  122. package/src/build-components/OnboardDot/OnboardDot.tsx +113 -4
  123. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +29 -0
  124. package/src/build-components/OnboardDot/pattern.json +55 -2
  125. package/src/build-components/OnboardFooter/OnboardFooter.tsx +20 -4
  126. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +11 -5
  127. package/src/build-components/OnboardFooter/pattern.json +58 -2
  128. package/src/build-components/OnboardImage/OnboardImage.tsx +49 -5
  129. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +43 -3
  130. package/src/build-components/OnboardImage/pattern.json +21 -0
  131. package/src/build-components/OnboardItem/OnboardItem.tsx +17 -1
  132. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +42 -3
  133. package/src/build-components/OnboardItem/pattern.json +38 -2
  134. package/src/build-components/OnboardProvider/OnboardProvider.tsx +52 -18
  135. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +44 -5
  136. package/src/build-components/OnboardProvider/pattern.json +44 -5
  137. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +11 -5
  138. package/src/build-components/OnboardSubtitle/pattern.json +7 -1
  139. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +11 -5
  140. package/src/build-components/OnboardTitle/pattern.json +7 -1
  141. package/src/build-components/RenderNode.generated.tsx +3 -0
  142. package/src/build-components/Text/Text.tsx +34 -6
  143. package/src/build-components/Text/TextProps.generated.ts +11 -5
  144. package/src/build-components/Text/pattern.json +38 -2
  145. package/src/build-components/View/View.tsx +33 -6
  146. package/src/build-components/View/ViewProps.generated.ts +10 -4
  147. package/src/build-components/View/pattern.json +285 -19
  148. package/src/build-components/index.ts +5 -0
  149. package/src/build-components/patterns.generated.ts +6346 -143
  150. package/src/components/AttributesEditorPanel.tsx +17 -64
  151. package/src/components/Breadcrumb.tsx +37 -5
  152. package/src/components/Builder.tsx +311 -108
  153. package/src/components/BuilderButton.tsx +127 -0
  154. package/src/components/Checkbox.tsx +81 -0
  155. package/src/components/DeviceButton.tsx +39 -0
  156. package/src/components/DeviceNavigationBar.tsx +201 -0
  157. package/src/components/DeviceStatusBar.tsx +85 -0
  158. package/src/components/EditorHeader.tsx +26 -74
  159. package/src/index.ts +2 -2
  160. package/src/mockOS/components/MockLaunchScreenComponent.tsx +43 -0
  161. package/src/mockOS/components/MockOSRouter.tsx +123 -0
  162. package/src/mockOS/components/PermissionModal.tsx +270 -0
  163. package/src/mockOS/context/MockOSContext.tsx +179 -0
  164. package/src/mockOS/hooks/useMockNavigation.ts +11 -0
  165. package/src/mockOS/hooks/useMockPermission.ts +11 -0
  166. package/src/mockOS/index.ts +26 -0
  167. package/src/mockOS/managers/mockPermissionManager.ts +54 -0
  168. package/src/mockOS/managers/navigationManager.ts +91 -0
  169. package/src/modals/AddComponentModal.tsx +313 -0
  170. package/src/modals/ColorModal.tsx +425 -0
  171. package/src/modals/DeviceSelectorModal.tsx +57 -0
  172. package/src/modals/LocalicationModal.tsx +54 -0
  173. package/src/modals/Modal.tsx +57 -0
  174. package/src/modals/index.ts +5 -0
  175. package/src/pages/ProjectPage.tsx +307 -71
  176. package/src/pages/tabs/{BuilderTab.tsx → BuilderPanel.tsx} +13 -9
  177. package/src/pages/tabs/SideTool.tsx +259 -0
  178. package/src/size-matters/index.ts +27 -5
  179. package/src/store.ts +13 -5
  180. package/src/styles/base/_global.scss +404 -0
  181. package/src/styles/components/_attributes-editor.scss +273 -0
  182. package/src/styles/components/_editor-shell.scss +212 -0
  183. package/src/styles/components/_mockos-router.scss +140 -0
  184. package/src/styles/components/_ui-components.scss +183 -0
  185. package/src/styles/foundation/_colors.scss +8 -0
  186. package/src/styles/{_mixins.scss → foundation/_mixins.scss} +5 -4
  187. package/src/styles/{_reset.scss → foundation/_reset.scss} +5 -2
  188. package/src/styles/foundation/_sizes.scss +37 -0
  189. package/src/styles/foundation/_typography.scss +4 -0
  190. package/src/styles/foundation/_variables.scss +3 -0
  191. package/src/styles/index.scss +22 -136
  192. package/src/styles/layout/_builder.scss +124 -0
  193. package/src/styles/layout/_pages.scss +3 -0
  194. package/src/styles/modals/_add-component.scss +122 -0
  195. package/src/styles/modals/_color-modal.scss +159 -0
  196. package/src/styles/modals/_device-selector.scss +18 -0
  197. package/src/styles/modals/_localication-modal.scss +68 -0
  198. package/src/styles/modals/_modal-shell.scss +46 -0
  199. package/src/styles/utilities/_carousel.scss +125 -0
  200. package/src/types/Project.ts +14 -0
  201. package/src/types/images.d.ts +8 -0
  202. package/src/utils/analyseNode.ts +98 -0
  203. package/src/utils/extractTextStyle.ts +28 -10
  204. package/src/utils/extractViewStyle.ts +77 -9
  205. package/src/utils/parseColor.ts +43 -0
  206. package/src/utils/patterns.ts +33 -0
  207. package/dist/build-components/OnboardDot/OnboardExpandingDotProps.generated.d.ts +0 -10
  208. package/dist/pages/tabs/BuilderTab.d.ts +0 -9
  209. package/dist/pages/tabs/PreviewTab.d.ts +0 -3
  210. package/src/build-components/OnboardDot/OnboardExpandingDotProps.generated.ts +0 -20
  211. package/src/pages/tabs/DebugTab.tsx +0 -23
  212. package/src/pages/tabs/PreviewTab.tsx +0 -194
  213. package/src/styles/_variables.scss +0 -27
  214. package/src/styles/builder.scss +0 -60
  215. package/src/styles/components.scss +0 -88
  216. package/src/styles/editor.scss +0 -174
  217. package/src/styles/global.scss +0 -200
  218. package/src/styles/pages.scss +0 -2
@@ -0,0 +1,125 @@
1
+ /* Embla carousel utilities stay isolated from builder core styles. */
2
+ .embla {
3
+ max-width: 48rem;
4
+ margin: auto;
5
+ --slide-height: 19rem;
6
+ --slide-spacing: 1rem;
7
+ --slide-size: 70%;
8
+ }
9
+ .embla__viewport {
10
+ overflow: hidden;
11
+ }
12
+ .embla__container {
13
+ display: flex;
14
+ touch-action: pan-y pinch-zoom;
15
+ margin-left: calc(var(--slide-spacing) * -1);
16
+ }
17
+ .embla__slide {
18
+ transform: translate3d(0, 0, 0);
19
+ min-width: 0;
20
+ padding-left: var(--slide-spacing);
21
+ flex: 0 0 100%;
22
+ }
23
+ .embla__slide__number {
24
+ box-shadow: inset 0 0 0 0.2rem var(--detail-medium-contrast);
25
+ border-radius: 1.8rem;
26
+ font-size: 4rem;
27
+ font-weight: 600;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ height: var(--slide-height);
32
+ user-select: none;
33
+ }
34
+ .embla__controls {
35
+ display: grid;
36
+ grid-template-columns: auto 1fr;
37
+ justify-content: space-between;
38
+ gap: 1.2rem;
39
+ margin-top: 1.8rem;
40
+ }
41
+ .embla__buttons {
42
+ display: grid;
43
+ grid-template-columns: repeat(2, 1fr);
44
+ gap: 0.6rem;
45
+ align-items: center;
46
+ }
47
+ .embla__button {
48
+ -webkit-tap-highlight-color: rgba(var(--text-high-contrast-rgb-value), 0.5);
49
+ -webkit-appearance: none;
50
+ appearance: none;
51
+ background-color: transparent;
52
+ touch-action: manipulation;
53
+ display: inline-flex;
54
+ text-decoration: none;
55
+ cursor: pointer;
56
+ border: 0;
57
+ padding: 0;
58
+ margin: 0;
59
+ box-shadow: inset 0 0 0 0.2rem var(--detail-medium-contrast);
60
+ width: 3.6rem;
61
+ height: 3.6rem;
62
+ z-index: 1;
63
+ border-radius: 50%;
64
+ color: var(--text-body);
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ }
69
+ .embla__button:disabled {
70
+ color: var(--detail-high-contrast);
71
+ }
72
+ .embla__button__svg {
73
+ width: 35%;
74
+ height: 35%;
75
+ }
76
+ .embla__dots {
77
+ flex-wrap: wrap;
78
+ margin-right: 0;
79
+ height: 50px;
80
+ margin: 0 auto;
81
+ }
82
+ .embla__dot {
83
+ -webkit-tap-highlight-color: rgba(var(--text-high-contrast-rgb-value), 0.5);
84
+ -webkit-appearance: none;
85
+ appearance: none;
86
+ background-color: transparent;
87
+ touch-action: manipulation;
88
+ display: inline-flex;
89
+ text-decoration: none;
90
+ cursor: pointer;
91
+ border: 0;
92
+ padding: 0;
93
+ margin: 0;
94
+ width: 2.6rem;
95
+ height: 2.6rem;
96
+ display: flex;
97
+ align-items: center;
98
+ border-radius: 50%;
99
+ }
100
+ .embla__dot:after {
101
+ box-shadow: inset 0 0 0 0.2rem var(--detail-medium-contrast);
102
+ width: 1.4rem;
103
+ height: 1.4rem;
104
+ border-radius: 50%;
105
+ display: flex;
106
+ align-items: center;
107
+ content: '';
108
+ }
109
+ .embla__dot--selected:after {
110
+ box-shadow: inset 0 0 0 0.2rem var(--text-body);
111
+ }
112
+ .carousel-provider {
113
+ height: 100%;
114
+ }
115
+ .embla {
116
+ height: 100%;
117
+ }
118
+ .embla__viewport {
119
+ height: 100%;
120
+ display: flex;
121
+ flex-direction: column;
122
+ }
123
+ .embla__container {
124
+ flex: 1;
125
+ }
@@ -1,11 +1,25 @@
1
1
  import { Node } from '../types/Node';
2
2
  import { AppConfig } from './PreviewConfig';
3
3
 
4
+ export type ProjectColorTokenMap = Record<string, string>;
5
+
6
+ export type ProjectThemeColors = {
7
+ light?: ProjectColorTokenMap;
8
+ dark?: ProjectColorTokenMap;
9
+ [themeName: string]: ProjectColorTokenMap | undefined;
10
+ };
11
+
12
+ export interface ProjectColors {
13
+ STATIC_COLORS?: ProjectColorTokenMap;
14
+ THEME_COLORS?: ProjectThemeColors;
15
+ }
16
+
4
17
  export interface ProjectBase<T> {
5
18
  name: string;
6
19
  version: string;
7
20
  data: T;
8
21
  appConfig?: AppConfig;
22
+ projectColors?: ProjectColors;
9
23
  }
10
24
 
11
25
  export interface Project extends ProjectBase<Node> {}
@@ -0,0 +1,8 @@
1
+ declare module '*.svg' {
2
+ const content: string;
3
+ export default content;
4
+ }
5
+ declare module '*.jpg' {
6
+ const content: string;
7
+ export default content;
8
+ }
@@ -1,4 +1,5 @@
1
1
  import { Node, NodeData, NodeDefaultAttribute } from '../types/Node';
2
+ import { generateRandomKeyForNode } from './generateRandomKeyForNode';
2
3
 
3
4
  export function isNodeNullOrUndefined<T = NodeDefaultAttribute>(
4
5
  node: Node<T>,
@@ -17,6 +18,82 @@ export function isEmptyObject<T = NodeDefaultAttribute>(
17
18
  return Object.keys(node as Object).length === 0;
18
19
  }
19
20
 
21
+ function collectDuplicateKey(
22
+ node: Node<NodeDefaultAttribute>,
23
+ usedKeys: Set<string>,
24
+ ): string | null {
25
+ if (isNodeNullOrUndefined(node) || isNodeString(node)) {
26
+ return null;
27
+ }
28
+
29
+ if (isNodeArray(node)) {
30
+ const nodeArray = node as unknown as Node<NodeDefaultAttribute>[];
31
+ for (const value of nodeArray) {
32
+ const duplicate = collectDuplicateKey(value, usedKeys);
33
+ if (duplicate) {
34
+ return duplicate;
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+
40
+ const recordData = node as NodeData<NodeDefaultAttribute>;
41
+ if (recordData.key) {
42
+ if (usedKeys.has(recordData.key)) {
43
+ return recordData.key;
44
+ }
45
+ usedKeys.add(recordData.key);
46
+ }
47
+
48
+ if (recordData.children) {
49
+ return collectDuplicateKey(
50
+ recordData.children as Node<NodeDefaultAttribute>,
51
+ usedKeys,
52
+ );
53
+ }
54
+
55
+ return null;
56
+ }
57
+
58
+ function assignMissingKeys(
59
+ node: Node<NodeDefaultAttribute>,
60
+ usedKeys: Set<string>,
61
+ ): Node<NodeDefaultAttribute> {
62
+ if (isNodeNullOrUndefined(node) || isNodeString(node)) {
63
+ return node;
64
+ }
65
+
66
+ if (isNodeArray(node)) {
67
+ const nodeArray = node as unknown as Node<NodeDefaultAttribute>[];
68
+ return nodeArray.map((child) =>
69
+ assignMissingKeys(child, usedKeys),
70
+ ) as unknown as Node<NodeDefaultAttribute>;
71
+ }
72
+
73
+ const recordData = node as NodeData<NodeDefaultAttribute>;
74
+
75
+ let key = recordData.key;
76
+ if (!key) {
77
+ do {
78
+ key = generateRandomKeyForNode(recordData.type);
79
+ } while (usedKeys.has(key));
80
+ usedKeys.add(key);
81
+ }
82
+
83
+ const children = recordData.children
84
+ ? (assignMissingKeys(
85
+ recordData.children as Node<NodeDefaultAttribute>,
86
+ usedKeys,
87
+ ) as Node<NodeDefaultAttribute>)
88
+ : recordData.children;
89
+
90
+ return {
91
+ ...recordData,
92
+ key,
93
+ children,
94
+ };
95
+ }
96
+
20
97
  export function analyseNode(node: Node<NodeDefaultAttribute>): {
21
98
  valid: boolean;
22
99
  message?: string;
@@ -75,3 +152,24 @@ export function analyseNode(node: Node<NodeDefaultAttribute>): {
75
152
  };
76
153
  }
77
154
  }
155
+
156
+ export function analyseAndProccess(
157
+ node: Node<NodeDefaultAttribute>,
158
+ ): Node<NodeDefaultAttribute> | null {
159
+ if (isNodeNullOrUndefined(node)) {
160
+ return null;
161
+ }
162
+
163
+ const { valid, message } = analyseNode(node);
164
+ if (!valid) {
165
+ throw new Error(message ?? 'Node is not valid');
166
+ }
167
+
168
+ const usedKeys = new Set<string>();
169
+ const duplicateKey = collectDuplicateKey(node, usedKeys);
170
+ if (duplicateKey) {
171
+ throw new Error(`Duplicate node key detected: ${duplicateKey}`);
172
+ }
173
+
174
+ return assignMissingKeys(node, usedKeys);
175
+ }
@@ -1,16 +1,23 @@
1
1
  import type { NodeData } from '../types/Node';
2
2
  import type { TextPropsGenerated } from '../build-components/Text/TextProps.generated';
3
+ import type { AppConfig } from '../types/PreviewConfig';
4
+ import { defaultAppConfig } from '../types/PreviewConfig';
5
+ import type { ProjectColors } from '../types/Project';
3
6
  import { fs, parseSize } from '../size-matters';
4
- import { useRenderStore } from '../store';
7
+ import { parseColor } from './parseColor';
8
+
9
+ type ExtractTextStyleOptions = {
10
+ appConfig?: AppConfig;
11
+ projectColors?: ProjectColors;
12
+ };
5
13
 
6
14
  export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
7
15
  node: NodeData<T>,
16
+ options: ExtractTextStyleOptions = {},
8
17
  ) {
9
18
  const attributes = node.attributes;
10
- //TODO: it should be passed as a prop to the function (need a state)
11
- const {
12
- appConfig: { screenStyle, theme },
13
- } = useRenderStore.getState();
19
+ const resolvedAppConfig = options.appConfig ?? defaultAppConfig;
20
+ const { screenStyle, theme } = resolvedAppConfig;
14
21
  const fallbackColor =
15
22
  theme === 'light' ? screenStyle.light.color : screenStyle.dark.color;
16
23
 
@@ -30,7 +37,11 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
30
37
  style.fontSize = fs(14);
31
38
  }
32
39
  if (attributes.fontWeight) style.fontWeight = attributes.fontWeight;
33
- style.color = attributes.color ?? fallbackColor;
40
+ const resolvedTextColor = parseColor(attributes.color, {
41
+ projectColors: options.projectColors,
42
+ appConfig: resolvedAppConfig,
43
+ });
44
+ style.color = resolvedTextColor ?? fallbackColor;
34
45
  if (attributes.textAlign)
35
46
  style.textAlign = attributes.textAlign as React.CSSProperties['textAlign'];
36
47
 
@@ -50,8 +61,10 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
50
61
  style.paddingTop = v as React.CSSProperties['paddingTop'];
51
62
  style.paddingBottom = v as React.CSSProperties['paddingBottom'];
52
63
  }
53
- if (attributes.marginHorizontal !== undefined) {
54
- const v = parseSize(attributes.marginHorizontal);
64
+ const marginHorizontalRaw = (attributes as Record<string, unknown>)
65
+ .marginHorizontal as string | number | undefined;
66
+ if (marginHorizontalRaw !== undefined) {
67
+ const v = parseSize(marginHorizontalRaw);
55
68
  style.marginLeft = v as React.CSSProperties['marginLeft'];
56
69
  style.marginRight = v as React.CSSProperties['marginRight'];
57
70
  }
@@ -97,8 +110,13 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
97
110
  ) as React.CSSProperties['marginRight'];
98
111
 
99
112
  // Decor
100
- if (attributes.backgroundColor)
101
- style.backgroundColor = attributes.backgroundColor;
113
+ if (attributes.backgroundColor) {
114
+ style.backgroundColor =
115
+ parseColor(attributes.backgroundColor, {
116
+ projectColors: options.projectColors,
117
+ appConfig: resolvedAppConfig,
118
+ }) ?? attributes.backgroundColor;
119
+ }
102
120
  if (attributes.borderRadius !== undefined)
103
121
  style.borderRadius =
104
122
  attributes.borderRadius as React.CSSProperties['borderRadius'];
@@ -1,8 +1,18 @@
1
1
  import { ViewPropsGenerated } from '../build-components/View/ViewProps.generated';
2
2
  import type { NodeData } from '../types/Node';
3
+ import type { AppConfig } from '../types/PreviewConfig';
4
+ import type { ProjectColors } from '../types/Project';
5
+ import { parseSize } from '../size-matters';
6
+ import { parseColor } from './parseColor';
7
+
8
+ type ExtractViewStyleOptions = {
9
+ appConfig?: AppConfig;
10
+ projectColors?: ProjectColors;
11
+ };
3
12
 
4
13
  export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
5
14
  node: NodeData<T>,
15
+ options: ExtractViewStyleOptions = {},
6
16
  ) {
7
17
  const attributes = node.attributes;
8
18
  const scrollable = attributes?.scrollable ?? false;
@@ -31,14 +41,72 @@ export function extractViewStyle<T extends ViewPropsGenerated['attributes']>(
31
41
  if (attributes.justifyContent)
32
42
  style.justifyContent =
33
43
  attributes.justifyContent as React.CSSProperties['justifyContent'];
34
- if (attributes.gap !== undefined) style.gap = attributes.gap;
35
- if (attributes.padding !== undefined) style.padding = attributes.padding;
36
- if (attributes.margin !== undefined) style.margin = attributes.margin;
37
- if (attributes.backgroundColor)
38
- style.backgroundColor = attributes.backgroundColor;
39
- if (attributes.borderRadius !== undefined)
40
- style.borderRadius = attributes.borderRadius;
41
- if (attributes.width !== undefined) style.width = attributes.width;
42
- if (attributes.height !== undefined) style.height = attributes.height;
44
+ const setParsedSize = <K extends keyof React.CSSProperties>(
45
+ property: K,
46
+ rawValue: string | number | undefined,
47
+ ) => {
48
+ if (rawValue === undefined) return;
49
+ const parsed = parseSize(rawValue);
50
+ style[property] = parsed as React.CSSProperties[K];
51
+ };
52
+
53
+ setParsedSize('gap', attributes.gap);
54
+ setParsedSize('padding', attributes.padding);
55
+ setParsedSize('margin', attributes.margin);
56
+
57
+ if (attributes.paddingHorizontal !== undefined) {
58
+ const parsed = parseSize(attributes.paddingHorizontal);
59
+ style.paddingLeft = parsed as React.CSSProperties['paddingLeft'];
60
+ style.paddingRight = parsed as React.CSSProperties['paddingRight'];
61
+ }
62
+ if (attributes.paddingVertical !== undefined) {
63
+ const parsed = parseSize(attributes.paddingVertical);
64
+ style.paddingTop = parsed as React.CSSProperties['paddingTop'];
65
+ style.paddingBottom = parsed as React.CSSProperties['paddingBottom'];
66
+ }
67
+
68
+ const marginHorizontalRaw = (attributes as Record<string, unknown>)
69
+ .marginHorizontal as string | number | undefined;
70
+ if (marginHorizontalRaw !== undefined) {
71
+ const parsed = parseSize(marginHorizontalRaw);
72
+ style.marginLeft = parsed as React.CSSProperties['marginLeft'];
73
+ style.marginRight = parsed as React.CSSProperties['marginRight'];
74
+ }
75
+
76
+ if (attributes.marginVertical !== undefined) {
77
+ const parsed = parseSize(attributes.marginVertical);
78
+ style.marginTop = parsed as React.CSSProperties['marginTop'];
79
+ style.marginBottom = parsed as React.CSSProperties['marginBottom'];
80
+ }
81
+
82
+ setParsedSize('paddingTop', attributes.paddingTop);
83
+ setParsedSize('paddingBottom', attributes.paddingBottom);
84
+ setParsedSize('paddingLeft', attributes.paddingLeft);
85
+ setParsedSize('paddingRight', attributes.paddingRight);
86
+ setParsedSize('marginTop', attributes.marginTop);
87
+ setParsedSize('marginBottom', attributes.marginBottom);
88
+ setParsedSize('marginLeft', attributes.marginLeft);
89
+ setParsedSize('marginRight', attributes.marginRight);
90
+ console.log('attributes.backgroundColor', attributes.backgroundColor);
91
+ console.log(
92
+ 'parseColor(attributes.backgroundColor)',
93
+ parseColor(attributes.backgroundColor),
94
+ );
95
+ if (attributes.backgroundColor) {
96
+ style.backgroundColor =
97
+ parseColor(attributes.backgroundColor, {
98
+ projectColors: options.projectColors,
99
+ appConfig: options.appConfig,
100
+ }) ?? attributes.backgroundColor;
101
+ }
102
+ setParsedSize('borderRadius', attributes.borderRadius);
103
+ setParsedSize('width', attributes.width);
104
+ setParsedSize('height', attributes.height);
105
+ if (attributes.position)
106
+ style.position = attributes.position as React.CSSProperties['position'];
107
+ setParsedSize('top', attributes.top);
108
+ setParsedSize('bottom', attributes.bottom);
109
+ setParsedSize('left', attributes.left);
110
+ setParsedSize('right', attributes.right);
43
111
  return style;
44
112
  }
@@ -0,0 +1,43 @@
1
+ import type { AppConfig } from '../types/PreviewConfig';
2
+ import type { ProjectColors } from '../types/Project';
3
+
4
+ const STATIC_PREFIX = 'STATIC_COLORS.';
5
+ const THEME_PREFIX = 'THEME_COLORS.';
6
+
7
+ export type ParseColorOptions = {
8
+ projectColors?: ProjectColors;
9
+ appConfig?: AppConfig;
10
+ };
11
+
12
+ export function parseColor(value?: string, options: ParseColorOptions = {}) {
13
+ if (typeof value !== 'string') return value;
14
+ const trimmed = value.trim();
15
+ if (!trimmed) return undefined;
16
+
17
+ const { projectColors, appConfig } = options;
18
+ if (!projectColors) return trimmed;
19
+
20
+ if (trimmed.startsWith(STATIC_PREFIX)) {
21
+ const token = trimmed.slice(STATIC_PREFIX.length);
22
+ const resolved = projectColors.STATIC_COLORS?.[token];
23
+ return typeof resolved === 'string' && resolved.trim()
24
+ ? resolved.trim()
25
+ : trimmed;
26
+ }
27
+
28
+ if (trimmed.startsWith(THEME_PREFIX)) {
29
+ const token = trimmed.slice(THEME_PREFIX.length);
30
+ if (!token) return trimmed;
31
+
32
+ const theme = appConfig?.theme ?? 'light';
33
+ const themeTokens = projectColors.THEME_COLORS?.[theme];
34
+ const resolved = themeTokens?.[token];
35
+ if (typeof resolved === 'string' && resolved.trim()) {
36
+ return resolved.trim();
37
+ }
38
+
39
+ return trimmed;
40
+ }
41
+
42
+ return trimmed;
43
+ }
@@ -1,6 +1,31 @@
1
1
  import { patterns as generatedPatterns } from '../build-components';
2
2
  import type { NodeDefaultAttribute } from '../types/Node';
3
3
 
4
+ export type AttributeMeta = {
5
+ label?: string;
6
+ description?: string;
7
+ category?: 'style' | 'container' | 'other' | string;
8
+ specialCategory?: 'padding' | 'margin' | 'offset' | null | string;
9
+ sort?: number;
10
+ preferedScale?: 's' | 'vs' | 'f' | '%' | '' | string;
11
+ };
12
+
13
+ export type SpecialCategoryMeta = {
14
+ label?: string;
15
+ description?: string;
16
+ category?: 'style' | 'container' | 'other' | string;
17
+ sort?: number;
18
+ };
19
+
20
+ type PatternMeta = {
21
+ label?: string;
22
+ description?: string;
23
+ attributes?: Record<string, AttributeMeta>;
24
+ specialCategories?: Record<string, SpecialCategoryMeta>;
25
+ desiredParent?: string[];
26
+ desiredChildren?: string[];
27
+ };
28
+
4
29
  type Pattern = {
5
30
  schemaVersion: number;
6
31
  allowUnknownAttributes: boolean;
@@ -17,6 +42,7 @@ type Pattern = {
17
42
  // where the inner record maps fieldName -> primitive type or enum options
18
43
  types?: Record<string, Record<string, string | string[]>>;
19
44
  // Optional defaults to be applied to node.attributes if not provided
45
+ meta?: PatternMeta;
20
46
  };
21
47
 
22
48
  const patterns: Pattern[] = generatedPatterns as unknown as Pattern[];
@@ -38,6 +64,13 @@ export function getAttributeSchema(
38
64
  return p?.pattern.attributes;
39
65
  }
40
66
 
67
+ export function getAttributeMeta(
68
+ type?: string | null,
69
+ ): Record<string, AttributeMeta> | undefined {
70
+ const p = getPatternByType(type);
71
+ return p?.meta?.attributes;
72
+ }
73
+
41
74
  /** Returns defaults block (if any) for a given component type */
42
75
  export function getDefaultsForType(
43
76
  type?: string | null,
@@ -1,10 +0,0 @@
1
- import type { NodeData } from '../../types/Node';
2
- export interface OnboardDotPropsGenerated {
3
- child: string;
4
- attributes: {
5
- dotType?: 'expanding_dot' | 'normal_dot' | 'scaling_dot' | 'sliding_border' | 'sliding_dot' | 'liquid_like';
6
- };
7
- }
8
- export interface OnboardDotComponentProps {
9
- node: NodeData<OnboardDotPropsGenerated['attributes']>;
10
- }
@@ -1,9 +0,0 @@
1
- import { Node } from '../..';
2
- type BuilderTabProps = {
3
- data: Node;
4
- setData: (data: Node) => void;
5
- current: Node;
6
- setCurrent: (current: Node) => void;
7
- };
8
- export declare function BuilderTab({ data, setData, current, setCurrent, }: BuilderTabProps): import("react/jsx-runtime").JSX.Element;
9
- export {};
@@ -1,3 +0,0 @@
1
- type PreviewTabProps = {};
2
- export declare function PreviewTab({}: PreviewTabProps): import("react/jsx-runtime").JSX.Element;
3
- export {};
@@ -1,20 +0,0 @@
1
- /* AUTO-GENERATED FILE - DO NOT EDIT */
2
-
3
- import type { NodeData } from '../../types/Node';
4
-
5
- export interface OnboardDotPropsGenerated {
6
- child: string;
7
- attributes: {
8
- dotType?:
9
- | 'expanding_dot'
10
- | 'normal_dot'
11
- | 'scaling_dot'
12
- | 'sliding_border'
13
- | 'sliding_dot'
14
- | 'liquid_like';
15
- };
16
- }
17
-
18
- export interface OnboardDotComponentProps {
19
- node: NodeData<OnboardDotPropsGenerated['attributes']>;
20
- }
@@ -1,23 +0,0 @@
1
- import { JsonEditor } from 'json-edit-react';
2
- import { Node } from '../..';
3
- import { useLogRender } from '../../utils/useLogRender';
4
-
5
- type DebugTabProps = {
6
- data: Node;
7
- setData: (data: Node) => void;
8
- };
9
-
10
- export function DebugTab({ data, setData }: DebugTabProps) {
11
- useLogRender('DebugTab');
12
- return (
13
- <div
14
- role="tabpanel"
15
- className="editor-panel editor-panel--active editor-panels-debug"
16
- aria-hidden={false}
17
- >
18
- <div style={{ flex: '1 1 auto', minHeight: 0, overflow: 'auto' }}>
19
- <JsonEditor data={data as any} setData={setData as any} />
20
- </div>
21
- </div>
22
- );
23
- }