@builder.io/sdk-react-nextjs 0.4.5
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.
- package/README.md +80 -0
- package/dist/blocks/button/button.d.ts +11 -0
- package/dist/blocks/button/button.js +12 -0
- package/dist/blocks/button/component-info.d.ts +2 -0
- package/dist/blocks/button/component-info.js +34 -0
- package/dist/blocks/columns/columns.d.ts +16 -0
- package/dist/blocks/columns/columns.js +119 -0
- package/dist/blocks/columns/component-info.d.ts +2 -0
- package/dist/blocks/columns/component-info.js +219 -0
- package/dist/blocks/custom-code/component-info.d.ts +2 -0
- package/dist/blocks/custom-code/component-info.js +23 -0
- package/dist/blocks/custom-code/custom-code.d.ts +6 -0
- package/dist/blocks/custom-code/custom-code.js +51 -0
- package/dist/blocks/embed/component-info.d.ts +2 -0
- package/dist/blocks/embed/component-info.js +38 -0
- package/dist/blocks/embed/embed.d.ts +5 -0
- package/dist/blocks/embed/embed.js +42 -0
- package/dist/blocks/embed/helpers.d.ts +1 -0
- package/dist/blocks/embed/helpers.js +2 -0
- package/dist/blocks/fragment/component-info.d.ts +2 -0
- package/dist/blocks/fragment/component-info.js +7 -0
- package/dist/blocks/fragment/fragment.d.ts +7 -0
- package/dist/blocks/fragment/fragment.js +6 -0
- package/dist/blocks/helpers.d.ts +13 -0
- package/dist/blocks/helpers.js +40 -0
- package/dist/blocks/image/component-info.d.ts +2 -0
- package/dist/blocks/image/component-info.js +121 -0
- package/dist/blocks/image/image.d.ts +21 -0
- package/dist/blocks/image/image.helpers.d.ts +1 -0
- package/dist/blocks/image/image.helpers.js +47 -0
- package/dist/blocks/image/image.js +81 -0
- package/dist/blocks/img/component-info.d.ts +2 -0
- package/dist/blocks/img/component-info.js +15 -0
- package/dist/blocks/img/img.d.ts +13 -0
- package/dist/blocks/img/img.js +10 -0
- package/dist/blocks/section/component-info.d.ts +2 -0
- package/dist/blocks/section/component-info.js +40 -0
- package/dist/blocks/section/section.d.ts +11 -0
- package/dist/blocks/section/section.js +17 -0
- package/dist/blocks/symbol/component-info.d.ts +2 -0
- package/dist/blocks/symbol/component-info.js +34 -0
- package/dist/blocks/symbol/symbol.d.ts +25 -0
- package/dist/blocks/symbol/symbol.helpers.d.ts +14 -0
- package/dist/blocks/symbol/symbol.helpers.js +30 -0
- package/dist/blocks/symbol/symbol.js +29 -0
- package/dist/blocks/text/component-info.d.ts +2 -0
- package/dist/blocks/text/component-info.js +19 -0
- package/dist/blocks/text/text.d.ts +5 -0
- package/dist/blocks/text/text.js +7 -0
- package/dist/blocks/video/component-info.d.ts +2 -0
- package/dist/blocks/video/component-info.js +82 -0
- package/dist/blocks/video/video.d.ts +19 -0
- package/dist/blocks/video/video.js +47 -0
- package/dist/components/block/block.d.ts +9 -0
- package/dist/components/block/block.helpers.d.ts +13 -0
- package/dist/components/block/block.helpers.js +67 -0
- package/dist/components/block/block.js +92 -0
- package/dist/components/block/components/block-styles.d.ts +8 -0
- package/dist/components/block/components/block-styles.js +65 -0
- package/dist/components/block/components/block-wrapper.d.ts +17 -0
- package/dist/components/block/components/block-wrapper.js +36 -0
- package/dist/components/block/components/component-ref/component-ref.d.ts +3 -0
- package/dist/components/block/components/component-ref/component-ref.helpers.d.ts +28 -0
- package/dist/components/block/components/component-ref/component-ref.helpers.js +21 -0
- package/dist/components/block/components/component-ref/component-ref.js +21 -0
- package/dist/components/block/components/interactive-element.d.ts +11 -0
- package/dist/components/block/components/interactive-element.js +20 -0
- package/dist/components/block/components/repeated-block.d.ts +9 -0
- package/dist/components/block/components/repeated-block.js +7 -0
- package/dist/components/block/types.d.ts +6 -0
- package/dist/components/block/types.js +1 -0
- package/dist/components/blocks/blocks-wrapper.d.ts +10 -0
- package/dist/components/blocks/blocks-wrapper.js +38 -0
- package/dist/components/blocks/blocks.d.ts +8 -0
- package/dist/components/blocks/blocks.js +10 -0
- package/dist/components/content/components/enable-editor.d.ts +9 -0
- package/dist/components/content/components/enable-editor.js +249 -0
- package/dist/components/content/components/styles.d.ts +8 -0
- package/dist/components/content/components/styles.helpers.d.ts +15 -0
- package/dist/components/content/components/styles.helpers.js +56 -0
- package/dist/components/content/components/styles.js +30 -0
- package/dist/components/content/content.d.ts +3 -0
- package/dist/components/content/content.helpers.d.ts +7 -0
- package/dist/components/content/content.helpers.js +25 -0
- package/dist/components/content/content.js +72 -0
- package/dist/components/content/content.types.d.ts +24 -0
- package/dist/components/content/content.types.js +1 -0
- package/dist/components/content/wrap-component-ref.d.ts +6 -0
- package/dist/components/content/wrap-component-ref.js +6 -0
- package/dist/components/content-variants/content-variants.d.ts +9 -0
- package/dist/components/content-variants/content-variants.js +39 -0
- package/dist/components/content-variants/content-variants.types.d.ts +20 -0
- package/dist/components/content-variants/content-variants.types.js +1 -0
- package/dist/components/content-variants/helpers.d.ts +41 -0
- package/dist/components/content-variants/helpers.js +188 -0
- package/dist/components/inlined-script.d.ts +6 -0
- package/dist/components/inlined-script.js +5 -0
- package/dist/components/inlined-styles.d.ts +6 -0
- package/dist/components/inlined-styles.js +5 -0
- package/dist/constants/builder-registered-components.d.ts +6 -0
- package/dist/constants/builder-registered-components.js +60 -0
- package/dist/constants/device-sizes.d.ts +13 -0
- package/dist/constants/device-sizes.js +45 -0
- package/dist/constants/sdk-version.d.ts +1 -0
- package/dist/constants/sdk-version.js +1 -0
- package/dist/constants/target.d.ts +2 -0
- package/dist/constants/target.js +2 -0
- package/dist/context/builder.context.d.ts +3 -0
- package/dist/context/builder.context.js +12 -0
- package/dist/context/types.d.ts +35 -0
- package/dist/context/types.js +1 -0
- package/dist/functions/apply-patch-with-mutation.d.ts +10 -0
- package/dist/functions/apply-patch-with-mutation.js +54 -0
- package/dist/functions/camel-to-kebab-case.d.ts +1 -0
- package/dist/functions/camel-to-kebab-case.js +1 -0
- package/dist/functions/evaluate.d.ts +7 -0
- package/dist/functions/evaluate.js +46 -0
- package/dist/functions/event-handler-name.d.ts +1 -0
- package/dist/functions/event-handler-name.js +4 -0
- package/dist/functions/extract-text-styles.d.ts +4 -0
- package/dist/functions/extract-text-styles.js +21 -0
- package/dist/functions/fast-clone.d.ts +4 -0
- package/dist/functions/fast-clone.js +4 -0
- package/dist/functions/get-block-actions-handler.d.ts +8 -0
- package/dist/functions/get-block-actions-handler.js +10 -0
- package/dist/functions/get-block-actions.d.ts +10 -0
- package/dist/functions/get-block-actions.js +28 -0
- package/dist/functions/get-block-component-options.d.ts +2 -0
- package/dist/functions/get-block-component-options.js +8 -0
- package/dist/functions/get-block-properties.d.ts +6 -0
- package/dist/functions/get-block-properties.js +71 -0
- package/dist/functions/get-builder-search-params/index.d.ts +12 -0
- package/dist/functions/get-builder-search-params/index.js +38 -0
- package/dist/functions/get-content/generate-content-url.d.ts +2 -0
- package/dist/functions/get-content/generate-content-url.js +32 -0
- package/dist/functions/get-content/index.d.ts +16 -0
- package/dist/functions/get-content/index.js +82 -0
- package/dist/functions/get-content/processCookies.d.ts +2 -0
- package/dist/functions/get-content/processCookies.js +35 -0
- package/dist/functions/get-content/types.d.ts +51 -0
- package/dist/functions/get-content/types.js +1 -0
- package/dist/functions/get-fetch.d.ts +1 -0
- package/dist/functions/get-fetch.js +11 -0
- package/dist/functions/get-global-this.d.ts +4 -0
- package/dist/functions/get-global-this.js +15 -0
- package/dist/functions/get-processed-block.d.ts +10 -0
- package/dist/functions/get-processed-block.js +43 -0
- package/dist/functions/get-react-native-block-styles.d.ts +7 -0
- package/dist/functions/get-react-native-block-styles.js +16 -0
- package/dist/functions/is-browser.d.ts +1 -0
- package/dist/functions/is-browser.js +3 -0
- package/dist/functions/is-editing.d.ts +1 -0
- package/dist/functions/is-editing.js +5 -0
- package/dist/functions/is-iframe.d.ts +1 -0
- package/dist/functions/is-iframe.js +4 -0
- package/dist/functions/is-previewing.d.ts +1 -0
- package/dist/functions/is-previewing.js +11 -0
- package/dist/functions/register-component.d.ts +15 -0
- package/dist/functions/register-component.js +34 -0
- package/dist/functions/register.d.ts +16 -0
- package/dist/functions/register.js +27 -0
- package/dist/functions/sanitize-react-native-block-styles.d.ts +3 -0
- package/dist/functions/sanitize-react-native-block-styles.js +58 -0
- package/dist/functions/set-editor-settings.d.ts +4 -0
- package/dist/functions/set-editor-settings.js +12 -0
- package/dist/functions/set.d.ts +7 -0
- package/dist/functions/set.js +14 -0
- package/dist/functions/track/helpers.d.ts +5 -0
- package/dist/functions/track/helpers.js +50 -0
- package/dist/functions/track/index.d.ts +51 -0
- package/dist/functions/track/index.js +69 -0
- package/dist/functions/track/interaction.d.ts +13 -0
- package/dist/functions/track/interaction.js +53 -0
- package/dist/functions/transform-block-properties.d.ts +1 -0
- package/dist/functions/transform-block-properties.js +5 -0
- package/dist/functions/transform-block.d.ts +2 -0
- package/dist/functions/transform-block.js +3 -0
- package/dist/helpers/ab-tests.d.ts +9 -0
- package/dist/helpers/ab-tests.js +116 -0
- package/dist/helpers/canTrack.d.ts +1 -0
- package/dist/helpers/canTrack.js +2 -0
- package/dist/helpers/cookie.d.ts +19 -0
- package/dist/helpers/cookie.js +54 -0
- package/dist/helpers/css.d.ts +7 -0
- package/dist/helpers/css.js +27 -0
- package/dist/helpers/flatten.d.ts +6 -0
- package/dist/helpers/flatten.js +17 -0
- package/dist/helpers/localStorage.d.ts +9 -0
- package/dist/helpers/localStorage.js +24 -0
- package/dist/helpers/logger.d.ts +6 -0
- package/dist/helpers/logger.js +7 -0
- package/dist/helpers/nullable.d.ts +2 -0
- package/dist/helpers/nullable.js +1 -0
- package/dist/helpers/preview-lru-cache/get.d.ts +1 -0
- package/dist/helpers/preview-lru-cache/get.js +7 -0
- package/dist/helpers/preview-lru-cache/helpers.d.ts +1 -0
- package/dist/helpers/preview-lru-cache/helpers.js +9 -0
- package/dist/helpers/preview-lru-cache/init.d.ts +1 -0
- package/dist/helpers/preview-lru-cache/init.js +15 -0
- package/dist/helpers/preview-lru-cache/set.d.ts +7 -0
- package/dist/helpers/preview-lru-cache/set.js +9 -0
- package/dist/helpers/preview-lru-cache/types.d.ts +12 -0
- package/dist/helpers/preview-lru-cache/types.js +1 -0
- package/dist/helpers/sessionId.d.ts +6 -0
- package/dist/helpers/sessionId.js +30 -0
- package/dist/helpers/url.d.ts +6 -0
- package/dist/helpers/url.js +15 -0
- package/dist/helpers/uuid.d.ts +8 -0
- package/dist/helpers/uuid.js +15 -0
- package/dist/helpers/visitorId.d.ts +6 -0
- package/dist/helpers/visitorId.js +30 -0
- package/dist/index-helpers/blocks-exports.d.ts +10 -0
- package/dist/index-helpers/blocks-exports.js +10 -0
- package/dist/index-helpers/top-of-file.d.ts +1 -0
- package/dist/index-helpers/top-of-file.js +4 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +10 -0
- package/dist/scripts/init-editing.d.ts +6 -0
- package/dist/scripts/init-editing.js +109 -0
- package/dist/types/api-version.d.ts +2 -0
- package/dist/types/api-version.js +1 -0
- package/dist/types/builder-block.d.ts +66 -0
- package/dist/types/builder-block.js +1 -0
- package/dist/types/builder-content.d.ts +44 -0
- package/dist/types/builder-content.js +1 -0
- package/dist/types/builder-props.d.ts +9 -0
- package/dist/types/builder-props.js +1 -0
- package/dist/types/can-track.d.ts +3 -0
- package/dist/types/can-track.js +1 -0
- package/dist/types/components.d.ts +111 -0
- package/dist/types/components.js +1 -0
- package/dist/types/deep-partial.d.ts +3 -0
- package/dist/types/deep-partial.js +1 -0
- package/dist/types/element.d.ts +59 -0
- package/dist/types/element.js +1 -0
- package/dist/types/enforced-partials.d.ts +21 -0
- package/dist/types/enforced-partials.js +1 -0
- package/dist/types/input.d.ts +121 -0
- package/dist/types/input.js +1 -0
- package/dist/types/targets.d.ts +1 -0
- package/dist/types/targets.js +1 -0
- package/dist/types/typescript.d.ts +11 -0
- package/dist/types/typescript.js +1 -0
- package/package.json +27 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const TEXT_STYLE_KEYS = ['color', 'whiteSpace', 'direction', 'hyphens', 'overflowWrap'];
|
|
2
|
+
/**
|
|
3
|
+
* Check if the key represent a CSS style property that applies to text
|
|
4
|
+
* See MDN docs for refrence of what properties apply to text.
|
|
5
|
+
* https://developer.mozilla.org/en-US/docs/Learn/CSS/Styling_text/Fundamentals#summary
|
|
6
|
+
*/
|
|
7
|
+
const isTextStyle = (key) => {
|
|
8
|
+
return TEXT_STYLE_KEYS.includes(key) || key.startsWith('font') || key.startsWith('text') || key.startsWith('letter') || key.startsWith('line') || key.startsWith('word') || key.startsWith('writing');
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Extract styles that apply to text from a style object.
|
|
12
|
+
*/
|
|
13
|
+
export const extractTextStyles = (styles) => {
|
|
14
|
+
const textStyles = {}; // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
Object.entries(styles).forEach(([key, value]) => {
|
|
16
|
+
if (isTextStyle(key)) {
|
|
17
|
+
textStyles[key] = value;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return textStyles;
|
|
21
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BuilderContextInterface } from '../context/types.js';
|
|
2
|
+
import type { BuilderBlock } from '../types/builder-block.js';
|
|
3
|
+
type Options = {
|
|
4
|
+
block: BuilderBlock;
|
|
5
|
+
} & Pick<BuilderContextInterface, 'localState' | 'context' | 'rootState' | 'rootSetState'>;
|
|
6
|
+
type EventHandler = (event: Event) => any;
|
|
7
|
+
export declare const createEventHandler: (value: string, options: Options) => EventHandler;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { evaluate } from './evaluate.js';
|
|
2
|
+
export const createEventHandler = (value, options) => event => evaluate({
|
|
3
|
+
code: value,
|
|
4
|
+
context: options.context,
|
|
5
|
+
localState: options.localState,
|
|
6
|
+
rootState: options.rootState,
|
|
7
|
+
rootSetState: options.rootSetState,
|
|
8
|
+
event,
|
|
9
|
+
isExpression: false
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BuilderContextInterface } from '../context/types.js';
|
|
2
|
+
import type { BuilderBlock } from '../types/builder-block.js';
|
|
3
|
+
type Actions = {
|
|
4
|
+
[index: string]: (event: Event) => any;
|
|
5
|
+
};
|
|
6
|
+
export declare function getBlockActions(options: {
|
|
7
|
+
block: BuilderBlock;
|
|
8
|
+
stripPrefix?: boolean;
|
|
9
|
+
} & Pick<BuilderContextInterface, 'localState' | 'context' | 'rootState' | 'rootSetState'>): Actions;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { TARGET } from '../constants/target.js';
|
|
2
|
+
import { getEventHandlerName } from './event-handler-name.js';
|
|
3
|
+
import { createEventHandler } from './get-block-actions-handler.js';
|
|
4
|
+
export function getBlockActions(options) {
|
|
5
|
+
const obj = {};
|
|
6
|
+
const optionActions = options.block.actions ?? {};
|
|
7
|
+
for (const key in optionActions) {
|
|
8
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
9
|
+
if (!optionActions.hasOwnProperty(key)) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const value = optionActions[key];
|
|
13
|
+
let eventHandlerName = getEventHandlerName(key);
|
|
14
|
+
if (options.stripPrefix) {
|
|
15
|
+
switch (TARGET) {
|
|
16
|
+
case 'vue2':
|
|
17
|
+
case 'vue3':
|
|
18
|
+
eventHandlerName = eventHandlerName.replace('v-on:', '');
|
|
19
|
+
break;
|
|
20
|
+
case 'svelte':
|
|
21
|
+
eventHandlerName = eventHandlerName.replace('on:', '');
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
obj[eventHandlerName] = createEventHandler(value, options);
|
|
26
|
+
}
|
|
27
|
+
return obj;
|
|
28
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { TARGET } from '../constants/target.js';
|
|
2
|
+
import { convertStyleMapToCSSArray } from '../helpers/css.js';
|
|
3
|
+
import { getReactNativeBlockStyles } from './get-react-native-block-styles.js';
|
|
4
|
+
import { transformBlockProperties } from './transform-block-properties.js';
|
|
5
|
+
const extractRelevantRootBlockProperties = (block) => {
|
|
6
|
+
// currently we are only spreading the `href` property
|
|
7
|
+
// TO-DO: potentially spread all properties from block, but only if they are not already defined by BuilderBlock
|
|
8
|
+
// const {
|
|
9
|
+
// '@type': _type,
|
|
10
|
+
// '@version': _version,
|
|
11
|
+
// id: _id,
|
|
12
|
+
// tagName: _tagName,
|
|
13
|
+
// layerName: _layerName,
|
|
14
|
+
// groupLocked: _groupLocked,
|
|
15
|
+
// layerLocked: _layerLocked,
|
|
16
|
+
// class: _class,
|
|
17
|
+
// children: _children,
|
|
18
|
+
// responsiveStyles: _responsiveStyles,
|
|
19
|
+
// component: _component,
|
|
20
|
+
// bindings: _bindings,
|
|
21
|
+
// meta: _meta,
|
|
22
|
+
// actions: _actions,
|
|
23
|
+
// properties: _properties,
|
|
24
|
+
// code: _code,
|
|
25
|
+
// repeat: _repeat,
|
|
26
|
+
// animations: _animations,
|
|
27
|
+
// style: _style,
|
|
28
|
+
// hide: _hide,
|
|
29
|
+
// show: _show,
|
|
30
|
+
// // anything set by dynamic bindings outside of predefined `BuilderBlock` properties
|
|
31
|
+
// ...remainingBlockProperties
|
|
32
|
+
// } = block;
|
|
33
|
+
return {
|
|
34
|
+
href: block.href
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export function getBlockProperties({ block, context }) {
|
|
38
|
+
const properties = { ...extractRelevantRootBlockProperties(block),
|
|
39
|
+
...block.properties,
|
|
40
|
+
'builder-id': block.id,
|
|
41
|
+
style: block.style ? getStyleAttribute(block.style) : undefined,
|
|
42
|
+
class: [block.id, 'builder-block', block.class, block.properties?.class].filter(Boolean).join(' ')
|
|
43
|
+
};
|
|
44
|
+
if (TARGET === 'reactNative') {
|
|
45
|
+
properties.style = getReactNativeBlockStyles({
|
|
46
|
+
block,
|
|
47
|
+
context,
|
|
48
|
+
blockStyles: properties.style
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return transformBlockProperties(properties);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Svelte does not support style attribute as an object so we need to flatten it.
|
|
55
|
+
*
|
|
56
|
+
* Additionally, Svelte, Vue and other frameworks use kebab-case styles, so we need to convert them.
|
|
57
|
+
*/
|
|
58
|
+
function getStyleAttribute(style) {
|
|
59
|
+
switch (TARGET) {
|
|
60
|
+
case 'svelte':
|
|
61
|
+
case 'vue2':
|
|
62
|
+
case 'vue3':
|
|
63
|
+
case 'solid':
|
|
64
|
+
return convertStyleMapToCSSArray(style).join(' ');
|
|
65
|
+
case 'qwik':
|
|
66
|
+
case 'reactNative':
|
|
67
|
+
case 'react':
|
|
68
|
+
case 'rsc':
|
|
69
|
+
return style;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type QueryObject = Record<string, string | string[]>;
|
|
2
|
+
export declare const convertSearchParamsToQueryObject: (searchParams: URLSearchParams) => QueryObject;
|
|
3
|
+
/**
|
|
4
|
+
* Receives a `URLSearchParams` object or a regular query object, and returns the subset of query params that are
|
|
5
|
+
* relevant to the Builder SDK.
|
|
6
|
+
*
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export declare const getBuilderSearchParams: (_options: QueryObject | URLSearchParams | undefined) => QueryObject;
|
|
10
|
+
export declare const getBuilderSearchParamsFromWindow: () => QueryObject;
|
|
11
|
+
export declare const normalizeSearchParams: (searchParams: QueryObject | URLSearchParams) => QueryObject;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isBrowser } from '../is-browser.js';
|
|
2
|
+
const BUILDER_SEARCHPARAMS_PREFIX = 'builder.';
|
|
3
|
+
const BUILDER_OPTIONS_PREFIX = 'options.';
|
|
4
|
+
export const convertSearchParamsToQueryObject = (searchParams) => {
|
|
5
|
+
const options = {};
|
|
6
|
+
searchParams.forEach((value, key) => {
|
|
7
|
+
options[key] = value;
|
|
8
|
+
});
|
|
9
|
+
return options;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Receives a `URLSearchParams` object or a regular query object, and returns the subset of query params that are
|
|
13
|
+
* relevant to the Builder SDK.
|
|
14
|
+
*
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
export const getBuilderSearchParams = (_options) => {
|
|
18
|
+
if (!_options) {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
const options = normalizeSearchParams(_options);
|
|
22
|
+
const newOptions = {};
|
|
23
|
+
Object.keys(options).forEach(key => {
|
|
24
|
+
if (key.startsWith(BUILDER_SEARCHPARAMS_PREFIX)) {
|
|
25
|
+
const trimmedKey = key.replace(BUILDER_SEARCHPARAMS_PREFIX, '').replace(BUILDER_OPTIONS_PREFIX, '');
|
|
26
|
+
newOptions[trimmedKey] = options[key];
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return newOptions;
|
|
30
|
+
};
|
|
31
|
+
export const getBuilderSearchParamsFromWindow = () => {
|
|
32
|
+
if (!isBrowser()) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
36
|
+
return getBuilderSearchParams(searchParams);
|
|
37
|
+
};
|
|
38
|
+
export const normalizeSearchParams = (searchParams) => searchParams instanceof URLSearchParams ? convertSearchParamsToQueryObject(searchParams) : searchParams;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { flatten } from '../../helpers/flatten.js';
|
|
2
|
+
import { getBuilderSearchParamsFromWindow, normalizeSearchParams } from '../get-builder-search-params/index.js';
|
|
3
|
+
import { DEFAULT_API_VERSION } from '../../types/api-version.js';
|
|
4
|
+
export const generateContentUrl = (options) => {
|
|
5
|
+
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, enrich, locale, apiVersion = DEFAULT_API_VERSION } = options;
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
throw new Error('Missing API key');
|
|
8
|
+
}
|
|
9
|
+
if (!['v2', 'v3'].includes(apiVersion)) {
|
|
10
|
+
throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
|
|
11
|
+
}
|
|
12
|
+
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ''}${enrich ? `&enrich=${enrich}` : ''}`);
|
|
13
|
+
const queryOptions = { ...getBuilderSearchParamsFromWindow(),
|
|
14
|
+
...normalizeSearchParams(options.options || {})
|
|
15
|
+
};
|
|
16
|
+
const flattened = flatten(queryOptions);
|
|
17
|
+
for (const key in flattened) {
|
|
18
|
+
url.searchParams.set(key, String(flattened[key]));
|
|
19
|
+
}
|
|
20
|
+
if (userAttributes) {
|
|
21
|
+
url.searchParams.set('userAttributes', JSON.stringify(userAttributes));
|
|
22
|
+
}
|
|
23
|
+
if (query) {
|
|
24
|
+
const flattened = flatten({
|
|
25
|
+
query
|
|
26
|
+
});
|
|
27
|
+
for (const key in flattened) {
|
|
28
|
+
url.searchParams.set(key, JSON.stringify(flattened[key]));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return url;
|
|
32
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BuilderContent } from '../../types/builder-content.js';
|
|
2
|
+
import type { GetContentOptions } from './types.js';
|
|
3
|
+
export declare function getContent(options: GetContentOptions): Promise<BuilderContent | null>;
|
|
4
|
+
type ContentResults = {
|
|
5
|
+
results: BuilderContent[];
|
|
6
|
+
};
|
|
7
|
+
type ContentResponse = ContentResults | {
|
|
8
|
+
status: number;
|
|
9
|
+
message: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Exported only for testing purposes. Should not be used directly.
|
|
13
|
+
*/
|
|
14
|
+
export declare const processContentResult: (options: GetContentOptions, content: ContentResults, url?: URL) => Promise<ContentResults>;
|
|
15
|
+
export declare function getAllContent(options: GetContentOptions): Promise<ContentResponse | null>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { TARGET } from '../../constants/target.js';
|
|
2
|
+
import { handleABTesting } from '../../helpers/ab-tests.js';
|
|
3
|
+
import { getDefaultCanTrack } from '../../helpers/canTrack.js';
|
|
4
|
+
import { logger } from '../../helpers/logger.js';
|
|
5
|
+
import { getPreviewContent } from '../../helpers/preview-lru-cache/get.js';
|
|
6
|
+
import { fetch } from '../get-fetch.js';
|
|
7
|
+
import { isBrowser } from '../is-browser.js';
|
|
8
|
+
import { generateContentUrl } from './generate-content-url.js';
|
|
9
|
+
const checkContentHasResults = (content) => 'results' in content;
|
|
10
|
+
export async function getContent(options) {
|
|
11
|
+
const allContent = await getAllContent({ ...options,
|
|
12
|
+
limit: 1
|
|
13
|
+
});
|
|
14
|
+
if (allContent && checkContentHasResults(allContent)) {
|
|
15
|
+
return allContent.results[0] || null;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const fetchContent = async (options) => {
|
|
20
|
+
const url = generateContentUrl(options);
|
|
21
|
+
const res = await fetch(url.href);
|
|
22
|
+
const content = await res.json();
|
|
23
|
+
return content;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Exported only for testing purposes. Should not be used directly.
|
|
27
|
+
*/
|
|
28
|
+
export const processContentResult = async (options, content, url = generateContentUrl(options)) => {
|
|
29
|
+
const canTrack = getDefaultCanTrack(options.canTrack);
|
|
30
|
+
const isPreviewing = url.search.includes(`preview=`);
|
|
31
|
+
if (TARGET === 'rsc' && isPreviewing) {
|
|
32
|
+
const newResults = [];
|
|
33
|
+
for (const item of content.results) {
|
|
34
|
+
const previewContent = getPreviewContent(url.searchParams);
|
|
35
|
+
newResults.push(previewContent || item);
|
|
36
|
+
}
|
|
37
|
+
content.results = newResults;
|
|
38
|
+
}
|
|
39
|
+
if (!canTrack)
|
|
40
|
+
return content;
|
|
41
|
+
if (!(isBrowser() || TARGET === 'reactNative'))
|
|
42
|
+
return content;
|
|
43
|
+
/**
|
|
44
|
+
* For client-side navigations, it is ideal to handle AB testing at this point instead of using our
|
|
45
|
+
* complex multi-rendering variants approach, which is only needed for SSR'd content.
|
|
46
|
+
*
|
|
47
|
+
* This is also where react-native would handle AB testing.
|
|
48
|
+
*/
|
|
49
|
+
try {
|
|
50
|
+
const newResults = [];
|
|
51
|
+
for (const item of content.results) {
|
|
52
|
+
newResults.push(await handleABTesting({
|
|
53
|
+
item,
|
|
54
|
+
canTrack
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
content.results = newResults;
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
logger.error('Could not process A/B tests. ', e);
|
|
61
|
+
}
|
|
62
|
+
return content;
|
|
63
|
+
};
|
|
64
|
+
export async function getAllContent(options) {
|
|
65
|
+
try {
|
|
66
|
+
const url = generateContentUrl(options);
|
|
67
|
+
const content = await fetchContent(options);
|
|
68
|
+
if (!checkContentHasResults(content)) {
|
|
69
|
+
logger.error('Error fetching data. ', {
|
|
70
|
+
url,
|
|
71
|
+
content,
|
|
72
|
+
options
|
|
73
|
+
});
|
|
74
|
+
return content;
|
|
75
|
+
}
|
|
76
|
+
return processContentResult(options, content);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logger.error('Error fetching data. ', error);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cookies } from 'next/headers';
|
|
2
|
+
import { applyPatchWithMinimalMutationChain } from '../apply-patch-with-mutation';
|
|
3
|
+
export const processCookies = (content) => {
|
|
4
|
+
const cookieStore = cookies();
|
|
5
|
+
const builderPatches = cookieStore
|
|
6
|
+
.getAll()
|
|
7
|
+
.filter((x) => x.name.startsWith('builder.patch.' + content.id + '.'))
|
|
8
|
+
.map((x) => {
|
|
9
|
+
// split into: `builder.patch.${contentId}.${blockId}.${index}`
|
|
10
|
+
const [, , , blockId, index] = x.name.split('.');
|
|
11
|
+
return {
|
|
12
|
+
blockId,
|
|
13
|
+
index: parseInt(index),
|
|
14
|
+
value: x.value,
|
|
15
|
+
};
|
|
16
|
+
})
|
|
17
|
+
.sort((a, b) => a.index - b.index);
|
|
18
|
+
if (!builderPatches.length)
|
|
19
|
+
return content;
|
|
20
|
+
let newContent = content;
|
|
21
|
+
for (const patchCookie of builderPatches) {
|
|
22
|
+
const { value } = patchCookie;
|
|
23
|
+
try {
|
|
24
|
+
const blockPatches = JSON.parse(value);
|
|
25
|
+
for (const patch of blockPatches) {
|
|
26
|
+
newContent = applyPatchWithMinimalMutationChain(newContent, patch, true);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.log('error parsing patch cookie', { value });
|
|
31
|
+
console.log('ignoring cookie');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return newContent;
|
|
35
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface GetContentOptions {
|
|
2
|
+
/** The model to get content for */
|
|
3
|
+
model: string;
|
|
4
|
+
/** Your public API key */
|
|
5
|
+
apiKey: string;
|
|
6
|
+
/** Number of items to fetch. Default is 1 */
|
|
7
|
+
limit?: number;
|
|
8
|
+
/** User attributes to target on, such as { urlPath: '/foo', device: 'mobile', ...etc } */
|
|
9
|
+
userAttributes?: (Record<string, string> & {
|
|
10
|
+
urlPath?: string;
|
|
11
|
+
}) | null;
|
|
12
|
+
/** Custom query */
|
|
13
|
+
query?: Record<string, any>;
|
|
14
|
+
/**
|
|
15
|
+
* Any other API options.
|
|
16
|
+
* Accepts both a key/value object or a `URLSearchParams` instance
|
|
17
|
+
* */
|
|
18
|
+
options?: Record<string, any> | URLSearchParams;
|
|
19
|
+
/**
|
|
20
|
+
* If set to `true`, it will lazy load symbols/references.
|
|
21
|
+
* If set to `false`, it will render the entire content tree eagerly.
|
|
22
|
+
* @deprecated use `enrich` instead
|
|
23
|
+
*/
|
|
24
|
+
noTraverse?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* If set to `false`, it will not use cookies to target content. Therefore, A/B Testing will be disabled and
|
|
27
|
+
* only the default variation will be returned to every user.
|
|
28
|
+
*
|
|
29
|
+
* Defaults to `true`.
|
|
30
|
+
*/
|
|
31
|
+
canTrack?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Include references in the response. Defaults to `true`.
|
|
34
|
+
* @deprecated use `enrich` instead
|
|
35
|
+
*/
|
|
36
|
+
includeRefs?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Include multilevel references in the response.
|
|
39
|
+
*/
|
|
40
|
+
enrich?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* If provided, the API will auto-resolve localized objects to the value of this `locale` key.
|
|
43
|
+
*/
|
|
44
|
+
locale?: string;
|
|
45
|
+
/**
|
|
46
|
+
* If provided, sets the Builder API version used to fetch content.
|
|
47
|
+
*
|
|
48
|
+
* Defaults to `v3`.
|
|
49
|
+
*/
|
|
50
|
+
apiVersion?: 'v2' | 'v3';
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fetch: typeof globalThis.fetch;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { getGlobalThis } from './get-global-this.js';
|
|
2
|
+
function getFetch() {
|
|
3
|
+
const globalFetch = getGlobalThis().fetch;
|
|
4
|
+
if (typeof globalFetch === 'undefined') {
|
|
5
|
+
console.warn(`Builder SDK could not find a global fetch function. Make sure you have a polyfill for fetch in your project.
|
|
6
|
+
For more information, read https://github.com/BuilderIO/this-package-uses-fetch`);
|
|
7
|
+
throw new Error('Builder SDK could not find a global `fetch` function');
|
|
8
|
+
}
|
|
9
|
+
return globalFetch;
|
|
10
|
+
}
|
|
11
|
+
export const fetch = getFetch();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function getGlobalThis() {
|
|
2
|
+
if (typeof globalThis !== 'undefined') {
|
|
3
|
+
return globalThis;
|
|
4
|
+
}
|
|
5
|
+
if (typeof window !== 'undefined') {
|
|
6
|
+
return window;
|
|
7
|
+
}
|
|
8
|
+
if (typeof global !== 'undefined') {
|
|
9
|
+
return global;
|
|
10
|
+
}
|
|
11
|
+
if (typeof self !== 'undefined') {
|
|
12
|
+
return self;
|
|
13
|
+
}
|
|
14
|
+
return globalThis;
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BuilderContextInterface } from '../context/types.js';
|
|
2
|
+
import type { BuilderBlock } from '../types/builder-block.js';
|
|
3
|
+
export declare function getProcessedBlock({ block, context, shouldEvaluateBindings, localState, rootState, rootSetState }: {
|
|
4
|
+
block: BuilderBlock;
|
|
5
|
+
/**
|
|
6
|
+
* In some cases, we want to avoid evaluating bindings and only want framework-specific block transformation. It is
|
|
7
|
+
* also sometimes too early to consider bindings, e.g. when we might be looking at a repeated block.
|
|
8
|
+
*/
|
|
9
|
+
shouldEvaluateBindings: boolean;
|
|
10
|
+
} & Pick<BuilderContextInterface, 'localState' | 'context' | 'rootState' | 'rootSetState'>): BuilderBlock;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { evaluate } from './evaluate.js';
|
|
2
|
+
import { fastClone } from './fast-clone.js';
|
|
3
|
+
import { set } from './set.js';
|
|
4
|
+
import { transformBlock } from './transform-block.js';
|
|
5
|
+
const evaluateBindings = ({ block, context, localState, rootState, rootSetState }) => {
|
|
6
|
+
if (!block.bindings) {
|
|
7
|
+
return block;
|
|
8
|
+
}
|
|
9
|
+
const copy = fastClone(block);
|
|
10
|
+
const copied = { ...copy,
|
|
11
|
+
properties: { ...copy.properties
|
|
12
|
+
},
|
|
13
|
+
actions: { ...copy.actions
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
for (const binding in block.bindings) {
|
|
17
|
+
const expression = block.bindings[binding];
|
|
18
|
+
const value = evaluate({
|
|
19
|
+
code: expression,
|
|
20
|
+
localState,
|
|
21
|
+
rootState,
|
|
22
|
+
rootSetState,
|
|
23
|
+
context
|
|
24
|
+
});
|
|
25
|
+
set(copied, binding, value);
|
|
26
|
+
}
|
|
27
|
+
return copied;
|
|
28
|
+
};
|
|
29
|
+
export function getProcessedBlock({ block, context, shouldEvaluateBindings, localState, rootState, rootSetState }) {
|
|
30
|
+
const transformedBlock = transformBlock(block);
|
|
31
|
+
if (shouldEvaluateBindings) {
|
|
32
|
+
return evaluateBindings({
|
|
33
|
+
block: transformedBlock,
|
|
34
|
+
localState,
|
|
35
|
+
rootState,
|
|
36
|
+
rootSetState,
|
|
37
|
+
context
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return transformedBlock;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BuilderContextInterface } from '../context/types.js';
|
|
2
|
+
import type { BuilderBlock } from '../types/builder-block.js';
|
|
3
|
+
export declare function getReactNativeBlockStyles({ block, context, blockStyles }: {
|
|
4
|
+
block: BuilderBlock;
|
|
5
|
+
context: BuilderContextInterface;
|
|
6
|
+
blockStyles: any;
|
|
7
|
+
}): CSSStyleDeclaration | Record<string, string | undefined>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { sanitizeReactNativeBlockStyles } from './sanitize-react-native-block-styles.js';
|
|
2
|
+
export function getReactNativeBlockStyles({ block, context, blockStyles }) {
|
|
3
|
+
const responsiveStyles = block.responsiveStyles;
|
|
4
|
+
if (!responsiveStyles) {
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
const styles = {
|
|
8
|
+
...context.inheritedStyles,
|
|
9
|
+
...(responsiveStyles.large || {}),
|
|
10
|
+
...(responsiveStyles.medium || {}),
|
|
11
|
+
...(responsiveStyles.small || {}),
|
|
12
|
+
...blockStyles
|
|
13
|
+
};
|
|
14
|
+
const newStyles = sanitizeReactNativeBlockStyles(styles);
|
|
15
|
+
return newStyles;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isBrowser(): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isEditing(): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isIframe(): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isPreviewing(): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isBrowser } from './is-browser.js';
|
|
2
|
+
import { isEditing } from './is-editing.js';
|
|
3
|
+
export function isPreviewing() {
|
|
4
|
+
if (!isBrowser()) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
if (isEditing()) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return Boolean(location.search.indexOf('builder.preview=') !== -1);
|
|
11
|
+
}
|