@developer_tribe/react-builder 0.1.27 → 0.1.28

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 (73) hide show
  1. package/dist/RenderPage.d.ts +13 -13
  2. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +18 -4
  3. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +6 -1
  4. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +4 -0
  5. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +23 -1
  6. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +23 -0
  7. package/dist/build-components/Text/TextProps.generated.d.ts +23 -0
  8. package/dist/build-components/View/ViewProps.generated.d.ts +15 -3
  9. package/dist/build-components/index.d.ts +1 -0
  10. package/dist/build-components/patterns.generated.d.ts +389 -0
  11. package/dist/index.cjs.js +28 -1
  12. package/dist/index.d.ts +1 -2
  13. package/dist/index.esm.js +28 -1
  14. package/dist/size-matters/index.d.ts +6 -0
  15. package/dist/store.d.ts +25 -0
  16. package/dist/styles.css +1 -1
  17. package/dist/types/PreviewConfig.d.ts +2 -0
  18. package/dist/utils/getDevices.d.ts +1 -0
  19. package/dist/utils/patterns.d.ts +3 -2
  20. package/package.json +2 -1
  21. package/scripts/prebuild/build-components.js +2 -0
  22. package/scripts/prebuild/utils/createBuildComponentsIndex.js +5 -1
  23. package/scripts/prebuild/utils/createPatternsGenerated.js +23 -0
  24. package/scripts/prebuild/utils/index.js +1 -0
  25. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +126 -1
  26. package/src/RenderPage.tsx +33 -29
  27. package/src/build-components/Button/Button.tsx +2 -2
  28. package/src/build-components/Carousel/Carousel.tsx +2 -2
  29. package/src/build-components/CarouselButtons/CarouselButtons.tsx +2 -2
  30. package/src/build-components/CarouselDots/CarouselDots.tsx +2 -2
  31. package/src/build-components/CarouselItem/CarouselItem.tsx +2 -2
  32. package/src/build-components/CarouselProvider/CarouselProvider.tsx +2 -2
  33. package/src/build-components/Image/Image.tsx +2 -3
  34. package/src/build-components/Onboard/Onboard.tsx +2 -2
  35. package/src/build-components/OnboardButton/OnboardButton.tsx +7 -4
  36. package/src/build-components/OnboardButtons/OnboardButtons.tsx +14 -9
  37. package/src/build-components/OnboardDot/OnboardDot.tsx +2 -2
  38. package/src/build-components/OnboardFooter/OnboardFooter.tsx +22 -12
  39. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +29 -4
  40. package/src/build-components/OnboardFooter/pattern.json +4 -19
  41. package/src/build-components/OnboardImage/OnboardImage.tsx +2 -2
  42. package/src/build-components/OnboardItem/OnboardItem.tsx +20 -19
  43. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +6 -1
  44. package/src/build-components/OnboardItem/pattern.json +12 -1
  45. package/src/build-components/OnboardProvider/OnboardProvider.tsx +15 -12
  46. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +4 -0
  47. package/src/build-components/OnboardProvider/pattern.json +11 -1
  48. package/src/build-components/OnboardSubtitle/OnboardSubtitle.tsx +3 -17
  49. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +29 -1
  50. package/src/build-components/OnboardSubtitle/pattern.json +3 -19
  51. package/src/build-components/OnboardTitle/OnboardTitle.tsx +4 -17
  52. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +29 -0
  53. package/src/build-components/OnboardTitle/pattern.json +5 -19
  54. package/src/build-components/Text/Text.tsx +21 -9
  55. package/src/build-components/Text/TextProps.generated.ts +29 -0
  56. package/src/build-components/Text/pattern.json +1 -0
  57. package/src/build-components/View/View.tsx +3 -3
  58. package/src/build-components/View/ViewProps.generated.ts +15 -3
  59. package/src/build-components/View/pattern.json +15 -3
  60. package/src/build-components/index.ts +2 -0
  61. package/src/build-components/patterns.generated.ts +502 -0
  62. package/src/build-components/useNode.ts +1 -0
  63. package/src/index.ts +1 -2
  64. package/src/size-matters/index.ts +64 -0
  65. package/src/store.ts +56 -0
  66. package/src/styles/_reset.scss +30 -0
  67. package/src/styles/index.scss +2 -0
  68. package/src/types/PreviewConfig.ts +2 -2
  69. package/src/utils/getDevices.ts +4 -0
  70. package/src/utils/novaToJson.ts +34 -4
  71. package/src/utils/patterns.ts +14 -45
  72. package/dist/RenderMainNode.d.ts +0 -16
  73. package/src/RenderMainNode.tsx +0 -37
@@ -0,0 +1,6 @@
1
+ export declare function scale(size: number): number;
2
+ export declare function verticalScale(size: number): number;
3
+ export declare const s: typeof scale;
4
+ export declare const vs: typeof verticalScale;
5
+ export declare const fs: typeof verticalScale;
6
+ export declare function parseSize(value?: string | number): string | number | undefined;
@@ -0,0 +1,25 @@
1
+ import type { Device } from './types/Device';
2
+ import type { Localication } from './types/PreviewConfig';
3
+ import { ScreenStyle } from './RenderPage';
4
+ type RenderStore = {
5
+ device: Device;
6
+ localication: Localication | null;
7
+ defaultLanguage?: string;
8
+ baseSize: {
9
+ width: number;
10
+ height: number;
11
+ };
12
+ theme: 'dark' | 'light';
13
+ screenStyle: ScreenStyle;
14
+ setBaseSize: (baseSize: {
15
+ width: number;
16
+ height: number;
17
+ }) => void;
18
+ setDevice: (device: Device) => void;
19
+ setLocalication: (localication: Localication | null) => void;
20
+ setDefaultLanguage: (defaultLanguage?: string) => void;
21
+ setTheme: (theme: 'dark' | 'light') => void;
22
+ setScreenStyle: (screenStyle: ScreenStyle) => void;
23
+ };
24
+ export declare const useRenderStore: import("zustand/traditional").UseBoundStoreWithEqualityFn<import("zustand/vanilla").StoreApi<RenderStore>>;
25
+ export {};
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- .embla{max-width:48rem;margin:auto;--slide-height: 19rem;--slide-spacing: 1rem;--slide-size: 70%}.embla__viewport{overflow:hidden}.embla__container{display:flex;touch-action:pan-y pinch-zoom;margin-left:calc(var(--slide-spacing)*-1)}.embla__slide{transform:translate3d(0, 0, 0);flex:0 0 var(--slide-size);min-width:0;padding-left:var(--slide-spacing);flex:0 0 100%}.embla__slide__number{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);border-radius:1.8rem;font-size:4rem;font-weight:600;display:flex;align-items:center;justify-content:center;height:var(--slide-height);user-select:none}.embla__controls{display:grid;grid-template-columns:auto 1fr;justify-content:space-between;gap:1.2rem;margin-top:1.8rem}.embla__buttons{display:grid;grid-template-columns:repeat(2, 1fr);gap:.6rem;align-items:center}.embla__button{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:3.6rem;height:3.6rem;z-index:1;border-radius:50%;color:var(--text-body);display:flex;align-items:center;justify-content:center}.embla__button:disabled{color:var(--detail-high-contrast)}.embla__button__svg{width:35%;height:35%}.embla__dots{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;margin-right:0;height:50px}.embla__dot{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;width:2.6rem;height:2.6rem;display:flex;align-items:center;justify-content:center;border-radius:50%}.embla__dot:after{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:1.4rem;height:1.4rem;border-radius:50%;display:flex;align-items:center;content:""}.embla__dot--selected:after{box-shadow:inset 0 0 0 .2rem var(--text-body)}.carousel-provider{height:100%}.embla{height:100%}.embla__viewport{height:100%;display:flex;flex-direction:column}.embla__container{flex:1}
1
+ *,*::before,*::after{box-sizing:border-box}html,body,#root{height:100%;margin:0;padding:0}body{background:#fff;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow:hidden}button{font-family:inherit}input,button{font-size:100%}p{margin:0;padding:0}.embla{max-width:48rem;margin:auto;--slide-height: 19rem;--slide-spacing: 1rem;--slide-size: 70%}.embla__viewport{overflow:hidden}.embla__container{display:flex;touch-action:pan-y pinch-zoom;margin-left:calc(var(--slide-spacing)*-1)}.embla__slide{transform:translate3d(0, 0, 0);flex:0 0 var(--slide-size);min-width:0;padding-left:var(--slide-spacing);flex:0 0 100%}.embla__slide__number{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);border-radius:1.8rem;font-size:4rem;font-weight:600;display:flex;align-items:center;justify-content:center;height:var(--slide-height);user-select:none}.embla__controls{display:grid;grid-template-columns:auto 1fr;justify-content:space-between;gap:1.2rem;margin-top:1.8rem}.embla__buttons{display:grid;grid-template-columns:repeat(2, 1fr);gap:.6rem;align-items:center}.embla__button{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:3.6rem;height:3.6rem;z-index:1;border-radius:50%;color:var(--text-body);display:flex;align-items:center;justify-content:center}.embla__button:disabled{color:var(--detail-high-contrast)}.embla__button__svg{width:35%;height:35%}.embla__dots{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;margin-right:0;height:50px}.embla__dot{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;width:2.6rem;height:2.6rem;display:flex;align-items:center;justify-content:center;border-radius:50%}.embla__dot:after{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:1.4rem;height:1.4rem;border-radius:50%;display:flex;align-items:center;content:""}.embla__dot--selected:after{box-shadow:inset 0 0 0 .2rem var(--text-body)}.carousel-provider{height:100%}.embla{height:100%}.embla__viewport{height:100%;display:flex;flex-direction:column}.embla__container{flex:1}
@@ -7,10 +7,12 @@ export interface PreviewConfig {
7
7
  light: {
8
8
  backgroundColor: string;
9
9
  color: string;
10
+ seperatorColor?: string;
10
11
  };
11
12
  dark: {
12
13
  backgroundColor: string;
13
14
  color: string;
15
+ seperatorColor?: string;
14
16
  };
15
17
  };
16
18
  localication: Localication;
@@ -1,2 +1,3 @@
1
1
  import { Device } from '../types/Device';
2
2
  export declare function getDevices(): Device[];
3
+ export declare function getDefaultDevice(): Device;
@@ -2,13 +2,14 @@ import type { NodeDefaultAttribute } from '../types/Node';
2
2
  type Pattern = {
3
3
  schemaVersion: number;
4
4
  allowUnknownAttributes: boolean;
5
+ extends: string;
5
6
  pattern: {
6
7
  type: string;
7
8
  children: unknown;
8
- attributes: Record<string, string | string[]>;
9
+ attributes?: Record<string, string | string[]>;
9
10
  };
10
- types?: Record<string, Record<string, string | string[]>>;
11
11
  defaults?: NodeDefaultAttribute;
12
+ types?: Record<string, Record<string, string | string[]>>;
12
13
  };
13
14
  export declare function getPatternByType(type?: string | null): Pattern | undefined;
14
15
  export declare function getAttributeSchema(type?: string | null): Record<string, string | string[]> | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@developer_tribe/react-builder",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "type": "module",
5
5
  "restricted": true,
6
6
  "main": "dist/index.cjs.js",
@@ -56,6 +56,7 @@
56
56
  "sass": "^1.93.2",
57
57
  "typescript": "^5.9.2",
58
58
  "typescript-eslint": "^8.44.1",
59
+ "use-sync-external-store": "^1.6.0",
59
60
  "yargs": "^18.0.0"
60
61
  },
61
62
  "engines": {
@@ -13,6 +13,7 @@ import {
13
13
  validateExistingComponentTsx,
14
14
  createRenderNodeGenerated,
15
15
  createBuildComponentsIndex,
16
+ createPatternsGenerated,
16
17
  // createGetDefaultsPerComponent,
17
18
  // createBuildComponentsRootGetDefaults,
18
19
  formatAllSourceFiles,
@@ -42,6 +43,7 @@ async function run() {
42
43
  }
43
44
 
44
45
  await createRenderNodeGenerated(validated, paths);
46
+ await createPatternsGenerated(validated, paths);
45
47
  await createBuildComponentsIndex(validated, paths);
46
48
  // Removed: root getDefaults generator
47
49
  await formatAllSourceFiles(paths);
@@ -16,7 +16,11 @@ export async function createBuildComponentsIndex(validated, paths) {
16
16
 
17
17
  const renderNodeExport = `export { default as RenderNode } from './RenderNode.generated';`;
18
18
 
19
- const sections = [renderNodeExport, exportLines].filter(Boolean).join('\n\n');
19
+ const patternsExport = `export { patterns } from './patterns.generated';`;
20
+
21
+ const sections = [renderNodeExport, patternsExport, exportLines]
22
+ .filter(Boolean)
23
+ .join('\n\n');
20
24
 
21
25
  const fileContent =
22
26
  `/* AUTO-GENERATED FILE - DO NOT EDIT */\n\n` +
@@ -0,0 +1,23 @@
1
+ import path from 'path';
2
+ import { promises as fs } from 'fs';
3
+ import { formatWithPrettier } from './formatWithPrettier.js';
4
+
5
+ // Creates src/build-components/patterns.generated.ts that aggregates all component pattern.json files
6
+ export async function createPatternsGenerated(validated, paths) {
7
+ const { COMPONENTS_ROOT } = paths;
8
+ const targetPath = path.join(COMPONENTS_ROOT, 'patterns.generated.ts');
9
+
10
+ // Use already-validated and resolved patternJson objects and emit inline
11
+ const objectEntries = validated
12
+ .map(({ patternJson }) => JSON.stringify(patternJson))
13
+ .join(',\n ');
14
+
15
+ const fileContent =
16
+ `/* AUTO-GENERATED FILE - DO NOT EDIT */\n` +
17
+ `\n` +
18
+ `// Export resolved patterns (after extends resolution)\n` +
19
+ `export const patterns = [\n ${objectEntries}\n] as const;\n`;
20
+
21
+ const formatted = await formatWithPrettier(fileContent);
22
+ await fs.writeFile(targetPath, formatted, 'utf8');
23
+ }
@@ -11,6 +11,7 @@ export { ensurePropsTs } from './ensurePropsTs.js';
11
11
  export { createComponentTsx } from './createComponentTsx.js';
12
12
  export { createRenderNodeGenerated } from './createRenderNodeGenerated.js';
13
13
  export { createBuildComponentsIndex } from './createBuildComponentsIndex.js';
14
+ export { createPatternsGenerated } from './createPatternsGenerated.js';
14
15
  export { formatAllSourceFiles } from './formatAllSourceFiles.js';
15
16
  export { validateExistingComponentTsx } from './validateExistingComponentTsx.js';
16
17
  export { createGetDefaultsPerComponent } from './createGetDefaultsPerComponent.js';
@@ -24,7 +24,8 @@ async function getAllEntriesInComponentsRoot(paths) {
24
24
  d.name !== 'index.ts' &&
25
25
  d.name !== 'getDefaults.ts' &&
26
26
  d.name !== 'useDefaults.ts' &&
27
- d.name !== 'useNode.ts'
27
+ d.name !== 'useNode.ts' &&
28
+ d.name !== 'patterns.generated.ts'
28
29
  );
29
30
  });
30
31
  }
@@ -173,6 +174,130 @@ async function validatePatternJson(componentDir, componentName) {
173
174
  }
174
175
  }
175
176
 
177
+ // Resolve chained extends: walk up the chain, detect cycles, merge from base to child
178
+ const componentsRoot = path.dirname(componentDir);
179
+ const visited = new Set();
180
+ const ancestorStack = [];
181
+
182
+ // Track both componentName and current type for cycle detection
183
+ visited.add(componentName);
184
+ if (typeof data?.pattern?.type === 'string') visited.add(data.pattern.type);
185
+
186
+ let cursor = data;
187
+ // Collect raw ancestors without mutating child yet
188
+ while (
189
+ typeof cursor?.pattern?.extends === 'string' &&
190
+ cursor.pattern.extends.trim().length > 0
191
+ ) {
192
+ const parentName = cursor.pattern.extends.trim();
193
+ if (visited.has(parentName)) {
194
+ return fail(
195
+ `Circular dependency detected in extends chain at '${parentName}'. We don't allow circular dependency.`
196
+ );
197
+ }
198
+ visited.add(parentName);
199
+
200
+ const parentDir = path.join(componentsRoot, parentName);
201
+ const parentDirExists = await fs
202
+ .stat(parentDir)
203
+ .then(() => true)
204
+ .catch(() => false);
205
+ if (!parentDirExists) {
206
+ return fail(
207
+ `[${componentName}] extends '${parentName}' but folder not found at ${parentDir}`
208
+ );
209
+ }
210
+ const parentPatternPath = path.join(parentDir, 'pattern.json');
211
+ const parentPatternExists = await fs
212
+ .stat(parentPatternPath)
213
+ .then(() => true)
214
+ .catch(() => false);
215
+ if (!parentPatternExists) {
216
+ return fail(
217
+ `[${componentName}] extends '${parentName}' but missing pattern.json at ${parentPatternPath}`
218
+ );
219
+ }
220
+
221
+ let parentData;
222
+ try {
223
+ const parentContent = await fs.readFile(parentPatternPath, 'utf8');
224
+ parentData = JSON.parse(parentContent);
225
+ } catch (error) {
226
+ const reason =
227
+ error instanceof SyntaxError
228
+ ? 'Invalid JSON'
229
+ : error.code || error.message;
230
+ return fail(`Failed to read JSON at ${parentPatternPath}: ${reason}`);
231
+ }
232
+ if (typeof parentData?.pattern !== 'object' || parentData.pattern == null) {
233
+ return fail(
234
+ `[${componentName}] extends '${parentName}' but parent pattern.json -> 'pattern' must be an object`
235
+ );
236
+ }
237
+ if (typeof parentData.pattern.type !== 'string') {
238
+ return fail(
239
+ `[${componentName}] extends '${parentName}' but parent pattern.json -> 'pattern.type' must be a string`
240
+ );
241
+ }
242
+
243
+ // Detect cycle by type name too
244
+ const parentType = parentData.pattern.type;
245
+ if (visited.has(parentType)) {
246
+ return fail(
247
+ `Circular dependency detected in extends chain via type '${parentType}'. We don't allow circular dependency.`
248
+ );
249
+ }
250
+ visited.add(parentType);
251
+
252
+ ancestorStack.push(parentData);
253
+ cursor = parentData;
254
+ }
255
+
256
+ // Merge from the top-most ancestor down to the child
257
+ for (let i = ancestorStack.length - 1; i >= 0; i -= 1) {
258
+ const parentData = ancestorStack[i];
259
+ const parentAttributes = parentData?.pattern?.attributes || {};
260
+ const childAttributes = data?.pattern?.attributes || {};
261
+ const mergedAttributes = { ...parentAttributes, ...childAttributes };
262
+
263
+ // If child does not define children, inherit parent's
264
+ const childHasChildren = Object.prototype.hasOwnProperty.call(
265
+ data.pattern,
266
+ 'children'
267
+ );
268
+ const mergedChildren = childHasChildren
269
+ ? data.pattern.children
270
+ : parentData?.pattern?.children;
271
+
272
+ const mergedTypes = { ...(parentData.types || {}), ...(data.types || {}) };
273
+ const mergedDefaults = {
274
+ ...(parentData.defaults || {}),
275
+ ...(data.defaults || {}),
276
+ };
277
+ const mergedAllowUnknown =
278
+ typeof data.allowUnknownAttributes === 'boolean'
279
+ ? data.allowUnknownAttributes
280
+ : parentData.allowUnknownAttributes;
281
+
282
+ const mergedPattern = {
283
+ ...parentData.pattern,
284
+ ...data.pattern,
285
+ type: data.pattern.type, // keep child's type
286
+ attributes: mergedAttributes,
287
+ children: mergedChildren,
288
+ };
289
+ delete mergedPattern.extends;
290
+
291
+ data = {
292
+ ...parentData,
293
+ ...data,
294
+ allowUnknownAttributes: mergedAllowUnknown,
295
+ types: mergedTypes,
296
+ defaults: mergedDefaults,
297
+ pattern: mergedPattern,
298
+ };
299
+ }
300
+
176
301
  return data;
177
302
  }
178
303
 
@@ -1,26 +1,24 @@
1
1
  import { Localication } from './types/PreviewConfig';
2
2
  import { TargetedScreenSize } from './types/TargetedScreenSize';
3
- import { RenderMainNode } from './RenderMainNode';
4
3
  import { DeviceMockFrame } from './DeviceMockFrame';
5
4
  import { Node } from './types/Node';
6
5
  import { RenderNode } from './build-components';
7
6
  import { Device } from './types/Device';
8
- import { createContext } from 'react';
7
+ import { useEffect } from 'react';
8
+ import { useRenderStore } from './store';
9
+ export type ScreenStyle = {
10
+ light: { backgroundColor: string; color: string; seperatorColor?: string };
11
+ dark: { backgroundColor: string; color: string; seperatorColor?: string };
12
+ };
9
13
  type RenderPageProps = {
10
14
  data: Node;
11
15
  isRtl: boolean;
12
- screenStyle: {
13
- light: { backgroundColor: string; color: string };
14
- dark: { backgroundColor: string; color: string };
15
- };
16
+ screenStyle: ScreenStyle;
16
17
  theme: 'dark' | 'light';
17
18
  localication: Localication;
18
19
  defaultLanguage?: string;
19
20
  device: Device;
20
21
  };
21
- export const renderPageContext = createContext<{
22
- device: Device;
23
- } | null>(null);
24
22
  export function RenderPage({
25
23
  data,
26
24
  theme,
@@ -36,26 +34,32 @@ export function RenderPage({
36
34
  // width = (previewHeight * targetWidth) / targetHeight
37
35
  const height = screenPreviewHeight;
38
36
  const width = (height * device.width) / device.height;
37
+
38
+ useEffect(() => {
39
+ const {
40
+ setDevice,
41
+ setLocalication,
42
+ setDefaultLanguage,
43
+ setTheme,
44
+ setScreenStyle,
45
+ } = useRenderStore.getState();
46
+ setDevice(device);
47
+ setLocalication(localication);
48
+ setDefaultLanguage(defaultLanguage);
49
+ setTheme(theme);
50
+ setScreenStyle(screenStyle);
51
+ }, [device, localication, defaultLanguage, theme, screenStyle]);
52
+
39
53
  return (
40
- <renderPageContext.Provider value={{ device }}>
41
- <DeviceMockFrame
42
- width={width}
43
- height={height}
44
- isRtl={isRtl}
45
- screenStyle={screenStyle}
46
- theme={theme}
47
- device={device}
48
- >
49
- {
50
- <RenderMainNode
51
- localication={localication}
52
- defaultLanguage={defaultLanguage}
53
- theme={theme}
54
- >
55
- <RenderNode node={data} />
56
- </RenderMainNode>
57
- }
58
- </DeviceMockFrame>
59
- </renderPageContext.Provider>
54
+ <DeviceMockFrame
55
+ width={width}
56
+ height={height}
57
+ isRtl={isRtl}
58
+ screenStyle={screenStyle}
59
+ theme={theme}
60
+ device={device}
61
+ >
62
+ <RenderNode node={data} />
63
+ </DeviceMockFrame>
60
64
  );
61
65
  }
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import type { ButtonComponentProps } from './ButtonProps.generated';
3
- import useDefaults from '../useNode';
3
+ import useNode from '../useNode';
4
4
 
5
5
  function Button({ node }: ButtonComponentProps) {
6
- node = useDefaults(node);
6
+ node = useNode(node);
7
7
  return String(node?.type ?? 'button');
8
8
  }
9
9
 
@@ -2,10 +2,10 @@ import React from 'react';
2
2
  import type { CarouselComponentProps } from './CarouselProps.generated';
3
3
  import RenderNode from '../RenderNode.generated';
4
4
  import { isCarouselItem } from '../../utils/isCarousel';
5
- import useDefaults from '../useNode';
5
+ import useNode from '../useNode';
6
6
 
7
7
  function Carousel({ node }: CarouselComponentProps) {
8
- node = useDefaults(node);
8
+ node = useNode(node);
9
9
  // Ensure children are carouselItems
10
10
  const renderChildren = () => {
11
11
  if (Array.isArray(node.children)) {
@@ -1,10 +1,10 @@
1
1
  import React, { useContext } from 'react';
2
2
  import type { CarouselButtonsComponentProps } from './CarouselButtonsProps.generated';
3
3
  import { carouselContext } from '../CarouselProvider/CarouselProvider';
4
- import useDefaults from '../useNode';
4
+ import useNode from '../useNode';
5
5
 
6
6
  function CarouselButtons({ node }: CarouselButtonsComponentProps) {
7
- node = useDefaults(node);
7
+ node = useNode(node);
8
8
  const emblaApi = useContext(carouselContext);
9
9
  const buttonTypes = node.attributes?.buttonType || [
10
10
  'previous_button',
@@ -1,10 +1,10 @@
1
1
  import React, { useContext, useEffect, useState } from 'react';
2
2
  import type { CarouselDotsComponentProps } from './CarouselDotsProps.generated';
3
3
  import { carouselContext } from '../CarouselProvider/CarouselProvider';
4
- import useDefaults from '../useNode';
4
+ import useNode from '../useNode';
5
5
 
6
6
  function CarouselDots({ node }: CarouselDotsComponentProps) {
7
- node = useDefaults(node);
7
+ node = useNode(node);
8
8
  const dotType = node.attributes?.dotType || 'normal_dot';
9
9
  const emblaApi = useContext(carouselContext);
10
10
  const [selectedIndex, setSelectedIndex] = useState(0);
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { CarouselItemComponentProps } from './CarouselItemProps.generated';
3
3
  import { RenderNode } from '../..';
4
- import useDefaults from '../useNode';
4
+ import useNode from '../useNode';
5
5
 
6
6
  export function CarouselItem({ node }: CarouselItemComponentProps) {
7
- node = useDefaults(node);
7
+ node = useNode(node);
8
8
  return (
9
9
  <div className="embla__slide" {...node.attributes}>
10
10
  {node.children && <RenderNode node={node.children} />}
@@ -2,11 +2,11 @@ import React, { createContext } from 'react';
2
2
  import type { CarouselProviderComponentProps } from './CarouselProviderProps.generated';
3
3
  import { RenderNode } from '../..';
4
4
  import useEmblaCarousel from 'embla-carousel-react';
5
- import useDefaults from '../useNode';
5
+ import useNode from '../useNode';
6
6
 
7
7
  export const carouselContext = createContext<any>(undefined);
8
8
  function CarouselProvider({ node }: CarouselProviderComponentProps) {
9
- node = useDefaults(node);
9
+ node = useNode(node);
10
10
  const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
11
11
  return (
12
12
  <carouselContext.Provider value={emblaApi}>
@@ -1,13 +1,12 @@
1
1
  import React from 'react';
2
2
  import type { ImageComponentProps } from './ImageProps.generated';
3
- import useDefaults from '../useNode';
3
+ import useNode from '../useNode';
4
4
 
5
5
  function Image({ node }: ImageComponentProps) {
6
- node = useDefaults(node);
6
+ node = useNode(node);
7
7
  return (
8
8
  <img
9
9
  key={node.key}
10
- className="primitive primitive-image"
11
10
  src={node.attributes?.src}
12
11
  width={node.attributes?.width}
13
12
  height={node.attributes?.height}
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { OnboardComponentProps } from './OnboardProps.generated';
3
3
  import Carousel from '../Carousel/Carousel';
4
- import useDefaults from '../useNode';
4
+ import useNode from '../useNode';
5
5
 
6
6
  function Onboard({ node }: OnboardComponentProps) {
7
- node = useDefaults(node);
7
+ node = useNode(node);
8
8
  return <Carousel node={{ ...node, type: 'carousel' } as any} />;
9
9
  }
10
10
 
@@ -1,13 +1,16 @@
1
1
  import React, { useContext } from 'react';
2
2
  import type { OnboardButtonComponentProps } from './OnboardButtonProps.generated';
3
3
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
4
- import { mainNodeContext } from '../../RenderMainNode';
5
- import useDefaults from '../useNode';
4
+ import useNode from '../useNode';
5
+ import { useRenderStore } from '../../store';
6
6
 
7
7
  function OnboardButton({ node }: OnboardButtonComponentProps) {
8
- node = useDefaults(node);
8
+ node = useNode(node);
9
9
  const { emblaApi } = useContext(onboardContext) ?? {};
10
- const { localication, defaultLanguage } = useContext(mainNodeContext) ?? {};
10
+ const { defaultLanguage, localication } = useRenderStore((s) => ({
11
+ defaultLanguage: s.defaultLanguage,
12
+ localication: s.localication,
13
+ }));
11
14
 
12
15
  const labelRaw = node.attributes?.labelKey ?? '';
13
16
  const label =
@@ -3,14 +3,19 @@ import type { Node } from '../../types/Node';
3
3
  import type { OnboardButtonsComponentProps } from './OnboardButtonsProps.generated';
4
4
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
5
5
  import RenderNode from '../RenderNode.generated';
6
- import useDefaults from '../useNode';
7
-
8
- const THEME_COLORS = {
9
- ONBOARD_SEPARATOR_COLOR: '#E5E7EB',
10
- };
6
+ import useNode from '../useNode';
7
+ import { useRenderStore } from '../../store';
11
8
 
12
9
  function OnboardButtons({ node }: OnboardButtonsComponentProps) {
13
- node = useDefaults(node);
10
+ node = useNode(node);
11
+ const { screenStyle, theme } = useRenderStore((s) => ({
12
+ screenStyle: s.screenStyle,
13
+ theme: s.theme,
14
+ }));
15
+ const seperatorColorDefault =
16
+ theme === 'light'
17
+ ? screenStyle.light.seperatorColor
18
+ : screenStyle.dark.seperatorColor;
14
19
  const ctx = useContext(onboardContext) ?? {};
15
20
  const emblaApi = ctx.emblaApi;
16
21
  const [selectedIndex, setSelectedIndex] = useState(ctx.selectedIndex ?? 0);
@@ -30,7 +35,8 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
30
35
 
31
36
  const direction =
32
37
  node.attributes?.buttons_direction === 'column' ? 'column' : 'row';
33
- const seperatorColor = node.attributes?.seperatorColor;
38
+ const seperatorColor =
39
+ node.attributes?.seperatorColor ?? seperatorColorDefault;
34
40
 
35
41
  const renderChildren = () => {
36
42
  if (Array.isArray(node.children)) {
@@ -47,8 +53,7 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
47
53
  className="onboard__separator"
48
54
  style={{
49
55
  height: 1,
50
- backgroundColor:
51
- seperatorColor ?? THEME_COLORS.ONBOARD_SEPARATOR_COLOR,
56
+ backgroundColor: seperatorColor,
52
57
  width: '100%',
53
58
  }}
54
59
  />
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { OnboardDotComponentProps } from './OnboardExpandingDotProps.generated';
3
3
  import CarouselDots from '../CarouselDots/CarouselDots';
4
- import useDefaults from '../useNode';
4
+ import useNode from '../useNode';
5
5
 
6
6
  function OnboardDot({ node }: OnboardDotComponentProps) {
7
- node = useDefaults(node);
7
+ node = useNode(node);
8
8
  return <CarouselDots node={{ ...node, type: 'carouselDots' } as any} />;
9
9
  }
10
10