@developer_tribe/react-builder 1.0.1 → 1.0.2

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 (187) hide show
  1. package/dist/DeviceMockFrame.d.ts +2 -1
  2. package/dist/RenderPage.d.ts +4 -3
  3. package/dist/attributes-editor/Field.d.ts +16 -0
  4. package/dist/attributes-editor/FieldInfoTooltip.d.ts +7 -0
  5. package/dist/attributes-editor/LayoutPreviewPicker.d.ts +12 -0
  6. package/dist/attributes-editor/SpecialCategorySection.d.ts +19 -0
  7. package/dist/attributes-editor/types.d.ts +14 -0
  8. package/dist/background.jpg +0 -0
  9. package/dist/build-components/Button/Button.d.ts +1 -1
  10. package/dist/build-components/Button/ButtonProps.generated.d.ts +26 -1
  11. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +27 -1
  12. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +25 -0
  13. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +25 -0
  14. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +27 -1
  15. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +27 -1
  16. package/dist/build-components/Image/ImageProps.generated.d.ts +25 -3
  17. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +27 -1
  18. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +25 -0
  19. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +25 -0
  20. package/dist/build-components/OnboardDot/OnboardDot.d.ts +1 -1
  21. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +22 -0
  22. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +4 -5
  23. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +25 -3
  24. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +24 -3
  25. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +25 -4
  26. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +4 -5
  27. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +4 -5
  28. package/dist/build-components/Text/TextProps.generated.d.ts +4 -5
  29. package/dist/build-components/View/ViewProps.generated.d.ts +3 -4
  30. package/dist/build-components/patterns.generated.d.ts +4855 -132
  31. package/dist/components/Breadcrumb.d.ts +3 -1
  32. package/dist/components/Checkbox.d.ts +17 -0
  33. package/dist/components/DeviceButton.d.ts +8 -0
  34. package/dist/components/DeviceNavigationBar.d.ts +10 -0
  35. package/dist/components/DeviceStatusBar.d.ts +9 -0
  36. package/dist/components/EditorHeader.d.ts +3 -8
  37. package/dist/index.cjs.js +5 -5
  38. package/dist/index.cjs.js.map +1 -1
  39. package/dist/index.esm.js +5 -5
  40. package/dist/index.esm.js.map +1 -1
  41. package/dist/mockOS/components/MockLaunchScreenComponent.d.ts +6 -0
  42. package/dist/mockOS/components/MockOSRouter.d.ts +8 -0
  43. package/dist/mockOS/components/PermissionModal.d.ts +9 -0
  44. package/dist/mockOS/context/MockOSContext.d.ts +36 -0
  45. package/dist/mockOS/hooks/useMockNavigation.d.ts +3 -0
  46. package/dist/mockOS/hooks/useMockPermission.d.ts +3 -0
  47. package/dist/mockOS/index.d.ts +9 -0
  48. package/dist/mockOS/managers/mockPermissionManager.d.ts +10 -0
  49. package/dist/mockOS/managers/navigationManager.d.ts +17 -0
  50. package/dist/modals/AddComponentModal.d.ts +8 -0
  51. package/dist/modals/ColorModal.d.ts +9 -0
  52. package/dist/modals/DeviceSelectorModal.d.ts +9 -0
  53. package/dist/modals/LocalicationModal.d.ts +8 -0
  54. package/dist/modals/Modal.d.ts +12 -0
  55. package/dist/modals/index.d.ts +5 -0
  56. package/dist/pages/ProjectPage.d.ts +1 -1
  57. package/dist/store.d.ts +0 -2
  58. package/dist/styles.css +1 -1
  59. package/dist/utils/patterns.d.ts +24 -0
  60. package/package.json +2 -1
  61. package/scripts/prebuild/utils/createGeneratedProps.js +11 -3
  62. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +45 -6
  63. package/scripts/prebuild/utils/validatePatternJson.js +13 -5
  64. package/src/AttributesEditor.tsx +433 -312
  65. package/src/DeviceMockFrame.tsx +21 -37
  66. package/src/RenderPage.tsx +5 -4
  67. package/src/assets/images/android.svg +42 -42
  68. package/src/assets/images/apple.svg +15 -15
  69. package/src/attributes-editor/Field.tsx +662 -0
  70. package/src/attributes-editor/FieldInfoTooltip.tsx +49 -0
  71. package/src/attributes-editor/LayoutPreviewPicker.tsx +199 -0
  72. package/src/attributes-editor/SpecialCategorySection.tsx +284 -0
  73. package/src/attributes-editor/types.ts +30 -0
  74. package/src/build-components/Button/Button.tsx +10 -2
  75. package/src/build-components/Button/ButtonProps.generated.ts +37 -1
  76. package/src/build-components/Button/pattern.json +31 -2
  77. package/src/build-components/Carousel/Carousel.tsx +15 -2
  78. package/src/build-components/Carousel/CarouselProps.generated.ts +39 -1
  79. package/src/build-components/Carousel/pattern.json +10 -0
  80. package/src/build-components/CarouselButtons/CarouselButtons.tsx +6 -2
  81. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +36 -0
  82. package/src/build-components/CarouselButtons/pattern.json +22 -0
  83. package/src/build-components/CarouselDots/CarouselDots.tsx +40 -8
  84. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +36 -0
  85. package/src/build-components/CarouselDots/pattern.json +15 -0
  86. package/src/build-components/CarouselItem/CarouselItem.tsx +5 -2
  87. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +39 -1
  88. package/src/build-components/CarouselItem/pattern.json +7 -0
  89. package/src/build-components/CarouselProvider/CarouselProvider.tsx +10 -2
  90. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +39 -1
  91. package/src/build-components/CarouselProvider/pattern.json +7 -0
  92. package/src/build-components/Image/Image.tsx +8 -2
  93. package/src/build-components/Image/ImageProps.generated.ts +36 -3
  94. package/src/build-components/Image/pattern.json +46 -3
  95. package/src/build-components/Onboard/Onboard.tsx +6 -1
  96. package/src/build-components/Onboard/OnboardProps.generated.ts +39 -1
  97. package/src/build-components/Onboard/pattern.json +11 -0
  98. package/src/build-components/OnboardButton/OnboardButton.tsx +46 -5
  99. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +36 -0
  100. package/src/build-components/OnboardButton/pattern.json +71 -5
  101. package/src/build-components/OnboardButtons/OnboardButtons.tsx +20 -10
  102. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +36 -0
  103. package/src/build-components/OnboardButtons/pattern.json +70 -4
  104. package/src/build-components/OnboardDot/OnboardDot.tsx +104 -4
  105. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +22 -0
  106. package/src/build-components/OnboardDot/pattern.json +54 -1
  107. package/src/build-components/OnboardFooter/OnboardFooter.tsx +9 -3
  108. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +4 -5
  109. package/src/build-components/OnboardFooter/pattern.json +58 -2
  110. package/src/build-components/OnboardImage/OnboardImage.tsx +27 -5
  111. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +36 -3
  112. package/src/build-components/OnboardImage/pattern.json +21 -0
  113. package/src/build-components/OnboardItem/OnboardItem.tsx +6 -1
  114. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +35 -3
  115. package/src/build-components/OnboardItem/pattern.json +38 -2
  116. package/src/build-components/OnboardProvider/OnboardProvider.tsx +20 -8
  117. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +37 -4
  118. package/src/build-components/OnboardProvider/pattern.json +51 -4
  119. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +4 -5
  120. package/src/build-components/OnboardSubtitle/pattern.json +6 -0
  121. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +4 -5
  122. package/src/build-components/OnboardTitle/pattern.json +6 -0
  123. package/src/build-components/Text/Text.tsx +7 -3
  124. package/src/build-components/Text/TextProps.generated.ts +4 -5
  125. package/src/build-components/Text/pattern.json +38 -2
  126. package/src/build-components/View/View.tsx +9 -6
  127. package/src/build-components/View/ViewProps.generated.ts +3 -4
  128. package/src/build-components/View/pattern.json +227 -19
  129. package/src/build-components/patterns.generated.ts +4905 -139
  130. package/src/components/AttributesEditorPanel.tsx +7 -61
  131. package/src/components/Breadcrumb.tsx +37 -5
  132. package/src/components/Builder.tsx +180 -77
  133. package/src/components/Checkbox.tsx +81 -0
  134. package/src/components/DeviceButton.tsx +39 -0
  135. package/src/components/DeviceNavigationBar.tsx +201 -0
  136. package/src/components/DeviceStatusBar.tsx +85 -0
  137. package/src/components/EditorHeader.tsx +26 -74
  138. package/src/mockOS/components/MockLaunchScreenComponent.tsx +43 -0
  139. package/src/mockOS/components/MockOSRouter.tsx +115 -0
  140. package/src/mockOS/components/PermissionModal.tsx +270 -0
  141. package/src/mockOS/context/MockOSContext.tsx +179 -0
  142. package/src/mockOS/hooks/useMockNavigation.ts +11 -0
  143. package/src/mockOS/hooks/useMockPermission.ts +11 -0
  144. package/src/mockOS/index.ts +26 -0
  145. package/src/mockOS/managers/mockPermissionManager.ts +54 -0
  146. package/src/mockOS/managers/navigationManager.ts +91 -0
  147. package/src/modals/AddComponentModal.tsx +313 -0
  148. package/src/modals/ColorModal.tsx +268 -0
  149. package/src/modals/DeviceSelectorModal.tsx +57 -0
  150. package/src/modals/LocalicationModal.tsx +54 -0
  151. package/src/modals/Modal.tsx +57 -0
  152. package/src/modals/index.ts +5 -0
  153. package/src/pages/ProjectPage.tsx +19 -21
  154. package/src/pages/tabs/DebugTab.tsx +50 -9
  155. package/src/pages/tabs/PreviewTab.tsx +52 -40
  156. package/src/size-matters/index.ts +21 -5
  157. package/src/store.ts +0 -4
  158. package/src/styles/{global.scss → base/_global.scss} +92 -39
  159. package/src/styles/components/_attributes-editor.scss +261 -0
  160. package/src/styles/{editor.scss → components/_editor-shell.scss} +72 -57
  161. package/src/styles/components/_mockos-router.scss +140 -0
  162. package/src/styles/components/_ui-components.scss +183 -0
  163. package/src/styles/foundation/_colors.scss +8 -0
  164. package/src/styles/{_mixins.scss → foundation/_mixins.scss} +5 -4
  165. package/src/styles/{_reset.scss → foundation/_reset.scss} +5 -2
  166. package/src/styles/foundation/_sizes.scss +37 -0
  167. package/src/styles/foundation/_typography.scss +4 -0
  168. package/src/styles/foundation/_variables.scss +3 -0
  169. package/src/styles/index.scss +22 -136
  170. package/src/styles/layout/_builder.scss +68 -0
  171. package/src/styles/layout/_pages.scss +3 -0
  172. package/src/styles/modals/_add-component.scss +122 -0
  173. package/src/styles/modals/_color-modal.scss +130 -0
  174. package/src/styles/modals/_device-selector.scss +18 -0
  175. package/src/styles/modals/_localication-modal.scss +68 -0
  176. package/src/styles/modals/_modal-shell.scss +46 -0
  177. package/src/styles/utilities/_carousel.scss +125 -0
  178. package/src/types/images.d.ts +8 -0
  179. package/src/utils/extractTextStyle.ts +4 -2
  180. package/src/utils/extractViewStyle.ts +51 -7
  181. package/src/utils/patterns.ts +33 -0
  182. package/dist/build-components/OnboardDot/OnboardExpandingDotProps.generated.d.ts +0 -10
  183. package/src/build-components/OnboardDot/OnboardExpandingDotProps.generated.ts +0 -20
  184. package/src/styles/_variables.scss +0 -27
  185. package/src/styles/builder.scss +0 -60
  186. package/src/styles/components.scss +0 -88
  187. package/src/styles/pages.scss +0 -2
@@ -2,9 +2,47 @@
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
+
5
20
  export interface OnboardPropsGenerated {
6
21
  child: string;
7
- attributes: {};
22
+ attributes: {
23
+ scrollable?: boolean;
24
+ flexDirection?: FlexDirectionOptionType;
25
+ alignItems?: AlignItemsOptionType;
26
+ justifyContent?: JustifyContentOptionType;
27
+ gap?: string;
28
+ padding?: string;
29
+ paddingHorizontal?: string;
30
+ paddingVertical?: string;
31
+ paddingTop?: string;
32
+ paddingBottom?: string;
33
+ paddingLeft?: string;
34
+ paddingRight?: string;
35
+ margin?: string;
36
+ marginVertical?: string;
37
+ marginTop?: string;
38
+ marginBottom?: string;
39
+ marginLeft?: string;
40
+ marginRight?: string;
41
+ backgroundColor?: string;
42
+ borderRadius?: string;
43
+ width?: string;
44
+ height?: string;
45
+ };
8
46
  }
9
47
 
10
48
  export interface OnboardComponentProps {
@@ -4,6 +4,17 @@
4
4
  "pattern": {
5
5
  "type": "Onboard",
6
6
  "children": "node",
7
+ "extends": "View",
8
+ "attributes": {},
9
+ "defaults": {
10
+ "flexDirection": "row"
11
+ }
12
+ },
13
+ "meta": {
14
+ "desiredParent": ["=OnboardProvider"],
15
+ "desiredChildren": ["=OnboardItem"],
16
+ "label": "Onboard",
17
+ "description": "Wraps the onboarding flow.",
7
18
  "attributes": {}
8
19
  }
9
20
  }
@@ -1,18 +1,29 @@
1
- import React, { useContext } from 'react';
2
- import type { OnboardButtonComponentProps } from './OnboardButtonProps.generated';
1
+ import React, { useContext, useMemo, useRef } from 'react';
2
+ import type {
3
+ EventObjectGenerated,
4
+ OnboardButtonComponentProps,
5
+ } from './OnboardButtonProps.generated';
3
6
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
4
7
  import useNode from '../useNode';
5
8
  import { useRenderStore } from '../../store';
6
9
  import { useLogRender } from '../../utils/useLogRender';
10
+ import { extractViewStyle } from '../../utils/extractViewStyle';
11
+ import { useMockOSContext, useMockPermission } from '../../mockOS';
7
12
 
8
13
  function OnboardButton({ node }: OnboardButtonComponentProps) {
9
14
  useLogRender('OnboardButton');
10
15
  node = useNode(node);
16
+ const attributeKey =
17
+ (node as any)?.sourceType ?? node.type ?? 'OnboardButton';
11
18
  const { emblaApi } = useContext(onboardContext) ?? {};
12
19
  const { appConfig } = useRenderStore((s) => ({
13
20
  appConfig: s.appConfig,
14
21
  }));
15
22
 
23
+ const context = useMockOSContext();
24
+ const mockPermissionManager = useMockPermission(context);
25
+ const handledEventsRef = useRef<EventObjectGenerated[]>([]);
26
+
16
27
  const labelRaw = node.attributes?.labelKey ?? '';
17
28
  const label =
18
29
  (appConfig.localication?.[appConfig.defaultLanguage ?? 'en']?.[
@@ -22,18 +33,46 @@ function OnboardButton({ node }: OnboardButtonComponentProps) {
22
33
  const flex = node.attributes?.flex ?? 1;
23
34
  const textColor = node.attributes?.button_text_color ?? '#FFFFFF';
24
35
  const backgroundColor = node.attributes?.button_background_color ?? '#0066FF';
36
+ const viewStyle = useMemo(() => extractViewStyle(node), [node]);
25
37
 
26
38
  const handleClick = () => {
27
- const events = (node.attributes as any)?.events || [];
39
+ //TODO: any ??
40
+ const events: EventObjectGenerated[] = node.attributes?.events ?? [];
28
41
  let navigateHandled = false;
42
+
29
43
  for (const e of events) {
44
+ // Check if event is already handled
45
+ if (handledEventsRef.current.includes(e)) {
46
+ continue;
47
+ }
48
+
30
49
  if (e.type === 'Permission') {
31
- alert(`Permission requested: ${e.permission ?? 'unknown'}`);
50
+ const permission = e.permission ?? 'camera';
51
+ mockPermissionManager.requestPermission(permission);
52
+ handledEventsRef.current.push(e);
53
+ //TODO: cause user to click second time
54
+ return;
32
55
  } else if (e.type === 'Navigate') {
33
- const eventTargetIndex = (e as any)?.targetIndex;
56
+ const eventTargetIndex = e.targetIndex;
34
57
  if (typeof eventTargetIndex === 'number') {
35
58
  emblaApi?.scrollTo(eventTargetIndex);
36
59
  navigateHandled = true;
60
+ handledEventsRef.current.push(e);
61
+ //TODO: cause user to click second time
62
+ return;
63
+ } else if (e.navigate_to) {
64
+ const eventTarget = e.navigate_to;
65
+ if (typeof eventTarget === 'string') {
66
+ navigateHandled = true;
67
+ handledEventsRef.current.push(e);
68
+ //TODO: cause user to click second time
69
+ if (context) {
70
+ context.navigation(eventTarget as any);
71
+ } else {
72
+ alert('Mock OS context not available for navigation.');
73
+ }
74
+ }
75
+ return;
37
76
  }
38
77
  }
39
78
  }
@@ -42,9 +81,11 @@ function OnboardButton({ node }: OnboardButtonComponentProps) {
42
81
 
43
82
  return (
44
83
  <button
84
+ attribute-key={attributeKey}
45
85
  className="onboard__button"
46
86
  onClick={handleClick}
47
87
  style={{
88
+ ...viewStyle,
48
89
  flex,
49
90
  color: textColor,
50
91
  backgroundColor,
@@ -4,6 +4,20 @@ import type { NodeData } from '../../types/Node';
4
4
 
5
5
  export type TypeOptionType = 'Permission' | 'Navigate';
6
6
  export type PermissionOptionType = 'att' | 'notification' | 'rating' | 'GDPR';
7
+ export type FlexDirectionOptionType = 'row' | 'column';
8
+ export type AlignItemsOptionType =
9
+ | 'flex-start'
10
+ | 'center'
11
+ | 'flex-end'
12
+ | 'stretch'
13
+ | 'baseline';
14
+ export type JustifyContentOptionType =
15
+ | 'flex-start'
16
+ | 'center'
17
+ | 'flex-end'
18
+ | 'space-between'
19
+ | 'space-around'
20
+ | 'space-evenly';
7
21
  export type AnimationOptionType =
8
22
  | 'simple-animation'
9
23
  | 'line-animation'
@@ -21,6 +35,28 @@ export interface EventObjectGenerated {
21
35
  export interface OnboardButtonPropsGenerated {
22
36
  child: string;
23
37
  attributes: {
38
+ scrollable?: boolean;
39
+ flexDirection?: FlexDirectionOptionType;
40
+ alignItems?: AlignItemsOptionType;
41
+ justifyContent?: JustifyContentOptionType;
42
+ gap?: string;
43
+ padding?: string;
44
+ paddingHorizontal?: string;
45
+ paddingVertical?: string;
46
+ paddingTop?: string;
47
+ paddingBottom?: string;
48
+ paddingLeft?: string;
49
+ paddingRight?: string;
50
+ margin?: string;
51
+ marginVertical?: string;
52
+ marginTop?: string;
53
+ marginBottom?: string;
54
+ marginLeft?: string;
55
+ marginRight?: string;
56
+ backgroundColor?: string;
57
+ borderRadius?: string;
58
+ width?: string;
59
+ height?: string;
24
60
  labelKey?: string;
25
61
  button_text_color?: string;
26
62
  animation?: AnimationOptionType;
@@ -4,9 +4,10 @@
4
4
  "pattern": {
5
5
  "type": "OnboardButton",
6
6
  "children": "never",
7
+ "extends": "View",
7
8
  "attributes": {
8
9
  "labelKey": "string",
9
- "button_text_color": "string",
10
+ "button_text_color": "color",
10
11
  "animation": [
11
12
  "simple-animation",
12
13
  "line-animation",
@@ -14,18 +15,83 @@
14
15
  "blur-animation",
15
16
  "blur-line-animation"
16
17
  ],
17
- "animation_color": "string",
18
- "button_background_color": "string",
18
+ "animation_color": "color",
19
+ "button_background_color": "color",
19
20
  "flex": "number",
20
21
  "events": "EventObject[]"
21
22
  }
22
23
  },
23
24
  "types": {
24
25
  "EventObject": {
25
- "type": ["Permission", "Navigate"],
26
- "permission": ["att", "notification", "rating", "GDPR", "null"],
26
+ "type": [
27
+ "Permission",
28
+ "Navigate"
29
+ ],
30
+ "permission": [
31
+ "att",
32
+ "notification",
33
+ "rating",
34
+ "GDPR",
35
+ "null"
36
+ ],
27
37
  "navigate_to": "string",
28
38
  "targetIndex": "number"
29
39
  }
40
+ },
41
+ "meta": {
42
+ "desiredParent": ["=OnboardButtons"],
43
+ "label": "Onboard Button",
44
+ "description": "Single action button for onboarding.",
45
+ "attributes": {
46
+ "labelKey": {
47
+ "label": "Label Key",
48
+ "description": "Localization key for the button text.",
49
+ "category": "other",
50
+ "specialCategory": null,
51
+ "sort": 1
52
+ },
53
+ "button_text_color": {
54
+ "label": "Button Text Color",
55
+ "description": "Text color of the button.",
56
+ "category": "style",
57
+ "specialCategory": null,
58
+ "sort": 2
59
+ },
60
+ "animation": {
61
+ "label": "Animation",
62
+ "description": "Animation style for the button.",
63
+ "category": "style",
64
+ "specialCategory": null,
65
+ "sort": 3
66
+ },
67
+ "animation_color": {
68
+ "label": "Animation Color",
69
+ "description": "Color used by the animation.",
70
+ "category": "style",
71
+ "specialCategory": null,
72
+ "sort": 4
73
+ },
74
+ "button_background_color": {
75
+ "label": "Button Background Color",
76
+ "description": "Background color of the button.",
77
+ "category": "style",
78
+ "specialCategory": null,
79
+ "sort": 5
80
+ },
81
+ "flex": {
82
+ "label": "Flex",
83
+ "description": "Flex grow value in layout.",
84
+ "category": "container",
85
+ "specialCategory": null,
86
+ "sort": 6
87
+ },
88
+ "events": {
89
+ "label": "Events",
90
+ "description": "List of events fired by the button.",
91
+ "category": "other",
92
+ "specialCategory": null,
93
+ "sort": 7
94
+ }
95
+ }
30
96
  }
31
97
  }
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect, useState } from 'react';
1
+ import React, { useContext, useEffect, 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,10 +6,13 @@ 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);
14
+ const attributeKey =
15
+ (node as any)?.sourceType ?? node.type ?? 'OnboardButtons';
13
16
  const { appConfig } = useRenderStore((s) => ({
14
17
  appConfig: s.appConfig,
15
18
  }));
@@ -26,13 +29,6 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
26
29
  }
27
30
  }, [ctx.selectedIndex]);
28
31
 
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
32
  const direction =
37
33
  node.attributes?.buttons_direction === 'column' ? 'column' : 'row';
38
34
  const seperatorColor =
@@ -47,8 +43,22 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
47
43
  return <RenderNode node={node.children as Node} />;
48
44
  };
49
45
 
46
+ const viewStyle = useMemo(() => extractViewStyle(node), [node]);
47
+
48
+ // New condition logic: hide when condition is carousel-index and does not match
49
+ const condition = (node.attributes as any)?.condition;
50
+ const conditionVariable = (node.attributes as any)?.conditionVariable;
51
+ const shouldHide =
52
+ condition === 'carousel-index' &&
53
+ typeof conditionVariable === 'number' &&
54
+ conditionVariable !== selectedIndex;
55
+
56
+ if (shouldHide) {
57
+ return null;
58
+ }
59
+
50
60
  return (
51
- <>
61
+ <div attribute-key={attributeKey} style={viewStyle}>
52
62
  <div
53
63
  className="onboard__separator"
54
64
  style={{
@@ -71,7 +81,7 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
71
81
  >
72
82
  {renderChildren()}
73
83
  </div>
74
- </>
84
+ </div>
75
85
  );
76
86
  }
77
87
 
@@ -2,6 +2,20 @@
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';
5
19
  export type ButtonTypeOptionType =
6
20
  | 'previous_button'
7
21
  | 'next_button'
@@ -12,6 +26,28 @@ export type ConditionOptionType = 'carousel-index';
12
26
  export interface OnboardButtonsPropsGenerated {
13
27
  child: string;
14
28
  attributes: {
29
+ scrollable?: boolean;
30
+ flexDirection?: FlexDirectionOptionType;
31
+ alignItems?: AlignItemsOptionType;
32
+ justifyContent?: JustifyContentOptionType;
33
+ gap?: string;
34
+ padding?: string;
35
+ paddingHorizontal?: string;
36
+ paddingVertical?: string;
37
+ paddingTop?: string;
38
+ paddingBottom?: string;
39
+ paddingLeft?: string;
40
+ paddingRight?: string;
41
+ margin?: string;
42
+ marginVertical?: string;
43
+ marginTop?: string;
44
+ marginBottom?: string;
45
+ marginLeft?: string;
46
+ marginRight?: string;
47
+ backgroundColor?: string;
48
+ borderRadius?: string;
49
+ width?: string;
50
+ height?: string;
15
51
  buttonType?: ButtonTypeOptionType;
16
52
  skipNumber?: number;
17
53
  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,113 @@
1
- import React from 'react';
2
- import type { OnboardDotComponentProps } from './OnboardExpandingDotProps.generated';
3
- import CarouselDots from '../CarouselDots/CarouselDots';
1
+ import React, { useContext, useEffect, 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 attributeKey = node.type ?? 'OnboardDot';
15
+ const dotType = node.attributes?.dotType || 'normal_dot';
16
+ const GHOST_DOT_DARK_COLOR = '#E4E5E7';
17
+ const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
18
+ const isDark = useRenderStore((s) => s.appConfig.theme === 'dark');
19
+
20
+ // OnboardDot specific attributes
21
+ const inactiveDotColor = isDark
22
+ ? GHOST_DOT_DARK_COLOR
23
+ : GHOST_DOT_LIGHT_COLOR;
24
+ const inactiveDotOpacity = node.attributes?.inactive_dot_opacity ?? 0.3;
25
+ const dotStyle = node.attributes?.dot_style;
26
+ const containerStyle = node.attributes?.container_style;
27
+ const activeDotColor = node.attributes?.active_dot_color;
28
+
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]);
42
+
43
+ const onboardApi = useContext(onboardContext);
44
+ const emblaApi = onboardApi?.emblaApi;
45
+
46
+ const [selectedIndex, setSelectedIndex] = useState(0);
47
+ const [scrollSnaps, setScrollSnaps] = useState<number[]>([]);
48
+
49
+ useEffect(() => {
50
+ if (!emblaApi) return;
51
+ const snaps = emblaApi.scrollSnapList();
52
+ const selected = emblaApi.selectedScrollSnap();
53
+ setScrollSnaps(snaps);
54
+ setSelectedIndex(selected);
55
+
56
+ const onSelect = () => {
57
+ const sel = emblaApi.selectedScrollSnap();
58
+ setSelectedIndex(sel);
59
+ };
60
+ emblaApi.on('select', onSelect);
61
+
62
+ return () => {
63
+ if (emblaApi && emblaApi.off) {
64
+ emblaApi.off('select', onSelect);
65
+ }
66
+ };
67
+ }, [emblaApi]);
68
+
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
+ return (
80
+ <div
81
+ attribute-key={attributeKey}
82
+ className={`embla__dots embla__dots--${dotType}`}
83
+ style={style}
84
+ >
85
+ {scrollSnaps.map((snap, index) => {
86
+ const isSelected = selectedIndex === index;
87
+ const dotStyles: React.CSSProperties = {
88
+ ...parsedDotStyle,
89
+ opacity: isSelected ? 1 : inactiveDotOpacity,
90
+ };
91
+
92
+ if (activeDotColor && isSelected) {
93
+ dotStyles.color = activeDotColor;
94
+ } else if (!isSelected) {
95
+ dotStyles.color = inactiveDotColor;
96
+ }
97
+
98
+ return (
99
+ <button
100
+ key={index}
101
+ onClick={() => emblaApi?.scrollTo(snap)}
102
+ className={`embla__dot ${isSelected ? 'embla__dot--selected' : ''}`}
103
+ style={dotStyles}
104
+ >
105
+ {isSelected ? '●' : '○'}
106
+ </button>
107
+ );
108
+ })}
109
+ </div>
110
+ );
11
111
  }
12
112
 
13
113
  export default React.memo(OnboardDot);
@@ -13,6 +13,28 @@ export type DotTypeOptionType =
13
13
  export interface OnboardDotPropsGenerated {
14
14
  child: string;
15
15
  attributes: {
16
+ scrollable?: boolean;
17
+ flexDirection?: never;
18
+ alignItems?: never;
19
+ justifyContent?: never;
20
+ gap?: string;
21
+ padding?: string;
22
+ paddingHorizontal?: string;
23
+ paddingVertical?: string;
24
+ paddingTop?: string;
25
+ paddingBottom?: string;
26
+ paddingLeft?: string;
27
+ paddingRight?: string;
28
+ margin?: string;
29
+ marginVertical?: string;
30
+ marginTop?: string;
31
+ marginBottom?: string;
32
+ marginLeft?: string;
33
+ marginRight?: string;
34
+ backgroundColor?: string;
35
+ borderRadius?: string;
36
+ width?: string;
37
+ height?: string;
16
38
  dotType?: DotTypeOptionType;
17
39
  inactive_dot_opacity?: number;
18
40
  expanding_dot_width?: number;