@builder.io/sdk-react-native 1.0.30 → 1.0.31-0

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 (225) hide show
  1. package/lib/browser/commonjs/constants/sdk-version.js +1 -1
  2. package/lib/browser/module/constants/sdk-version.js +1 -1
  3. package/lib/browser/typescript/constants/sdk-version.d.ts +1 -1
  4. package/lib/edge/commonjs/constants/sdk-version.js +1 -1
  5. package/lib/edge/module/constants/sdk-version.js +1 -1
  6. package/lib/edge/typescript/constants/sdk-version.d.ts +1 -1
  7. package/lib/node/commonjs/constants/sdk-version.js +1 -1
  8. package/lib/node/index.cjs +6910 -0
  9. package/lib/node/index.mjs +7477 -0
  10. package/lib/node/module/constants/sdk-version.js +1 -1
  11. package/lib/node/typescript/constants/sdk-version.d.ts +1 -1
  12. package/package.json +9 -5
  13. package/src/blocks/BaseText.tsx +17 -0
  14. package/src/blocks/accordion/accordion.tsx +181 -0
  15. package/src/blocks/accordion/accordion.types.ts +12 -0
  16. package/src/blocks/accordion/component-info.ts +124 -0
  17. package/src/blocks/accordion/helpers.ts +3 -0
  18. package/src/blocks/accordion/index.ts +1 -0
  19. package/src/blocks/button/button.tsx +56 -0
  20. package/src/blocks/button/button.types.ts +7 -0
  21. package/src/blocks/button/component-info.ts +35 -0
  22. package/src/blocks/button/index.ts +1 -0
  23. package/src/blocks/columns/columns.tsx +199 -0
  24. package/src/blocks/columns/columns.types.ts +14 -0
  25. package/src/blocks/columns/component-info.ts +219 -0
  26. package/src/blocks/columns/helpers.ts +3 -0
  27. package/src/blocks/columns/index.ts +1 -0
  28. package/src/blocks/custom-code/component-info.ts +24 -0
  29. package/src/blocks/custom-code/custom-code.tsx +71 -0
  30. package/src/blocks/custom-code/index.ts +1 -0
  31. package/src/blocks/embed/component-info.ts +38 -0
  32. package/src/blocks/embed/embed.tsx +62 -0
  33. package/src/blocks/embed/helpers.ts +2 -0
  34. package/src/blocks/embed/index.ts +1 -0
  35. package/src/blocks/form/form/component-info.ts +233 -0
  36. package/src/blocks/form/form/form.tsx +324 -0
  37. package/src/blocks/form/form/index.ts +1 -0
  38. package/src/blocks/form/input/component-info.ts +47 -0
  39. package/src/blocks/form/input/index.ts +1 -0
  40. package/src/blocks/form/input/input.tsx +49 -0
  41. package/src/blocks/form/select/component-info.ts +44 -0
  42. package/src/blocks/form/select/index.ts +1 -0
  43. package/src/blocks/form/select/select.tsx +54 -0
  44. package/src/blocks/form/submit-button/component-info.ts +27 -0
  45. package/src/blocks/form/submit-button/index.ts +1 -0
  46. package/src/blocks/form/submit-button/submit-button.tsx +34 -0
  47. package/src/blocks/fragment/component-info.ts +8 -0
  48. package/src/blocks/fragment/fragment.tsx +18 -0
  49. package/src/blocks/fragment/fragment.types.ts +5 -0
  50. package/src/blocks/fragment/index.ts +1 -0
  51. package/src/blocks/helpers.ts +43 -0
  52. package/src/blocks/image/component-info.ts +124 -0
  53. package/src/blocks/image/image.helpers.ts +47 -0
  54. package/src/blocks/image/image.tsx +65 -0
  55. package/src/blocks/image/image.types.ts +19 -0
  56. package/src/blocks/image/index.ts +1 -0
  57. package/src/blocks/img/component-info.ts +16 -0
  58. package/src/blocks/img/img.tsx +55 -0
  59. package/src/blocks/img/index.ts +1 -0
  60. package/src/blocks/raw-text/component-info.ts +11 -0
  61. package/src/blocks/raw-text/index.ts +1 -0
  62. package/src/blocks/raw-text/raw-text.tsx +1 -0
  63. package/src/blocks/section/component-info.ts +41 -0
  64. package/src/blocks/section/index.ts +1 -0
  65. package/src/blocks/section/section.tsx +39 -0
  66. package/src/blocks/section/section.types.ts +6 -0
  67. package/src/blocks/slot/component-info.ts +15 -0
  68. package/src/blocks/slot/index.ts +1 -0
  69. package/src/blocks/slot/slot.tsx +42 -0
  70. package/src/blocks/symbol/component-info.ts +35 -0
  71. package/src/blocks/symbol/index.ts +1 -0
  72. package/src/blocks/symbol/symbol.helpers.ts +47 -0
  73. package/src/blocks/symbol/symbol.tsx +99 -0
  74. package/src/blocks/symbol/symbol.types.ts +17 -0
  75. package/src/blocks/tabs/component-info.ts +139 -0
  76. package/src/blocks/tabs/index.ts +1 -0
  77. package/src/blocks/tabs/tabs.tsx +79 -0
  78. package/src/blocks/tabs/tabs.types.ts +13 -0
  79. package/src/blocks/text/component-info.ts +20 -0
  80. package/src/blocks/text/index.ts +1 -0
  81. package/src/blocks/text/text.tsx +105 -0
  82. package/src/blocks/text/text.types.ts +4 -0
  83. package/src/blocks/textarea/component-info.ts +38 -0
  84. package/src/blocks/textarea/index.ts +1 -0
  85. package/src/blocks/textarea/textarea.tsx +41 -0
  86. package/src/blocks/video/component-info.ts +83 -0
  87. package/src/blocks/video/index.ts +1 -0
  88. package/src/blocks/video/video.tsx +70 -0
  89. package/src/blocks/video/video.types.ts +21 -0
  90. package/src/components/block/animator.ts +220 -0
  91. package/src/components/block/block.helpers.ts +106 -0
  92. package/src/components/block/block.tsx +235 -0
  93. package/src/components/block/components/block-styles.tsx +136 -0
  94. package/src/components/block/components/block-wrapper.tsx +53 -0
  95. package/src/components/block/components/component-ref/component-ref.helpers.ts +55 -0
  96. package/src/components/block/components/component-ref/component-ref.tsx +66 -0
  97. package/src/components/block/components/interactive-element.tsx +53 -0
  98. package/src/components/block/components/repeated-block.tsx +37 -0
  99. package/src/components/block/types.ts +6 -0
  100. package/src/components/blocks/blocks-wrapper.tsx +93 -0
  101. package/src/components/blocks/blocks.tsx +57 -0
  102. package/src/components/blocks/blocks.types.ts +7 -0
  103. package/src/components/blocks/index.ts +1 -0
  104. package/src/components/content/components/enable-editor.tsx +471 -0
  105. package/src/components/content/components/styles.helpers.ts +101 -0
  106. package/src/components/content/components/styles.tsx +42 -0
  107. package/src/components/content/content.helpers.ts +40 -0
  108. package/src/components/content/content.tsx +150 -0
  109. package/src/components/content/content.types.ts +13 -0
  110. package/src/components/content/contentProps.types.ts +17 -0
  111. package/src/components/content/index.ts +1 -0
  112. package/src/components/content/wrap-component-ref.ts +6 -0
  113. package/src/components/content-variants/content-variants.tsx +146 -0
  114. package/src/components/content-variants/content-variants.types.ts +84 -0
  115. package/src/components/content-variants/helpers.ts +72 -0
  116. package/src/components/content-variants/index.ts +1 -0
  117. package/src/components/content-variants/inlined-fns.ts +22 -0
  118. package/src/components/dynamic-div.tsx +30 -0
  119. package/src/components/dynamic-renderer/dynamic-renderer.helpers.ts +7 -0
  120. package/src/components/dynamic-renderer/dynamic-renderer.tsx +47 -0
  121. package/src/components/error-boundary.tsx +38 -0
  122. package/src/components/inlined-script.tsx +10 -0
  123. package/src/components/inlined-styles.tsx +10 -0
  124. package/src/constants/builder-registered-components.ts +59 -0
  125. package/src/constants/device-sizes.ts +59 -0
  126. package/src/constants/extra-components.ts +1 -0
  127. package/src/constants/sdk-version.ts +1 -0
  128. package/src/constants/target.ts +3 -0
  129. package/src/context/builder.context.ts +15 -0
  130. package/src/context/components.context.ts +3 -0
  131. package/src/context/index.ts +1 -0
  132. package/src/context/types.ts +37 -0
  133. package/src/functions/apply-patch-with-mutation.ts +61 -0
  134. package/src/functions/camel-to-kebab-case.ts +1 -0
  135. package/src/functions/deopt.ts +6 -0
  136. package/src/functions/evaluate/browser-runtime/browser.ts +61 -0
  137. package/src/functions/evaluate/browser-runtime/index.ts +1 -0
  138. package/src/functions/evaluate/choose-eval.ts +23 -0
  139. package/src/functions/evaluate/edge-runtime/acorn-interpreter.ts +2891 -0
  140. package/src/functions/evaluate/edge-runtime/edge-runtime.ts +96 -0
  141. package/src/functions/evaluate/edge-runtime/index.ts +1 -0
  142. package/src/functions/evaluate/evaluate.ts +76 -0
  143. package/src/functions/evaluate/helpers.ts +56 -0
  144. package/src/functions/evaluate/index.ts +1 -0
  145. package/src/functions/evaluate/node-runtime/index.ts +1 -0
  146. package/src/functions/evaluate/node-runtime/init.ts +33 -0
  147. package/src/functions/evaluate/node-runtime/node-runtime.ts +176 -0
  148. package/src/functions/evaluate/node-runtime/safeDynamicRequire.ts +24 -0
  149. package/src/functions/evaluate/placeholder-runtime.ts +4 -0
  150. package/src/functions/evaluate/should-force-browser-runtime-in-node.ts +16 -0
  151. package/src/functions/event-handler-name.ts +4 -0
  152. package/src/functions/extract-text-styles.ts +24 -0
  153. package/src/functions/fast-clone.ts +4 -0
  154. package/src/functions/fetch-builder-props.ts +75 -0
  155. package/src/functions/get-block-actions-handler.ts +17 -0
  156. package/src/functions/get-block-actions.ts +35 -0
  157. package/src/functions/get-block-component-options.ts +11 -0
  158. package/src/functions/get-block-properties.ts +62 -0
  159. package/src/functions/get-builder-search-params/index.ts +33 -0
  160. package/src/functions/get-class-prop-name.ts +15 -0
  161. package/src/functions/get-content/generate-content-url.ts +88 -0
  162. package/src/functions/get-content/index.ts +99 -0
  163. package/src/functions/get-content/types.ts +157 -0
  164. package/src/functions/get-env.ts +5 -0
  165. package/src/functions/get-fetch.ts +11 -0
  166. package/src/functions/get-global-this.ts +16 -0
  167. package/src/functions/get-processed-block.ts +70 -0
  168. package/src/functions/get-style.ts +38 -0
  169. package/src/functions/get.ts +4 -0
  170. package/src/functions/is-browser.ts +3 -0
  171. package/src/functions/is-edge-runtime.ts +9 -0
  172. package/src/functions/is-editing.ts +8 -0
  173. package/src/functions/is-from-trusted-host.ts +8 -0
  174. package/src/functions/is-iframe.ts +4 -0
  175. package/src/functions/is-node-runtime.ts +8 -0
  176. package/src/functions/is-previewing.ts +16 -0
  177. package/src/functions/on-change.ts +29 -0
  178. package/src/functions/register-component.ts +30 -0
  179. package/src/functions/register.ts +44 -0
  180. package/src/functions/set-editor-settings.ts +15 -0
  181. package/src/functions/set.ts +14 -0
  182. package/src/functions/track/helpers.ts +51 -0
  183. package/src/functions/track/index.ts +131 -0
  184. package/src/functions/track/interaction.ts +63 -0
  185. package/src/functions/transform-block-properties.ts +33 -0
  186. package/src/functions/transform-block.ts +30 -0
  187. package/src/functions/transform-style-property.ts +296 -0
  188. package/src/helpers/ab-tests.ts +166 -0
  189. package/src/helpers/canTrack.ts +2 -0
  190. package/src/helpers/cookie.ts +97 -0
  191. package/src/helpers/css.ts +33 -0
  192. package/src/helpers/flatten.ts +41 -0
  193. package/src/helpers/localStorage.ts +36 -0
  194. package/src/helpers/logger.ts +7 -0
  195. package/src/helpers/nullable.ts +2 -0
  196. package/src/helpers/omit.ts +7 -0
  197. package/src/helpers/preview-lru-cache/get.ts +4 -0
  198. package/src/helpers/preview-lru-cache/helpers.ts +1 -0
  199. package/src/helpers/preview-lru-cache/init.ts +7 -0
  200. package/src/helpers/preview-lru-cache/set.ts +12 -0
  201. package/src/helpers/preview-lru-cache/types.ts +1 -0
  202. package/src/helpers/search/search.ts +18 -0
  203. package/src/helpers/sessionId.ts +37 -0
  204. package/src/helpers/subscribe-to-editor.ts +95 -0
  205. package/src/helpers/time.ts +2 -0
  206. package/src/helpers/url.ts +15 -0
  207. package/src/helpers/uuid.ts +17 -0
  208. package/src/helpers/visitorId.ts +37 -0
  209. package/src/index-helpers/blocks-exports.ts +16 -0
  210. package/src/index-helpers/top-of-file.ts +2 -0
  211. package/src/index.ts +15 -0
  212. package/src/scripts/init-editing.ts +119 -0
  213. package/src/server-index.ts +43 -0
  214. package/src/types/api-version.ts +2 -0
  215. package/src/types/builder-block.ts +89 -0
  216. package/src/types/builder-content.ts +47 -0
  217. package/src/types/builder-props.ts +12 -0
  218. package/src/types/can-track.ts +3 -0
  219. package/src/types/components.ts +119 -0
  220. package/src/types/deep-partial.ts +1 -0
  221. package/src/types/element.ts +57 -0
  222. package/src/types/enforced-partials.ts +19 -0
  223. package/src/types/input.ts +123 -0
  224. package/src/types/targets.ts +1 -0
  225. package/src/types/typescript.ts +9 -0
@@ -0,0 +1,93 @@
1
+ import * as React from "react";
2
+ import {
3
+ FlatList,
4
+ ScrollView,
5
+ View,
6
+ StyleSheet,
7
+ Image,
8
+ Text,
9
+ Pressable,
10
+ TextInput,
11
+ } from "react-native";
12
+
13
+ export type BlocksWrapperProps = {
14
+ blocks: BuilderBlock[] | undefined;
15
+ parent: string | undefined;
16
+ path: string | undefined;
17
+ styleProp: Record<string, any> | undefined;
18
+ /**
19
+ * The element that wraps each list of blocks. Defaults to a `div` element ('ScrollView' in React Native).
20
+ */
21
+ BlocksWrapper: any;
22
+ /**
23
+ * Additonal props to pass to `blocksWrapper`. Defaults to `{}`.
24
+ */
25
+ BlocksWrapperProps: any;
26
+ children?: any;
27
+ };
28
+ import { isEditing } from "../../functions/is-editing";
29
+ import type { BuilderBlock } from "../../types/builder-block";
30
+
31
+ function BlocksWrapper(props: BlocksWrapperProps) {
32
+ function className() {
33
+ return "builder-blocks" + (!props.blocks?.length ? " no-blocks" : "");
34
+ }
35
+
36
+ function onClick() {
37
+ if (isEditing() && !props.blocks?.length) {
38
+ window.parent?.postMessage(
39
+ {
40
+ type: "builder.clickEmptyBlocks",
41
+ data: {
42
+ parentElementId: props.parent,
43
+ dataPath: props.path,
44
+ },
45
+ },
46
+ "*"
47
+ );
48
+ }
49
+ }
50
+
51
+ function onMouseEnter() {
52
+ if (isEditing() && !props.blocks?.length) {
53
+ window.parent?.postMessage(
54
+ {
55
+ type: "builder.hoverEmptyBlocks",
56
+ data: {
57
+ parentElementId: props.parent,
58
+ dataPath: props.path,
59
+ },
60
+ },
61
+ "*"
62
+ );
63
+ }
64
+ }
65
+
66
+ return (
67
+ <props.BlocksWrapper
68
+ builder-path={props.path}
69
+ builder-parent-id={props.parent}
70
+ {...{
71
+ dataSet: {
72
+ class: className(),
73
+ },
74
+ }}
75
+ style={{
76
+ ...styles.propsBlocksWrapper1,
77
+ ...props.styleProp,
78
+ }}
79
+ onPress={(event) => onClick()}
80
+ onMouseEnter={(event) => onMouseEnter()}
81
+ onKeyPress={(event) => onClick()}
82
+ {...props.BlocksWrapperProps}
83
+ >
84
+ {props.children}
85
+ </props.BlocksWrapper>
86
+ );
87
+ }
88
+
89
+ const styles = StyleSheet.create({
90
+ propsBlocksWrapper1: { display: "flex", flexDirection: "column" },
91
+ });
92
+
93
+ export default BlocksWrapper;
@@ -0,0 +1,57 @@
1
+ import * as React from "react";
2
+ import {
3
+ FlatList,
4
+ ScrollView,
5
+ View,
6
+ StyleSheet,
7
+ Image,
8
+ Text,
9
+ Pressable,
10
+ TextInput,
11
+ } from "react-native";
12
+ import { useContext } from "react";
13
+ import BuilderContext from "../../context/builder.context";
14
+ import ComponentsContext from "../../context/components.context";
15
+ import Block from "../block/block";
16
+ import BlocksWrapper from "./blocks-wrapper";
17
+ import type { BlocksProps } from "./blocks.types";
18
+
19
+ function Blocks(props: BlocksProps) {
20
+ const builderContext = useContext(BuilderContext);
21
+
22
+ const componentsContext = useContext(ComponentsContext);
23
+
24
+ return (
25
+ <BlocksWrapper
26
+ blocks={props.blocks}
27
+ parent={props.parent}
28
+ path={props.path}
29
+ styleProp={props.styleProp}
30
+ BlocksWrapper={
31
+ props.context?.BlocksWrapper || builderContext.BlocksWrapper
32
+ }
33
+ BlocksWrapperProps={
34
+ props.context?.BlocksWrapperProps || builderContext.BlocksWrapperProps
35
+ }
36
+ >
37
+ {props.blocks ? (
38
+ <>
39
+ {props.blocks?.map((block) => (
40
+ <Block
41
+ key={block.id}
42
+ block={block}
43
+ linkComponent={props.linkComponent}
44
+ context={props.context || builderContext}
45
+ registeredComponents={
46
+ props.registeredComponents ||
47
+ componentsContext.registeredComponents
48
+ }
49
+ />
50
+ ))}
51
+ </>
52
+ ) : null}
53
+ </BlocksWrapper>
54
+ );
55
+ }
56
+
57
+ export default Blocks;
@@ -0,0 +1,7 @@
1
+ import type { BuilderContextInterface, RegisteredComponents } from '../../context/types';
2
+ import type { BlocksWrapperProps } from './blocks-wrapper';
3
+ export type BlocksProps = Partial<Omit<BlocksWrapperProps, 'BlocksWrapper' | 'BlocksWrapperProps'>> & {
4
+ context?: BuilderContextInterface;
5
+ registeredComponents?: RegisteredComponents;
6
+ linkComponent?: any;
7
+ }
@@ -0,0 +1 @@
1
+ export { default } from './blocks'
@@ -0,0 +1,471 @@
1
+ import * as React from "react";
2
+ import {
3
+ FlatList,
4
+ ScrollView,
5
+ View,
6
+ StyleSheet,
7
+ Image,
8
+ Text,
9
+ Pressable,
10
+ TextInput,
11
+ } from "react-native";
12
+ import { useState, useContext, useRef, useEffect } from "react";
13
+
14
+ type BuilderEditorProps = Omit<
15
+ ContentProps,
16
+ | "customComponents"
17
+ | "apiVersion"
18
+ | "isSsrAbTest"
19
+ | "blocksWrapper"
20
+ | "blocksWrapperProps"
21
+ | "isNestedRender"
22
+ > & {
23
+ builderContextSignal: BuilderContextInterface;
24
+ setBuilderContextSignal?: (signal: any) => any;
25
+ children?: any;
26
+ };
27
+ import builderContext from "../../../context/builder.context";
28
+ import type { BuilderContextInterface } from "../../../context/types";
29
+ import { evaluate } from "../../../functions/evaluate/index";
30
+ import { fastClone } from "../../../functions/fast-clone";
31
+ import { fetchOneEntry } from "../../../functions/get-content/index";
32
+ import { fetch } from "../../../functions/get-fetch";
33
+ import { isBrowser } from "../../../functions/is-browser";
34
+ import { isEditing } from "../../../functions/is-editing";
35
+ import { isPreviewing } from "../../../functions/is-previewing";
36
+ import { createRegisterComponentMessage } from "../../../functions/register-component";
37
+ import { _track } from "../../../functions/track/index";
38
+ import { getInteractionPropertiesForEvent } from "../../../functions/track/interaction";
39
+ import { getDefaultCanTrack } from "../../../helpers/canTrack";
40
+ import { logger } from "../../../helpers/logger";
41
+ import { postPreviewContent } from "../../../helpers/preview-lru-cache/set";
42
+ import { createEditorListener } from "../../../helpers/subscribe-to-editor";
43
+ import {
44
+ registerInsertMenu,
45
+ setupBrowserForEditing,
46
+ } from "../../../scripts/init-editing";
47
+ import type { BuilderContent } from "../../../types/builder-content";
48
+ import type { ComponentInfo } from "../../../types/components";
49
+ import type { Dictionary } from "../../../types/typescript";
50
+ import { triggerAnimation } from "../../block/animator";
51
+ import DynamicDiv from "../../dynamic-div";
52
+ import type {
53
+ BuilderComponentStateChange,
54
+ ContentProps,
55
+ } from "../content.types";
56
+ import { getWrapperClassName } from "./styles.helpers";
57
+
58
+ function EnableEditor(props: BuilderEditorProps) {
59
+ const elementRef = useRef<HTMLDivElement>(null);
60
+ function mergeNewRootState(newData: Dictionary<any>) {
61
+ const combinedState = {
62
+ ...props.builderContextSignal.rootState,
63
+ ...newData,
64
+ };
65
+ if (props.builderContextSignal.rootSetState) {
66
+ props.builderContextSignal.rootSetState?.(combinedState);
67
+ } else {
68
+ props.setBuilderContextSignal((PREVIOUS_VALUE) => ({
69
+ ...PREVIOUS_VALUE,
70
+ rootState: combinedState,
71
+ }));
72
+ }
73
+ }
74
+
75
+ function mergeNewContent(newContent: BuilderContent) {
76
+ const newContentValue = {
77
+ ...props.builderContextSignal.content,
78
+ ...newContent,
79
+ data: {
80
+ ...props.builderContextSignal.content?.data,
81
+ ...newContent?.data,
82
+ },
83
+ meta: {
84
+ ...props.builderContextSignal.content?.meta,
85
+ ...newContent?.meta,
86
+ breakpoints:
87
+ newContent?.meta?.breakpoints ||
88
+ props.builderContextSignal.content?.meta?.breakpoints,
89
+ },
90
+ };
91
+ props.setBuilderContextSignal((PREVIOUS_VALUE) => ({
92
+ ...PREVIOUS_VALUE,
93
+ content: newContentValue,
94
+ }));
95
+ }
96
+
97
+ function showContentProps() {
98
+ return props.showContent
99
+ ? {}
100
+ : {
101
+ hidden: true,
102
+ "aria-hidden": true,
103
+ };
104
+ }
105
+
106
+ const [ContentWrapper, setContentWrapper] = useState(
107
+ () => props.contentWrapper || ScrollView
108
+ );
109
+
110
+ function processMessage(event: MessageEvent) {
111
+ return createEditorListener({
112
+ model: props.model,
113
+ trustedHosts: props.trustedHosts,
114
+ callbacks: {
115
+ configureSdk: (messageContent) => {
116
+ const { breakpoints, contentId } = messageContent;
117
+ if (
118
+ !contentId ||
119
+ contentId !== props.builderContextSignal.content?.id
120
+ ) {
121
+ return;
122
+ }
123
+ if (breakpoints) {
124
+ mergeNewContent({
125
+ meta: {
126
+ breakpoints,
127
+ },
128
+ });
129
+ }
130
+ },
131
+ animation: (animation) => {
132
+ triggerAnimation(animation);
133
+ },
134
+ contentUpdate: (newContent) => {
135
+ mergeNewContent(newContent);
136
+ },
137
+ },
138
+ })(event);
139
+ }
140
+
141
+ function evaluateJsCode() {
142
+ // run any dynamic JS code attached to content
143
+ const jsCode = props.builderContextSignal.content?.data?.jsCode;
144
+ if (jsCode) {
145
+ evaluate({
146
+ code: jsCode,
147
+ context: props.context || {},
148
+ localState: undefined,
149
+ rootState: props.builderContextSignal.rootState,
150
+ rootSetState: props.builderContextSignal.rootSetState,
151
+ /**
152
+ * We don't want to cache the result of the JS code, since it's arbitrary side effect code.
153
+ */
154
+ enableCache: false,
155
+ });
156
+ }
157
+ }
158
+
159
+ const [httpReqsData, setHttpReqsData] = useState(() => ({}));
160
+
161
+ const [httpReqsPending, setHttpReqsPending] = useState(() => ({}));
162
+
163
+ const [clicked, setClicked] = useState(() => false);
164
+
165
+ function onClick(event: any) {
166
+ if (props.builderContextSignal.content) {
167
+ const variationId = props.builderContextSignal.content?.testVariationId;
168
+ const contentId = props.builderContextSignal.content?.id;
169
+ _track({
170
+ type: "click",
171
+ canTrack: getDefaultCanTrack(props.canTrack),
172
+ contentId,
173
+ apiKey: props.apiKey,
174
+ variationId: variationId !== contentId ? variationId : undefined,
175
+ ...getInteractionPropertiesForEvent(event),
176
+ unique: !clicked,
177
+ });
178
+ }
179
+ if (!clicked) {
180
+ setClicked(true);
181
+ }
182
+ }
183
+
184
+ function runHttpRequests() {
185
+ const requests: {
186
+ [key: string]: string;
187
+ } = props.builderContextSignal.content?.data?.httpRequests ?? {};
188
+ Object.entries(requests).forEach(([key, url]) => {
189
+ if (!url) return;
190
+
191
+ // request already in progress
192
+ if (httpReqsPending[key]) return;
193
+
194
+ // request already completed, and not in edit mode
195
+ if (httpReqsData[key] && !isEditing()) return;
196
+ httpReqsPending[key] = true;
197
+ const evaluatedUrl = url.replace(/{{([^}]+)}}/g, (_match, group) =>
198
+ String(
199
+ evaluate({
200
+ code: group,
201
+ context: props.context || {},
202
+ localState: undefined,
203
+ rootState: props.builderContextSignal.rootState,
204
+ rootSetState: props.builderContextSignal.rootSetState,
205
+ enableCache: true,
206
+ })
207
+ )
208
+ );
209
+ fetch(evaluatedUrl)
210
+ .then((response) => response.json())
211
+ .then((json) => {
212
+ mergeNewRootState({
213
+ [key]: json,
214
+ });
215
+ httpReqsData[key] = true;
216
+ })
217
+ .catch((err) => {
218
+ console.error("error fetching dynamic data", url, err);
219
+ })
220
+ .finally(() => {
221
+ httpReqsPending[key] = false;
222
+ });
223
+ });
224
+ }
225
+
226
+ function emitStateUpdate() {
227
+ if (isEditing()) {
228
+ window.dispatchEvent(
229
+ new CustomEvent<BuilderComponentStateChange>(
230
+ "builder:component:stateChange",
231
+ {
232
+ detail: {
233
+ state: fastClone(props.builderContextSignal.rootState),
234
+ ref: {
235
+ name: props.model,
236
+ },
237
+ },
238
+ }
239
+ )
240
+ );
241
+ }
242
+ }
243
+
244
+ function elementRef_onIniteditingbldr(event) {
245
+ window.addEventListener("message", processMessage);
246
+ registerInsertMenu();
247
+ setupBrowserForEditing({
248
+ ...(props.locale
249
+ ? {
250
+ locale: props.locale,
251
+ }
252
+ : {}),
253
+ ...(props.enrich
254
+ ? {
255
+ enrich: props.enrich,
256
+ }
257
+ : {}),
258
+ ...(props.trustedHosts
259
+ ? {
260
+ trustedHosts: props.trustedHosts,
261
+ }
262
+ : {}),
263
+ });
264
+ Object.values<ComponentInfo>(
265
+ props.builderContextSignal.componentInfos
266
+ ).forEach((registeredComponent) => {
267
+ const message = createRegisterComponentMessage(registeredComponent);
268
+ window.parent?.postMessage(message, "*");
269
+ });
270
+ window.addEventListener(
271
+ "builder:component:stateChangeListenerActivated",
272
+ emitStateUpdate
273
+ );
274
+ }
275
+
276
+ function elementRef_onInitpreviewingbldr(event) {
277
+ const searchParams = new URL(location.href).searchParams;
278
+ const searchParamPreviewModel = searchParams.get("builder.preview");
279
+ const searchParamPreviewId = searchParams.get(
280
+ `builder.overrides.${searchParamPreviewModel}`
281
+ );
282
+ const previewApiKey =
283
+ searchParams.get("apiKey") || searchParams.get("builder.space");
284
+
285
+ /**
286
+ * Make sure that:
287
+ * - the preview model name is the same as the one we're rendering, since there can be multiple models rendered * at the same time, e.g. header/page/footer. * - the API key is the same, since we don't want to preview content from other organizations.
288
+ * - if there is content, that the preview ID is the same as that of the one we receive.
289
+ *
290
+ * TO-DO: should we only update the state when there is a change?
291
+ **/
292
+ if (
293
+ searchParamPreviewModel === props.model &&
294
+ previewApiKey === props.apiKey &&
295
+ (!props.content || searchParamPreviewId === props.content.id)
296
+ ) {
297
+ fetchOneEntry({
298
+ model: props.model,
299
+ apiKey: props.apiKey,
300
+ apiVersion: props.builderContextSignal.apiVersion,
301
+ }).then((content) => {
302
+ if (content) {
303
+ mergeNewContent(content);
304
+ }
305
+ });
306
+ }
307
+ }
308
+
309
+ useEffect(() => {
310
+ if (isBrowser()) {
311
+ if (isEditing()) {
312
+ window.addEventListener("message", processMessage);
313
+ registerInsertMenu();
314
+ setupBrowserForEditing({
315
+ ...(props.locale
316
+ ? {
317
+ locale: props.locale,
318
+ }
319
+ : {}),
320
+ ...(props.enrich
321
+ ? {
322
+ enrich: props.enrich,
323
+ }
324
+ : {}),
325
+ ...(props.trustedHosts
326
+ ? {
327
+ trustedHosts: props.trustedHosts,
328
+ }
329
+ : {}),
330
+ });
331
+ Object.values<ComponentInfo>(
332
+ props.builderContextSignal.componentInfos
333
+ ).forEach((registeredComponent) => {
334
+ const message = createRegisterComponentMessage(registeredComponent);
335
+ window.parent?.postMessage(message, "*");
336
+ });
337
+ window.addEventListener(
338
+ "builder:component:stateChangeListenerActivated",
339
+ emitStateUpdate
340
+ );
341
+ }
342
+ const shouldTrackImpression =
343
+ props.builderContextSignal.content &&
344
+ getDefaultCanTrack(props.canTrack);
345
+ if (shouldTrackImpression) {
346
+ const variationId = props.builderContextSignal.content?.testVariationId;
347
+ const contentId = props.builderContextSignal.content?.id;
348
+ const apiKeyProp = props.apiKey;
349
+ _track({
350
+ type: "impression",
351
+ canTrack: true,
352
+ contentId,
353
+ apiKey: apiKeyProp!,
354
+ variationId: variationId !== contentId ? variationId : undefined,
355
+ });
356
+ }
357
+
358
+ /**
359
+ * Override normal content in preview mode.
360
+ * We ignore this when editing, since the edited content is already being sent from the editor via post messages.
361
+ */
362
+ if (isPreviewing() && !isEditing()) {
363
+ const searchParams = new URL(location.href).searchParams;
364
+ const searchParamPreviewModel = searchParams.get("builder.preview");
365
+ const searchParamPreviewId = searchParams.get(
366
+ `builder.overrides.${searchParamPreviewModel}`
367
+ );
368
+ const previewApiKey =
369
+ searchParams.get("apiKey") || searchParams.get("builder.space");
370
+
371
+ /**
372
+ * Make sure that:
373
+ * - the preview model name is the same as the one we're rendering, since there can be multiple models rendered * at the same time, e.g. header/page/footer. * - the API key is the same, since we don't want to preview content from other organizations.
374
+ * - if there is content, that the preview ID is the same as that of the one we receive.
375
+ *
376
+ * TO-DO: should we only update the state when there is a change?
377
+ **/
378
+ if (
379
+ searchParamPreviewModel === props.model &&
380
+ previewApiKey === props.apiKey &&
381
+ (!props.content || searchParamPreviewId === props.content.id)
382
+ ) {
383
+ fetchOneEntry({
384
+ model: props.model,
385
+ apiKey: props.apiKey,
386
+ apiVersion: props.builderContextSignal.apiVersion,
387
+ }).then((content) => {
388
+ if (content) {
389
+ mergeNewContent(content);
390
+ }
391
+ });
392
+ }
393
+ }
394
+ }
395
+ }, []);
396
+ useEffect(() => {
397
+ if (!props.apiKey) {
398
+ logger.error(
399
+ "No API key provided to `Content` component. This can cause issues. Please provide an API key using the `apiKey` prop."
400
+ );
401
+ }
402
+ evaluateJsCode();
403
+ runHttpRequests();
404
+ emitStateUpdate();
405
+ }, []);
406
+
407
+ useEffect(() => {
408
+ if (props.content) {
409
+ mergeNewContent(props.content);
410
+ }
411
+ }, [props.content]);
412
+ useEffect(() => {
413
+ evaluateJsCode();
414
+ }, [props.builderContextSignal.content?.data?.jsCode]);
415
+ useEffect(() => {
416
+ runHttpRequests();
417
+ }, [props.builderContextSignal.content?.data?.httpRequests]);
418
+ useEffect(() => {
419
+ emitStateUpdate();
420
+ }, [props.builderContextSignal.rootState]);
421
+ useEffect(() => {
422
+ if (props.data) {
423
+ mergeNewRootState(props.data);
424
+ }
425
+ }, [props.data]);
426
+ useEffect(() => {
427
+ if (props.locale) {
428
+ mergeNewRootState({
429
+ locale: props.locale,
430
+ });
431
+ }
432
+ }, [props.locale]);
433
+
434
+ useEffect(() => {
435
+ return () => {
436
+ if (isBrowser()) {
437
+ window.removeEventListener("message", processMessage);
438
+ window.removeEventListener(
439
+ "builder:component:stateChangeListenerActivated",
440
+ emitStateUpdate
441
+ );
442
+ }
443
+ };
444
+ }, []);
445
+
446
+ return (
447
+ <builderContext.Provider value={props.builderContextSignal}>
448
+ {props.builderContextSignal.content ? (
449
+ <ContentWrapper
450
+ {...{}}
451
+ ref={elementRef}
452
+ onPress={(event) => onClick(event)}
453
+ builder-content-id={props.builderContextSignal.content?.id}
454
+ builder-model={props.model}
455
+ {...{
456
+ // currently, we can't set the actual ID here. // we don't need it right now, we just need to identify content divs for testing.
457
+ dataSet: {
458
+ "builder-content-id": "",
459
+ },
460
+ }}
461
+ {...showContentProps()}
462
+ {...props.contentWrapperProps}
463
+ >
464
+ {props.children}
465
+ </ContentWrapper>
466
+ ) : null}
467
+ </builderContext.Provider>
468
+ );
469
+ }
470
+
471
+ export default EnableEditor;