@developer_tribe/react-builder 0.1.32 → 1.0.1

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 (86) hide show
  1. package/dist/DeviceMockFrame.d.ts +1 -17
  2. package/dist/RenderPage.d.ts +1 -9
  3. package/dist/build-components/index.d.ts +1 -0
  4. package/dist/components/AttributesEditorPanel.d.ts +9 -0
  5. package/dist/components/Breadcrumb.d.ts +13 -0
  6. package/dist/components/Builder.d.ts +9 -0
  7. package/dist/components/EditorHeader.d.ts +15 -0
  8. package/dist/index.cjs.js +6 -5
  9. package/dist/index.cjs.js.map +1 -0
  10. package/dist/index.d.ts +8 -4
  11. package/dist/index.esm.js +6 -5
  12. package/dist/index.esm.js.map +1 -0
  13. package/dist/pages/ProjectPage.d.ts +11 -0
  14. package/dist/pages/tabs/BuilderTab.d.ts +9 -0
  15. package/dist/pages/tabs/DebugTab.d.ts +7 -0
  16. package/dist/pages/tabs/PreviewTab.d.ts +3 -0
  17. package/dist/store.d.ts +17 -18
  18. package/dist/styles.css +1 -1
  19. package/dist/types/PreviewConfig.d.ts +6 -3
  20. package/dist/types/Project.d.ts +12 -2
  21. package/dist/utils/copyNode.d.ts +2 -0
  22. package/dist/utils/logger.d.ts +11 -0
  23. package/dist/utils/useLogRender.d.ts +1 -0
  24. package/package.json +16 -9
  25. package/scripts/prebuild/utils/createBuildComponentsIndex.js +15 -1
  26. package/src/AttributesEditor.tsx +2 -0
  27. package/src/DeviceMockFrame.tsx +22 -31
  28. package/src/RenderPage.tsx +5 -42
  29. package/src/assets/images/android.svg +43 -0
  30. package/src/assets/images/apple.svg +16 -0
  31. package/src/assets/images/background.jpg +0 -0
  32. package/src/assets/samples/carousel-sample.json +2 -3
  33. package/src/assets/samples/getSamples.ts +49 -12
  34. package/src/assets/samples/simple-1.json +1 -2
  35. package/src/assets/samples/simple-2.json +1 -2
  36. package/src/assets/samples/vpn-onboard-1.json +1 -2
  37. package/src/assets/samples/vpn-onboard-2.json +1 -2
  38. package/src/assets/samples/vpn-onboard-3.json +1 -2
  39. package/src/assets/samples/vpn-onboard-4.json +1 -2
  40. package/src/assets/samples/vpn-onboard-5.json +1 -2
  41. package/src/assets/samples/vpn-onboard-6.json +1 -2
  42. package/src/build-components/Button/Button.tsx +2 -0
  43. package/src/build-components/Carousel/Carousel.tsx +2 -0
  44. package/src/build-components/CarouselButtons/CarouselButtons.tsx +2 -0
  45. package/src/build-components/CarouselDots/CarouselDots.tsx +2 -0
  46. package/src/build-components/CarouselItem/CarouselItem.tsx +2 -0
  47. package/src/build-components/Image/Image.tsx +2 -0
  48. package/src/build-components/Onboard/Onboard.tsx +2 -0
  49. package/src/build-components/OnboardButton/OnboardButton.tsx +7 -4
  50. package/src/build-components/OnboardButtons/OnboardButtons.tsx +7 -7
  51. package/src/build-components/OnboardDot/OnboardDot.tsx +2 -0
  52. package/src/build-components/OnboardFooter/OnboardFooter.tsx +5 -3
  53. package/src/build-components/OnboardImage/OnboardImage.tsx +2 -0
  54. package/src/build-components/OnboardItem/OnboardItem.tsx +2 -0
  55. package/src/build-components/OnboardProvider/OnboardProvider.tsx +2 -0
  56. package/src/build-components/OnboardSubtitle/OnboardSubtitle.tsx +2 -0
  57. package/src/build-components/OnboardTitle/OnboardTitle.tsx +2 -0
  58. package/src/build-components/Text/Text.tsx +5 -3
  59. package/src/build-components/View/View.tsx +2 -0
  60. package/src/build-components/index.ts +22 -0
  61. package/src/components/AttributesEditorPanel.tsx +112 -0
  62. package/src/components/Breadcrumb.tsx +48 -0
  63. package/src/components/Builder.tsx +272 -0
  64. package/src/components/EditorHeader.tsx +186 -0
  65. package/src/index.ts +8 -4
  66. package/src/pages/ProjectPage.tsx +152 -0
  67. package/src/pages/tabs/BuilderTab.tsx +33 -0
  68. package/src/pages/tabs/DebugTab.tsx +23 -0
  69. package/src/pages/tabs/PreviewTab.tsx +194 -0
  70. package/src/size-matters/index.ts +5 -1
  71. package/src/store.ts +60 -38
  72. package/src/styles/_mixins.scss +21 -0
  73. package/src/styles/_variables.scss +27 -0
  74. package/src/styles/builder.scss +60 -0
  75. package/src/styles/components.scss +88 -0
  76. package/src/styles/editor.scss +174 -0
  77. package/src/styles/global.scss +200 -0
  78. package/src/styles/index.scss +7 -0
  79. package/src/styles/pages.scss +2 -0
  80. package/src/types/PreviewConfig.ts +14 -5
  81. package/src/types/Project.ts +15 -2
  82. package/src/utils/copyNode.ts +7 -0
  83. package/src/utils/extractTextStyle.ts +4 -2
  84. package/src/utils/getDevices.ts +1 -0
  85. package/src/utils/logger.ts +76 -0
  86. package/src/utils/useLogRender.ts +13 -0
@@ -0,0 +1,200 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
3
+ @use './reset';
4
+
5
+ /* Global utility classes */
6
+ html,
7
+ body,
8
+ #root {
9
+ font-family: $font-sans;
10
+ }
11
+
12
+ .editor-container {
13
+ height: 100vh;
14
+ width: 100vw;
15
+ display: flex;
16
+ overflow: hidden; /* Split panels manage their own scroll */
17
+ }
18
+ .editor-panel-builder {
19
+ padding: 4px 8px;
20
+ }
21
+ .app-shell {
22
+ min-height: 100vh;
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+
27
+ .app-main {
28
+ flex: 1 1 auto;
29
+ background: $color-background;
30
+ }
31
+
32
+ .page-bg {
33
+ background: $color-background;
34
+ }
35
+
36
+ .grid-cards {
37
+ display: grid;
38
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
39
+ gap: $space-4;
40
+ }
41
+
42
+ .btn-add {
43
+ height: 120px;
44
+ border: 2px dashed $color-muted;
45
+ border-radius: $radius-md;
46
+ background: #fff;
47
+ cursor: pointer;
48
+ font-weight: 600;
49
+ color: $color-text;
50
+ transition:
51
+ border-color 0.2s ease,
52
+ transform 0.1s ease,
53
+ box-shadow 0.2s ease;
54
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
55
+
56
+ &:hover {
57
+ border-color: darken($color-muted, 10%);
58
+ transform: translateY(-1px);
59
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
60
+ }
61
+ }
62
+
63
+ .split-left {
64
+ @include thin-scrollbar;
65
+ flex: 1 1 30%;
66
+ min-width: 0;
67
+ border-right: 1px solid $color-border;
68
+ overflow: auto;
69
+ }
70
+
71
+ .split-right {
72
+ position: relative;
73
+ flex: 1 1 45%;
74
+ min-width: 0;
75
+ max-height: calc(100vh - 120px);
76
+ overflow: auto;
77
+ }
78
+
79
+ .split-third {
80
+ flex: 1 1 25%;
81
+ min-width: 0;
82
+ border-right: 1px solid $color-border;
83
+ overflow: auto;
84
+ max-height: calc(100vh - 120px);
85
+ }
86
+
87
+ .split-right-background {
88
+ position: absolute;
89
+ inset: 0;
90
+ background-size: cover;
91
+ background-position: center;
92
+ background-repeat: repeat;
93
+ background-size: 500px auto;
94
+ opacity: 0.2;
95
+ }
96
+
97
+ .stage-wrapper {
98
+ display: flex;
99
+ justify-content: center;
100
+ background: $color-background;
101
+ padding: $space-4;
102
+ }
103
+
104
+ .stage {
105
+ @include card;
106
+ border: 1px solid $color-border;
107
+
108
+ .scroll-container {
109
+ /* Mobile-like scrollbar styling */
110
+ &::-webkit-scrollbar {
111
+ width: 8px;
112
+ height: 8px;
113
+ }
114
+
115
+ &::-webkit-scrollbar-track {
116
+ background: transparent;
117
+ }
118
+
119
+ &::-webkit-scrollbar-thumb {
120
+ background: rgba(0, 0, 0, 0.25);
121
+ border-radius: 8px;
122
+ }
123
+
124
+ /* For Firefox */
125
+ scrollbar-width: thin;
126
+ scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
127
+ }
128
+ }
129
+
130
+ /* Header */
131
+ .app-header {
132
+ position: sticky;
133
+ top: 0;
134
+ z-index: 10;
135
+ background: #fff;
136
+ border-bottom: 1px solid $color-border;
137
+ height: 60px;
138
+ padding: 0 $space-4;
139
+ display: flex;
140
+ align-items: center;
141
+ justify-content: space-between;
142
+
143
+ a {
144
+ color: $color-text;
145
+ text-decoration: none;
146
+ }
147
+ }
148
+
149
+ .app-header__brand {
150
+ font-weight: 700;
151
+ }
152
+
153
+ .app-header__nav {
154
+ display: flex;
155
+ gap: $space-4;
156
+ }
157
+ .warning {
158
+ color: $color-error;
159
+ font-size: 12px;
160
+ font-weight: 600;
161
+ margin-bottom: $space-4;
162
+ }
163
+
164
+ /* Breadcrumb */
165
+ .breadcrumb {
166
+ display: block;
167
+ font-size: 12px;
168
+ color: $color-muted;
169
+ }
170
+
171
+ .breadcrumb__list {
172
+ list-style: none;
173
+ padding: 0;
174
+ margin: 0;
175
+ display: flex;
176
+ align-items: center;
177
+ gap: $space-2;
178
+ }
179
+
180
+ .breadcrumb__item {
181
+ display: inline-flex;
182
+ align-items: center;
183
+ }
184
+
185
+ .breadcrumb__separator {
186
+ color: $color-border;
187
+ margin: 0 $space-1;
188
+ }
189
+
190
+ .breadcrumb__link {
191
+ color: $color-text;
192
+ text-decoration: none;
193
+ &:hover {
194
+ text-decoration: underline;
195
+ }
196
+ }
197
+
198
+ .breadcrumb__current {
199
+ color: $color-muted;
200
+ }
@@ -1,4 +1,11 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
1
3
  @use './reset';
4
+ @use './global.scss';
5
+ @use './pages.scss';
6
+ @use './components.scss';
7
+ @use './builder.scss';
8
+ @use './editor.scss';
2
9
 
3
10
  .embla {
4
11
  max-width: 48rem;
@@ -0,0 +1,2 @@
1
+ @use './variables' as *;
2
+ @use './mixins' as *;
@@ -1,17 +1,26 @@
1
- import { TargetedScreenSize } from './TargetedScreenSize';
2
-
3
- export interface PreviewConfig {
1
+ export interface AppConfig {
4
2
  theme: 'light' | 'dark';
5
- screenSize: TargetedScreenSize;
6
- isRtl: boolean;
3
+ isRtl: boolean; //This could be device in future
7
4
  screenStyle: {
8
5
  light: { backgroundColor: string; color: string; seperatorColor?: string };
9
6
  dark: { backgroundColor: string; color: string; seperatorColor?: string };
10
7
  };
11
8
  localication: Localication;
12
9
  defaultLanguage?: string;
10
+ baseSize: { width: number; height: number };
13
11
  }
14
12
 
13
+ export const defaultAppConfig: AppConfig = {
14
+ theme: 'light',
15
+ isRtl: false,
16
+ screenStyle: {
17
+ light: { backgroundColor: '#FDFDFD', color: '#161827' },
18
+ dark: { backgroundColor: '#12131A', color: '#E9EBF9' },
19
+ },
20
+ localication: {},
21
+ baseSize: { width: 375, height: 812 },
22
+ };
23
+
15
24
  export type Localication = {
16
25
  [key: string]: {
17
26
  [key: string]: string;
@@ -1,11 +1,24 @@
1
1
  import { Node } from '../types/Node';
2
- import { PreviewConfig } from './PreviewConfig';
2
+ import { AppConfig } from './PreviewConfig';
3
3
 
4
4
  export interface ProjectBase<T> {
5
5
  name: string;
6
6
  version: string;
7
7
  data: T;
8
- previewConfig?: PreviewConfig;
8
+ appConfig?: AppConfig;
9
9
  }
10
10
 
11
11
  export interface Project extends ProjectBase<Node> {}
12
+
13
+ export type LogLevel = 'NONE' | 'ERROR' | 'WARN' | 'INFO' | 'VERBOSE';
14
+
15
+ export type LogSource = string;
16
+
17
+ export interface LogEntry {
18
+ id: string;
19
+ timestamp: number;
20
+ level: LogLevel;
21
+ source: LogSource;
22
+ message: string;
23
+ payload?: unknown;
24
+ }
@@ -0,0 +1,7 @@
1
+ import { useRenderStore } from '../store';
2
+ import { Node } from '../types/Node';
3
+
4
+ export function copyNode(node: Node) {
5
+ const { setCopiedNode } = useRenderStore.getState();
6
+ setCopiedNode(node);
7
+ }
@@ -7,8 +7,10 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
7
7
  node: NodeData<T>,
8
8
  ) {
9
9
  const attributes = node.attributes;
10
-
11
- const { screenStyle, theme } = useRenderStore.getState();
10
+ //TODO: it should be passed as a prop to the function (need a state)
11
+ const {
12
+ appConfig: { screenStyle, theme },
13
+ } = useRenderStore.getState();
12
14
  const fallbackColor =
13
15
  theme === 'light' ? screenStyle.light.color : screenStyle.dark.color;
14
16
 
@@ -11,6 +11,7 @@ export function getDevices(): Device[] {
11
11
  return deviceList;
12
12
  }
13
13
 
14
+ //TODO: object instead of function
14
15
  export function getDefaultDevice(): Device {
15
16
  return getDevices()[0];
16
17
  }
@@ -0,0 +1,76 @@
1
+ import { useRenderStore } from '../store';
2
+ import type { LogLevel, LogSource } from '../types/Project';
3
+
4
+ const levelPriority: Record<Exclude<LogLevel, 'NONE'>, number> = {
5
+ ERROR: 0,
6
+ WARN: 1,
7
+ INFO: 2,
8
+ VERBOSE: 3,
9
+ };
10
+
11
+ function shouldLog(currentLevel: LogLevel, level: LogLevel): boolean {
12
+ if (currentLevel === 'NONE' || level === 'NONE') return false;
13
+ const curr = levelPriority[currentLevel as Exclude<LogLevel, 'NONE'>];
14
+ const incoming = levelPriority[level as Exclude<LogLevel, 'NONE'>];
15
+ return incoming <= curr;
16
+ }
17
+
18
+ function consoleLog(
19
+ level: LogLevel,
20
+ source: LogSource,
21
+ message: string,
22
+ payload?: unknown,
23
+ ) {
24
+ const prefix = `[${source}] ${message}`;
25
+ switch (level) {
26
+ case 'ERROR':
27
+ // eslint-disable-next-line no-console
28
+ console.error(prefix, payload);
29
+ break;
30
+ case 'WARN':
31
+ // eslint-disable-next-line no-console
32
+ console.warn(prefix, payload);
33
+ break;
34
+ case 'INFO':
35
+ // eslint-disable-next-line no-console
36
+ console.info(prefix, payload);
37
+ break;
38
+ case 'VERBOSE':
39
+ // eslint-disable-next-line no-console
40
+ console.debug(prefix, payload);
41
+ break;
42
+ default:
43
+ break;
44
+ }
45
+ }
46
+
47
+ export const logger = {
48
+ setLevel(level: LogLevel) {
49
+ useRenderStore.getState().setLogLevel(level);
50
+ // eslint-disable-next-line no-console
51
+ console.info(`[Logger] level set to ${level}`);
52
+ },
53
+ log(level: LogLevel, source: LogSource, message: string, payload?: unknown) {
54
+ const { logLevel, addLog } = useRenderStore.getState();
55
+ if (!shouldLog(logLevel, level)) return;
56
+ addLog({ level, source, message, payload });
57
+ consoleLog(level, source, message, payload);
58
+ },
59
+ verbose(source: LogSource, message: string, payload?: unknown) {
60
+ this.log('VERBOSE', source, message, payload);
61
+ },
62
+ info(source: LogSource, message: string, payload?: unknown) {
63
+ this.log('INFO', source, message, payload);
64
+ },
65
+ warn(source: LogSource, message: string, payload?: unknown) {
66
+ this.log('WARN', source, message, payload);
67
+ },
68
+ error(source: LogSource, message: string, payload?: unknown) {
69
+ this.log('ERROR', source, message, payload);
70
+ },
71
+ clear() {
72
+ useRenderStore.getState().clearLogs();
73
+ },
74
+ };
75
+
76
+ export type { LogLevel };
@@ -0,0 +1,13 @@
1
+ import { useEffect } from 'react';
2
+ import { logger } from './logger';
3
+
4
+ export function useLogRender(sourceName: string, payload?: unknown) {
5
+ useEffect(() => {
6
+ logger.verbose(sourceName, 'rendered', payload);
7
+ return () => {
8
+ logger.verbose(sourceName, 'unmount');
9
+ };
10
+ // We intentionally log once per mount/update cycle only for rendered
11
+ // eslint-disable-next-line react-hooks/exhaustive-deps
12
+ }, []);
13
+ }