@developer_tribe/react-builder 1.0.1 → 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 (218) hide show
  1. package/dist/AttributesEditor.d.ts +3 -1
  2. package/dist/DeviceMockFrame.d.ts +2 -1
  3. package/dist/RenderPage.d.ts +5 -3
  4. package/dist/attributes-editor/Field.d.ts +17 -0
  5. package/dist/attributes-editor/FieldInfoTooltip.d.ts +7 -0
  6. package/dist/attributes-editor/LayoutPreviewPicker.d.ts +12 -0
  7. package/dist/attributes-editor/SpecialCategorySection.d.ts +20 -0
  8. package/dist/attributes-editor/types.d.ts +14 -0
  9. package/dist/background.jpg +0 -0
  10. package/dist/build-components/BackgroundImage/BackgroundImage.d.ts +5 -0
  11. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +44 -0
  12. package/dist/build-components/Button/Button.d.ts +1 -1
  13. package/dist/build-components/Button/ButtonProps.generated.d.ts +33 -1
  14. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +34 -1
  15. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +32 -0
  16. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +32 -0
  17. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +34 -1
  18. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +34 -1
  19. package/dist/build-components/Image/ImageProps.generated.d.ts +32 -3
  20. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +34 -1
  21. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +32 -0
  22. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +32 -0
  23. package/dist/build-components/OnboardDot/OnboardDot.d.ts +1 -1
  24. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +29 -0
  25. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +11 -5
  26. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +32 -3
  27. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +31 -3
  28. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +32 -5
  29. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +11 -5
  30. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +11 -5
  31. package/dist/build-components/Text/TextProps.generated.d.ts +11 -5
  32. package/dist/build-components/View/ViewProps.generated.d.ts +10 -4
  33. package/dist/build-components/index.d.ts +2 -1
  34. package/dist/build-components/patterns.generated.d.ts +6288 -136
  35. package/dist/components/AttributesEditorPanel.d.ts +3 -4
  36. package/dist/components/Breadcrumb.d.ts +3 -1
  37. package/dist/components/Builder.d.ts +2 -1
  38. package/dist/components/BuilderButton.d.ts +9 -0
  39. package/dist/components/Checkbox.d.ts +17 -0
  40. package/dist/components/DeviceButton.d.ts +8 -0
  41. package/dist/components/DeviceNavigationBar.d.ts +10 -0
  42. package/dist/components/DeviceStatusBar.d.ts +9 -0
  43. package/dist/components/EditorHeader.d.ts +3 -8
  44. package/dist/index.cjs.js +5 -5
  45. package/dist/index.cjs.js.map +1 -1
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.esm.js +5 -5
  48. package/dist/index.esm.js.map +1 -1
  49. package/dist/mockOS/components/MockLaunchScreenComponent.d.ts +6 -0
  50. package/dist/mockOS/components/MockOSRouter.d.ts +8 -0
  51. package/dist/mockOS/components/PermissionModal.d.ts +9 -0
  52. package/dist/mockOS/context/MockOSContext.d.ts +36 -0
  53. package/dist/mockOS/hooks/useMockNavigation.d.ts +3 -0
  54. package/dist/mockOS/hooks/useMockPermission.d.ts +3 -0
  55. package/dist/mockOS/index.d.ts +9 -0
  56. package/dist/mockOS/managers/mockPermissionManager.d.ts +10 -0
  57. package/dist/mockOS/managers/navigationManager.d.ts +17 -0
  58. package/dist/modals/AddComponentModal.d.ts +8 -0
  59. package/dist/modals/ColorModal.d.ts +11 -0
  60. package/dist/modals/DeviceSelectorModal.d.ts +9 -0
  61. package/dist/modals/LocalicationModal.d.ts +8 -0
  62. package/dist/modals/Modal.d.ts +12 -0
  63. package/dist/modals/index.d.ts +5 -0
  64. package/dist/pages/ProjectPage.d.ts +3 -3
  65. package/dist/pages/tabs/BuilderPanel.d.ts +8 -0
  66. package/dist/pages/tabs/{DebugTab.d.ts → SideTool.d.ts} +2 -2
  67. package/dist/store.d.ts +7 -3
  68. package/dist/styles.css +1 -1
  69. package/dist/types/Project.d.ts +11 -0
  70. package/dist/utils/analyseNode.d.ts +1 -0
  71. package/dist/utils/extractTextStyle.d.ts +8 -1
  72. package/dist/utils/extractViewStyle.d.ts +8 -1
  73. package/dist/utils/parseColor.d.ts +7 -0
  74. package/dist/utils/patterns.d.ts +24 -0
  75. package/package.json +2 -1
  76. package/scripts/prebuild/utils/createGeneratedProps.js +11 -3
  77. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +45 -6
  78. package/scripts/prebuild/utils/validatePatternJson.js +13 -5
  79. package/src/AttributesEditor.tsx +493 -310
  80. package/src/DeviceMockFrame.tsx +21 -37
  81. package/src/RenderPage.tsx +86 -7
  82. package/src/assets/images/android.svg +42 -42
  83. package/src/assets/images/apple.svg +15 -15
  84. package/src/attributes-editor/Field.tsx +669 -0
  85. package/src/attributes-editor/FieldInfoTooltip.tsx +49 -0
  86. package/src/attributes-editor/LayoutPreviewPicker.tsx +199 -0
  87. package/src/attributes-editor/SpecialCategorySection.tsx +285 -0
  88. package/src/attributes-editor/types.ts +30 -0
  89. package/src/build-components/BackgroundImage/BackgroundImage.tsx +87 -0
  90. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +60 -0
  91. package/src/build-components/BackgroundImage/pattern.json +45 -0
  92. package/src/build-components/Button/Button.tsx +37 -2
  93. package/src/build-components/Button/ButtonProps.generated.ts +44 -1
  94. package/src/build-components/Button/pattern.json +31 -2
  95. package/src/build-components/Carousel/Carousel.tsx +39 -2
  96. package/src/build-components/Carousel/CarouselProps.generated.ts +46 -1
  97. package/src/build-components/Carousel/pattern.json +10 -0
  98. package/src/build-components/CarouselButtons/CarouselButtons.tsx +21 -2
  99. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +43 -0
  100. package/src/build-components/CarouselButtons/pattern.json +22 -0
  101. package/src/build-components/CarouselDots/CarouselDots.tsx +49 -8
  102. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +43 -0
  103. package/src/build-components/CarouselDots/pattern.json +15 -0
  104. package/src/build-components/CarouselItem/CarouselItem.tsx +21 -2
  105. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +46 -1
  106. package/src/build-components/CarouselItem/pattern.json +7 -0
  107. package/src/build-components/CarouselProvider/CarouselProvider.tsx +21 -2
  108. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +46 -1
  109. package/src/build-components/CarouselProvider/pattern.json +7 -0
  110. package/src/build-components/Image/Image.tsx +33 -2
  111. package/src/build-components/Image/ImageProps.generated.ts +43 -3
  112. package/src/build-components/Image/pattern.json +46 -3
  113. package/src/build-components/Onboard/Onboard.tsx +6 -1
  114. package/src/build-components/Onboard/OnboardProps.generated.ts +46 -1
  115. package/src/build-components/Onboard/pattern.json +11 -0
  116. package/src/build-components/OnboardButton/OnboardButton.tsx +54 -6
  117. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +43 -0
  118. package/src/build-components/OnboardButton/pattern.json +71 -5
  119. package/src/build-components/OnboardButtons/OnboardButtons.tsx +33 -11
  120. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +43 -0
  121. package/src/build-components/OnboardButtons/pattern.json +70 -4
  122. package/src/build-components/OnboardDot/OnboardDot.tsx +113 -4
  123. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +29 -0
  124. package/src/build-components/OnboardDot/pattern.json +55 -2
  125. package/src/build-components/OnboardFooter/OnboardFooter.tsx +20 -4
  126. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +11 -5
  127. package/src/build-components/OnboardFooter/pattern.json +58 -2
  128. package/src/build-components/OnboardImage/OnboardImage.tsx +49 -5
  129. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +43 -3
  130. package/src/build-components/OnboardImage/pattern.json +21 -0
  131. package/src/build-components/OnboardItem/OnboardItem.tsx +17 -1
  132. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +42 -3
  133. package/src/build-components/OnboardItem/pattern.json +38 -2
  134. package/src/build-components/OnboardProvider/OnboardProvider.tsx +52 -18
  135. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +44 -5
  136. package/src/build-components/OnboardProvider/pattern.json +44 -5
  137. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +11 -5
  138. package/src/build-components/OnboardSubtitle/pattern.json +7 -1
  139. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +11 -5
  140. package/src/build-components/OnboardTitle/pattern.json +7 -1
  141. package/src/build-components/RenderNode.generated.tsx +3 -0
  142. package/src/build-components/Text/Text.tsx +34 -6
  143. package/src/build-components/Text/TextProps.generated.ts +11 -5
  144. package/src/build-components/Text/pattern.json +38 -2
  145. package/src/build-components/View/View.tsx +33 -6
  146. package/src/build-components/View/ViewProps.generated.ts +10 -4
  147. package/src/build-components/View/pattern.json +285 -19
  148. package/src/build-components/index.ts +5 -0
  149. package/src/build-components/patterns.generated.ts +6346 -143
  150. package/src/components/AttributesEditorPanel.tsx +17 -64
  151. package/src/components/Breadcrumb.tsx +37 -5
  152. package/src/components/Builder.tsx +311 -108
  153. package/src/components/BuilderButton.tsx +127 -0
  154. package/src/components/Checkbox.tsx +81 -0
  155. package/src/components/DeviceButton.tsx +39 -0
  156. package/src/components/DeviceNavigationBar.tsx +201 -0
  157. package/src/components/DeviceStatusBar.tsx +85 -0
  158. package/src/components/EditorHeader.tsx +26 -74
  159. package/src/index.ts +2 -2
  160. package/src/mockOS/components/MockLaunchScreenComponent.tsx +43 -0
  161. package/src/mockOS/components/MockOSRouter.tsx +123 -0
  162. package/src/mockOS/components/PermissionModal.tsx +270 -0
  163. package/src/mockOS/context/MockOSContext.tsx +179 -0
  164. package/src/mockOS/hooks/useMockNavigation.ts +11 -0
  165. package/src/mockOS/hooks/useMockPermission.ts +11 -0
  166. package/src/mockOS/index.ts +26 -0
  167. package/src/mockOS/managers/mockPermissionManager.ts +54 -0
  168. package/src/mockOS/managers/navigationManager.ts +91 -0
  169. package/src/modals/AddComponentModal.tsx +313 -0
  170. package/src/modals/ColorModal.tsx +425 -0
  171. package/src/modals/DeviceSelectorModal.tsx +57 -0
  172. package/src/modals/LocalicationModal.tsx +54 -0
  173. package/src/modals/Modal.tsx +57 -0
  174. package/src/modals/index.ts +5 -0
  175. package/src/pages/ProjectPage.tsx +307 -71
  176. package/src/pages/tabs/{BuilderTab.tsx → BuilderPanel.tsx} +13 -9
  177. package/src/pages/tabs/SideTool.tsx +259 -0
  178. package/src/size-matters/index.ts +27 -5
  179. package/src/store.ts +13 -5
  180. package/src/styles/base/_global.scss +404 -0
  181. package/src/styles/components/_attributes-editor.scss +273 -0
  182. package/src/styles/components/_editor-shell.scss +212 -0
  183. package/src/styles/components/_mockos-router.scss +140 -0
  184. package/src/styles/components/_ui-components.scss +183 -0
  185. package/src/styles/foundation/_colors.scss +8 -0
  186. package/src/styles/{_mixins.scss → foundation/_mixins.scss} +5 -4
  187. package/src/styles/{_reset.scss → foundation/_reset.scss} +5 -2
  188. package/src/styles/foundation/_sizes.scss +37 -0
  189. package/src/styles/foundation/_typography.scss +4 -0
  190. package/src/styles/foundation/_variables.scss +3 -0
  191. package/src/styles/index.scss +22 -136
  192. package/src/styles/layout/_builder.scss +124 -0
  193. package/src/styles/layout/_pages.scss +3 -0
  194. package/src/styles/modals/_add-component.scss +122 -0
  195. package/src/styles/modals/_color-modal.scss +159 -0
  196. package/src/styles/modals/_device-selector.scss +18 -0
  197. package/src/styles/modals/_localication-modal.scss +68 -0
  198. package/src/styles/modals/_modal-shell.scss +46 -0
  199. package/src/styles/utilities/_carousel.scss +125 -0
  200. package/src/types/Project.ts +14 -0
  201. package/src/types/images.d.ts +8 -0
  202. package/src/utils/analyseNode.ts +98 -0
  203. package/src/utils/extractTextStyle.ts +28 -10
  204. package/src/utils/extractViewStyle.ts +77 -9
  205. package/src/utils/parseColor.ts +43 -0
  206. package/src/utils/patterns.ts +33 -0
  207. package/dist/build-components/OnboardDot/OnboardExpandingDotProps.generated.d.ts +0 -10
  208. package/dist/pages/tabs/BuilderTab.d.ts +0 -9
  209. package/dist/pages/tabs/PreviewTab.d.ts +0 -3
  210. package/src/build-components/OnboardDot/OnboardExpandingDotProps.generated.ts +0 -20
  211. package/src/pages/tabs/DebugTab.tsx +0 -23
  212. package/src/pages/tabs/PreviewTab.tsx +0 -194
  213. package/src/styles/_variables.scss +0 -27
  214. package/src/styles/builder.scss +0 -60
  215. package/src/styles/components.scss +0 -88
  216. package/src/styles/editor.scss +0 -174
  217. package/src/styles/global.scss +0 -200
  218. package/src/styles/pages.scss +0 -2
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect, 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';
@@ -6,12 +6,16 @@ import RenderNode from '../RenderNode.generated';
6
6
  import useNode from '../useNode';
7
7
  import { useRenderStore } from '../../store';
8
8
  import { useLogRender } from '../../utils/useLogRender';
9
+ import { extractViewStyle } from '../../utils/extractViewStyle';
9
10
 
10
11
  function OnboardButtons({ node }: OnboardButtonsComponentProps) {
11
12
  useLogRender('OnboardButtons');
12
13
  node = useNode(node);
13
- const { appConfig } = useRenderStore((s) => ({
14
+ const attributeName =
15
+ (node as any)?.sourceType ?? node.type ?? 'OnboardButtons';
16
+ const { appConfig, projectColors } = useRenderStore((s) => ({
14
17
  appConfig: s.appConfig,
18
+ projectColors: s.projectColors,
15
19
  }));
16
20
  const seperatorColorDefault =
17
21
  appConfig.theme === 'light'
@@ -26,13 +30,6 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
26
30
  }
27
31
  }, [ctx.selectedIndex]);
28
32
 
29
- // New condition logic: hide when condition is carousel-index and does not match
30
- const condition = (node.attributes as any)?.condition;
31
- const conditionVariable = (node.attributes as any)?.conditionVariable;
32
- if (condition === 'carousel-index' && typeof conditionVariable === 'number') {
33
- if (conditionVariable !== selectedIndex) return null;
34
- }
35
-
36
33
  const direction =
37
34
  node.attributes?.buttons_direction === 'column' ? 'column' : 'row';
38
35
  const seperatorColor =
@@ -47,8 +44,33 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
47
44
  return <RenderNode node={node.children as Node} />;
48
45
  };
49
46
 
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();
55
+
56
+ // New condition logic: hide when condition is carousel-index and does not match
57
+ const condition = (node.attributes as any)?.condition;
58
+ const conditionVariable = (node.attributes as any)?.conditionVariable;
59
+ const shouldHide =
60
+ condition === 'carousel-index' &&
61
+ typeof conditionVariable === 'number' &&
62
+ conditionVariable !== selectedIndex;
63
+
64
+ if (shouldHide) {
65
+ return null;
66
+ }
67
+
50
68
  return (
51
- <>
69
+ <div
70
+ attribute-name={attributeName}
71
+ attribute-key={node.key ?? generatedId}
72
+ style={viewStyle}
73
+ >
52
74
  <div
53
75
  className="onboard__separator"
54
76
  style={{
@@ -71,7 +93,7 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
71
93
  >
72
94
  {renderChildren()}
73
95
  </div>
74
- </>
96
+ </div>
75
97
  );
76
98
  }
77
99
 
@@ -2,6 +2,21 @@
2
2
 
3
3
  import type { NodeData } from '../../types/Node';
4
4
 
5
+ export type FlexDirectionOptionType = 'row' | 'column';
6
+ export type AlignItemsOptionType =
7
+ | 'flex-start'
8
+ | 'center'
9
+ | 'flex-end'
10
+ | 'stretch'
11
+ | 'baseline';
12
+ export type JustifyContentOptionType =
13
+ | 'flex-start'
14
+ | 'center'
15
+ | 'flex-end'
16
+ | 'space-between'
17
+ | 'space-around'
18
+ | 'space-evenly';
19
+ export type PositionOptionType = 'relative' | 'absolute';
5
20
  export type ButtonTypeOptionType =
6
21
  | 'previous_button'
7
22
  | 'next_button'
@@ -12,6 +27,34 @@ export type ConditionOptionType = 'carousel-index';
12
27
  export interface OnboardButtonsPropsGenerated {
13
28
  child: string;
14
29
  attributes: {
30
+ scrollable?: boolean;
31
+ flexDirection?: FlexDirectionOptionType;
32
+ alignItems?: AlignItemsOptionType;
33
+ justifyContent?: JustifyContentOptionType;
34
+ gap?: string;
35
+ padding?: string;
36
+ paddingHorizontal?: string;
37
+ paddingVertical?: string;
38
+ paddingTop?: string;
39
+ paddingBottom?: string;
40
+ paddingLeft?: string;
41
+ paddingRight?: string;
42
+ margin?: string;
43
+ marginVertical?: string;
44
+ marginTop?: string;
45
+ marginBottom?: string;
46
+ marginLeft?: string;
47
+ marginRight?: string;
48
+ backgroundColor?: string;
49
+ borderRadius?: string;
50
+ width?: string;
51
+ height?: string;
52
+ position?: PositionOptionType;
53
+ top?: string;
54
+ bottom?: string;
55
+ left?: string;
56
+ right?: string;
57
+ zIndex?: number;
15
58
  buttonType?: ButtonTypeOptionType;
16
59
  skipNumber?: number;
17
60
  buttons_direction?: ButtonsDirectionOptionType;
@@ -4,14 +4,80 @@
4
4
  "pattern": {
5
5
  "type": "OnboardButtons",
6
6
  "children": "node",
7
+ "extends": "View",
7
8
  "attributes": {
8
- "buttonType": ["previous_button", "next_button", "skip_button"],
9
+ "buttonType": [
10
+ "previous_button",
11
+ "next_button",
12
+ "skip_button"
13
+ ],
9
14
  "skipNumber": "number",
10
- "buttons_direction": ["row", "column"],
15
+ "buttons_direction": [
16
+ "row",
17
+ "column"
18
+ ],
11
19
  "forIndex": "number",
12
- "seperatorColor": "string",
13
- "condition": ["carousel-index"],
20
+ "seperatorColor": "color",
21
+ "condition": [
22
+ "carousel-index"
23
+ ],
14
24
  "conditionVariable": "number"
15
25
  }
26
+ },
27
+ "meta": {
28
+ "desiredParent": ["=OnboardItem"],
29
+ "label": "Onboard Buttons",
30
+ "description": "Wrapper for onboarding button set.",
31
+ "attributes": {
32
+ "buttonType": {
33
+ "label": "Button Type",
34
+ "description": "Which onboard button to show.",
35
+ "category": "other",
36
+ "specialCategory": null,
37
+ "sort": 1
38
+ },
39
+ "skipNumber": {
40
+ "label": "Skip Number",
41
+ "description": "Slide index to skip to.",
42
+ "category": "other",
43
+ "specialCategory": null,
44
+ "sort": 2
45
+ },
46
+ "buttons_direction": {
47
+ "label": "Buttons Direction",
48
+ "description": "Direction to lay out buttons.",
49
+ "category": "container",
50
+ "specialCategory": null,
51
+ "sort": 3
52
+ },
53
+ "forIndex": {
54
+ "label": "For Index",
55
+ "description": "Show only for this slide index.",
56
+ "category": "other",
57
+ "specialCategory": null,
58
+ "sort": 4
59
+ },
60
+ "seperatorColor": {
61
+ "label": "Seperator Color",
62
+ "description": "Color of the divider line.",
63
+ "category": "style",
64
+ "specialCategory": null,
65
+ "sort": 5
66
+ },
67
+ "condition": {
68
+ "label": "Condition",
69
+ "description": "Built-in condition to check.",
70
+ "category": "other",
71
+ "specialCategory": null,
72
+ "sort": 6
73
+ },
74
+ "conditionVariable": {
75
+ "label": "Condition Variable",
76
+ "description": "Value used when checking the condition.",
77
+ "category": "other",
78
+ "specialCategory": null,
79
+ "sort": 7
80
+ }
81
+ }
16
82
  }
17
83
  }
@@ -1,13 +1,122 @@
1
- import React from 'react';
2
- import type { OnboardDotComponentProps } from './OnboardExpandingDotProps.generated';
3
- import CarouselDots from '../CarouselDots/CarouselDots';
1
+ import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
2
+ import type { OnboardDotComponentProps } from './OnboardDotProps.generated';
3
+ import { onboardContext } from '../OnboardProvider/OnboardProvider';
4
4
  import useNode from '../useNode';
5
5
  import { useLogRender } from '../../utils/useLogRender';
6
+ import { extractViewStyle } from '../../utils/extractViewStyle';
7
+ import { useRenderStore } from '../../store';
6
8
 
7
9
  function OnboardDot({ node }: OnboardDotComponentProps) {
8
10
  useLogRender('OnboardDot');
11
+
9
12
  node = useNode(node);
10
- return <CarouselDots node={{ ...node, type: 'carouselDots' } as any} />;
13
+
14
+ const generatedId = useId();
15
+ const attributeName = node.type ?? 'OnboardDot';
16
+ const attributeKey = node.key ?? generatedId;
17
+ const dotType = node.attributes?.dotType || 'normal_dot';
18
+ const GHOST_DOT_DARK_COLOR = '#E4E5E7';
19
+ const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
20
+ const { appConfig, projectColors } = useRenderStore((s) => ({
21
+ appConfig: s.appConfig,
22
+ projectColors: s.projectColors,
23
+ }));
24
+ const isDark = appConfig.theme === 'dark';
25
+
26
+ // OnboardDot specific attributes
27
+ const inactiveDotColor = isDark
28
+ ? GHOST_DOT_DARK_COLOR
29
+ : GHOST_DOT_LIGHT_COLOR;
30
+ const inactiveDotOpacity = node.attributes?.inactive_dot_opacity ?? 0.3;
31
+ const dotStyle = node.attributes?.dot_style;
32
+ const containerStyle = node.attributes?.container_style;
33
+ const activeDotColor = node.attributes?.active_dot_color;
34
+
35
+ const style = useMemo(() => {
36
+ const baseStyle = extractViewStyle(node, { appConfig, projectColors });
37
+ // Merge container_style if provided
38
+ if (containerStyle) {
39
+ try {
40
+ const parsedContainerStyle = JSON.parse(containerStyle);
41
+ Object.assign(baseStyle, parsedContainerStyle);
42
+ } catch (e) {
43
+ // Invalid JSON, ignore
44
+ }
45
+ }
46
+ return baseStyle;
47
+ }, [node, containerStyle, appConfig, projectColors]);
48
+
49
+ const onboardApi = useContext(onboardContext);
50
+ const emblaApi = onboardApi?.emblaApi;
51
+
52
+ const [selectedIndex, setSelectedIndex] = useState(0);
53
+ const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);
54
+
55
+ useEffect(() => {
56
+ if (!emblaApi) return;
57
+ const snaps = emblaApi.scrollSnapList();
58
+ const selected = emblaApi.selectedScrollSnap();
59
+ setScrollSnaps(snaps);
60
+ setSelectedIndex(selected);
61
+
62
+ const onSelect = () => {
63
+ const sel = emblaApi.selectedScrollSnap();
64
+ setSelectedIndex(sel);
65
+ };
66
+ emblaApi.on('select', onSelect);
67
+
68
+ return () => {
69
+ if (emblaApi && emblaApi.off) {
70
+ emblaApi.off('select', onSelect);
71
+ }
72
+ };
73
+ }, [emblaApi]);
74
+
75
+ // Parse dot_style if provided
76
+ const parsedDotStyle = useMemo(() => {
77
+ if (!dotStyle) return {};
78
+ try {
79
+ return JSON.parse(dotStyle);
80
+ } catch (e) {
81
+ return {};
82
+ }
83
+ }, [dotStyle]);
84
+
85
+ return (
86
+ <div
87
+ attribute-name={attributeName}
88
+ attribute-key={attributeKey}
89
+ className={`embla__dots embla__dots--${dotType}`}
90
+ style={style}
91
+ >
92
+ {scrollSnaps.map((snap, index) => {
93
+ const isSelected = selectedIndex === index;
94
+ const dotStyles: React.CSSProperties = {
95
+ ...parsedDotStyle,
96
+ opacity: isSelected ? 1 : inactiveDotOpacity,
97
+ };
98
+
99
+ if (activeDotColor && isSelected) {
100
+ dotStyles.color = activeDotColor;
101
+ } else if (!isSelected) {
102
+ dotStyles.color = inactiveDotColor;
103
+ }
104
+
105
+ return (
106
+ <button
107
+ key={index}
108
+ onClick={() => {
109
+ emblaApi?.scrollTo(snap);
110
+ }}
111
+ className={`embla__dot ${isSelected ? 'embla__dot--selected' : ''}`}
112
+ style={dotStyles}
113
+ >
114
+ {isSelected ? '●' : '○'}
115
+ </button>
116
+ );
117
+ })}
118
+ </div>
119
+ );
11
120
  }
12
121
 
13
122
  export default React.memo(OnboardDot);
@@ -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'
@@ -13,6 +14,34 @@ export type DotTypeOptionType =
13
14
  export interface OnboardDotPropsGenerated {
14
15
  child: string;
15
16
  attributes: {
17
+ scrollable?: boolean;
18
+ flexDirection?: never;
19
+ alignItems?: never;
20
+ justifyContent?: never;
21
+ gap?: string;
22
+ padding?: string;
23
+ paddingHorizontal?: string;
24
+ paddingVertical?: string;
25
+ paddingTop?: string;
26
+ paddingBottom?: string;
27
+ paddingLeft?: string;
28
+ paddingRight?: string;
29
+ margin?: string;
30
+ marginVertical?: string;
31
+ marginTop?: string;
32
+ marginBottom?: string;
33
+ marginLeft?: string;
34
+ marginRight?: string;
35
+ backgroundColor?: string;
36
+ borderRadius?: string;
37
+ width?: string;
38
+ height?: string;
39
+ position?: PositionOptionType;
40
+ top?: string;
41
+ bottom?: string;
42
+ left?: string;
43
+ right?: string;
44
+ zIndex?: number;
16
45
  dotType?: DotTypeOptionType;
17
46
  inactive_dot_opacity?: number;
18
47
  expanding_dot_width?: number;
@@ -3,7 +3,8 @@
3
3
  "allowUnknownAttributes": false,
4
4
  "pattern": {
5
5
  "type": "OnboardDot",
6
- "children": "node",
6
+ "children": "never",
7
+ "extends": "View",
7
8
  "attributes": {
8
9
  "dotType": [
9
10
  "expanding_dot",
@@ -17,7 +18,59 @@
17
18
  "expanding_dot_width": "number",
18
19
  "dot_style": "string",
19
20
  "container_style": "string",
20
- "active_dot_color": "string"
21
+ "active_dot_color": "color",
22
+ "flexDirection": "never",
23
+ "alignItems": "never",
24
+ "justifyContent": "never"
25
+ }
26
+ },
27
+ "meta": {
28
+ "desiredParent": [">OnboardProvider"],
29
+ "label": "Onboard Dot",
30
+ "description": "Renders onboarding progress dots.",
31
+ "attributes": {
32
+ "dotType": {
33
+ "label": "Dot Type",
34
+ "description": "Dot animation style.",
35
+ "category": "style",
36
+ "specialCategory": null,
37
+ "sort": 1
38
+ },
39
+ "inactive_dot_opacity": {
40
+ "label": "Inactive Dot Opacity",
41
+ "description": "Opacity for inactive dots.",
42
+ "category": "style",
43
+ "specialCategory": null,
44
+ "sort": 2
45
+ },
46
+ "expanding_dot_width": {
47
+ "label": "Expanding Dot Width",
48
+ "description": "Width used while expanding.",
49
+ "category": "style",
50
+ "specialCategory": null,
51
+ "sort": 3
52
+ },
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
+ "active_dot_color": {
68
+ "label": "Active Dot Color",
69
+ "description": "Color of the active dot.",
70
+ "category": "style",
71
+ "specialCategory": null,
72
+ "sort": 6
73
+ }
21
74
  }
22
75
  }
23
76
  }
@@ -1,9 +1,10 @@
1
- import React 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';
5
5
  import { parseSize } from '../../size-matters';
6
6
  import { extractTextStyle } from '../../utils/extractTextStyle';
7
+ import { extractViewStyle } from '../../utils/extractViewStyle';
7
8
  import { useLogRender } from '../../utils/useLogRender';
8
9
 
9
10
  type Segment =
@@ -89,15 +90,25 @@ function buildSegments(
89
90
  function OnboardFooter({ node }: OnboardFooterComponentProps) {
90
91
  useLogRender('OnboardFooter');
91
92
  node = useNode(node);
92
- const { appConfig } = useRenderStore((s) => ({
93
+ const attributeName =
94
+ (node as any)?.sourceType ?? node.type ?? 'OnboardFooter';
95
+ const { appConfig, projectColors } = useRenderStore((s) => ({
93
96
  appConfig: s.appConfig,
97
+ projectColors: s.projectColors,
94
98
  }));
95
99
  const { localication, defaultLanguage } = appConfig;
96
100
  const t = (key?: string) =>
97
101
  key ? (localication?.[defaultLanguage ?? 'en']?.[key] ?? key) : '';
98
102
 
99
103
  const text = t(node?.attributes?.textLocalizationKey);
100
- const style: React.CSSProperties = extractTextStyle(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
+ );
101
112
 
102
113
  const linkStyle = (color?: string): React.CSSProperties => ({
103
114
  color,
@@ -105,10 +116,15 @@ function OnboardFooter({ node }: OnboardFooterComponentProps) {
105
116
  });
106
117
 
107
118
  const paddingHorizontal = parseSize(node?.attributes?.paddingHorizontal);
119
+ const generatedId = useId();
120
+ const attributeKey = node.key ?? generatedId;
108
121
  return (
109
122
  <div
123
+ attribute-name={attributeName}
124
+ attribute-key={attributeKey}
110
125
  style={{
111
- ...style,
126
+ ...viewStyle,
127
+ ...textStyle,
112
128
  paddingLeft: paddingHorizontal,
113
129
  paddingRight: paddingHorizontal,
114
130
  textAlign: 'center',
@@ -29,12 +29,13 @@ 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;
35
36
  attributes: {
36
37
  color?: string;
37
- fontSize?: number;
38
+ fontSize?: string;
38
39
  fontWeight?: FontWeightOptionType;
39
40
  textAlign?: TextAlignOptionType;
40
41
  scrollable?: boolean;
@@ -42,7 +43,7 @@ export interface OnboardFooterPropsGenerated {
42
43
  alignItems?: AlignItemsOptionType;
43
44
  justifyContent?: JustifyContentOptionType;
44
45
  gap?: string;
45
- padding?: number;
46
+ padding?: string;
46
47
  paddingHorizontal?: string;
47
48
  paddingVertical?: string;
48
49
  paddingTop?: string;
@@ -50,7 +51,6 @@ export interface OnboardFooterPropsGenerated {
50
51
  paddingLeft?: string;
51
52
  paddingRight?: string;
52
53
  margin?: string;
53
- marginHorizontal?: string;
54
54
  marginVertical?: string;
55
55
  marginTop?: string;
56
56
  marginBottom?: string;
@@ -58,8 +58,14 @@ export interface OnboardFooterPropsGenerated {
58
58
  marginRight?: string;
59
59
  backgroundColor?: string;
60
60
  borderRadius?: string;
61
- width?: number;
62
- height?: number;
61
+ width?: string;
62
+ height?: string;
63
+ position?: PositionOptionType;
64
+ top?: string;
65
+ bottom?: string;
66
+ left?: string;
67
+ right?: string;
68
+ zIndex?: number;
63
69
  textLocalizationKey?: string;
64
70
  linkedWordFirstLocalizationKey?: string;
65
71
  linkedWordFirstColor?: string;
@@ -8,14 +8,70 @@
8
8
  "attributes": {
9
9
  "textLocalizationKey": "string",
10
10
  "linkedWordFirstLocalizationKey": "string",
11
- "linkedWordFirstColor": "string",
11
+ "linkedWordFirstColor": "color",
12
12
  "linkedWordFirstPage": "string",
13
13
  "linkedWordSecondLocalizationKey": "string",
14
- "linkedWordSecondColor": "string",
14
+ "linkedWordSecondColor": "color",
15
15
  "linkedWordSecondPage": "string"
16
16
  }
17
17
  },
18
18
  "defaults": {
19
19
  "paddingHorizontal": "24@s"
20
+ },
21
+ "meta": {
22
+ "desiredParent": [">OnboardItem"],
23
+ "label": "Onboard Footer",
24
+ "description": "Footer text with optional links.",
25
+ "attributes": {
26
+ "textLocalizationKey": {
27
+ "label": "Text Localization Key",
28
+ "description": "Localization key for the footer text.",
29
+ "category": "other",
30
+ "specialCategory": null,
31
+ "sort": 1
32
+ },
33
+ "linkedWordFirstLocalizationKey": {
34
+ "label": "Linked Word First Localization Key",
35
+ "description": "Key for the first linked word.",
36
+ "category": "other",
37
+ "specialCategory": null,
38
+ "sort": 2
39
+ },
40
+ "linkedWordFirstColor": {
41
+ "label": "Linked Word First Color",
42
+ "description": "Color of the first linked word.",
43
+ "category": "style",
44
+ "specialCategory": null,
45
+ "sort": 3
46
+ },
47
+ "linkedWordFirstPage": {
48
+ "label": "Linked Word First Page",
49
+ "description": "Page opened by the first link.",
50
+ "category": "other",
51
+ "specialCategory": null,
52
+ "sort": 4
53
+ },
54
+ "linkedWordSecondLocalizationKey": {
55
+ "label": "Linked Word Second Localization Key",
56
+ "description": "Key for the second linked word.",
57
+ "category": "other",
58
+ "specialCategory": null,
59
+ "sort": 5
60
+ },
61
+ "linkedWordSecondColor": {
62
+ "label": "Linked Word Second Color",
63
+ "description": "Color of the second linked word.",
64
+ "category": "style",
65
+ "specialCategory": null,
66
+ "sort": 6
67
+ },
68
+ "linkedWordSecondPage": {
69
+ "label": "Linked Word Second Page",
70
+ "description": "Page opened by the second link.",
71
+ "category": "other",
72
+ "specialCategory": null,
73
+ "sort": 7
74
+ }
75
+ }
20
76
  }
21
77
  }