@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
@@ -0,0 +1,87 @@
1
+ import React, { useId, useMemo } from 'react';
2
+ import type { BackgroundImageComponentProps } from './BackgroundImageProps.generated';
3
+ import useNode from '../useNode';
4
+ import { useRenderStore } from '../../store';
5
+ import { extractViewStyle } from '../../utils/extractViewStyle';
6
+ import { useLogRender } from '../../utils/useLogRender';
7
+
8
+ function BackgroundImage({ node }: BackgroundImageComponentProps) {
9
+ useLogRender('BackgroundImage');
10
+ node = useNode(node);
11
+ const generatedId = useId();
12
+ const attributeName =
13
+ (node as any)?.sourceType ?? node.type ?? 'background-image';
14
+ const attributeKey = node.key ?? generatedId;
15
+
16
+ const { previewMode, current, appConfig, projectColors } = useRenderStore(
17
+ (s) => ({
18
+ previewMode: s.previewMode,
19
+ current: s.current,
20
+ appConfig: s.appConfig,
21
+ projectColors: s.projectColors,
22
+ }),
23
+ );
24
+
25
+ const baseStyle = useMemo(
26
+ () => extractViewStyle(node, { appConfig, projectColors }),
27
+ [node, appConfig, projectColors],
28
+ );
29
+ const backgroundStyle = useMemo(() => {
30
+ const attrs = node.attributes;
31
+ const style: React.CSSProperties = {
32
+ backgroundRepeat: 'no-repeat',
33
+ backgroundPosition: 'center',
34
+ };
35
+
36
+ if (attrs?.src) {
37
+ style.backgroundImage = `url(${attrs.src})`;
38
+ }
39
+
40
+ switch (attrs?.resizeMode) {
41
+ case 'cover':
42
+ style.backgroundSize = 'cover';
43
+ break;
44
+ case 'contain':
45
+ style.backgroundSize = 'contain';
46
+ break;
47
+ case 'stretch':
48
+ style.backgroundSize = '100% 100%';
49
+ break;
50
+ case 'center':
51
+ style.backgroundSize = 'auto';
52
+ break;
53
+ default:
54
+ style.backgroundSize = 'cover';
55
+ }
56
+
57
+ return style;
58
+ }, [node]);
59
+ const isSelected =
60
+ previewMode &&
61
+ !!current &&
62
+ (current as any)?.key &&
63
+ (node as any)?.key &&
64
+ (current as any).key === (node as any).key;
65
+
66
+ const mergedStyle = useMemo(
67
+ () => ({
68
+ ...baseStyle,
69
+ ...backgroundStyle,
70
+ }),
71
+ [baseStyle, backgroundStyle],
72
+ );
73
+
74
+ const style = isSelected
75
+ ? { ...mergedStyle, outline: '2px solid #2684FF' }
76
+ : mergedStyle;
77
+
78
+ return (
79
+ <div
80
+ attribute-name={attributeName}
81
+ attribute-key={attributeKey}
82
+ style={style}
83
+ />
84
+ );
85
+ }
86
+
87
+ export default React.memo(BackgroundImage);
@@ -0,0 +1,60 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
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';
20
+ export type ResizeModeOptionType = 'cover' | 'contain' | 'stretch' | 'center';
21
+
22
+ export interface BackgroundImagePropsGenerated {
23
+ child: string;
24
+ attributes: {
25
+ scrollable?: boolean;
26
+ flexDirection?: FlexDirectionOptionType;
27
+ alignItems?: AlignItemsOptionType;
28
+ justifyContent?: JustifyContentOptionType;
29
+ gap?: string;
30
+ padding?: string;
31
+ paddingHorizontal?: string;
32
+ paddingVertical?: string;
33
+ paddingTop?: string;
34
+ paddingBottom?: string;
35
+ paddingLeft?: string;
36
+ paddingRight?: string;
37
+ margin?: string;
38
+ marginVertical?: string;
39
+ marginTop?: string;
40
+ marginBottom?: string;
41
+ marginLeft?: string;
42
+ marginRight?: string;
43
+ backgroundColor?: string;
44
+ borderRadius?: string;
45
+ width?: string;
46
+ height?: string;
47
+ position?: PositionOptionType;
48
+ top?: string;
49
+ bottom?: string;
50
+ left?: string;
51
+ right?: string;
52
+ zIndex?: number;
53
+ src?: string;
54
+ resizeMode?: ResizeModeOptionType;
55
+ };
56
+ }
57
+
58
+ export interface BackgroundImageComponentProps {
59
+ node: NodeData<BackgroundImagePropsGenerated['attributes']>;
60
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "allowUnknownAttributes": false,
4
+ "pattern": {
5
+ "type": "background-image",
6
+ "children": "never",
7
+ "extends": "View",
8
+ "attributes": {
9
+ "src": "string",
10
+ "resizeMode": ["cover", "contain", "stretch", "center"]
11
+ },
12
+ "defaults": {
13
+ "resizeMode": "cover",
14
+ "width": "100%",
15
+ "height": "100%",
16
+ "position": "fixed",
17
+ "top": 0,
18
+ "left": 0,
19
+ "right": 0,
20
+ "bottom": 0,
21
+ "zIndex": 0
22
+ }
23
+ },
24
+ "meta": {
25
+ "desiredParent": ["all", "background"],
26
+ "label": "Background Image",
27
+ "description": "Background image.",
28
+ "attributes": {
29
+ "src": {
30
+ "label": "Src",
31
+ "description": "Image source URL.",
32
+ "category": "other",
33
+ "specialCategory": null,
34
+ "sort": 1
35
+ },
36
+ "resizeMode": {
37
+ "label": "Resize Mode",
38
+ "description": "How the image fits its container.",
39
+ "category": "style",
40
+ "specialCategory": null,
41
+ "sort": 4
42
+ }
43
+ }
44
+ }
45
+ }
@@ -1,17 +1,44 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useId, useMemo } from 'react';
2
2
  import type { ButtonComponentProps } from './ButtonProps.generated';
3
3
  import useNode from '../useNode';
4
+ import { useRenderStore } from '../../store';
4
5
  import { useLogRender } from '../../utils/useLogRender';
5
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
6
7
 
7
8
  function Button({ node }: ButtonComponentProps) {
8
9
  useLogRender('Button');
9
10
  node = useNode(node);
10
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'button';
11
- const style = useMemo(() => extractViewStyle(node), [node]);
11
+ const generatedId = useId();
12
+ const attributeName = (node as any)?.sourceType ?? node.type ?? 'button';
13
+ const attributeKey = node.key ?? generatedId;
14
+ const { previewMode, current, appConfig, projectColors } = useRenderStore(
15
+ (s) => ({
16
+ previewMode: s.previewMode,
17
+ current: s.current,
18
+ appConfig: s.appConfig,
19
+ projectColors: s.projectColors,
20
+ }),
21
+ );
22
+ const baseStyle = useMemo(
23
+ () => extractViewStyle(node, { appConfig, projectColors }),
24
+ [node, appConfig, projectColors],
25
+ );
26
+ const isSelected =
27
+ previewMode &&
28
+ !!current &&
29
+ (current as any)?.key &&
30
+ (node as any)?.key &&
31
+ (current as any).key === (node as any).key;
32
+ const style = isSelected
33
+ ? { ...baseStyle, outline: '2px solid #2684FF' }
34
+ : baseStyle;
12
35
 
13
36
  return (
14
- <div attribute-key={attributeKey} style={style}>
37
+ <div
38
+ attribute-name={attributeName}
39
+ attribute-key={attributeKey}
40
+ style={style}
41
+ >
15
42
  {String(node?.type ?? 'button')}
16
43
  </div>
17
44
  );
@@ -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 FontWeightOptionType =
20
21
  | 'normal'
21
22
  | 'bold'
@@ -54,6 +55,12 @@ export interface ButtonPropsGenerated {
54
55
  borderRadius?: string;
55
56
  width?: string;
56
57
  height?: string;
58
+ position?: PositionOptionType;
59
+ top?: string;
60
+ bottom?: string;
61
+ left?: string;
62
+ right?: string;
63
+ zIndex?: number;
57
64
  color?: string;
58
65
  fontSize?: string;
59
66
  fontWeight?: FontWeightOptionType;
@@ -1,16 +1,39 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useId, useMemo } from 'react';
2
2
  import type { CarouselComponentProps } from './CarouselProps.generated';
3
3
  import RenderNode from '../RenderNode.generated';
4
4
  import { isCarouselItem } from '../../utils/isCarousel';
5
5
  import useNode from '../useNode';
6
+ import { useRenderStore } from '../../store';
6
7
  import { useLogRender } from '../../utils/useLogRender';
7
8
  import { extractViewStyle } from '../../utils/extractViewStyle';
8
9
 
9
10
  function Carousel({ node }: CarouselComponentProps) {
10
11
  useLogRender('Carousel');
11
12
  node = useNode(node);
12
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'carousel';
13
- const style = useMemo(() => extractViewStyle(node), [node]);
13
+ const generatedId = useId();
14
+ const attributeName = (node as any)?.sourceType ?? node.type ?? 'carousel';
15
+ const attributeKey = node.key ?? generatedId;
16
+ const { previewMode, current, appConfig, projectColors } = useRenderStore(
17
+ (s) => ({
18
+ previewMode: s.previewMode,
19
+ current: s.current,
20
+ appConfig: s.appConfig,
21
+ projectColors: s.projectColors,
22
+ }),
23
+ );
24
+ const baseStyle = useMemo(
25
+ () => extractViewStyle(node, { appConfig, projectColors }),
26
+ [node, appConfig, projectColors],
27
+ );
28
+ const isSelected =
29
+ previewMode &&
30
+ !!current &&
31
+ (current as any)?.key &&
32
+ (node as any)?.key &&
33
+ (current as any).key === (node as any).key;
34
+ const style = isSelected
35
+ ? { ...baseStyle, outline: '2px solid #2684FF' }
36
+ : baseStyle;
14
37
  // Ensure children are carouselItems
15
38
  const renderChildren = () => {
16
39
  if (Array.isArray(node.children)) {
@@ -27,6 +50,7 @@ function Carousel({ node }: CarouselComponentProps) {
27
50
  //TODO: add to md file for agents
28
51
  return (
29
52
  <div
53
+ attribute-name={attributeName}
30
54
  attribute-key={attributeKey}
31
55
  className="embla__container"
32
56
  style={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 CarouselPropsGenerated {
21
22
  child: string;
@@ -42,6 +43,12 @@ export interface CarouselPropsGenerated {
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,16 +1,26 @@
1
- import React, { useContext, useMemo } from 'react';
1
+ import React, { useContext, useId, useMemo } from 'react';
2
2
  import type { CarouselButtonsComponentProps } from './CarouselButtonsProps.generated';
3
3
  import { carouselContext } from '../CarouselProvider/CarouselProvider';
4
4
  import useNode from '../useNode';
5
5
  import { useLogRender } from '../../utils/useLogRender';
6
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
7
+ import { useRenderStore } from '../../store';
7
8
 
8
9
  function CarouselButtons({ node }: CarouselButtonsComponentProps) {
9
10
  useLogRender('CarouselButtons');
10
11
  node = useNode(node);
11
- const attributeKey =
12
+ const generatedId = useId();
13
+ const attributeName =
12
14
  (node as any)?.sourceType ?? node.type ?? 'carouselButtons';
13
- const style = useMemo(() => extractViewStyle(node), [node]);
15
+ const attributeKey = node.key ?? generatedId;
16
+ const { appConfig, projectColors } = useRenderStore((s) => ({
17
+ appConfig: s.appConfig,
18
+ projectColors: s.projectColors,
19
+ }));
20
+ const style = useMemo(
21
+ () => extractViewStyle(node, { appConfig, projectColors }),
22
+ [node, appConfig, projectColors],
23
+ );
14
24
  const emblaApi = useContext(carouselContext);
15
25
  const buttonTypes = node.attributes?.buttonType || [
16
26
  'previous_button',
@@ -18,7 +28,12 @@ function CarouselButtons({ node }: CarouselButtonsComponentProps) {
18
28
  ];
19
29
 
20
30
  return (
21
- <div attribute-key={attributeKey} className="embla__buttons" style={style}>
31
+ <div
32
+ attribute-name={attributeName}
33
+ attribute-key={attributeKey}
34
+ className="embla__buttons"
35
+ style={style}
36
+ >
22
37
  {buttonTypes.includes('previous_button') && (
23
38
  <button
24
39
  onClick={() => emblaApi?.scrollPrev()}
@@ -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'
@@ -46,6 +47,12 @@ export interface CarouselButtonsPropsGenerated {
46
47
  borderRadius?: string;
47
48
  width?: string;
48
49
  height?: string;
50
+ position?: PositionOptionType;
51
+ top?: string;
52
+ bottom?: string;
53
+ left?: string;
54
+ right?: string;
55
+ zIndex?: number;
49
56
  buttonType?: ButtonTypeOptionType;
50
57
  skipNumber?: number;
51
58
  };
@@ -1,23 +1,31 @@
1
- import React, { useContext, useEffect, useMemo, useState } from 'react';
1
+ import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
2
2
  import type { CarouselDotsComponentProps } from './CarouselDotsProps.generated';
3
3
  import { carouselContext } from '../CarouselProvider/CarouselProvider';
4
4
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
5
5
  import useNode from '../useNode';
6
6
  import { useLogRender } from '../../utils/useLogRender';
7
7
  import { extractViewStyle } from '../../utils/extractViewStyle';
8
+ import { useRenderStore } from '../../store';
8
9
 
9
10
  function CarouselDots({ node }: CarouselDotsComponentProps) {
10
11
  useLogRender('CarouselDots');
11
12
 
12
13
  node = useNode(node);
13
14
 
14
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'carouselDots';
15
+ const generatedId = useId();
16
+ const attributeName =
17
+ (node as any)?.sourceType ?? node.type ?? 'carouselDots';
18
+ const attributeKey = node.key ?? generatedId;
15
19
 
16
20
  const dotType = node.attributes?.dotType || 'normal_dot';
21
+ const { appConfig, projectColors } = useRenderStore((s) => ({
22
+ appConfig: s.appConfig,
23
+ projectColors: s.projectColors,
24
+ }));
17
25
 
18
26
  const style = useMemo(() => {
19
- return extractViewStyle(node);
20
- }, [node]);
27
+ return extractViewStyle(node, { appConfig, projectColors });
28
+ }, [node, appConfig, projectColors]);
21
29
 
22
30
  // Use the appropriate context based on sourceType
23
31
  const isOnboard = (node as any)?.sourceType === 'OnboardDot';
@@ -51,6 +59,7 @@ function CarouselDots({ node }: CarouselDotsComponentProps) {
51
59
 
52
60
  return (
53
61
  <div
62
+ attribute-name={attributeName}
54
63
  attribute-key={attributeKey}
55
64
  className={`embla__dots embla__dots--${dotType}`}
56
65
  style={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 DotTypeOptionType =
20
21
  | 'expanding_dot'
21
22
  | 'normal_dot'
@@ -49,6 +50,12 @@ export interface CarouselDotsPropsGenerated {
49
50
  borderRadius?: string;
50
51
  width?: string;
51
52
  height?: string;
53
+ position?: PositionOptionType;
54
+ top?: string;
55
+ bottom?: string;
56
+ left?: string;
57
+ right?: string;
58
+ zIndex?: number;
52
59
  dotType?: DotTypeOptionType;
53
60
  };
54
61
  }
@@ -1,17 +1,33 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useId, useMemo } from 'react';
2
2
  import type { CarouselItemComponentProps } from './CarouselItemProps.generated';
3
3
  import { RenderNode } from '../..';
4
4
  import useNode from '../useNode';
5
5
  import { useLogRender } from '../../utils/useLogRender';
6
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
7
+ import { useRenderStore } from '../../store';
7
8
 
8
9
  export function CarouselItem({ node }: CarouselItemComponentProps) {
9
10
  useLogRender('CarouselItem');
10
11
  node = useNode(node);
11
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'carouselItem';
12
- const style = useMemo(() => extractViewStyle(node), [node]);
12
+ const generatedId = useId();
13
+ const attributeName =
14
+ (node as any)?.sourceType ?? node.type ?? 'carouselItem';
15
+ const attributeKey = node.key ?? generatedId;
16
+ const { appConfig, projectColors } = useRenderStore((s) => ({
17
+ appConfig: s.appConfig,
18
+ projectColors: s.projectColors,
19
+ }));
20
+ const style = useMemo(
21
+ () => extractViewStyle(node, { appConfig, projectColors }),
22
+ [node, appConfig, projectColors],
23
+ );
13
24
  return (
14
- <div className="embla__slide" attribute-key={attributeKey} style={style}>
25
+ <div
26
+ className="embla__slide"
27
+ attribute-name={attributeName}
28
+ attribute-key={attributeKey}
29
+ style={style}
30
+ >
15
31
  {node.children && <RenderNode node={node.children} />}
16
32
  </div>
17
33
  );
@@ -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 CarouselItemPropsGenerated {
21
22
  child: string;
@@ -42,6 +43,12 @@ export interface CarouselItemPropsGenerated {
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,20 +1,31 @@
1
- import React, { createContext, useMemo } from 'react';
1
+ import React, { createContext, useId, useMemo } from 'react';
2
2
  import type { CarouselProviderComponentProps } from './CarouselProviderProps.generated';
3
3
  import { RenderNode } from '../..';
4
4
  import useEmblaCarousel from 'embla-carousel-react';
5
5
  import useNode from '../useNode';
6
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
7
+ import { useRenderStore } from '../../store';
7
8
 
8
9
  export const carouselContext = createContext<any>(undefined);
9
10
  function CarouselProvider({ node }: CarouselProviderComponentProps) {
10
11
  node = useNode(node);
11
12
  const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
12
- const attributeKey =
13
+ const generatedId = useId();
14
+ const attributeName =
13
15
  (node as any)?.sourceType ?? node.type ?? 'carouselProvider';
14
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
16
+ const attributeKey = node.key ?? generatedId;
17
+ const { appConfig, projectColors } = useRenderStore((s) => ({
18
+ appConfig: s.appConfig,
19
+ projectColors: s.projectColors,
20
+ }));
21
+ const viewStyle = useMemo(
22
+ () => extractViewStyle(node, { appConfig, projectColors }),
23
+ [node, appConfig, projectColors],
24
+ );
15
25
  return (
16
26
  <carouselContext.Provider value={emblaApi}>
17
27
  <div
28
+ attribute-name={attributeName}
18
29
  attribute-key={attributeKey}
19
30
  className="carousel-provider"
20
31
  style={viewStyle}
@@ -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 CarouselProviderPropsGenerated {
21
22
  child: string;
@@ -42,6 +43,12 @@ export interface CarouselProviderPropsGenerated {
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,6 +1,7 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useId, useMemo } from 'react';
2
2
  import type { ImageComponentProps } from './ImageProps.generated';
3
3
  import useNode from '../useNode';
4
+ import { useRenderStore } from '../../store';
4
5
  import { extractImageStyle } from '../../utils/extractImageStyle';
5
6
  import { extractViewStyle } from '../../utils/extractViewStyle';
6
7
  import { useLogRender } from '../../utils/useLogRender';
@@ -8,13 +9,37 @@ import { useLogRender } from '../../utils/useLogRender';
8
9
  function Image({ node }: ImageComponentProps) {
9
10
  useLogRender('Image');
10
11
  node = useNode(node);
11
- const attributeKey = (node as any)?.sourceType ?? node.type ?? 'image';
12
- const viewStyle = useMemo(() => extractViewStyle(node), [node]);
12
+ const generatedId = useId();
13
+ const attributeName = (node as any)?.sourceType ?? node.type ?? 'image';
14
+ const attributeKey = node.key ?? generatedId;
15
+ const { previewMode, current, appConfig, projectColors } = useRenderStore(
16
+ (s) => ({
17
+ previewMode: s.previewMode,
18
+ current: s.current,
19
+ appConfig: s.appConfig,
20
+ projectColors: s.projectColors,
21
+ }),
22
+ );
23
+ const viewStyle = useMemo(
24
+ () => extractViewStyle(node, { appConfig, projectColors }),
25
+ [node, appConfig, projectColors],
26
+ );
13
27
  const imageStyle = extractImageStyle(node);
14
- const style = { ...viewStyle, ...imageStyle };
28
+ const isSelected =
29
+ previewMode &&
30
+ !!current &&
31
+ (current as any)?.key &&
32
+ (node as any)?.key &&
33
+ (current as any).key === (node as any).key;
34
+ const style = {
35
+ ...viewStyle,
36
+ ...imageStyle,
37
+ ...(isSelected ? { outline: '2px solid #2684FF' } : {}),
38
+ };
15
39
  return (
16
40
  <img
17
41
  key={node.key}
42
+ attribute-name={attributeName}
18
43
  attribute-key={attributeKey}
19
44
  src={node.attributes?.src}
20
45
  width={node.attributes?.width}
@@ -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 ResizeModeOptionType = 'cover' | 'contain' | 'stretch' | 'center';
20
21
 
21
22
  export interface ImagePropsGenerated {
@@ -43,6 +44,12 @@ export interface ImagePropsGenerated {
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
  src?: string;
47
54
  resizeMode?: ResizeModeOptionType;
48
55
  };
@@ -7,10 +7,10 @@ import { useLogRender } from '../../utils/useLogRender';
7
7
  function Onboard({ node }: OnboardComponentProps) {
8
8
  useLogRender('Onboard');
9
9
  node = useNode(node);
10
- const attributeKey = node.type ?? 'Onboard';
10
+ const attributeName = node.type ?? 'Onboard';
11
11
  return (
12
12
  <Carousel
13
- node={{ ...node, type: 'carousel', sourceType: attributeKey } as any}
13
+ node={{ ...node, type: 'carousel', sourceType: attributeName } as any}
14
14
  />
15
15
  );
16
16
  }