@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
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect, useMemo, useState } from 'react';
1
+ import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
2
2
  import type { Node } from '../../types/Node';
3
3
  import type { OnboardButtonsComponentProps } from './OnboardButtonsProps.generated';
4
4
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
@@ -11,10 +11,11 @@ import { extractViewStyle } from '../../utils/extractViewStyle';
11
11
  function OnboardButtons({ node }: OnboardButtonsComponentProps) {
12
12
  useLogRender('OnboardButtons');
13
13
  node = useNode(node);
14
- const attributeKey =
14
+ const attributeName =
15
15
  (node as any)?.sourceType ?? node.type ?? 'OnboardButtons';
16
- const { appConfig } = useRenderStore((s) => ({
16
+ const { appConfig, projectColors } = useRenderStore((s) => ({
17
17
  appConfig: s.appConfig,
18
+ projectColors: s.projectColors,
18
19
  }));
19
20
  const seperatorColorDefault =
20
21
  appConfig.theme === 'light'
@@ -43,7 +44,14 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
43
44
  return <RenderNode node={node.children as Node} />;
44
45
  };
45
46
 
46
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
47
+ const viewStyle = useMemo(
48
+ () => extractViewStyle(node, { appConfig, projectColors }),
49
+ [node, appConfig, projectColors],
50
+ );
51
+
52
+ // NOTE: Hooks must not be called conditionally.
53
+ // Generate the id before any early returns so the hook order stays stable.
54
+ const generatedId = useId();
47
55
 
48
56
  // New condition logic: hide when condition is carousel-index and does not match
49
57
  const condition = (node.attributes as any)?.condition;
@@ -58,7 +66,11 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
58
66
  }
59
67
 
60
68
  return (
61
- <div attribute-key={attributeKey} style={viewStyle}>
69
+ <div
70
+ attribute-name={attributeName}
71
+ attribute-key={node.key ?? generatedId}
72
+ style={viewStyle}
73
+ >
62
74
  <div
63
75
  className="onboard__separator"
64
76
  style={{
@@ -16,6 +16,7 @@ export type JustifyContentOptionType =
16
16
  | 'space-between'
17
17
  | 'space-around'
18
18
  | 'space-evenly';
19
+ export type PositionOptionType = 'relative' | 'absolute';
19
20
  export type ButtonTypeOptionType =
20
21
  | 'previous_button'
21
22
  | 'next_button'
@@ -48,6 +49,13 @@ export interface OnboardButtonsPropsGenerated {
48
49
  borderRadius?: string;
49
50
  width?: string;
50
51
  height?: string;
52
+ flex?: number;
53
+ position?: PositionOptionType;
54
+ top?: string;
55
+ bottom?: string;
56
+ left?: string;
57
+ right?: string;
58
+ zIndex?: number;
51
59
  buttonType?: ButtonTypeOptionType;
52
60
  skipNumber?: number;
53
61
  buttons_direction?: ButtonsDirectionOptionType;
@@ -1,44 +1,78 @@
1
- import React, { useContext, useEffect, useMemo, useState } from 'react';
1
+ import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
2
2
  import type { OnboardDotComponentProps } from './OnboardDotProps.generated';
3
3
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
4
4
  import useNode from '../useNode';
5
5
  import { useLogRender } from '../../utils/useLogRender';
6
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
7
7
  import { useRenderStore } from '../../store';
8
+ import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
9
+ import { useMergedStyle } from '../../utils/useMergedStyle';
10
+ import { parseColor } from '../../utils/parseColor';
11
+ import { parseSize } from '../../size-matters';
8
12
 
9
13
  function OnboardDot({ node }: OnboardDotComponentProps) {
10
14
  useLogRender('OnboardDot');
11
15
 
12
16
  node = useNode(node);
13
17
 
14
- const attributeKey = node.type ?? 'OnboardDot';
18
+ const generatedId = useId();
19
+ const attributeName = node.type ?? 'OnboardDot';
20
+ const attributeKey = node.key ?? generatedId;
15
21
  const dotType = node.attributes?.dotType || 'normal_dot';
16
22
  const GHOST_DOT_DARK_COLOR = '#E4E5E7';
17
23
  const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
18
- const isDark = useRenderStore((s) => s.appConfig.theme === 'dark');
24
+ const { previewMode, current, appConfig, projectColors } = useRenderStore(
25
+ (s) => ({
26
+ previewMode: s.previewMode,
27
+ current: s.current,
28
+ appConfig: s.appConfig,
29
+ projectColors: s.projectColors,
30
+ }),
31
+ );
32
+ const isDark = appConfig.theme === 'dark';
19
33
 
20
34
  // OnboardDot specific attributes
21
35
  const inactiveDotColor = isDark
22
36
  ? GHOST_DOT_DARK_COLOR
23
37
  : GHOST_DOT_LIGHT_COLOR;
24
38
  const inactiveDotOpacity = node.attributes?.inactive_dot_opacity ?? 0.3;
25
- const dotStyle = node.attributes?.dot_style;
26
- const containerStyle = node.attributes?.container_style;
27
39
  const activeDotColor = node.attributes?.active_dot_color;
40
+ const resolvedActiveDotColor = useMemo(
41
+ () => parseColor(activeDotColor, { appConfig, projectColors }),
42
+ [activeDotColor, appConfig, projectColors],
43
+ );
28
44
 
29
- const style = useMemo(() => {
30
- const baseStyle = extractViewStyle(node);
31
- // Merge container_style if provided
32
- if (containerStyle) {
33
- try {
34
- const parsedContainerStyle = JSON.parse(containerStyle);
35
- Object.assign(baseStyle, parsedContainerStyle);
36
- } catch (e) {
37
- // Invalid JSON, ignore
38
- }
39
- }
40
- return baseStyle;
41
- }, [node, containerStyle]);
45
+ const baseStyle = useMemo(() => {
46
+ let innerStyle = extractViewStyle(node, { appConfig, projectColors });
47
+ delete innerStyle.flexDirection;
48
+ return innerStyle;
49
+ }, [node, appConfig, projectColors]);
50
+ const isSelected = isNodeSelected({ previewMode, current, node });
51
+ const style = useMergedStyle(
52
+ baseStyle,
53
+ isSelected ? SELECTED_OUTLINE_STYLE : undefined,
54
+ );
55
+ const expandingDotWidthRaw = node.attributes?.expanding_dot_width;
56
+ const expandingDotWidthOverride = useMemo(() => {
57
+ const parsed = parseSize(expandingDotWidthRaw);
58
+ if (parsed === undefined) return undefined;
59
+
60
+ // `parseSize` may return number (px) or a string (e.g. "50%").
61
+ const cssWidth =
62
+ typeof parsed === 'number'
63
+ ? `${parsed}px`
64
+ : typeof parsed === 'string'
65
+ ? parsed
66
+ : undefined;
67
+
68
+ if (!cssWidth) return undefined;
69
+
70
+ return {
71
+ // Controls the actual dot diameter (`.embla__dot:after`).
72
+ ['--embla-dot-size' as any]: cssWidth,
73
+ } as React.CSSProperties;
74
+ }, [expandingDotWidthRaw]);
75
+ const containerStyle = useMergedStyle(style, expandingDotWidthOverride);
42
76
 
43
77
  const onboardApi = useContext(onboardContext);
44
78
  const emblaApi = onboardApi?.emblaApi;
@@ -66,43 +100,38 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
66
100
  };
67
101
  }, [emblaApi]);
68
102
 
69
- // Parse dot_style if provided
70
- const parsedDotStyle = useMemo(() => {
71
- if (!dotStyle) return {};
72
- try {
73
- return JSON.parse(dotStyle);
74
- } catch (e) {
75
- return {};
76
- }
77
- }, [dotStyle]);
78
-
79
103
  return (
80
104
  <div
105
+ attribute-name={attributeName}
81
106
  attribute-key={attributeKey}
82
107
  className={`embla__dots embla__dots--${dotType}`}
83
- style={style}
108
+ style={containerStyle}
84
109
  >
85
110
  {scrollSnaps.map((snap, index) => {
86
- const isSelected = selectedIndex === index;
111
+ const isDotSelected = selectedIndex === index;
87
112
  const dotStyles: React.CSSProperties = {
88
- ...parsedDotStyle,
89
- opacity: isSelected ? 1 : inactiveDotOpacity,
113
+ opacity: isDotSelected ? 1 : inactiveDotOpacity,
90
114
  };
91
115
 
92
- if (activeDotColor && isSelected) {
93
- dotStyles.color = activeDotColor;
94
- } else if (!isSelected) {
95
- dotStyles.color = inactiveDotColor;
116
+ if (resolvedActiveDotColor && isDotSelected) {
117
+ // Style the actual visual dot (rendered via `.embla__dot:after`) using a CSS variable.
118
+ (dotStyles as any)['--embla-dot-color'] = resolvedActiveDotColor;
119
+ } else if (!isDotSelected) {
120
+ (dotStyles as any)['--embla-dot-color'] = inactiveDotColor;
96
121
  }
97
122
 
98
123
  return (
99
124
  <button
100
125
  key={index}
101
- onClick={() => emblaApi?.scrollTo(snap)}
102
- className={`embla__dot ${isSelected ? 'embla__dot--selected' : ''}`}
126
+ onClick={() => {
127
+ emblaApi?.scrollTo(snap);
128
+ }}
129
+ className={`embla__dot ${isDotSelected ? 'embla__dot--selected' : ''}`}
103
130
  style={dotStyles}
131
+ aria-label={`Go to slide ${index + 1}`}
132
+ aria-current={isDotSelected ? 'true' : undefined}
104
133
  >
105
- {isSelected ? '●' : '○'}
134
+ {/* Dot visuals are rendered via CSS (`.embla__dot:after`). */}
106
135
  </button>
107
136
  );
108
137
  })}
@@ -2,6 +2,7 @@
2
2
 
3
3
  import type { NodeData } from '../../types/Node';
4
4
 
5
+ export type PositionOptionType = 'relative' | 'absolute';
5
6
  export type DotTypeOptionType =
6
7
  | 'expanding_dot'
7
8
  | 'normal_dot'
@@ -35,11 +36,16 @@ export interface OnboardDotPropsGenerated {
35
36
  borderRadius?: string;
36
37
  width?: string;
37
38
  height?: string;
39
+ flex?: number;
40
+ position?: PositionOptionType;
41
+ top?: string;
42
+ bottom?: string;
43
+ left?: string;
44
+ right?: string;
45
+ zIndex?: number;
38
46
  dotType?: DotTypeOptionType;
39
47
  inactive_dot_opacity?: number;
40
- expanding_dot_width?: number;
41
- dot_style?: string;
42
- container_style?: string;
48
+ expanding_dot_width?: string;
43
49
  active_dot_color?: string;
44
50
  };
45
51
  }
@@ -3,7 +3,7 @@
3
3
  "allowUnknownAttributes": false,
4
4
  "pattern": {
5
5
  "type": "OnboardDot",
6
- "children": "node",
6
+ "children": "never",
7
7
  "extends": "View",
8
8
  "attributes": {
9
9
  "dotType": [
@@ -15,9 +15,7 @@
15
15
  "liquid_like"
16
16
  ],
17
17
  "inactive_dot_opacity": "number",
18
- "expanding_dot_width": "number",
19
- "dot_style": "string",
20
- "container_style": "string",
18
+ "expanding_dot_width": "size",
21
19
  "active_dot_color": "color",
22
20
  "flexDirection": "never",
23
21
  "alignItems": "never",
@@ -50,26 +48,12 @@
50
48
  "specialCategory": null,
51
49
  "sort": 3
52
50
  },
53
- "dot_style": {
54
- "label": "Dot Style",
55
- "description": "Custom style for each dot.",
56
- "category": "style",
57
- "specialCategory": null,
58
- "sort": 4
59
- },
60
- "container_style": {
61
- "label": "Container Style",
62
- "description": "Style for the dot wrapper.",
63
- "category": "style",
64
- "specialCategory": null,
65
- "sort": 5
66
- },
67
51
  "active_dot_color": {
68
52
  "label": "Active Dot Color",
69
53
  "description": "Color of the active dot.",
70
54
  "category": "style",
71
55
  "specialCategory": null,
72
- "sort": 6
56
+ "sort": 4
73
57
  }
74
58
  }
75
59
  }
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useId, useMemo } from 'react';
2
2
  import type { OnboardFooterComponentProps } from './OnboardFooterProps.generated';
3
3
  import useNode from '../useNode';
4
4
  import { useRenderStore } from '../../store';
@@ -6,6 +6,8 @@ import { parseSize } from '../../size-matters';
6
6
  import { extractTextStyle } from '../../utils/extractTextStyle';
7
7
  import { extractViewStyle } from '../../utils/extractViewStyle';
8
8
  import { useLogRender } from '../../utils/useLogRender';
9
+ import { isNodeSelected } from '../../utils/selection';
10
+ import { useMergedStyle } from '../../utils/useMergedStyle';
9
11
 
10
12
  type Segment =
11
13
  | { type: 'text'; value: string }
@@ -90,18 +92,29 @@ function buildSegments(
90
92
  function OnboardFooter({ node }: OnboardFooterComponentProps) {
91
93
  useLogRender('OnboardFooter');
92
94
  node = useNode(node);
93
- const attributeKey =
95
+ const attributeName =
94
96
  (node as any)?.sourceType ?? node.type ?? 'OnboardFooter';
95
- const { appConfig } = useRenderStore((s) => ({
96
- appConfig: s.appConfig,
97
- }));
97
+ const { appConfig, projectColors, previewMode, current } = useRenderStore(
98
+ (s) => ({
99
+ appConfig: s.appConfig,
100
+ projectColors: s.projectColors,
101
+ previewMode: s.previewMode,
102
+ current: s.current,
103
+ }),
104
+ );
98
105
  const { localication, defaultLanguage } = appConfig;
99
106
  const t = (key?: string) =>
100
107
  key ? (localication?.[defaultLanguage ?? 'en']?.[key] ?? key) : '';
101
108
 
102
109
  const text = t(node?.attributes?.textLocalizationKey);
103
- const textStyle: React.CSSProperties = extractTextStyle(node);
104
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
110
+ const textStyle = useMemo(
111
+ () => extractTextStyle(node, { appConfig, projectColors }),
112
+ [node, appConfig, projectColors],
113
+ );
114
+ const viewStyle = useMemo(
115
+ () => extractViewStyle(node, { appConfig, projectColors }),
116
+ [node, appConfig, projectColors],
117
+ );
105
118
 
106
119
  const linkStyle = (color?: string): React.CSSProperties => ({
107
120
  color,
@@ -109,16 +122,26 @@ function OnboardFooter({ node }: OnboardFooterComponentProps) {
109
122
  });
110
123
 
111
124
  const paddingHorizontal = parseSize(node?.attributes?.paddingHorizontal);
125
+ const layoutStyle = useMemo<React.CSSProperties>(
126
+ () => ({
127
+ paddingLeft: paddingHorizontal,
128
+ paddingRight: paddingHorizontal,
129
+ textAlign: 'center',
130
+ }),
131
+ [paddingHorizontal],
132
+ );
133
+
134
+ const isSelected = isNodeSelected({ previewMode, current, node });
135
+ const baseStyle = useMergedStyle(viewStyle, textStyle);
136
+ const paddedStyle = useMergedStyle(baseStyle, layoutStyle);
137
+ const generatedId = useId();
138
+ const attributeKey = node.key ?? generatedId;
112
139
  return (
113
140
  <div
141
+ attribute-name={attributeName}
114
142
  attribute-key={attributeKey}
115
- style={{
116
- ...viewStyle,
117
- ...textStyle,
118
- paddingLeft: paddingHorizontal,
119
- paddingRight: paddingHorizontal,
120
- textAlign: 'center',
121
- }}
143
+ className={isSelected ? 'rb-node-selected' : undefined}
144
+ style={paddedStyle}
122
145
  >
123
146
  {!!text &&
124
147
  (() => {
@@ -29,6 +29,7 @@ export type JustifyContentOptionType =
29
29
  | 'space-between'
30
30
  | 'space-around'
31
31
  | 'space-evenly';
32
+ export type PositionOptionType = 'relative' | 'absolute';
32
33
 
33
34
  export interface OnboardFooterPropsGenerated {
34
35
  child: string;
@@ -59,6 +60,13 @@ export interface OnboardFooterPropsGenerated {
59
60
  borderRadius?: string;
60
61
  width?: string;
61
62
  height?: string;
63
+ flex?: number;
64
+ position?: PositionOptionType;
65
+ top?: string;
66
+ bottom?: string;
67
+ left?: string;
68
+ right?: string;
69
+ zIndex?: number;
62
70
  textLocalizationKey?: string;
63
71
  linkedWordFirstLocalizationKey?: string;
64
72
  linkedWordFirstColor?: string;
@@ -1,17 +1,28 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useEffect, useId, useMemo, useState } from 'react';
2
2
  import type { OnboardImageComponentProps } from './OnboardImageProps.generated';
3
3
  import Image from '../Image/Image';
4
4
  import useNode from '../useNode';
5
5
  import Lottie from 'lottie-react';
6
6
  import { useLogRender } from '../../utils/useLogRender';
7
7
  import { extractViewStyle } from '../../utils/extractViewStyle';
8
+ import { useRenderStore } from '../../store';
8
9
 
9
10
  function OnboardImage({ node }: OnboardImageComponentProps) {
10
11
  useLogRender('OnboardImage');
11
12
  node = useNode(node);
12
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'OnboardImage';
13
+ const generatedId = useId();
14
+ const attributeName =
15
+ (node as any)?.sourceType ?? node.type ?? 'OnboardImage';
16
+ const attributeKey = node.key ?? generatedId;
13
17
  const [lottie, setLottie] = useState<string | null>(null);
14
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
18
+ const { appConfig, projectColors } = useRenderStore((s) => ({
19
+ appConfig: s.appConfig,
20
+ projectColors: s.projectColors,
21
+ }));
22
+ const viewStyle = useMemo(
23
+ () => extractViewStyle(node, { appConfig, projectColors }),
24
+ [node, appConfig, projectColors],
25
+ );
15
26
 
16
27
  useEffect(() => {
17
28
  if (node.attributes?.lottie) {
@@ -24,6 +35,7 @@ function OnboardImage({ node }: OnboardImageComponentProps) {
24
35
  if (node.attributes?.video_url) {
25
36
  return (
26
37
  <video
38
+ attribute-name={attributeName}
27
39
  attribute-key={attributeKey}
28
40
  autoPlay
29
41
  muted
@@ -37,13 +49,21 @@ function OnboardImage({ node }: OnboardImageComponentProps) {
37
49
  if (node.attributes?.lottie) {
38
50
  if (lottie) {
39
51
  return (
40
- <div attribute-key={attributeKey} style={viewStyle}>
52
+ <div
53
+ attribute-name={attributeName}
54
+ attribute-key={attributeKey}
55
+ style={viewStyle}
56
+ >
41
57
  <Lottie animationData={lottie} />
42
58
  </div>
43
59
  );
44
60
  } else {
45
61
  return (
46
- <div attribute-key={attributeKey} style={viewStyle}>
62
+ <div
63
+ attribute-name={attributeName}
64
+ attribute-key={attributeKey}
65
+ style={viewStyle}
66
+ >
47
67
  Loading...
48
68
  </div>
49
69
  );
@@ -51,7 +71,9 @@ function OnboardImage({ node }: OnboardImageComponentProps) {
51
71
  }
52
72
 
53
73
  return (
54
- <Image node={{ ...node, type: 'image', sourceType: attributeKey } as any} />
74
+ <Image
75
+ node={{ ...node, type: 'image', sourceType: attributeName } as any}
76
+ />
55
77
  );
56
78
  }
57
79
 
@@ -17,6 +17,7 @@ export type JustifyContentOptionType =
17
17
  | 'space-between'
18
18
  | 'space-around'
19
19
  | 'space-evenly';
20
+ export type PositionOptionType = 'relative' | 'absolute';
20
21
 
21
22
  export interface OnboardImagePropsGenerated {
22
23
  child: string;
@@ -25,7 +26,6 @@ export interface OnboardImagePropsGenerated {
25
26
  width?: string;
26
27
  height?: string;
27
28
  resizeMode?: ResizeModeOptionType;
28
- borderRadius?: string;
29
29
  scrollable?: boolean;
30
30
  flexDirection?: FlexDirectionOptionType;
31
31
  alignItems?: AlignItemsOptionType;
@@ -45,6 +45,14 @@ export interface OnboardImagePropsGenerated {
45
45
  marginLeft?: string;
46
46
  marginRight?: string;
47
47
  backgroundColor?: string;
48
+ borderRadius?: string;
49
+ flex?: number;
50
+ position?: PositionOptionType;
51
+ top?: string;
52
+ bottom?: string;
53
+ left?: string;
54
+ right?: string;
55
+ zIndex?: number;
48
56
  video_url?: string;
49
57
  lottie?: string;
50
58
  };
@@ -1,7 +1,8 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useId, useMemo } from 'react';
2
2
  import type { OnboardItemComponentProps } from './OnboardItemProps.generated';
3
3
  import useNode from '../useNode';
4
4
  import { RenderNode } from '../..';
5
+ import { useRenderStore } from '../../store';
5
6
  import { parseSize } from '../../size-matters';
6
7
  import { useLogRender } from '../../utils/useLogRender';
7
8
  import { extractViewStyle } from '../../utils/extractViewStyle';
@@ -9,23 +10,23 @@ import { extractViewStyle } from '../../utils/extractViewStyle';
9
10
  function OnboardItem({ node }: OnboardItemComponentProps) {
10
11
  useLogRender('OnboardItem');
11
12
  node = useNode(node);
12
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'OnboardItem';
13
- const flexDirection = node.attributes?.flexDirection;
14
- const display = node.attributes?.display;
15
- const paddingHorizontal = parseSize(node.attributes?.paddingHorizontal);
16
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
13
+ const generatedId = useId();
14
+ const attributeName = (node as any)?.sourceType ?? node.type ?? 'OnboardItem';
15
+ const attributeKey = node.key ?? generatedId;
16
+ const { appConfig, projectColors } = useRenderStore((s) => ({
17
+ appConfig: s.appConfig,
18
+ projectColors: s.projectColors,
19
+ }));
20
+ const viewStyle = useMemo(
21
+ () => extractViewStyle(node, { appConfig, projectColors }),
22
+ [node, appConfig, projectColors],
23
+ );
17
24
  return (
18
25
  <div
26
+ attribute-name={attributeName}
19
27
  attribute-key={attributeKey}
20
28
  className="embla__slide"
21
- style={{
22
- ...viewStyle,
23
- gap: parseSize(node.attributes?.gap),
24
- flexDirection,
25
- display,
26
- paddingRight: paddingHorizontal,
27
- paddingLeft: paddingHorizontal,
28
- }}
29
+ style={viewStyle}
29
30
  >
30
31
  {node.children && <RenderNode node={node.children} />}
31
32
  </div>
@@ -16,6 +16,7 @@ export type JustifyContentOptionType =
16
16
  | 'space-between'
17
17
  | 'space-around'
18
18
  | 'space-evenly';
19
+ export type PositionOptionType = 'relative' | 'absolute';
19
20
  export type DisplayOptionType = 'flex' | 'block';
20
21
 
21
22
  export interface OnboardItemPropsGenerated {
@@ -43,6 +44,13 @@ export interface OnboardItemPropsGenerated {
43
44
  borderRadius?: string;
44
45
  width?: string;
45
46
  height?: string;
47
+ flex?: number;
48
+ position?: PositionOptionType;
49
+ top?: string;
50
+ bottom?: string;
51
+ left?: string;
52
+ right?: string;
53
+ zIndex?: number;
46
54
  display?: DisplayOptionType;
47
55
  };
48
56
  }