@developer_tribe/react-builder 1.2.1 → 1.2.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 (67) hide show
  1. package/dist/RenderPage.d.ts +3 -1
  2. package/dist/build-components/PaywallOptions/PaywallOptionButton.d.ts +1 -1
  3. package/dist/components/BuilderProvider.d.ts +17 -0
  4. package/dist/components/Checkbox.d.ts +1 -1
  5. package/dist/hooks/useExtractTextStyle.d.ts +3 -0
  6. package/dist/hooks/useExtractViewStyle.d.ts +3 -0
  7. package/dist/hooks/useLocalize.d.ts +4 -1
  8. package/dist/hooks/useSafeAreaViewStyle.d.ts +2 -1
  9. package/dist/index.cjs.js +5 -5
  10. package/dist/index.cjs.js.map +1 -1
  11. package/dist/index.d.ts +2 -6
  12. package/dist/index.esm.js +2 -2
  13. package/dist/index.esm.js.map +1 -1
  14. package/dist/index.native.cjs.js +1 -28
  15. package/dist/index.native.cjs.js.map +1 -1
  16. package/dist/index.native.d.ts +1 -0
  17. package/dist/index.native.esm.js +1 -28
  18. package/dist/index.native.esm.js.map +1 -1
  19. package/dist/types/Node.d.ts +1 -0
  20. package/dist/utils/extractTextStyle/extractTextStyle.d.ts +13 -0
  21. package/dist/utils/extractTextStyle.d.ts +2 -10
  22. package/dist/utils/extractViewStyle/extractViewStyle.d.ts +8 -0
  23. package/dist/utils/extractViewStyle.d.ts +2 -9
  24. package/dist/utils/parseColor.d.ts +1 -2
  25. package/package.json +1 -1
  26. package/src/RenderPage.tsx +32 -20
  27. package/src/build-components/BIcon/BIcon.tsx +10 -17
  28. package/src/build-components/BackgroundImage/BackgroundImage.tsx +10 -17
  29. package/src/build-components/Button/Button.tsx +23 -27
  30. package/src/build-components/Carousel/Carousel.tsx +10 -16
  31. package/src/build-components/CarouselButtons/CarouselButtons.tsx +4 -13
  32. package/src/build-components/CarouselDots/CarouselDots.tsx +5 -14
  33. package/src/build-components/CarouselItem/CarouselItem.tsx +4 -13
  34. package/src/build-components/CarouselProvider/CarouselProvider.tsx +3 -12
  35. package/src/build-components/Image/Image.tsx +11 -13
  36. package/src/build-components/Main/Main.tsx +12 -24
  37. package/src/build-components/OnboardButton/OnboardButton.tsx +8 -16
  38. package/src/build-components/OnboardButtons/OnboardButtons.tsx +9 -16
  39. package/src/build-components/OnboardDot/OnboardDot.tsx +25 -21
  40. package/src/build-components/OnboardFooter/OnboardFooter.tsx +18 -22
  41. package/src/build-components/OnboardImage/OnboardImage.tsx +12 -14
  42. package/src/build-components/OnboardItem/OnboardItem.tsx +3 -12
  43. package/src/build-components/OnboardProvider/OnboardProvider.tsx +11 -18
  44. package/src/build-components/PaywallBackground/PaywallBackground.tsx +9 -15
  45. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +10 -17
  46. package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +12 -18
  47. package/src/build-components/PaywallProvider/PaywallProvider.tsx +16 -20
  48. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +11 -17
  49. package/src/build-components/RadioButton/RadioButton.tsx +12 -21
  50. package/src/build-components/Text/Text.tsx +14 -25
  51. package/src/build-components/View/View.tsx +11 -17
  52. package/src/build-components/other.tsx +1 -1
  53. package/src/components/BuilderProvider.tsx +38 -0
  54. package/src/hooks/useExtractTextStyle.ts +26 -0
  55. package/src/hooks/useExtractViewStyle.ts +19 -0
  56. package/src/hooks/useLocalize.ts +7 -6
  57. package/src/hooks/useSafeAreaViewStyle.ts +4 -5
  58. package/src/index.native.ts +3 -0
  59. package/src/index.ts +10 -7
  60. package/src/pages/ProjectDebug.tsx +16 -15
  61. package/src/pages/ProjectPage.tsx +17 -5
  62. package/src/types/Node.ts +1 -0
  63. package/src/utils/extractTextStyle/extractTextStyle.ts +179 -0
  64. package/src/utils/extractTextStyle.ts +2 -160
  65. package/src/utils/extractViewStyle/extractViewStyle.ts +144 -0
  66. package/src/utils/extractViewStyle.ts +2 -145
  67. package/src/utils/parseColor.ts +4 -5
@@ -2,6 +2,7 @@ export type NodeDefaultAttribute = Record<string, unknown>;
2
2
  export type Node<T = NodeDefaultAttribute> = null | undefined | string | {} | Node<T>[] | NodeData<T>;
3
3
  export interface NodeData<T = Record<string, unknown>> {
4
4
  type: string;
5
+ sourceType?: string;
5
6
  children: Node<Record<string, unknown>>;
6
7
  attributes?: T;
7
8
  key?: string;
@@ -0,0 +1,13 @@
1
+ import type { NodeData } from '../../types/Node';
2
+ import type { TextPropsGenerated } from '../../build-components/Text/TextProps.generated';
3
+ import type { AppConfig } from '../../types/PreviewConfig';
4
+ import type { ProjectColors } from '../../types/Project';
5
+ import type { Fonts } from '../../types/Fonts';
6
+ export type ExtractTextStyleOptions = {
7
+ appConfig?: AppConfig;
8
+ projectColors?: ProjectColors;
9
+ fonts?: Fonts;
10
+ onFontLoaded?: (fontFamily: string) => void;
11
+ onError?: (error: string) => void;
12
+ };
13
+ export declare function extractTextStyle<T extends TextPropsGenerated['attributes']>(node: NodeData<T>, options?: ExtractTextStyleOptions): import("react").CSSProperties;
@@ -1,10 +1,2 @@
1
- import type { NodeData } from '../types/Node';
2
- import type { TextPropsGenerated } from '../build-components/Text/TextProps.generated';
3
- import type { AppConfig } from '../types/PreviewConfig';
4
- import type { ProjectColors } from '../types/Project';
5
- type ExtractTextStyleOptions = {
6
- appConfig?: AppConfig;
7
- projectColors?: ProjectColors;
8
- };
9
- export declare function extractTextStyle<T extends TextPropsGenerated['attributes']>(node: NodeData<T>, options?: ExtractTextStyleOptions): import("react").CSSProperties;
10
- export {};
1
+ export type { ExtractTextStyleOptions } from './extractTextStyle/extractTextStyle';
2
+ export { extractTextStyle } from './extractTextStyle/extractTextStyle';
@@ -0,0 +1,8 @@
1
+ import { ViewPropsGenerated } from '../../build-components/View/ViewProps.generated';
2
+ import type { NodeData } from '../../types/Node';
3
+ import type { ProjectColors } from '../../types/Project';
4
+ export type ExtractViewStyleOptions = {
5
+ projectColors?: ProjectColors;
6
+ theme?: string;
7
+ };
8
+ export declare function extractViewStyle<T extends ViewPropsGenerated['attributes']>(node: NodeData<T>, options?: ExtractViewStyleOptions): import("react").CSSProperties;
@@ -1,9 +1,2 @@
1
- import { ViewPropsGenerated } from '../build-components/View/ViewProps.generated';
2
- import type { NodeData } from '../types/Node';
3
- import type { AppConfig } from '../types/PreviewConfig';
4
- import type { ProjectColors } from '../types/Project';
5
- export type ExtractViewStyleOptions = {
6
- appConfig?: AppConfig;
7
- projectColors?: ProjectColors;
8
- };
9
- export declare function extractViewStyle<T extends ViewPropsGenerated['attributes']>(node: NodeData<T>, options?: ExtractViewStyleOptions): import("react").CSSProperties;
1
+ export type { ExtractViewStyleOptions } from './extractViewStyle/extractViewStyle';
2
+ export { extractViewStyle } from './extractViewStyle/extractViewStyle';
@@ -1,7 +1,6 @@
1
- import type { AppConfig } from '../types/PreviewConfig';
2
1
  import type { ProjectColors } from '../types/Project';
3
2
  export type ParseColorOptions = {
4
3
  projectColors?: ProjectColors;
5
- appConfig?: AppConfig;
4
+ theme?: string;
6
5
  };
7
6
  export declare function parseColor(value?: string, options?: ParseColorOptions): string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@developer_tribe/react-builder",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "restricted": true,
@@ -5,6 +5,10 @@ import { RenderNode } from './build-components';
5
5
  import { useRenderStore } from './store';
6
6
  import { useLogRender } from './utils/useLogRender';
7
7
  import { findNodeByKeyNested } from './utils/findNodeByKeyNested';
8
+ import {
9
+ BuilderProvider,
10
+ type BuilderProviderParams,
11
+ } from './components/BuilderProvider';
8
12
  import type { NodeData } from './types/Node';
9
13
  export type ScreenStyle = {
10
14
  light: { backgroundColor: string; color: string; seperatorColor?: string };
@@ -14,6 +18,7 @@ interface RenderPageProps {
14
18
  data: Node;
15
19
  name: string;
16
20
  onSelectNode?: (node: Node | null) => void;
21
+ params: BuilderProviderParams;
17
22
  }
18
23
 
19
24
  function isNodeDataLike(value: unknown): value is NodeData {
@@ -59,7 +64,12 @@ function isEmptyPreview(node: Node): boolean {
59
64
  return false;
60
65
  }
61
66
 
62
- export function RenderPage({ data, name, onSelectNode }: RenderPageProps) {
67
+ export function RenderPage({
68
+ data,
69
+ name,
70
+ onSelectNode,
71
+ params,
72
+ }: RenderPageProps) {
63
73
  useLogRender('RenderPage');
64
74
  const { previewMode, forceRender, setCurrent, appFont } = useRenderStore(
65
75
  (s) => ({
@@ -109,26 +119,28 @@ export function RenderPage({ data, name, onSelectNode }: RenderPageProps) {
109
119
  }, [previewMode, data, onSelectNode, setCurrent, forceRender]); // forceRender: retrigger effect when we want to force a refresh (e.g. route change)
110
120
 
111
121
  return (
112
- <DeviceMockFrame appName={name}>
113
- <div
114
- className="screen-preview"
115
- ref={previewRootRef}
116
- style={{
117
- fontFamily: appFont ? `"${appFont}"` : undefined,
118
- }}
119
- >
120
- <RenderNode node={data} />
121
- {showEmptyState && (
122
- <div className="rb-empty-preview" aria-hidden="true">
123
- <div className="rb-empty-preview__card">
124
- <div className="rb-empty-preview__title">Empty screen</div>
125
- <div className="rb-empty-preview__hint">
126
- Add a component to start
122
+ <BuilderProvider params={params}>
123
+ <DeviceMockFrame appName={name}>
124
+ <div
125
+ className="screen-preview"
126
+ ref={previewRootRef}
127
+ style={{
128
+ fontFamily: appFont ? `"${appFont}"` : undefined,
129
+ }}
130
+ >
131
+ <RenderNode node={data} />
132
+ {showEmptyState && (
133
+ <div className="rb-empty-preview" aria-hidden="true">
134
+ <div className="rb-empty-preview__card">
135
+ <div className="rb-empty-preview__title">Empty screen</div>
136
+ <div className="rb-empty-preview__hint">
137
+ Add a component to start
138
+ </div>
127
139
  </div>
128
140
  </div>
129
- </div>
130
- )}
131
- </div>
132
- </DeviceMockFrame>
141
+ )}
142
+ </div>
143
+ </DeviceMockFrame>
144
+ </BuilderProvider>
133
145
  );
134
146
  }
@@ -1,36 +1,29 @@
1
1
  import React, { useId, useMemo } from 'react';
2
2
  import type { BIconComponentProps } from './BIconProps.generated';
3
3
  import useNode from '../useNode';
4
- import { useRenderStore } from '../../store';
5
- import { extractViewStyle } from '../../utils/extractViewStyle';
4
+ import { useBuilderParams } from '../../components/BuilderProvider';
6
5
  import { useLogRender } from '../../utils/useLogRender';
7
6
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
7
  import { useMergedStyle } from '../../utils/useMergedStyle';
9
8
  import { Icon } from '../../components/Icon.generated';
10
9
  import { IconsType } from '../../types/Icons';
11
- import { extractTextStyle } from '../../utils/extractTextStyle';
10
+ import { useExtractTextStyle } from '../../hooks/useExtractTextStyle';
12
11
 
13
12
  function BIcon({ node }: BIconComponentProps) {
14
13
  useLogRender('BIcon');
15
14
  node = useNode(node);
16
15
  const generatedId = useId();
17
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'BIcon';
16
+ const attributeName = node.sourceType ?? node.type ?? 'BIcon';
18
17
  const attributeKey = node.key ?? generatedId;
19
18
 
20
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
21
- (s) => ({
22
- previewMode: s.previewMode,
23
- current: s.current,
24
- appConfig: s.appConfig,
25
- projectColors: s.projectColors,
26
- }),
27
- );
19
+ const { previewMode, selectedKey } = useBuilderParams();
28
20
 
29
- const baseStyle = useMemo(
30
- () => extractTextStyle(node, { appConfig, projectColors }),
31
- [node, appConfig, projectColors],
32
- );
33
- const isSelected = isNodeSelected({ previewMode, current, node });
21
+ const baseStyle = useExtractTextStyle(node);
22
+ const isSelected = isNodeSelected({
23
+ previewMode: !!previewMode,
24
+ current: selectedKey ? { key: selectedKey } : undefined,
25
+ node,
26
+ });
34
27
  const style = useMergedStyle(
35
28
  baseStyle,
36
29
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -1,8 +1,8 @@
1
1
  import React, { useId, useMemo } from 'react';
2
2
  import type { BackgroundImageComponentProps } from './BackgroundImageProps.generated';
3
3
  import useNode from '../useNode';
4
- import { useRenderStore } from '../../store';
5
- import { extractViewStyle } from '../../utils/extractViewStyle';
4
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
6
6
  import { resolveImageSrc } from '../../utils/getImage';
7
7
  import { useLogRender } from '../../utils/useLogRender';
8
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
@@ -12,23 +12,12 @@ function BackgroundImage({ node }: BackgroundImageComponentProps) {
12
12
  useLogRender('BackgroundImage');
13
13
  node = useNode(node);
14
14
  const generatedId = useId();
15
- const attributeName =
16
- (node as any)?.sourceType ?? node.type ?? 'background-image';
15
+ const attributeName = node.sourceType ?? node.type ?? 'background-image';
17
16
  const attributeKey = node.key ?? generatedId;
18
17
 
19
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
20
- (s) => ({
21
- previewMode: s.previewMode,
22
- current: s.current,
23
- appConfig: s.appConfig,
24
- projectColors: s.projectColors,
25
- }),
26
- );
18
+ const { previewMode, selectedKey } = useBuilderParams();
27
19
 
28
- const baseStyle = useMemo(
29
- () => extractViewStyle(node, { appConfig, projectColors }),
30
- [node, appConfig, projectColors],
31
- );
20
+ const baseStyle = useExtractViewStyle(node);
32
21
  const backgroundStyle = useMemo(() => {
33
22
  const attrs = node.attributes;
34
23
  const style: React.CSSProperties = {
@@ -60,7 +49,11 @@ function BackgroundImage({ node }: BackgroundImageComponentProps) {
60
49
 
61
50
  return style;
62
51
  }, [node]);
63
- const isSelected = isNodeSelected({ previewMode, current, node });
52
+ const isSelected = isNodeSelected({
53
+ previewMode: !!previewMode,
54
+ current: selectedKey ? { key: selectedKey } : undefined,
55
+ node,
56
+ });
64
57
  const mergedStyle = useMergedStyle(baseStyle, backgroundStyle);
65
58
  const style = useMergedStyle(
66
59
  mergedStyle,
@@ -1,10 +1,10 @@
1
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
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
5
  import { useLogRender } from '../../utils/useLogRender';
6
- import { extractViewStyle } from '../../utils/extractViewStyle';
7
- import { extractTextStyle } from '../../utils/extractTextStyle';
6
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
7
+ import { useExtractTextStyle } from '../../hooks/useExtractTextStyle';
8
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
9
9
  import { useMergedStyle } from '../../utils/useMergedStyle';
10
10
  import { useLocalize } from '../../hooks/useLocalize';
@@ -13,33 +13,25 @@ function Button({ node }: ButtonComponentProps) {
13
13
  useLogRender('Button');
14
14
  node = useNode(node);
15
15
  const generatedId = useId();
16
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'button';
16
+ const attributeName = node.sourceType ?? node.type ?? 'button';
17
17
  const attributeKey = node.key ?? generatedId;
18
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
19
- (s) => ({
20
- previewMode: s.previewMode,
21
- current: s.current,
22
- appConfig: s.appConfig,
23
- projectColors: s.projectColors,
24
- }),
25
- );
26
- const localize = useLocalize();
27
- const baseStyle = useMemo(
28
- () => extractViewStyle(node, { appConfig, projectColors }),
29
- [node, appConfig, projectColors],
30
- );
18
+ const { previewMode, selectedKey, appConfig } = useBuilderParams();
19
+ const localize = useLocalize({ appConfig });
20
+ const baseStyle = useExtractViewStyle(node);
21
+ const combinedTextStyle = useExtractTextStyle(node);
31
22
  const textStyle = useMemo(() => {
32
- const combined = extractTextStyle(node as any, {
33
- appConfig,
34
- projectColors,
35
- });
36
23
  return {
37
- color: combined.color,
38
- fontSize: combined.fontSize,
39
- fontWeight: combined.fontWeight,
40
- textAlign: combined.textAlign,
24
+ color: combinedTextStyle.color,
25
+ fontSize: combinedTextStyle.fontSize,
26
+ fontWeight: combinedTextStyle.fontWeight,
27
+ textAlign: combinedTextStyle.textAlign,
41
28
  } as React.CSSProperties;
42
- }, [node, appConfig, projectColors]);
29
+ }, [
30
+ combinedTextStyle.color,
31
+ combinedTextStyle.fontSize,
32
+ combinedTextStyle.fontWeight,
33
+ combinedTextStyle.textAlign,
34
+ ]);
43
35
  const buttonDefaults = useMemo(() => {
44
36
  const hasExplicitBackground =
45
37
  node?.attributes?.backgroundColor !== undefined &&
@@ -53,7 +45,11 @@ function Button({ node }: ButtonComponentProps) {
53
45
  : { backgroundColor: 'transparent' }),
54
46
  } as React.CSSProperties;
55
47
  }, [node?.attributes?.backgroundColor]);
56
- const isSelected = isNodeSelected({ previewMode, current, node });
48
+ const isSelected = isNodeSelected({
49
+ previewMode: !!previewMode,
50
+ current: selectedKey ? { key: selectedKey } : undefined,
51
+ node,
52
+ });
57
53
  const withButtonDefaults = useMergedStyle(baseStyle, buttonDefaults);
58
54
  const style = useMergedStyle(
59
55
  withButtonDefaults,
@@ -3,9 +3,9 @@ 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
+ import { useBuilderParams } from '../../components/BuilderProvider';
7
7
  import { useLogRender } from '../../utils/useLogRender';
8
- import { extractViewStyle } from '../../utils/extractViewStyle';
8
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
9
9
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
10
10
  import { useMergedStyle } from '../../utils/useMergedStyle';
11
11
 
@@ -13,21 +13,15 @@ function Carousel({ node }: CarouselComponentProps) {
13
13
  useLogRender('Carousel');
14
14
  node = useNode(node);
15
15
  const generatedId = useId();
16
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'carousel';
16
+ const attributeName = node.sourceType ?? node.type ?? 'carousel';
17
17
  const attributeKey = node.key ?? generatedId;
18
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
19
- (s) => ({
20
- previewMode: s.previewMode,
21
- current: s.current,
22
- appConfig: s.appConfig,
23
- projectColors: s.projectColors,
24
- }),
25
- );
26
- const baseStyle = useMemo(
27
- () => extractViewStyle(node, { appConfig, projectColors }),
28
- [node, appConfig, projectColors],
29
- );
30
- const isSelected = isNodeSelected({ previewMode, current, node });
18
+ const { previewMode, selectedKey } = useBuilderParams();
19
+ const baseStyle = useExtractViewStyle(node);
20
+ const isSelected = isNodeSelected({
21
+ previewMode: !!previewMode,
22
+ current: selectedKey ? { key: selectedKey } : undefined,
23
+ node,
24
+ });
31
25
  const style = useMergedStyle(
32
26
  baseStyle,
33
27
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -1,26 +1,17 @@
1
- import React, { useContext, useId, useMemo } from 'react';
1
+ import React, { useContext, useId } 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
- import { extractViewStyle } from '../../utils/extractViewStyle';
7
- import { useRenderStore } from '../../store';
6
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
8
7
 
9
8
  function CarouselButtons({ node }: CarouselButtonsComponentProps) {
10
9
  useLogRender('CarouselButtons');
11
10
  node = useNode(node);
12
11
  const generatedId = useId();
13
- const attributeName =
14
- (node as any)?.sourceType ?? node.type ?? 'carouselButtons';
12
+ const attributeName = node.sourceType ?? node.type ?? 'carouselButtons';
15
13
  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
+ const style = useExtractViewStyle(node);
24
15
  const emblaApi = useContext(carouselContext);
25
16
  const buttonTypes = node.attributes?.buttonType || [
26
17
  'previous_button',
@@ -1,11 +1,10 @@
1
- import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
1
+ import React, { useContext, useEffect, useId, 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
- import { extractViewStyle } from '../../utils/extractViewStyle';
8
- import { useRenderStore } from '../../store';
7
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
9
8
 
10
9
  function CarouselDots({ node }: CarouselDotsComponentProps) {
11
10
  useLogRender('CarouselDots');
@@ -13,22 +12,14 @@ function CarouselDots({ node }: CarouselDotsComponentProps) {
13
12
  node = useNode(node);
14
13
 
15
14
  const generatedId = useId();
16
- const attributeName =
17
- (node as any)?.sourceType ?? node.type ?? 'carouselDots';
15
+ const attributeName = node.sourceType ?? node.type ?? 'carouselDots';
18
16
  const attributeKey = node.key ?? generatedId;
19
17
 
20
18
  const dotType = node.attributes?.dotType || 'normal_dot';
21
- const { appConfig, projectColors } = useRenderStore((s) => ({
22
- appConfig: s.appConfig,
23
- projectColors: s.projectColors,
24
- }));
25
-
26
- const style = useMemo(() => {
27
- return extractViewStyle(node, { appConfig, projectColors });
28
- }, [node, appConfig, projectColors]);
19
+ const style = useExtractViewStyle(node);
29
20
 
30
21
  // Use the appropriate context based on sourceType
31
- const isOnboard = (node as any)?.sourceType === 'OnboardDot';
22
+ const isOnboard = node.sourceType === 'OnboardDot';
32
23
  const carouselApi = useContext(carouselContext);
33
24
  const onboardApi = useContext(onboardContext);
34
25
  const emblaApi = isOnboard ? onboardApi?.emblaApi : carouselApi;
@@ -1,26 +1,17 @@
1
- import React, { useId, useMemo } from 'react';
1
+ import React, { useId } from 'react';
2
2
  import type { CarouselItemComponentProps } from './CarouselItemProps.generated';
3
3
  import RenderNode from '../RenderNode.generated';
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
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
8
7
 
9
8
  export function CarouselItem({ node }: CarouselItemComponentProps) {
10
9
  useLogRender('CarouselItem');
11
10
  node = useNode(node);
12
11
  const generatedId = useId();
13
- const attributeName =
14
- (node as any)?.sourceType ?? node.type ?? 'carouselItem';
12
+ const attributeName = node.sourceType ?? node.type ?? 'carouselItem';
15
13
  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
+ const style = useExtractViewStyle(node);
24
15
  return (
25
16
  <div
26
17
  className="embla__slide"
@@ -3,8 +3,7 @@ import type { CarouselProviderComponentProps } from './CarouselProviderProps.gen
3
3
  import RenderNode from '../RenderNode.generated';
4
4
  import useEmblaCarousel from 'embla-carousel-react';
5
5
  import useNode from '../useNode';
6
- import { extractViewStyle } from '../../utils/extractViewStyle';
7
- import { useRenderStore } from '../../store';
6
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
8
7
  import { isCarousel } from '../../utils/isCarousel';
9
8
  import type { Node, NodeData } from '../../types/Node';
10
9
 
@@ -13,17 +12,9 @@ function CarouselProvider({ node }: CarouselProviderComponentProps) {
13
12
  node = useNode(node);
14
13
  const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
15
14
  const generatedId = useId();
16
- const attributeName =
17
- (node as any)?.sourceType ?? node.type ?? 'carouselProvider';
15
+ const attributeName = node.sourceType ?? node.type ?? 'carouselProvider';
18
16
  const attributeKey = node.key ?? generatedId;
19
- const { appConfig, projectColors } = useRenderStore((s) => ({
20
- appConfig: s.appConfig,
21
- projectColors: s.projectColors,
22
- }));
23
- const viewStyle = useMemo(
24
- () => extractViewStyle(node, { appConfig, projectColors }),
25
- [node, appConfig, projectColors],
26
- );
17
+ const viewStyle = useExtractViewStyle(node);
27
18
 
28
19
  const { carouselChild, otherChildren } = useMemo(() => {
29
20
  const children = node.children as Node;
@@ -1,7 +1,7 @@
1
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
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
5
  import { extractImageStyle } from '../../utils/extractImageStyle';
6
6
  import { resolveImageSrc } from '../../utils/getImage';
7
7
  import { useLogRender } from '../../utils/useLogRender';
@@ -12,21 +12,19 @@ function Image({ node }: ImageComponentProps) {
12
12
  useLogRender('Image');
13
13
  node = useNode(node);
14
14
  const generatedId = useId();
15
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'image';
15
+ const attributeName = node.sourceType ?? node.type ?? 'image';
16
16
  const attributeKey = node.key ?? generatedId;
17
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
18
- (s) => ({
19
- previewMode: s.previewMode,
20
- current: s.current,
21
- appConfig: s.appConfig,
22
- projectColors: s.projectColors,
23
- }),
24
- );
17
+ const { previewMode, selectedKey, appConfig, projectColors } =
18
+ useBuilderParams();
25
19
  const imageStyle = useMemo(
26
- () => extractImageStyle(node, { appConfig, projectColors }),
27
- [node, appConfig, projectColors],
20
+ () => extractImageStyle(node, { theme: appConfig?.theme, projectColors }),
21
+ [node, appConfig?.theme, projectColors],
28
22
  );
29
- const isSelected = isNodeSelected({ previewMode, current, node });
23
+ const isSelected = isNodeSelected({
24
+ previewMode: !!previewMode,
25
+ current: selectedKey ? { key: selectedKey } : undefined,
26
+ node,
27
+ });
30
28
  const style = useMergedStyle(
31
29
  imageStyle,
32
30
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -1,47 +1,35 @@
1
- import React, { useId, useMemo } from 'react';
1
+ import React, { useId } from 'react';
2
2
  import type { MainComponentProps } from './MainProps.generated';
3
3
  import RenderNode from '../RenderNode.generated';
4
4
  import type { Node } from '../../types/Node';
5
5
  import useNode from '../useNode';
6
- import { useRenderStore } from '../../store';
7
- import { extractViewStyle } from '../../utils/extractViewStyle';
6
+ import { useBuilderParams } from '../../components/BuilderProvider';
7
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
8
8
  import { useLogRender } from '../../utils/useLogRender';
9
9
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
10
10
  import { useMergedStyle } from '../../utils/useMergedStyle';
11
11
  import { useSafeAreaViewStyle } from '../../hooks/useSafeAreaViewStyle';
12
- import type { NodeData } from '../../types/Node';
13
- import { ViewPropsGenerated } from '../View/ViewProps.generated';
14
12
 
15
13
  function Main({ node }: MainComponentProps) {
16
14
  useLogRender('Main');
17
15
  node = useNode(node);
18
16
 
19
17
  const generatedId = useId();
20
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'Main';
18
+ const attributeName = node.sourceType ?? node.type ?? 'Main';
21
19
  const attributeKey = node.key ?? generatedId;
22
20
 
23
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
24
- (s) => ({
25
- previewMode: s.previewMode,
26
- current: s.current,
27
- appConfig: s.appConfig,
28
- projectColors: s.projectColors,
29
- }),
30
- );
21
+ const { previewMode, selectedKey } = useBuilderParams();
31
22
 
32
- const baseStyle = useMemo(
33
- () =>
34
- extractViewStyle(node as NodeData<ViewPropsGenerated['attributes']>, {
35
- appConfig,
36
- projectColors,
37
- }),
38
- [node, appConfig, projectColors],
39
- );
23
+ const baseStyle = useExtractViewStyle(node);
40
24
 
41
- const useSafeAreaView = (node.attributes as any)?.useSafeAreaView ?? true;
25
+ const useSafeAreaView = node.attributes?.useSafeAreaView ?? true;
42
26
  const layoutStyle = useSafeAreaViewStyle(baseStyle, useSafeAreaView);
43
27
 
44
- const isSelected = isNodeSelected({ previewMode, current, node });
28
+ const isSelected = isNodeSelected({
29
+ previewMode: !!previewMode,
30
+ current: selectedKey ? { key: selectedKey } : undefined,
31
+ node,
32
+ });
45
33
  const style = useMergedStyle(
46
34
  layoutStyle,
47
35
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,