@developer_tribe/react-builder 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/AttributesEditor.d.ts +3 -1
  2. package/dist/RenderPage.d.ts +2 -1
  3. package/dist/attributes-editor/Field.d.ts +2 -1
  4. package/dist/attributes-editor/SpecialCategorySection.d.ts +2 -1
  5. package/dist/build-components/BackgroundImage/BackgroundImage.d.ts +5 -0
  6. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +44 -0
  7. package/dist/build-components/Button/ButtonProps.generated.d.ts +7 -0
  8. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +7 -0
  9. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +7 -0
  10. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +7 -0
  11. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +7 -0
  12. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +7 -0
  13. package/dist/build-components/Image/ImageProps.generated.d.ts +7 -0
  14. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +7 -0
  15. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +7 -0
  16. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +7 -0
  17. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +7 -0
  18. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +7 -0
  19. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +7 -0
  20. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +7 -0
  21. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +7 -1
  22. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +7 -0
  23. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +7 -0
  24. package/dist/build-components/Text/TextProps.generated.d.ts +7 -0
  25. package/dist/build-components/View/ViewProps.generated.d.ts +7 -0
  26. package/dist/build-components/index.d.ts +2 -1
  27. package/dist/build-components/patterns.generated.d.ts +1444 -15
  28. package/dist/components/AttributesEditorPanel.d.ts +3 -4
  29. package/dist/components/Builder.d.ts +2 -1
  30. package/dist/components/BuilderButton.d.ts +9 -0
  31. package/dist/index.cjs.js +5 -5
  32. package/dist/index.cjs.js.map +1 -1
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.esm.js +5 -5
  35. package/dist/index.esm.js.map +1 -1
  36. package/dist/modals/ColorModal.d.ts +3 -1
  37. package/dist/pages/ProjectPage.d.ts +3 -3
  38. package/dist/pages/tabs/BuilderPanel.d.ts +8 -0
  39. package/dist/pages/tabs/{DebugTab.d.ts → SideTool.d.ts} +2 -2
  40. package/dist/store.d.ts +7 -1
  41. package/dist/styles.css +1 -1
  42. package/dist/types/Project.d.ts +11 -0
  43. package/dist/utils/analyseNode.d.ts +1 -0
  44. package/dist/utils/extractTextStyle.d.ts +8 -1
  45. package/dist/utils/extractViewStyle.d.ts +8 -1
  46. package/dist/utils/parseColor.d.ts +7 -0
  47. package/package.json +1 -1
  48. package/src/AttributesEditor.tsx +76 -14
  49. package/src/RenderPage.tsx +82 -4
  50. package/src/attributes-editor/Field.tsx +12 -5
  51. package/src/attributes-editor/SpecialCategorySection.tsx +2 -1
  52. package/src/build-components/BackgroundImage/BackgroundImage.tsx +87 -0
  53. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +60 -0
  54. package/src/build-components/BackgroundImage/pattern.json +45 -0
  55. package/src/build-components/Button/Button.tsx +31 -4
  56. package/src/build-components/Button/ButtonProps.generated.ts +7 -0
  57. package/src/build-components/Carousel/Carousel.tsx +27 -3
  58. package/src/build-components/Carousel/CarouselProps.generated.ts +7 -0
  59. package/src/build-components/CarouselButtons/CarouselButtons.tsx +19 -4
  60. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +7 -0
  61. package/src/build-components/CarouselDots/CarouselDots.tsx +13 -4
  62. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +7 -0
  63. package/src/build-components/CarouselItem/CarouselItem.tsx +20 -4
  64. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +7 -0
  65. package/src/build-components/CarouselProvider/CarouselProvider.tsx +14 -3
  66. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +7 -0
  67. package/src/build-components/Image/Image.tsx +29 -4
  68. package/src/build-components/Image/ImageProps.generated.ts +7 -0
  69. package/src/build-components/Onboard/Onboard.tsx +2 -2
  70. package/src/build-components/Onboard/OnboardProps.generated.ts +7 -0
  71. package/src/build-components/OnboardButton/OnboardButton.tsx +11 -4
  72. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +7 -0
  73. package/src/build-components/OnboardButtons/OnboardButtons.tsx +17 -5
  74. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +7 -0
  75. package/src/build-components/OnboardDot/OnboardDot.tsx +15 -6
  76. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +7 -0
  77. package/src/build-components/OnboardDot/pattern.json +1 -1
  78. package/src/build-components/OnboardFooter/OnboardFooter.tsx +15 -5
  79. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +7 -0
  80. package/src/build-components/OnboardImage/OnboardImage.tsx +28 -6
  81. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +7 -0
  82. package/src/build-components/OnboardItem/OnboardItem.tsx +14 -3
  83. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +7 -0
  84. package/src/build-components/OnboardProvider/OnboardProvider.tsx +34 -12
  85. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +7 -1
  86. package/src/build-components/OnboardProvider/pattern.json +0 -8
  87. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +7 -0
  88. package/src/build-components/OnboardSubtitle/pattern.json +1 -1
  89. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +7 -0
  90. package/src/build-components/OnboardTitle/pattern.json +1 -1
  91. package/src/build-components/RenderNode.generated.tsx +3 -0
  92. package/src/build-components/Text/Text.tsx +33 -9
  93. package/src/build-components/Text/TextProps.generated.ts +7 -0
  94. package/src/build-components/View/View.tsx +27 -3
  95. package/src/build-components/View/ViewProps.generated.ts +7 -0
  96. package/src/build-components/View/pattern.json +59 -1
  97. package/src/build-components/index.ts +5 -0
  98. package/src/build-components/patterns.generated.ts +1452 -15
  99. package/src/components/AttributesEditorPanel.tsx +13 -6
  100. package/src/components/Builder.tsx +140 -40
  101. package/src/components/BuilderButton.tsx +127 -0
  102. package/src/index.ts +2 -2
  103. package/src/mockOS/components/MockOSRouter.tsx +11 -3
  104. package/src/modals/ColorModal.tsx +212 -55
  105. package/src/pages/ProjectPage.tsx +293 -55
  106. package/src/pages/tabs/{BuilderTab.tsx → BuilderPanel.tsx} +13 -9
  107. package/src/pages/tabs/SideTool.tsx +259 -0
  108. package/src/size-matters/index.ts +6 -0
  109. package/src/store.ts +13 -1
  110. package/src/styles/base/_global.scss +158 -7
  111. package/src/styles/components/_attributes-editor.scss +12 -0
  112. package/src/styles/components/_editor-shell.scss +23 -0
  113. package/src/styles/foundation/_sizes.scss +1 -1
  114. package/src/styles/layout/_builder.scss +66 -10
  115. package/src/styles/modals/_color-modal.scss +29 -0
  116. package/src/types/Project.ts +14 -0
  117. package/src/utils/analyseNode.ts +98 -0
  118. package/src/utils/extractTextStyle.ts +24 -8
  119. package/src/utils/extractViewStyle.ts +27 -3
  120. package/src/utils/parseColor.ts +43 -0
  121. package/dist/pages/tabs/BuilderTab.d.ts +0 -9
  122. package/dist/pages/tabs/PreviewTab.d.ts +0 -3
  123. package/src/pages/tabs/DebugTab.tsx +0 -64
  124. package/src/pages/tabs/PreviewTab.tsx +0 -206
@@ -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
 
20
21
  export interface OnboardPropsGenerated {
21
22
  child: string;
@@ -42,6 +43,12 @@ export interface OnboardPropsGenerated {
42
43
  borderRadius?: string;
43
44
  width?: string;
44
45
  height?: string;
46
+ position?: PositionOptionType;
47
+ top?: string;
48
+ bottom?: string;
49
+ left?: string;
50
+ right?: string;
51
+ zIndex?: number;
45
52
  };
46
53
  }
47
54
 
@@ -1,4 +1,4 @@
1
- import React, { useContext, useMemo, useRef } from 'react';
1
+ import React, { useContext, useId, useMemo, useRef } from 'react';
2
2
  import type {
3
3
  EventObjectGenerated,
4
4
  OnboardButtonComponentProps,
@@ -13,16 +13,19 @@ import { useMockOSContext, useMockPermission } from '../../mockOS';
13
13
  function OnboardButton({ node }: OnboardButtonComponentProps) {
14
14
  useLogRender('OnboardButton');
15
15
  node = useNode(node);
16
- const attributeKey =
16
+ const attributeName =
17
17
  (node as any)?.sourceType ?? node.type ?? 'OnboardButton';
18
18
  const { emblaApi } = useContext(onboardContext) ?? {};
19
- const { appConfig } = useRenderStore((s) => ({
19
+ const { appConfig, projectColors } = useRenderStore((s) => ({
20
20
  appConfig: s.appConfig,
21
+ projectColors: s.projectColors,
21
22
  }));
22
23
 
23
24
  const context = useMockOSContext();
24
25
  const mockPermissionManager = useMockPermission(context);
25
26
  const handledEventsRef = useRef<EventObjectGenerated[]>([]);
27
+ const generatedId = useId();
28
+ const attributeKey = node.key ?? generatedId;
26
29
 
27
30
  const labelRaw = node.attributes?.labelKey ?? '';
28
31
  const label =
@@ -33,7 +36,10 @@ function OnboardButton({ node }: OnboardButtonComponentProps) {
33
36
  const flex = node.attributes?.flex ?? 1;
34
37
  const textColor = node.attributes?.button_text_color ?? '#FFFFFF';
35
38
  const backgroundColor = node.attributes?.button_background_color ?? '#0066FF';
36
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
39
+ const viewStyle = useMemo(
40
+ () => extractViewStyle(node, { appConfig, projectColors }),
41
+ [node, appConfig, projectColors],
42
+ );
37
43
 
38
44
  const handleClick = () => {
39
45
  //TODO: any ??
@@ -81,6 +87,7 @@ function OnboardButton({ node }: OnboardButtonComponentProps) {
81
87
 
82
88
  return (
83
89
  <button
90
+ attribute-name={attributeName}
84
91
  attribute-key={attributeKey}
85
92
  className="onboard__button"
86
93
  onClick={handleClick}
@@ -18,6 +18,7 @@ export type JustifyContentOptionType =
18
18
  | 'space-between'
19
19
  | 'space-around'
20
20
  | 'space-evenly';
21
+ export type PositionOptionType = 'relative' | 'absolute';
21
22
  export type AnimationOptionType =
22
23
  | 'simple-animation'
23
24
  | 'line-animation'
@@ -57,6 +58,12 @@ export interface OnboardButtonPropsGenerated {
57
58
  borderRadius?: string;
58
59
  width?: string;
59
60
  height?: string;
61
+ position?: PositionOptionType;
62
+ top?: string;
63
+ bottom?: string;
64
+ left?: string;
65
+ right?: string;
66
+ zIndex?: number;
60
67
  labelKey?: string;
61
68
  button_text_color?: string;
62
69
  animation?: AnimationOptionType;
@@ -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,12 @@ export interface OnboardButtonsPropsGenerated {
48
49
  borderRadius?: string;
49
50
  width?: string;
50
51
  height?: string;
52
+ position?: PositionOptionType;
53
+ top?: string;
54
+ bottom?: string;
55
+ left?: string;
56
+ right?: string;
57
+ zIndex?: number;
51
58
  buttonType?: ButtonTypeOptionType;
52
59
  skipNumber?: number;
53
60
  buttons_direction?: ButtonsDirectionOptionType;
@@ -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 { OnboardDotComponentProps } from './OnboardDotProps.generated';
3
3
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
4
4
  import useNode from '../useNode';
@@ -11,11 +11,17 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
11
11
 
12
12
  node = useNode(node);
13
13
 
14
- const attributeKey = node.type ?? 'OnboardDot';
14
+ const generatedId = useId();
15
+ const attributeName = node.type ?? 'OnboardDot';
16
+ const attributeKey = node.key ?? generatedId;
15
17
  const dotType = node.attributes?.dotType || 'normal_dot';
16
18
  const GHOST_DOT_DARK_COLOR = '#E4E5E7';
17
19
  const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
18
- const isDark = useRenderStore((s) => s.appConfig.theme === 'dark');
20
+ const { appConfig, projectColors } = useRenderStore((s) => ({
21
+ appConfig: s.appConfig,
22
+ projectColors: s.projectColors,
23
+ }));
24
+ const isDark = appConfig.theme === 'dark';
19
25
 
20
26
  // OnboardDot specific attributes
21
27
  const inactiveDotColor = isDark
@@ -27,7 +33,7 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
27
33
  const activeDotColor = node.attributes?.active_dot_color;
28
34
 
29
35
  const style = useMemo(() => {
30
- const baseStyle = extractViewStyle(node);
36
+ const baseStyle = extractViewStyle(node, { appConfig, projectColors });
31
37
  // Merge container_style if provided
32
38
  if (containerStyle) {
33
39
  try {
@@ -38,7 +44,7 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
38
44
  }
39
45
  }
40
46
  return baseStyle;
41
- }, [node, containerStyle]);
47
+ }, [node, containerStyle, appConfig, projectColors]);
42
48
 
43
49
  const onboardApi = useContext(onboardContext);
44
50
  const emblaApi = onboardApi?.emblaApi;
@@ -78,6 +84,7 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
78
84
 
79
85
  return (
80
86
  <div
87
+ attribute-name={attributeName}
81
88
  attribute-key={attributeKey}
82
89
  className={`embla__dots embla__dots--${dotType}`}
83
90
  style={style}
@@ -98,7 +105,9 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
98
105
  return (
99
106
  <button
100
107
  key={index}
101
- onClick={() => emblaApi?.scrollTo(snap)}
108
+ onClick={() => {
109
+ emblaApi?.scrollTo(snap);
110
+ }}
102
111
  className={`embla__dot ${isSelected ? 'embla__dot--selected' : ''}`}
103
112
  style={dotStyles}
104
113
  >
@@ -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,6 +36,12 @@ export interface OnboardDotPropsGenerated {
35
36
  borderRadius?: string;
36
37
  width?: string;
37
38
  height?: string;
39
+ position?: PositionOptionType;
40
+ top?: string;
41
+ bottom?: string;
42
+ left?: string;
43
+ right?: string;
44
+ zIndex?: number;
38
45
  dotType?: DotTypeOptionType;
39
46
  inactive_dot_opacity?: number;
40
47
  expanding_dot_width?: number;
@@ -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": [
@@ -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';
@@ -90,18 +90,25 @@ function buildSegments(
90
90
  function OnboardFooter({ node }: OnboardFooterComponentProps) {
91
91
  useLogRender('OnboardFooter');
92
92
  node = useNode(node);
93
- const attributeKey =
93
+ const attributeName =
94
94
  (node as any)?.sourceType ?? node.type ?? 'OnboardFooter';
95
- const { appConfig } = useRenderStore((s) => ({
95
+ const { appConfig, projectColors } = useRenderStore((s) => ({
96
96
  appConfig: s.appConfig,
97
+ projectColors: s.projectColors,
97
98
  }));
98
99
  const { localication, defaultLanguage } = appConfig;
99
100
  const t = (key?: string) =>
100
101
  key ? (localication?.[defaultLanguage ?? 'en']?.[key] ?? key) : '';
101
102
 
102
103
  const text = t(node?.attributes?.textLocalizationKey);
103
- const textStyle: React.CSSProperties = extractTextStyle(node);
104
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
104
+ const textStyle: React.CSSProperties = extractTextStyle(node, {
105
+ appConfig,
106
+ projectColors,
107
+ });
108
+ const viewStyle = useMemo(
109
+ () => extractViewStyle(node, { appConfig, projectColors }),
110
+ [node, appConfig, projectColors],
111
+ );
105
112
 
106
113
  const linkStyle = (color?: string): React.CSSProperties => ({
107
114
  color,
@@ -109,8 +116,11 @@ function OnboardFooter({ node }: OnboardFooterComponentProps) {
109
116
  });
110
117
 
111
118
  const paddingHorizontal = parseSize(node?.attributes?.paddingHorizontal);
119
+ const generatedId = useId();
120
+ const attributeKey = node.key ?? generatedId;
112
121
  return (
113
122
  <div
123
+ attribute-name={attributeName}
114
124
  attribute-key={attributeKey}
115
125
  style={{
116
126
  ...viewStyle,
@@ -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,12 @@ export interface OnboardFooterPropsGenerated {
59
60
  borderRadius?: string;
60
61
  width?: string;
61
62
  height?: string;
63
+ position?: PositionOptionType;
64
+ top?: string;
65
+ bottom?: string;
66
+ left?: string;
67
+ right?: string;
68
+ zIndex?: number;
62
69
  textLocalizationKey?: string;
63
70
  linkedWordFirstLocalizationKey?: string;
64
71
  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;
@@ -45,6 +46,12 @@ export interface OnboardImagePropsGenerated {
45
46
  marginLeft?: string;
46
47
  marginRight?: string;
47
48
  backgroundColor?: string;
49
+ position?: PositionOptionType;
50
+ top?: string;
51
+ bottom?: string;
52
+ left?: string;
53
+ right?: string;
54
+ zIndex?: number;
48
55
  video_url?: string;
49
56
  lottie?: string;
50
57
  };
@@ -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,13 +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 generatedId = useId();
14
+ const attributeName = (node as any)?.sourceType ?? node.type ?? 'OnboardItem';
15
+ const attributeKey = node.key ?? generatedId;
13
16
  const flexDirection = node.attributes?.flexDirection;
14
17
  const display = node.attributes?.display;
15
18
  const paddingHorizontal = parseSize(node.attributes?.paddingHorizontal);
16
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
19
+ const { appConfig, projectColors } = useRenderStore((s) => ({
20
+ appConfig: s.appConfig,
21
+ projectColors: s.projectColors,
22
+ }));
23
+ const viewStyle = useMemo(
24
+ () => extractViewStyle(node, { appConfig, projectColors }),
25
+ [node, appConfig, projectColors],
26
+ );
17
27
  return (
18
28
  <div
29
+ attribute-name={attributeName}
19
30
  attribute-key={attributeKey}
20
31
  className="embla__slide"
21
32
  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 DisplayOptionType = 'flex' | 'block';
20
21
 
21
22
  export interface OnboardItemPropsGenerated {
@@ -43,6 +44,12 @@ export interface OnboardItemPropsGenerated {
43
44
  borderRadius?: string;
44
45
  width?: string;
45
46
  height?: string;
47
+ position?: PositionOptionType;
48
+ top?: string;
49
+ bottom?: string;
50
+ left?: string;
51
+ right?: string;
52
+ zIndex?: number;
46
53
  display?: DisplayOptionType;
47
54
  };
48
55
  }
@@ -2,6 +2,7 @@ import React, {
2
2
  createContext,
3
3
  useContext,
4
4
  useEffect,
5
+ useId,
5
6
  useMemo,
6
7
  useState,
7
8
  } from 'react';
@@ -19,26 +20,45 @@ export const onboardContext = createContext<any>(undefined);
19
20
  function OnboardProvider({ node }: OnboardProviderComponentProps) {
20
21
  useLogRender('OnboardProvider');
21
22
  node = useNode(node);
22
- const attributeKey =
23
+ const generatedId = useId();
24
+ const attributeName =
23
25
  (node as any)?.sourceType ?? node.type ?? 'OnboardProvider';
24
26
  const device = useRenderStore((s) => s.device);
27
+ const { appConfig, projectColors } = useRenderStore((s) => ({
28
+ appConfig: s.appConfig,
29
+ projectColors: s.projectColors,
30
+ }));
25
31
  const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
26
32
  const [selectedIndex, setSelectedIndex] = useState(0);
33
+ const attributeKey = node.key ?? generatedId;
27
34
 
28
35
  const children = useMemo(() => {
29
- const onboardChild: NodeData = (node.children as NodeData[]).filter(
30
- (c) => c.type === 'Onboard',
31
- )[0];
32
- if (onboardChild?.type !== 'Onboard') {
33
- throw new Error('OnboardProvider at least has an Onboard child');
36
+ const allChildren = (node.children as NodeData[]) ?? [];
37
+
38
+ // Find the main Onboard child, if any
39
+ const onboardChild = allChildren.find((c) => c.type === 'Onboard');
40
+ if (!onboardChild || onboardChild.type !== 'Onboard') {
41
+ // Fallback: no onboard structure, just render original children
42
+ return allChildren;
43
+ }
44
+
45
+ const onboardItems = (onboardChild.children as NodeData[]) ?? [];
46
+ if (!onboardItems.length) {
47
+ return allChildren;
34
48
  }
35
- const onboardItems = onboardChild.children as NodeData[];
36
49
 
50
+ // Clamp selected index to available items
51
+ const clampedIndex = Math.min(
52
+ Math.max(selectedIndex, 0),
53
+ onboardItems.length - 1,
54
+ );
55
+
56
+ const selectedItem = onboardItems[clampedIndex];
37
57
  const onboardButtons = (
38
- onboardItems[selectedIndex].children as NodeData[]
39
- ).filter((s) => (s as NodeData)?.type == 'OnboardButtons');
40
- const children: NodeData[] = node.children as NodeData[];
41
- return [...children, ...onboardButtons];
58
+ (selectedItem?.children as NodeData[]) ?? []
59
+ ).filter((s) => (s as NodeData)?.type === 'OnboardButtons');
60
+
61
+ return [...allChildren, ...onboardButtons];
42
62
  }, [selectedIndex, node.children]);
43
63
 
44
64
  useEffect(() => {
@@ -59,15 +79,17 @@ function OnboardProvider({ node }: OnboardProviderComponentProps) {
59
79
  const viewStyle = useMemo(() => {
60
80
  const style = extractViewStyle(
61
81
  node as NodeData<ViewPropsGenerated['attributes']>,
82
+ { appConfig, projectColors },
62
83
  );
63
84
  //NOTE: Embla için istisna
64
85
  style.display = 'block';
65
86
  return style;
66
- }, [node]);
87
+ }, [node, appConfig, projectColors]);
67
88
 
68
89
  return (
69
90
  <onboardContext.Provider value={{ emblaApi, selectedIndex }}>
70
91
  <div
92
+ attribute-name={attributeName}
71
93
  attribute-key={attributeKey}
72
94
  className="carousel-provider"
73
95
  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
 
20
21
  export interface OnboardProviderPropsGenerated {
21
22
  child: string;
@@ -42,7 +43,12 @@ export interface OnboardProviderPropsGenerated {
42
43
  borderRadius?: never;
43
44
  width?: string;
44
45
  height?: string;
45
- theme?: string;
46
+ position?: PositionOptionType;
47
+ top?: string;
48
+ bottom?: string;
49
+ left?: string;
50
+ right?: string;
51
+ zIndex?: number;
46
52
  use_safe_area_inset?: boolean;
47
53
  };
48
54
  }
@@ -6,7 +6,6 @@
6
6
  "children": "node",
7
7
  "extends": "View",
8
8
  "attributes": {
9
- "theme": "string",
10
9
  "use_safe_area_inset": "boolean",
11
10
  "borderRadius": "never"
12
11
  }
@@ -22,13 +21,6 @@
22
21
  "label": "Onboard Provider",
23
22
  "description": "Provides shared settings for onboarding.",
24
23
  "attributes": {
25
- "theme": {
26
- "label": "Theme",
27
- "description": "Theme key for onboarding screens.",
28
- "category": "other",
29
- "specialCategory": null,
30
- "sort": 1
31
- },
32
24
  "use_safe_area_inset": {
33
25
  "label": "Use Safe Area Inset",
34
26
  "description": "Adds safe area padding.",
@@ -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 OnboardSubtitlePropsGenerated {
34
35
  child: string;
@@ -59,6 +60,12 @@ export interface OnboardSubtitlePropsGenerated {
59
60
  borderRadius?: string;
60
61
  width?: string;
61
62
  height?: string;
63
+ position?: PositionOptionType;
64
+ top?: string;
65
+ bottom?: string;
66
+ left?: string;
67
+ right?: string;
68
+ zIndex?: number;
62
69
  };
63
70
  }
64
71
 
@@ -3,7 +3,7 @@
3
3
  "allowUnknownAttributes": false,
4
4
  "pattern": {
5
5
  "type": "OnboardSubtitle",
6
- "children": "node",
6
+ "children": "string",
7
7
  "extends": "Text",
8
8
  "attributes": {}
9
9
  },
@@ -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 OnboardTitlePropsGenerated {
34
35
  child: string;
@@ -59,6 +60,12 @@ export interface OnboardTitlePropsGenerated {
59
60
  borderRadius?: string;
60
61
  width?: string;
61
62
  height?: string;
63
+ position?: PositionOptionType;
64
+ top?: string;
65
+ bottom?: string;
66
+ left?: string;
67
+ right?: string;
68
+ zIndex?: number;
62
69
  };
63
70
  }
64
71
 
@@ -3,7 +3,7 @@
3
3
  "allowUnknownAttributes": false,
4
4
  "pattern": {
5
5
  "type": "OnboardTitle",
6
- "children": "node",
6
+ "children": "string",
7
7
  "extends": "Text",
8
8
  "attributes": {}
9
9
  },