@developer_tribe/react-builder 1.0.2 → 1.0.4

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 (147) hide show
  1. package/dist/AttributesEditor.d.ts +3 -1
  2. package/dist/RenderPage.d.ts +2 -1
  3. package/dist/android.svg +43 -0
  4. package/dist/apple.svg +16 -0
  5. package/dist/attributes-editor/Field.d.ts +4 -2
  6. package/dist/attributes-editor/SizeField.d.ts +9 -0
  7. package/dist/attributes-editor/SpecialCategorySection.d.ts +2 -1
  8. package/dist/build-components/BackgroundImage/BackgroundImage.d.ts +5 -0
  9. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +45 -0
  10. package/dist/build-components/Button/ButtonProps.generated.d.ts +8 -0
  11. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +8 -0
  12. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +8 -0
  13. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +8 -0
  14. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +8 -0
  15. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +8 -0
  16. package/dist/build-components/Image/ImageProps.generated.d.ts +8 -0
  17. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +8 -0
  18. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +8 -1
  19. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +8 -0
  20. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +9 -3
  21. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +8 -0
  22. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +9 -1
  23. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +8 -0
  24. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +8 -1
  25. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +8 -0
  26. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +8 -0
  27. package/dist/build-components/Text/TextProps.generated.d.ts +8 -0
  28. package/dist/build-components/View/ViewProps.generated.d.ts +8 -0
  29. package/dist/build-components/index.d.ts +2 -1
  30. package/dist/build-components/patterns.generated.d.ts +1612 -46
  31. package/dist/components/AttributesEditorPanel.d.ts +3 -4
  32. package/dist/components/Builder.d.ts +2 -1
  33. package/dist/components/BuilderButton.d.ts +9 -0
  34. package/dist/components/JsonTextEditor.d.ts +9 -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 -2
  38. package/dist/index.esm.js +5 -5
  39. package/dist/index.esm.js.map +1 -1
  40. package/dist/modals/ColorModal.d.ts +3 -1
  41. package/dist/pages/ProjectPage.d.ts +3 -3
  42. package/dist/pages/tabs/BuilderPanel.d.ts +8 -0
  43. package/dist/pages/tabs/SideTool.d.ts +8 -0
  44. package/dist/store.d.ts +9 -1
  45. package/dist/styles.css +1 -1
  46. package/dist/types/Project.d.ts +11 -0
  47. package/dist/utils/analyseNode.d.ts +1 -0
  48. package/dist/utils/extractImageStyle.d.ts +2 -1
  49. package/dist/utils/extractTextStyle.d.ts +8 -1
  50. package/dist/utils/extractViewStyle.d.ts +7 -1
  51. package/dist/utils/parseColor.d.ts +7 -0
  52. package/dist/utils/selection.d.ts +7 -0
  53. package/dist/utils/useMergedStyle.d.ts +2 -0
  54. package/package.json +2 -5
  55. package/src/.DS_Store +0 -0
  56. package/src/AttributesEditor.tsx +83 -16
  57. package/src/RenderPage.tsx +86 -4
  58. package/src/attributes-editor/Field.tsx +60 -165
  59. package/src/attributes-editor/SizeField.tsx +184 -0
  60. package/src/attributes-editor/SpecialCategorySection.tsx +12 -4
  61. package/src/build-components/BackgroundImage/BackgroundImage.tsx +77 -0
  62. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +61 -0
  63. package/src/build-components/BackgroundImage/pattern.json +45 -0
  64. package/src/build-components/Button/Button.tsx +29 -4
  65. package/src/build-components/Button/ButtonProps.generated.ts +8 -0
  66. package/src/build-components/Carousel/Carousel.tsx +25 -3
  67. package/src/build-components/Carousel/CarouselProps.generated.ts +8 -0
  68. package/src/build-components/CarouselButtons/CarouselButtons.tsx +19 -4
  69. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +8 -0
  70. package/src/build-components/CarouselDots/CarouselDots.tsx +13 -4
  71. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +8 -0
  72. package/src/build-components/CarouselItem/CarouselItem.tsx +20 -4
  73. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +8 -0
  74. package/src/build-components/CarouselProvider/CarouselProvider.tsx +14 -3
  75. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +8 -0
  76. package/src/build-components/Image/Image.tsx +27 -9
  77. package/src/build-components/Image/ImageProps.generated.ts +8 -0
  78. package/src/build-components/Image/pattern.json +1 -9
  79. package/src/build-components/Onboard/Onboard.tsx +2 -2
  80. package/src/build-components/Onboard/OnboardProps.generated.ts +8 -0
  81. package/src/build-components/OnboardButton/OnboardButton.tsx +11 -7
  82. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +8 -1
  83. package/src/build-components/OnboardButtons/OnboardButtons.tsx +17 -5
  84. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +8 -0
  85. package/src/build-components/OnboardDot/OnboardDot.tsx +68 -39
  86. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +9 -3
  87. package/src/build-components/OnboardDot/pattern.json +3 -19
  88. package/src/build-components/OnboardFooter/OnboardFooter.tsx +37 -14
  89. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +8 -0
  90. package/src/build-components/OnboardImage/OnboardImage.tsx +28 -6
  91. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +9 -1
  92. package/src/build-components/OnboardItem/OnboardItem.tsx +15 -14
  93. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +8 -0
  94. package/src/build-components/OnboardProvider/OnboardProvider.tsx +35 -20
  95. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +8 -1
  96. package/src/build-components/OnboardProvider/pattern.json +0 -8
  97. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +8 -0
  98. package/src/build-components/OnboardSubtitle/pattern.json +1 -1
  99. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +8 -0
  100. package/src/build-components/OnboardTitle/pattern.json +1 -1
  101. package/src/build-components/RenderNode.generated.tsx +3 -0
  102. package/src/build-components/Text/Text.tsx +28 -10
  103. package/src/build-components/Text/TextProps.generated.ts +8 -0
  104. package/src/build-components/View/View.tsx +25 -3
  105. package/src/build-components/View/ViewProps.generated.ts +8 -0
  106. package/src/build-components/View/pattern.json +67 -1
  107. package/src/build-components/index.ts +5 -0
  108. package/src/build-components/patterns.generated.ts +1620 -46
  109. package/src/components/AttributesEditorPanel.tsx +13 -6
  110. package/src/components/Builder.tsx +200 -56
  111. package/src/components/BuilderButton.tsx +127 -0
  112. package/src/components/DeviceNavigationBar.tsx +0 -1
  113. package/src/components/EditorHeader.tsx +11 -1
  114. package/src/components/JsonTextEditor.tsx +185 -0
  115. package/src/index.ts +2 -2
  116. package/src/mockOS/components/MockOSRouter.tsx +17 -3
  117. package/src/mockOS/context/MockOSContext.tsx +0 -5
  118. package/src/mockOS/managers/mockPermissionManager.ts +0 -4
  119. package/src/mockOS/managers/navigationManager.ts +1 -6
  120. package/src/modals/ColorModal.tsx +306 -71
  121. package/src/modals/LocalicationModal.tsx +4 -5
  122. package/src/modals/Modal.tsx +8 -1
  123. package/src/pages/ProjectPage.tsx +299 -55
  124. package/src/pages/tabs/{BuilderTab.tsx → BuilderPanel.tsx} +13 -9
  125. package/src/pages/tabs/SideTool.tsx +260 -0
  126. package/src/size-matters/index.ts +6 -0
  127. package/src/store.ts +18 -1
  128. package/src/styles/base/_global.scss +163 -7
  129. package/src/styles/components/_attributes-editor.scss +12 -0
  130. package/src/styles/components/_editor-shell.scss +25 -0
  131. package/src/styles/foundation/_sizes.scss +1 -1
  132. package/src/styles/layout/_builder.scss +66 -10
  133. package/src/styles/modals/_color-modal.scss +59 -1
  134. package/src/styles/utilities/_carousel.scss +9 -8
  135. package/src/types/Project.ts +14 -0
  136. package/src/utils/analyseNode.ts +98 -0
  137. package/src/utils/extractImageStyle.ts +3 -6
  138. package/src/utils/extractTextStyle.ts +19 -82
  139. package/src/utils/extractViewStyle.ts +41 -12
  140. package/src/utils/parseColor.ts +43 -0
  141. package/src/utils/selection.ts +24 -0
  142. package/src/utils/useMergedStyle.ts +16 -0
  143. package/dist/pages/tabs/BuilderTab.d.ts +0 -9
  144. package/dist/pages/tabs/DebugTab.d.ts +0 -7
  145. package/dist/pages/tabs/PreviewTab.d.ts +0 -3
  146. package/src/pages/tabs/DebugTab.tsx +0 -64
  147. package/src/pages/tabs/PreviewTab.tsx +0 -206
@@ -0,0 +1,185 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+
3
+ type JsonTextEditorProps = {
4
+ value: unknown;
5
+ onChange?: (next: unknown) => void;
6
+ rootName?: string;
7
+ readOnly?: boolean;
8
+ className?: string;
9
+ };
10
+
11
+ function safeStringify(value: unknown) {
12
+ try {
13
+ return JSON.stringify(value, null, 2) ?? '';
14
+ } catch {
15
+ // Fallback for circular structures or non-serializable values
16
+ return String(value ?? '');
17
+ }
18
+ }
19
+
20
+ export function JsonTextEditor({
21
+ value,
22
+ onChange,
23
+ rootName,
24
+ readOnly = false,
25
+ className,
26
+ }: JsonTextEditorProps) {
27
+ const initialText = useMemo(() => safeStringify(value), [value]);
28
+ const [text, setText] = useState(initialText);
29
+ const [parseError, setParseError] = useState<string | null>(null);
30
+ const [applyError, setApplyError] = useState<string | null>(null);
31
+ const [parsedValue, setParsedValue] = useState<unknown>(value);
32
+
33
+ useEffect(() => {
34
+ setText(initialText);
35
+ setParseError(null);
36
+ setApplyError(null);
37
+ setParsedValue(value);
38
+ }, [initialText, value]);
39
+
40
+ const handleCopy = async () => {
41
+ try {
42
+ await navigator.clipboard.writeText(text);
43
+ } catch {
44
+ // ignore (e.g. non-secure context)
45
+ }
46
+ };
47
+
48
+ const handleFormat = () => {
49
+ try {
50
+ const parsed = JSON.parse(text);
51
+ setText(JSON.stringify(parsed, null, 2));
52
+ setParseError(null);
53
+ setApplyError(null);
54
+ setParsedValue(parsed);
55
+ } catch (e) {
56
+ setParseError(e instanceof Error ? e.message : 'Invalid JSON');
57
+ }
58
+ };
59
+
60
+ const handleApply = () => {
61
+ if (!onChange) return;
62
+ try {
63
+ const parsed = JSON.parse(text);
64
+ setParseError(null);
65
+ setApplyError(null);
66
+ setParsedValue(parsed);
67
+ try {
68
+ onChange(parsed);
69
+ } catch (e) {
70
+ setApplyError(e instanceof Error ? e.message : 'Failed to apply JSON');
71
+ }
72
+ } catch (e) {
73
+ setParseError(e instanceof Error ? e.message : 'Invalid JSON');
74
+ }
75
+ };
76
+
77
+ const headerLabel = rootName ? `${rootName}.json` : 'data.json';
78
+
79
+ return (
80
+ <div
81
+ className={className}
82
+ style={{
83
+ height: '100%',
84
+ width: '100%',
85
+ display: 'flex',
86
+ flexDirection: 'column',
87
+ gap: 10,
88
+ }}
89
+ >
90
+ <div
91
+ style={{
92
+ display: 'flex',
93
+ alignItems: 'center',
94
+ justifyContent: 'space-between',
95
+ gap: 8,
96
+ flexWrap: 'wrap',
97
+ }}
98
+ >
99
+ <div style={{ fontSize: 12, opacity: 0.75 }}>{headerLabel}</div>
100
+ <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
101
+ <button type="button" className="editor-button" onClick={handleCopy}>
102
+ Copy
103
+ </button>
104
+ <button
105
+ type="button"
106
+ className="editor-button"
107
+ onClick={handleFormat}
108
+ >
109
+ Format
110
+ </button>
111
+ {!readOnly && (
112
+ <button
113
+ type="button"
114
+ className="editor-button"
115
+ onClick={handleApply}
116
+ disabled={!onChange}
117
+ title={onChange ? 'Apply JSON changes' : 'Read only'}
118
+ >
119
+ Apply
120
+ </button>
121
+ )}
122
+ </div>
123
+ </div>
124
+
125
+ <div
126
+ style={{
127
+ display: 'grid',
128
+ gridTemplateColumns: 'minmax(0, 1fr)',
129
+ gap: 10,
130
+ flex: 1,
131
+ minHeight: 0,
132
+ }}
133
+ >
134
+ <textarea
135
+ value={text}
136
+ onChange={(e) => {
137
+ const nextText = e.target.value;
138
+ setText(nextText);
139
+ setApplyError(null);
140
+ if (readOnly) return;
141
+ try {
142
+ const parsed = JSON.parse(nextText);
143
+ setParseError(null);
144
+ setParsedValue(parsed);
145
+ } catch (e) {
146
+ setParseError(e instanceof Error ? e.message : 'Invalid JSON');
147
+ }
148
+ }}
149
+ readOnly={readOnly}
150
+ spellCheck={false}
151
+ style={{
152
+ width: '100%',
153
+ height: '100%',
154
+ minHeight: 320,
155
+ resize: 'none',
156
+ border: '1px solid rgba(0,0,0,0.12)',
157
+ borderRadius: 10,
158
+ padding: 12,
159
+ fontFamily:
160
+ 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
161
+ fontSize: 12,
162
+ lineHeight: 1.5,
163
+ background: 'transparent',
164
+ outline: 'none',
165
+ }}
166
+ />
167
+ </div>
168
+
169
+ {parseError ? (
170
+ <div style={{ fontSize: 12, color: '#d12f2f' }}>
171
+ Invalid JSON: {parseError}
172
+ </div>
173
+ ) : applyError ? (
174
+ <div style={{ fontSize: 12, color: '#d12f2f' }}>
175
+ Could not apply: {applyError}
176
+ </div>
177
+ ) : (
178
+ <div style={{ fontSize: 12, opacity: 0.7 }}>
179
+ Valid JSON ({safeStringify(parsedValue).length.toLocaleString()}{' '}
180
+ chars)
181
+ </div>
182
+ )}
183
+ </div>
184
+ );
185
+ }
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@ import AttributesEditor from './AttributesEditor';
3
3
 
4
4
  export type { TargetedScreenSize } from './types/TargetedScreenSize';
5
5
  export type { Node, NodeData, NodeDefaultAttribute } from './types/Node';
6
- export type { Project } from './types/Project';
6
+ export type { Project, ProjectColors } from './types/Project';
7
7
  export {
8
8
  isNodeNullOrUndefined,
9
9
  isNodeString,
@@ -28,7 +28,7 @@ export { extractViewStyle } from './utils/extractViewStyle';
28
28
  export { extractImageStyle } from './utils/extractImageStyle';
29
29
  export { extractTextStyle } from './utils/extractTextStyle';
30
30
  export { ProjectPage } from './pages/ProjectPage';
31
- export type { ProjectPageProps, Tab } from './pages/ProjectPage';
31
+ export type { ProjectPageProps } from './pages/ProjectPage';
32
32
  export { copyNode } from './utils/copyNode';
33
33
  export { logger } from './utils/logger';
34
34
  export type { LogLevel } from './types/Project';
@@ -1,6 +1,7 @@
1
- import React, { ReactNode } from 'react';
1
+ import React, { ReactNode, useCallback, useEffect } from 'react';
2
2
  import { useMockOSContext } from '../context/MockOSContext';
3
3
  import { MockLaunchScreenComponent } from './MockLaunchScreenComponent';
4
+ import { useRenderStore } from '../../store';
4
5
  // Note: We might use react-router or similar library in the future for more complex routing
5
6
 
6
7
  interface MockOSRouterProps {
@@ -85,6 +86,7 @@ export function MockOSRouter({
85
86
  appName = 'My App',
86
87
  }: MockOSRouterProps) {
87
88
  const context = useMockOSContext();
89
+ const incForceRender = useRenderStore((s) => s.incForceRender);
88
90
 
89
91
  if (!context) {
90
92
  throw new Error('MockOSRouter must be used within MockOSProvider');
@@ -92,11 +94,23 @@ export function MockOSRouter({
92
94
 
93
95
  const { currentRoute, navigation } = context;
94
96
 
95
- function handleLaunchApp() {
97
+ const handleLaunchApp = useCallback(() => {
96
98
  // Navigate to the route specified in childrenBelongTo or default to 'onboard'
97
99
  const targetRoute = childrenBelongTo || 'onboard';
98
100
  navigation(targetRoute);
99
- }
101
+ }, [childrenBelongTo, navigation]);
102
+
103
+ useEffect(() => {
104
+ const timer = setTimeout(() => {
105
+ handleLaunchApp();
106
+ }, 1000);
107
+
108
+ return () => clearTimeout(timer);
109
+ }, [handleLaunchApp]);
110
+
111
+ useEffect(() => {
112
+ incForceRender();
113
+ }, [currentRoute, incForceRender]);
100
114
 
101
115
  return (
102
116
  <div className="mockos-router">
@@ -81,7 +81,6 @@ export function MockOSProvider({
81
81
  ]);
82
82
 
83
83
  const navigation = useCallback((route: RouteType) => {
84
- console.log(`[Mock OS] Navigating to: ${route}`);
85
84
  setCurrentRoute(route);
86
85
 
87
86
  // If navigating from launchscreen and the last item in stack is launchscreen,
@@ -109,12 +108,10 @@ export function MockOSProvider({
109
108
  newStack.pop();
110
109
  const previousRoute = newStack[newStack.length - 1];
111
110
 
112
- console.log(`[Mock OS] Going back to: ${previousRoute.route}`);
113
111
  setCurrentRoute(previousRoute.route);
114
112
  setNavigationStack(newStack);
115
113
  return true;
116
114
  }
117
- console.log('[Mock OS] Cannot go back - at root');
118
115
  return false;
119
116
  }, [navigationStack]);
120
117
 
@@ -129,12 +126,10 @@ export function MockOSProvider({
129
126
  };
130
127
 
131
128
  const handleAllow = () => {
132
- console.log(`[Mock OS] Permission granted: ${permission}`);
133
129
  setPermission(null);
134
130
  };
135
131
 
136
132
  const handleDeny = () => {
137
- console.log(`[Mock OS] Permission denied: ${permission}`);
138
133
  setPermission(null);
139
134
  };
140
135
 
@@ -26,7 +26,6 @@ export class MockPermissionManager {
26
26
  return 'not-determined';
27
27
  }
28
28
 
29
- console.log(`[Mock OS] Permission requested: ${permission}`);
30
29
  // Set permission to trigger modal display
31
30
  this.context.setPermission(permission);
32
31
  // Default behavior: grant all permissions in mock environment
@@ -39,7 +38,6 @@ export class MockPermissionManager {
39
38
  return 'not-determined';
40
39
  }
41
40
 
42
- console.log(`[Mock OS] Permission checked: ${permission}`);
43
41
  return 'granted';
44
42
  }
45
43
 
@@ -48,7 +46,5 @@ export class MockPermissionManager {
48
46
  alert('Opening Settings\n(Mock OS context not available)');
49
47
  return;
50
48
  }
51
-
52
- console.log('[Mock OS] Opening Settings');
53
49
  }
54
50
  }
@@ -31,7 +31,6 @@ export class MockNavigationManager {
31
31
  timestamp: Date.now(),
32
32
  };
33
33
  this.stack.push(item);
34
- console.log('[Mock OS] Navigate to Home', { stack: this.stack });
35
34
  }
36
35
 
37
36
  goToSubscriptions(): void {
@@ -45,7 +44,6 @@ export class MockNavigationManager {
45
44
  timestamp: Date.now(),
46
45
  };
47
46
  this.stack.push(item);
48
- console.log('[Mock OS] Navigate to Subscriptions', { stack: this.stack });
49
47
  }
50
48
 
51
49
  goToLaunchApp(): void {
@@ -59,7 +57,6 @@ export class MockNavigationManager {
59
57
  timestamp: Date.now(),
60
58
  };
61
59
  this.stack.push(item);
62
- console.log('[Mock OS] Navigate to Launch App', { stack: this.stack });
63
60
  }
64
61
 
65
62
  goBack(): boolean {
@@ -70,11 +67,9 @@ export class MockNavigationManager {
70
67
 
71
68
  if (this.stack.length > 0) {
72
69
  const popped = this.stack.pop();
73
- console.log('[Mock OS] Go Back', { popped, stack: this.stack });
74
70
  return true;
75
71
  }
76
72
 
77
- console.log('[Mock OS] Cannot go back - stack is empty');
78
73
  return false;
79
74
  }
80
75
 
@@ -85,7 +80,7 @@ export class MockNavigationManager {
85
80
  clearStack(): void {
86
81
  this.stack = [];
87
82
  if (this.context) {
88
- console.log('[Mock OS] Navigation stack cleared');
83
+ console.info('[Mock OS] Navigation stack cleared');
89
84
  }
90
85
  }
91
86
  }