@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
@@ -5,21 +5,18 @@ import type {
5
5
  } from './OnboardButtonProps.generated';
6
6
  import { onboardContext } from '../OnboardProvider/OnboardProvider';
7
7
  import useNode from '../useNode';
8
- import { useRenderStore } from '../../store';
8
+ import { useBuilderParams } from '../../components/BuilderProvider';
9
9
  import { useLogRender } from '../../utils/useLogRender';
10
- import { extractViewStyle } from '../../utils/extractViewStyle';
10
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
11
11
  import { useMockOSContext, useMockPermission } from '../../mockOS';
12
+ import { useLocalize } from '../../hooks/useLocalize';
12
13
 
13
14
  function OnboardButton({ node }: OnboardButtonComponentProps) {
14
15
  useLogRender('OnboardButton');
15
16
  node = useNode(node);
16
- const attributeName =
17
- (node as any)?.sourceType ?? node.type ?? 'OnboardButton';
17
+ const attributeName = node.sourceType ?? node.type ?? 'OnboardButton';
18
18
  const { emblaApi } = useContext(onboardContext) ?? {};
19
- const { appConfig, projectColors } = useRenderStore((s) => ({
20
- appConfig: s.appConfig,
21
- projectColors: s.projectColors,
22
- }));
19
+ const { appConfig } = useBuilderParams();
23
20
 
24
21
  const context = useMockOSContext();
25
22
  const mockPermissionManager = useMockPermission(context);
@@ -28,18 +25,13 @@ function OnboardButton({ node }: OnboardButtonComponentProps) {
28
25
  const attributeKey = node.key ?? generatedId;
29
26
 
30
27
  const labelRaw = node.attributes?.labelKey ?? '';
31
- const label =
32
- (appConfig.localication?.[appConfig.defaultLanguage ?? 'en']?.[
33
- labelRaw
34
- ] as string) ?? labelRaw;
28
+ const localize = useLocalize({ appConfig });
29
+ const label = localize(labelRaw);
35
30
 
36
31
  const flex = node.attributes?.flex ?? 1;
37
32
  const textColor = node.attributes?.button_text_color ?? '#FFFFFF';
38
33
  const backgroundColor = node.attributes?.button_background_color ?? '#0066FF';
39
- const viewStyle = useMemo(
40
- () => extractViewStyle(node, { appConfig, projectColors }),
41
- [node, appConfig, projectColors],
42
- );
34
+ const viewStyle = useExtractViewStyle(node);
43
35
 
44
36
  const handleClick = () => {
45
37
  //TODO: any ??
@@ -1,26 +1,22 @@
1
- import React, { useContext, useEffect, useId, useMemo, useState } from 'react';
1
+ import React, { useContext, useEffect, useId, 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';
5
5
  import RenderNode from '../RenderNode.generated';
6
6
  import useNode from '../useNode';
7
- import { useRenderStore } from '../../store';
7
+ import { useBuilderParams } from '../../components/BuilderProvider';
8
8
  import { useLogRender } from '../../utils/useLogRender';
9
- import { extractViewStyle } from '../../utils/extractViewStyle';
9
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
10
10
 
11
11
  function OnboardButtons({ node }: OnboardButtonsComponentProps) {
12
12
  useLogRender('OnboardButtons');
13
13
  node = useNode(node);
14
- const attributeName =
15
- (node as any)?.sourceType ?? node.type ?? 'OnboardButtons';
16
- const { appConfig, projectColors } = useRenderStore((s) => ({
17
- appConfig: s.appConfig,
18
- projectColors: s.projectColors,
19
- }));
14
+ const attributeName = node.sourceType ?? node.type ?? 'OnboardButtons';
15
+ const { appConfig } = useBuilderParams();
20
16
  const seperatorColorDefault =
21
- appConfig.theme === 'light'
22
- ? appConfig.screenStyle.light.seperatorColor
23
- : appConfig.screenStyle.dark.seperatorColor;
17
+ appConfig?.theme === 'light'
18
+ ? appConfig?.screenStyle?.light?.seperatorColor
19
+ : appConfig?.screenStyle?.dark?.seperatorColor;
24
20
  const ctx = useContext(onboardContext) ?? {};
25
21
  const [selectedIndex, setSelectedIndex] = useState(ctx.selectedIndex ?? 0);
26
22
 
@@ -44,10 +40,7 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
44
40
  return <RenderNode node={node.children as Node} />;
45
41
  };
46
42
 
47
- const viewStyle = useMemo(
48
- () => extractViewStyle(node, { appConfig, projectColors }),
49
- [node, appConfig, projectColors],
50
- );
43
+ const viewStyle = useExtractViewStyle(node);
51
44
 
52
45
  // NOTE: Hooks must not be called conditionally.
53
46
  // Generate the id before any early returns so the hook order stays stable.
@@ -3,12 +3,13 @@ import type { OnboardDotComponentProps } from './OnboardDotProps.generated';
3
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
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
7
+ import { useBuilderParams } from '../../components/BuilderProvider';
8
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
9
9
  import { useMergedStyle } from '../../utils/useMergedStyle';
10
10
  import { parseColor } from '../../utils/parseColor';
11
11
  import { parseSize } from '../../size-matters';
12
+ import { defaultAppConfig } from '../../types/PreviewConfig';
12
13
 
13
14
  function OnboardDot({ node }: OnboardDotComponentProps) {
14
15
  useLogRender('OnboardDot');
@@ -21,14 +22,13 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
21
22
  const dotType = node.attributes?.dotType || 'normal_dot';
22
23
  const GHOST_DOT_DARK_COLOR = '#E4E5E7';
23
24
  const GHOST_DOT_LIGHT_COLOR = '#F7F7F9';
24
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
25
- (s) => ({
26
- previewMode: s.previewMode,
27
- current: s.current,
28
- appConfig: s.appConfig,
29
- projectColors: s.projectColors,
30
- }),
31
- );
25
+ const {
26
+ previewMode,
27
+ selectedKey,
28
+ appConfig: builderAppConfig,
29
+ projectColors,
30
+ } = useBuilderParams();
31
+ const appConfig = builderAppConfig ?? defaultAppConfig;
32
32
  const isDark = appConfig.theme === 'dark';
33
33
 
34
34
  // OnboardDot specific attributes
@@ -38,16 +38,20 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
38
38
  const inactiveDotOpacity = node.attributes?.inactive_dot_opacity ?? 0.3;
39
39
  const activeDotColor = node.attributes?.active_dot_color;
40
40
  const resolvedActiveDotColor = useMemo(
41
- () => parseColor(activeDotColor, { appConfig, projectColors }),
42
- [activeDotColor, appConfig, projectColors],
41
+ () => parseColor(activeDotColor, { theme: appConfig.theme, projectColors }),
42
+ [activeDotColor, appConfig.theme, projectColors],
43
43
  );
44
44
 
45
+ const extractedStyle = useExtractViewStyle(node);
45
46
  const baseStyle = useMemo(() => {
46
- let innerStyle = extractViewStyle(node, { appConfig, projectColors });
47
- delete innerStyle.flexDirection;
47
+ const { flexDirection: _flexDirection, ...innerStyle } = extractedStyle;
48
48
  return innerStyle;
49
- }, [node, appConfig, projectColors]);
50
- const isSelected = isNodeSelected({ previewMode, current, node });
49
+ }, [extractedStyle]);
50
+ const isSelected = isNodeSelected({
51
+ previewMode: !!previewMode,
52
+ current: selectedKey ? { key: selectedKey } : undefined,
53
+ node,
54
+ });
51
55
  const style = useMergedStyle(
52
56
  baseStyle,
53
57
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -69,8 +73,8 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
69
73
 
70
74
  return {
71
75
  // Controls the actual dot diameter (`.embla__dot:after`).
72
- ['--embla-dot-size' as any]: cssWidth,
73
- } as React.CSSProperties;
76
+ '--embla-dot-size': cssWidth,
77
+ } as React.CSSProperties & Record<`--${string}`, string>;
74
78
  }, [expandingDotWidthRaw]);
75
79
  const containerStyle = useMergedStyle(style, expandingDotWidthOverride);
76
80
 
@@ -109,15 +113,15 @@ function OnboardDot({ node }: OnboardDotComponentProps) {
109
113
  >
110
114
  {scrollSnaps.map((snap, index) => {
111
115
  const isDotSelected = selectedIndex === index;
112
- const dotStyles: React.CSSProperties = {
116
+ const dotStyles: React.CSSProperties & Record<`--${string}`, string> = {
113
117
  opacity: isDotSelected ? 1 : inactiveDotOpacity,
114
118
  };
115
119
 
116
120
  if (resolvedActiveDotColor && isDotSelected) {
117
121
  // Style the actual visual dot (rendered via `.embla__dot:after`) using a CSS variable.
118
- (dotStyles as any)['--embla-dot-color'] = resolvedActiveDotColor;
122
+ dotStyles['--embla-dot-color'] = resolvedActiveDotColor;
119
123
  } else if (!isDotSelected) {
120
- (dotStyles as any)['--embla-dot-color'] = inactiveDotColor;
124
+ dotStyles['--embla-dot-color'] = inactiveDotColor;
121
125
  }
122
126
 
123
127
  return (
@@ -1,13 +1,14 @@
1
1
  import React, { useId, useMemo } from 'react';
2
2
  import type { OnboardFooterComponentProps } from './OnboardFooterProps.generated';
3
3
  import useNode from '../useNode';
4
- import { useRenderStore } from '../../store';
4
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
5
  import { parseSize } from '../../size-matters';
6
- import { extractTextStyle } from '../../utils/extractTextStyle';
7
- import { extractViewStyle } from '../../utils/extractViewStyle';
6
+ import { useExtractTextStyle } from '../../hooks/useExtractTextStyle';
7
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
8
8
  import { useLogRender } from '../../utils/useLogRender';
9
9
  import { isNodeSelected } from '../../utils/selection';
10
10
  import { useMergedStyle } from '../../utils/useMergedStyle';
11
+ import { defaultAppConfig } from '../../types/PreviewConfig';
11
12
 
12
13
  type Segment =
13
14
  | { type: 'text'; value: string }
@@ -92,29 +93,20 @@ function buildSegments(
92
93
  function OnboardFooter({ node }: OnboardFooterComponentProps) {
93
94
  useLogRender('OnboardFooter');
94
95
  node = useNode(node);
95
- const attributeName =
96
- (node as any)?.sourceType ?? node.type ?? 'OnboardFooter';
97
- const { appConfig, projectColors, previewMode, current } = useRenderStore(
98
- (s) => ({
99
- appConfig: s.appConfig,
100
- projectColors: s.projectColors,
101
- previewMode: s.previewMode,
102
- current: s.current,
103
- }),
104
- );
96
+ const attributeName = node.sourceType ?? node.type ?? 'OnboardFooter';
97
+ const {
98
+ appConfig: builderAppConfig,
99
+ previewMode,
100
+ selectedKey,
101
+ } = useBuilderParams();
102
+ const appConfig = builderAppConfig ?? defaultAppConfig;
105
103
  const { localication, defaultLanguage } = appConfig;
106
104
  const t = (key?: string) =>
107
105
  key ? (localication?.[defaultLanguage ?? 'en']?.[key] ?? key) : '';
108
106
 
109
107
  const text = t(node?.attributes?.textLocalizationKey);
110
- const textStyle = useMemo(
111
- () => extractTextStyle(node, { appConfig, projectColors }),
112
- [node, appConfig, projectColors],
113
- );
114
- const viewStyle = useMemo(
115
- () => extractViewStyle(node, { appConfig, projectColors }),
116
- [node, appConfig, projectColors],
117
- );
108
+ const textStyle = useExtractTextStyle(node);
109
+ const viewStyle = useExtractViewStyle(node);
118
110
 
119
111
  const linkStyle = (color?: string): React.CSSProperties => ({
120
112
  color,
@@ -131,7 +123,11 @@ function OnboardFooter({ node }: OnboardFooterComponentProps) {
131
123
  [paddingHorizontal],
132
124
  );
133
125
 
134
- const isSelected = isNodeSelected({ previewMode, current, node });
126
+ const isSelected = isNodeSelected({
127
+ previewMode: !!previewMode,
128
+ current: selectedKey ? { key: selectedKey } : undefined,
129
+ node,
130
+ });
135
131
  const baseStyle = useMergedStyle(viewStyle, textStyle);
136
132
  const paddedStyle = useMergedStyle(baseStyle, layoutStyle);
137
133
  const generatedId = useId();
@@ -1,28 +1,20 @@
1
- import React, { useEffect, useId, useMemo, useState } from 'react';
1
+ import React, { useEffect, useId, useState } from 'react';
2
2
  import type { OnboardImageComponentProps } from './OnboardImageProps.generated';
3
3
  import Image from '../Image/Image';
4
+ import type { ImageComponentProps } from '../Image/ImageProps.generated';
4
5
  import useNode from '../useNode';
5
6
  import Lottie from 'lottie-react';
6
7
  import { useLogRender } from '../../utils/useLogRender';
7
- import { extractViewStyle } from '../../utils/extractViewStyle';
8
- import { useRenderStore } from '../../store';
8
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
9
9
 
10
10
  function OnboardImage({ node }: OnboardImageComponentProps) {
11
11
  useLogRender('OnboardImage');
12
12
  node = useNode(node);
13
13
  const generatedId = useId();
14
- const attributeName =
15
- (node as any)?.sourceType ?? node.type ?? 'OnboardImage';
14
+ const attributeName = node.sourceType ?? node.type ?? 'OnboardImage';
16
15
  const attributeKey = node.key ?? generatedId;
17
16
  const [lottie, setLottie] = useState<string | null>(null);
18
- const { appConfig, projectColors } = useRenderStore((s) => ({
19
- appConfig: s.appConfig,
20
- projectColors: s.projectColors,
21
- }));
22
- const viewStyle = useMemo(
23
- () => extractViewStyle(node, { appConfig, projectColors }),
24
- [node, appConfig, projectColors],
25
- );
17
+ const viewStyle = useExtractViewStyle(node);
26
18
 
27
19
  useEffect(() => {
28
20
  if (node.attributes?.lottie) {
@@ -72,7 +64,13 @@ function OnboardImage({ node }: OnboardImageComponentProps) {
72
64
 
73
65
  return (
74
66
  <Image
75
- node={{ ...node, type: 'image', sourceType: attributeName } as any}
67
+ node={
68
+ {
69
+ ...node,
70
+ type: 'image',
71
+ sourceType: attributeName,
72
+ } as unknown as ImageComponentProps['node']
73
+ }
76
74
  />
77
75
  );
78
76
  }
@@ -2,25 +2,16 @@ import React, { useId, useMemo } from 'react';
2
2
  import type { OnboardItemComponentProps } from './OnboardItemProps.generated';
3
3
  import useNode from '../useNode';
4
4
  import RenderNode from '../RenderNode.generated';
5
- import { useRenderStore } from '../../store';
6
- import { parseSize } from '../../size-matters';
7
5
  import { useLogRender } from '../../utils/useLogRender';
8
- import { extractViewStyle } from '../../utils/extractViewStyle';
6
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
9
7
 
10
8
  function OnboardItem({ node }: OnboardItemComponentProps) {
11
9
  useLogRender('OnboardItem');
12
10
  node = useNode(node);
13
11
  const generatedId = useId();
14
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'OnboardItem';
12
+ const attributeName = node.sourceType ?? node.type ?? 'OnboardItem';
15
13
  const attributeKey = node.key ?? generatedId;
16
- const { appConfig, projectColors } = useRenderStore((s) => ({
17
- appConfig: s.appConfig,
18
- projectColors: s.projectColors,
19
- }));
20
- const viewStyle = useMemo(
21
- () => extractViewStyle(node, { appConfig, projectColors }),
22
- [node, appConfig, projectColors],
23
- );
14
+ const viewStyle = useExtractViewStyle(node);
24
15
  return (
25
16
  <div
26
17
  attribute-name={attributeName}
@@ -10,23 +10,16 @@ import type { NodeData } from '../../types/Node';
10
10
  import type { OnboardProviderComponentProps } from './OnboardProviderProps.generated';
11
11
  import useEmblaCarousel from 'embla-carousel-react';
12
12
  import RenderNode from '../RenderNode.generated';
13
- import { useRenderStore } from '../../store';
14
13
  import useNode from '../useNode';
15
14
  import { useLogRender } from '../../utils/useLogRender';
16
- import { extractViewStyle } from '../../utils/extractViewStyle';
17
- import { ViewPropsGenerated } from '../View/ViewProps.generated';
15
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
18
16
 
19
17
  export const onboardContext = createContext<any>(undefined);
20
18
  function OnboardProvider({ node }: OnboardProviderComponentProps) {
21
19
  useLogRender('OnboardProvider');
22
20
  node = useNode(node);
23
21
  const generatedId = useId();
24
- const attributeName =
25
- (node as any)?.sourceType ?? node.type ?? 'OnboardProvider';
26
- const { appConfig, projectColors } = useRenderStore((s) => ({
27
- appConfig: s.appConfig,
28
- projectColors: s.projectColors,
29
- }));
22
+ const attributeName = node.sourceType ?? node.type ?? 'OnboardProvider';
30
23
  const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
31
24
  const [selectedIndex, setSelectedIndex] = useState(0);
32
25
  const attributeKey = node.key ?? generatedId;
@@ -75,15 +68,15 @@ function OnboardProvider({ node }: OnboardProviderComponentProps) {
75
68
  }, [theme]);*/
76
69
 
77
70
  //TODO: pattern içinde direk gömmek yerine orada da inhertince eklenebilir
78
- const viewStyle = useMemo(() => {
79
- const style = extractViewStyle(
80
- node as NodeData<ViewPropsGenerated['attributes']>,
81
- { appConfig, projectColors },
82
- );
83
- //NOTE: Embla için istisna
84
- style.display = 'block';
85
- return style;
86
- }, [node, appConfig, projectColors]);
71
+ const baseStyle = useExtractViewStyle(node);
72
+ const viewStyle = useMemo(
73
+ () => ({
74
+ ...baseStyle,
75
+ // NOTE: Embla for web expects block layout here.
76
+ display: 'block',
77
+ }),
78
+ [baseStyle],
79
+ );
87
80
 
88
81
  return (
89
82
  <onboardContext.Provider value={{ emblaApi, selectedIndex }}>
@@ -1,8 +1,8 @@
1
1
  import React, { useId, useMemo } from 'react';
2
2
  import type { PaywallBackgroundComponentProps } from './PaywallBackgroundProps.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 { useLogRender } from '../../utils/useLogRender';
7
7
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
8
  import { useMergedStyle } from '../../utils/useMergedStyle';
@@ -15,21 +15,15 @@ function PaywallBackground({ node }: PaywallBackgroundComponentProps) {
15
15
  const attributeName = node.type ?? 'PaywallBackground';
16
16
  const attributeKey = node.key ?? generatedId;
17
17
 
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
- );
18
+ const { previewMode, selectedKey } = useBuilderParams();
26
19
 
27
- const baseStyle = useMemo(
28
- () => extractViewStyle(node, { appConfig, projectColors }),
29
- [node, appConfig, projectColors],
30
- );
20
+ const baseStyle = useExtractViewStyle(node);
31
21
 
32
- const isSelected = isNodeSelected({ previewMode, current, node });
22
+ const isSelected = isNodeSelected({
23
+ previewMode: !!previewMode,
24
+ current: selectedKey ? { key: selectedKey } : undefined,
25
+ node,
26
+ });
33
27
  const style = useMergedStyle(
34
28
  baseStyle,
35
29
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -1,8 +1,8 @@
1
1
  import React, { useId, useMemo } from 'react';
2
2
  import type { PaywallCloseButtonComponentProps } from './PaywallCloseButtonProps.generated';
3
3
  import useNode from '../useNode';
4
- import { useRenderStore } from '../../store';
5
- import { extractTextStyle } from '../../utils/extractTextStyle';
4
+ import { useBuilderParams } from '../../components/BuilderProvider';
5
+ import { useExtractTextStyle } from '../../hooks/useExtractTextStyle';
6
6
  import { useLogRender } from '../../utils/useLogRender';
7
7
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
8
  import { useMergedStyle } from '../../utils/useMergedStyle';
@@ -16,25 +16,18 @@ function PaywallCloseButton({ node }: PaywallCloseButtonComponentProps) {
16
16
  const { onClose } = usePaywallContext();
17
17
 
18
18
  const generatedId = useId();
19
- const attributeName =
20
- (node as any)?.sourceType ?? node.type ?? 'PaywallCloseButton';
19
+ const attributeName = node.sourceType ?? node.type ?? 'PaywallCloseButton';
21
20
  const attributeKey = node.key ?? generatedId;
22
21
 
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
- );
22
+ const { previewMode, selectedKey } = useBuilderParams();
31
23
 
32
- const baseStyle = useMemo(
33
- () => extractTextStyle(node, { appConfig, projectColors }),
34
- [node, appConfig, projectColors],
35
- );
24
+ const baseStyle = useExtractTextStyle(node);
36
25
 
37
- const isSelected = isNodeSelected({ previewMode, current, node });
26
+ const isSelected = isNodeSelected({
27
+ previewMode: !!previewMode,
28
+ current: selectedKey ? { key: selectedKey } : undefined,
29
+ node,
30
+ });
38
31
  const style = useMergedStyle(
39
32
  baseStyle,
40
33
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -1,17 +1,17 @@
1
1
  import { useId, useMemo } from 'react';
2
2
  import type { Product } from '../../paywall/types/paywall-types';
3
- import { extractViewStyle } from '../../utils/extractViewStyle';
3
+ import { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
4
4
  import type { NodeData } from '../../types/Node';
5
- import { useRenderStore } from '../../store';
5
+ import { useBuilderParams } from '../../components/BuilderProvider';
6
6
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
7
7
  import { useMergedStyle } from '../../utils/useMergedStyle';
8
- import { RenderNode } from '../..';
8
+ import RenderNode from '../RenderNode.generated';
9
9
 
10
10
  export type OptionsButtonProps = {
11
11
  product: Product;
12
12
  selected: boolean;
13
13
  onPress: (productId: string) => void;
14
- node: NodeData<any>;
14
+ node: NodeData<Record<string, unknown>>;
15
15
  };
16
16
 
17
17
  export function PaywallOptionButton({
@@ -23,27 +23,21 @@ export function PaywallOptionButton({
23
23
  const generatedId = useId();
24
24
  const productId = (product.productId ?? '').trim();
25
25
 
26
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
27
- (s) => ({
28
- previewMode: s.previewMode,
29
- current: s.current,
30
- appConfig: s.appConfig,
31
- projectColors: s.projectColors,
32
- }),
33
- );
26
+ const { previewMode, selectedKey } = useBuilderParams();
34
27
 
35
- const baseStyle = useMemo(
36
- () => extractViewStyle(node, { appConfig, projectColors }),
37
- [node, appConfig, projectColors],
38
- );
28
+ const baseStyle = useExtractViewStyle(node);
39
29
 
40
- const isSelected = isNodeSelected({ previewMode, current, node });
30
+ const isSelected = isNodeSelected({
31
+ previewMode: !!previewMode,
32
+ current: selectedKey ? { key: selectedKey } : undefined,
33
+ node,
34
+ });
41
35
 
42
36
  const mergedStyle = useMergedStyle(
43
37
  baseStyle,
44
38
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
45
39
  );
46
- const attributeName = (node as any)?.sourceType ?? node.type ?? 'text';
40
+ const attributeName = node.sourceType ?? node.type ?? 'text';
47
41
  const baseAttributeKey = (node.key ?? generatedId) as string;
48
42
  const attributeKey = productId
49
43
  ? `${baseAttributeKey}:${productId}`
@@ -3,8 +3,7 @@ import type { PaywallProviderComponentProps } from './PaywallProviderProps.gener
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 { useExtractViewStyle } from '../../hooks/useExtractViewStyle';
8
7
  import { useLogRender } from '../../utils/useLogRender';
9
8
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
10
9
  import { useMergedStyle } from '../../utils/useMergedStyle';
@@ -18,21 +17,17 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
18
17
  node = useNode(node);
19
18
 
20
19
  const generatedId = useId();
21
- const attributeName =
22
- (node as any)?.sourceType ?? node.type ?? 'PaywallProvider';
20
+ const attributeName = node.sourceType ?? node.type ?? 'PaywallProvider';
23
21
  const attributeKey = node.key ?? generatedId;
24
22
 
25
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
26
- (s) => ({
27
- previewMode: s.previewMode,
28
- current: s.current,
29
- appConfig: s.appConfig,
30
- projectColors: s.projectColors,
31
- }),
32
- );
33
-
34
- const { benefits, products, onPaywallClose, onPaywallSubscribe } =
35
- useBuilderParams();
23
+ const {
24
+ benefits,
25
+ products,
26
+ onPaywallClose,
27
+ onPaywallSubscribe,
28
+ previewMode,
29
+ selectedKey,
30
+ } = useBuilderParams();
36
31
  const mockOS = useMockOSContext();
37
32
  const benefitLocalizationParams = useMemo(() => {
38
33
  const raw =
@@ -55,12 +50,13 @@ function PaywallProvider({ node }: PaywallProviderComponentProps) {
55
50
  return params;
56
51
  }, [benefits]);
57
52
 
58
- const baseStyle = useMemo(
59
- () => extractViewStyle(node, { appConfig, projectColors }),
60
- [node, appConfig, projectColors],
61
- );
53
+ const baseStyle = useExtractViewStyle(node);
62
54
 
63
- const isSelected = isNodeSelected({ previewMode, current, node });
55
+ const isSelected = isNodeSelected({
56
+ previewMode: !!previewMode,
57
+ current: selectedKey ? { key: selectedKey } : undefined,
58
+ node,
59
+ });
64
60
  const style = useMergedStyle(
65
61
  baseStyle,
66
62
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
@@ -1,9 +1,9 @@
1
1
  import React, { useId, useMemo } from 'react';
2
2
  import type { PaywallSubscribeButtonComponentProps } from './PaywallSubscribeButtonProps.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 { extractTextStyle } from '../../utils/extractTextStyle';
6
+ import { useExtractTextStyle } from '../../hooks/useExtractTextStyle';
7
7
  import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
8
8
  import { useMergedStyle } from '../../utils/useMergedStyle';
9
9
  import { useLocalize } from '../../hooks/useLocalize';
@@ -18,30 +18,24 @@ function PaywallSubscribeButton({
18
18
 
19
19
  const generatedId = useId();
20
20
  const attributeName =
21
- (node as any)?.sourceType ?? node.type ?? 'PaywallSubscribeButton';
21
+ node.sourceType ?? node.type ?? 'PaywallSubscribeButton';
22
22
  const attributeKey = node.key ?? generatedId;
23
23
 
24
- const { previewMode, current, appConfig, projectColors } = useRenderStore(
25
- (s) => ({
26
- previewMode: s.previewMode,
27
- current: s.current,
28
- appConfig: s.appConfig,
29
- projectColors: s.projectColors,
30
- }),
31
- );
24
+ const { previewMode, selectedKey, appConfig } = useBuilderParams();
32
25
 
33
- const baseStyle = useMemo(
34
- () => extractTextStyle(node as any, { appConfig, projectColors }),
35
- [node, appConfig, projectColors],
36
- );
26
+ const baseStyle = useExtractTextStyle(node);
37
27
 
38
- const isSelected = isNodeSelected({ previewMode, current, node });
28
+ const isSelected = isNodeSelected({
29
+ previewMode: !!previewMode,
30
+ current: selectedKey ? { key: selectedKey } : undefined,
31
+ node,
32
+ });
39
33
  const style = useMergedStyle(
40
34
  baseStyle,
41
35
  isSelected ? SELECTED_OUTLINE_STYLE : undefined,
42
36
  );
43
37
 
44
- const localize = useLocalize();
38
+ const localize = useLocalize({ appConfig });
45
39
  const label =
46
40
  typeof node.children === 'string' && node.children.trim().length > 0
47
41
  ? node.children