@builder.io/sdk-svelte 0.4.3 → 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/package/--package.json +5 -2
- package/package/CHANGELOG.md +10 -0
- package/package/blocks/columns/columns.svelte +2 -2
- package/package/blocks/symbol/symbol.svelte +8 -5
- package/package/blocks/text/text.svelte +1 -1
- package/package/blocks/text/text.svelte.d.ts +1 -1
- package/package/components/inlined-script.svelte +7 -0
- package/package/components/inlined-script.svelte.d.ts +21 -0
- package/package/components/inlined-styles.svelte.d.ts +21 -0
- package/package/components/render-block/block-styles.svelte +2 -2
- package/package/components/render-content/components/render-styles.svelte +2 -2
- package/package/components/render-content/render-content.svelte +9 -8
- package/package/components/render-content/render-content.svelte.d.ts +1 -2
- package/package/components/render-content/render-content.types.d.ts +9 -23
- package/package/components/render-content-variants/helpers.d.ts +27 -3
- package/package/components/render-content-variants/helpers.js +38 -24
- package/package/components/render-content-variants/render-content-variants.svelte +57 -30
- package/package/components/render-content-variants/render-content-variants.svelte.d.ts +15 -4
- package/package/components/render-content-variants/render-content-variants.types.d.ts +20 -0
- package/package/components/render-content-variants/render-content-variants.types.js +1 -0
- package/package/constants/sdk-version.d.ts +1 -1
- package/package/constants/sdk-version.js +1 -1
- package/package/functions/track/index.js +1 -1
- package/package/helpers/ab-tests.js +6 -0
- package/package/types/enforced-partials.d.ts +21 -0
- package/package/types/enforced-partials.js +1 -0
- package/package/types/typescript.d.ts +3 -0
- package/package.json +1 -1
- package/src/blocks/columns/columns.svelte +2 -2
- package/src/blocks/symbol/symbol.svelte +8 -5
- package/src/blocks/text/text.svelte +2 -2
- package/src/components/inlined-script.svelte +13 -0
- package/src/components/render-block/block-styles.svelte +2 -2
- package/src/components/render-content/components/render-styles.svelte +2 -2
- package/src/components/render-content/render-content.svelte +9 -8
- package/src/components/render-content/render-content.types.ts +10 -25
- package/src/components/render-content-variants/helpers.ts +43 -38
- package/src/components/render-content-variants/render-content-variants.svelte +67 -32
- package/src/components/render-content-variants/render-content-variants.types.ts +22 -0
- package/src/constants/sdk-version.ts +1 -1
- package/src/functions/track/index.ts +1 -1
- package/src/helpers/ab-tests.ts +6 -0
- package/src/types/enforced-partials.ts +27 -0
- package/src/types/typescript.ts +5 -0
- package/package/components/render-inlined-styles.svelte.d.ts +0 -21
- /package/package/components/{render-inlined-styles.svelte → inlined-styles.svelte} +0 -0
- /package/src/components/{render-inlined-styles.svelte → inlined-styles.svelte} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BuilderRenderContext, RegisteredComponent } from '../../context/types';
|
|
2
|
+
import type { ApiVersion } from '../../types/api-version';
|
|
3
|
+
import type { BuilderContent } from '../../types/builder-content';
|
|
4
|
+
import type { Nullable } from '../../types/typescript';
|
|
5
|
+
export interface RenderContentVariantsProps {
|
|
6
|
+
content?: Nullable<BuilderContent>;
|
|
7
|
+
model?: string;
|
|
8
|
+
data?: {
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
};
|
|
11
|
+
context?: BuilderRenderContext;
|
|
12
|
+
apiKey: string;
|
|
13
|
+
apiVersion?: ApiVersion;
|
|
14
|
+
customComponents?: RegisteredComponent[];
|
|
15
|
+
canTrack?: boolean;
|
|
16
|
+
locale?: string;
|
|
17
|
+
/** @deprecated use `enrich` instead **/
|
|
18
|
+
includeRefs?: boolean;
|
|
19
|
+
enrich?: boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.4.
|
|
1
|
+
export declare const SDK_VERSION = "0.4.5";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.4.
|
|
1
|
+
export const SDK_VERSION = "0.4.5";
|
|
@@ -43,7 +43,7 @@ export async function _track(eventProps) {
|
|
|
43
43
|
if (!(isBrowser() || TARGET === 'reactNative')) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
return fetch(`https://builder.io/api/v1/track`, {
|
|
46
|
+
return fetch(`https://cdn.builder.io/api/v1/track`, {
|
|
47
47
|
method: 'POST',
|
|
48
48
|
body: JSON.stringify({
|
|
49
49
|
events: [await createEvent(eventProps)],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getCookie, getCookieSync, setCookie } from './cookie.js';
|
|
2
2
|
import { checkIsDefined } from '../helpers/nullable.js';
|
|
3
3
|
import { logger } from './logger.js';
|
|
4
|
+
import { TARGET } from '../constants/target.js';
|
|
4
5
|
const BUILDER_STORE_PREFIX = 'builder.tests';
|
|
5
6
|
const getContentTestKey = (id) => `${BUILDER_STORE_PREFIX}.${id}`;
|
|
6
7
|
const getContentVariationCookie = ({ contentId }) => getCookie({ name: getContentTestKey(contentId), canTrack: true });
|
|
@@ -59,6 +60,11 @@ const getTestFields = ({ item, testGroupId, }) => {
|
|
|
59
60
|
}
|
|
60
61
|
};
|
|
61
62
|
export const handleABTestingSync = ({ item, canTrack, }) => {
|
|
63
|
+
/**
|
|
64
|
+
* We cannot SSR in React-Native.
|
|
65
|
+
*/
|
|
66
|
+
if (TARGET === 'reactNative')
|
|
67
|
+
return item;
|
|
62
68
|
if (!canTrack) {
|
|
63
69
|
return item;
|
|
64
70
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Prettify } from './typescript';
|
|
2
|
+
type OptionalFieldsOnly<T> = {
|
|
3
|
+
[K in keyof T as T[K] extends Required<T>[K] ? never : K]: T[K];
|
|
4
|
+
};
|
|
5
|
+
type RequiredFieldsOnly<T> = {
|
|
6
|
+
[K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K];
|
|
7
|
+
};
|
|
8
|
+
type Enforced<T> = {
|
|
9
|
+
[K in keyof T]-?: T[K];
|
|
10
|
+
};
|
|
11
|
+
type AndUndefined<T> = {
|
|
12
|
+
[K in keyof T]: T[K] | undefined;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Enforce that all optional fields are undefined
|
|
16
|
+
* @example
|
|
17
|
+
* type Foo = { a: string, b?: number }
|
|
18
|
+
* type Bar = EnforcePartials<Foo> // { a: string, b: number | undefined }
|
|
19
|
+
*/
|
|
20
|
+
export type EnforcePartials<From> = Prettify<AndUndefined<Enforced<OptionalFieldsOnly<From>>> & RequiredFieldsOnly<From>>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import type { BuilderBlock } from "../../types/builder-block";
|
|
25
25
|
import { getSizesForBreakpoints } from "../../constants/device-sizes";
|
|
26
26
|
import type { SizeName } from "../../constants/device-sizes";
|
|
27
|
-
import
|
|
27
|
+
import InlinedStyles from "../../components/inlined-styles.svelte";
|
|
28
28
|
import { TARGET } from "../../constants/target.js";
|
|
29
29
|
import BuilderContext from "../../context/builder.context.js";
|
|
30
30
|
import type { Dictionary } from "../../types/typescript";
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
}}
|
|
172
172
|
>
|
|
173
173
|
{#if TARGET !== "reactNative"}
|
|
174
|
-
<
|
|
174
|
+
<InlinedStyles styles={columnsStyles()} />
|
|
175
175
|
{/if}
|
|
176
176
|
|
|
177
177
|
{#each columns as column, index (index)}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<script lang="ts">
|
|
22
22
|
import { getContext, onMount } from "svelte";
|
|
23
23
|
|
|
24
|
-
import
|
|
24
|
+
import RenderContentVariants from "../../components/render-content-variants/render-content-variants.svelte";
|
|
25
25
|
import BuilderContext from "../../context/builder.context.js";
|
|
26
26
|
import { getContent } from "../../functions/get-content/index.js";
|
|
27
27
|
import type { BuilderContent } from "../../types/builder-content.js";
|
|
@@ -84,9 +84,11 @@
|
|
|
84
84
|
model: symbol.model,
|
|
85
85
|
apiKey: $builderContext.apiKey,
|
|
86
86
|
apiVersion: $builderContext.apiVersion,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
...(symbol?.entry && {
|
|
88
|
+
query: {
|
|
89
|
+
id: symbol.entry,
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
90
92
|
})
|
|
91
93
|
.then((response) => {
|
|
92
94
|
if (response) {
|
|
@@ -129,7 +131,8 @@
|
|
|
129
131
|
class={className}
|
|
130
132
|
use:setAttrs={filterAttrs(attributes, isEvent)}
|
|
131
133
|
>
|
|
132
|
-
<
|
|
134
|
+
<RenderContentVariants
|
|
135
|
+
__isNestedRender={true}
|
|
133
136
|
apiVersion={$builderContext.apiVersion}
|
|
134
137
|
apiKey={$builderContext.apiKey}
|
|
135
138
|
context={$builderContext.context}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script context="module" lang="ts">
|
|
2
2
|
export interface TextProps {
|
|
3
|
-
text
|
|
3
|
+
text?: string;
|
|
4
4
|
}
|
|
5
5
|
</script>
|
|
6
6
|
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
use:mitosis_styling={{
|
|
23
23
|
outline: "none",
|
|
24
24
|
}}
|
|
25
|
-
class="builder-text">{@html text}</span
|
|
25
|
+
class="builder-text">{@html text?.toString()}</span
|
|
26
26
|
>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
scriptStr: string;
|
|
4
|
+
id?: string;
|
|
5
|
+
}
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<script lang="ts">
|
|
9
|
+
export let scriptStr: Props["scriptStr"];
|
|
10
|
+
export let id: Props["id"];
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<svelte:element this={"script"} {id}>{@html scriptStr}</svelte:element>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { createCssClass } from "../../helpers/css.js";
|
|
17
17
|
import { checkIsDefined } from "../../helpers/nullable.js";
|
|
18
18
|
import type { BuilderBlock } from "../../types/builder-block.js";
|
|
19
|
-
import
|
|
19
|
+
import InlinedStyles from "../inlined-styles.svelte";
|
|
20
20
|
|
|
21
21
|
export let block: BlockStylesProps["block"];
|
|
22
22
|
export let context: BlockStylesProps["context"];
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
</script>
|
|
86
86
|
|
|
87
87
|
{#if TARGET !== "reactNative" && css() && canShowBlock()}
|
|
88
|
-
<
|
|
88
|
+
<InlinedStyles styles={css()} />
|
|
89
89
|
{/if}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<script lang="ts">
|
|
10
|
-
import
|
|
10
|
+
import InlinedStyles from "../../inlined-styles.svelte";
|
|
11
11
|
import type { CustomFont } from "./render-styles.helpers";
|
|
12
12
|
import { getCss } from "./render-styles.helpers";
|
|
13
13
|
import { getFontCss } from "./render-styles.helpers";
|
|
@@ -40,4 +40,4 @@ ${getFontCss({
|
|
|
40
40
|
`.trim();
|
|
41
41
|
</script>
|
|
42
42
|
|
|
43
|
-
<
|
|
43
|
+
<InlinedStyles styles={injectedStyles} />
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
import { logger } from "../../helpers/logger.js";
|
|
46
46
|
import { getRenderContentScriptString } from "../render-content-variants/helpers.js";
|
|
47
47
|
import { wrapComponentRef } from "./wrap-component-ref.js";
|
|
48
|
+
import InlinedScript from "../inlined-script.svelte";
|
|
48
49
|
|
|
49
50
|
const isEvent = (attr) => attr.startsWith("on:");
|
|
50
51
|
const isNonEvent = (attr) => !attr.startsWith("on:");
|
|
@@ -80,12 +81,11 @@
|
|
|
80
81
|
export let context: RenderContentProps["context"];
|
|
81
82
|
export let apiKey: RenderContentProps["apiKey"];
|
|
82
83
|
export let content: RenderContentProps["content"];
|
|
83
|
-
export let parentContentId: RenderContentProps["parentContentId"];
|
|
84
84
|
export let data: RenderContentProps["data"];
|
|
85
85
|
export let locale: RenderContentProps["locale"];
|
|
86
86
|
export let apiVersion: RenderContentProps["apiVersion"];
|
|
87
87
|
export let customComponents: RenderContentProps["customComponents"];
|
|
88
|
-
export let
|
|
88
|
+
export let showContent: RenderContentProps["showContent"];
|
|
89
89
|
export let classNameProp: RenderContentProps["classNameProp"];
|
|
90
90
|
export let isSsrAbTest: RenderContentProps["isSsrAbTest"];
|
|
91
91
|
export let includeRefs: RenderContentProps["includeRefs"];
|
|
@@ -255,9 +255,10 @@
|
|
|
255
255
|
let httpReqsData = {};
|
|
256
256
|
let clicked = false;
|
|
257
257
|
let scriptStr = getRenderContentScriptString({
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
|
|
259
|
+
variationId: content?.testVariationId!,
|
|
258
260
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
|
|
259
261
|
contentId: content?.id!,
|
|
260
|
-
parentContentId: parentContentId!,
|
|
261
262
|
});
|
|
262
263
|
let builderContextSignal = writable({
|
|
263
264
|
content: getContentInitialValue({
|
|
@@ -446,12 +447,12 @@
|
|
|
446
447
|
: {},
|
|
447
448
|
isNonEvent
|
|
448
449
|
)}
|
|
449
|
-
{...
|
|
450
|
-
? {
|
|
450
|
+
{...showContent
|
|
451
|
+
? {}
|
|
452
|
+
: {
|
|
451
453
|
hidden: true,
|
|
452
454
|
"aria-hidden": true,
|
|
453
|
-
}
|
|
454
|
-
: {}}
|
|
455
|
+
}}
|
|
455
456
|
class={classNameProp}
|
|
456
457
|
use:setAttrs={filterAttrs(
|
|
457
458
|
TARGET === "reactNative"
|
|
@@ -467,7 +468,7 @@
|
|
|
467
468
|
)}
|
|
468
469
|
>
|
|
469
470
|
{#if isSsrAbTest}
|
|
470
|
-
<
|
|
471
|
+
<InlinedScript {scriptStr} />
|
|
471
472
|
{/if}
|
|
472
473
|
|
|
473
474
|
{#if TARGET !== "reactNative"}
|
|
@@ -1,34 +1,19 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
BuilderRenderState,
|
|
5
|
-
} from '../../context/types';
|
|
6
|
-
import type { BuilderContent } from '../../types/builder-content';
|
|
7
|
-
import type { Nullable } from '../../types/typescript';
|
|
8
|
-
import type { ApiVersion } from '../../types/api-version';
|
|
1
|
+
import type { BuilderRenderState } from '../../context/types';
|
|
2
|
+
import type { EnforcePartials } from '../../types/enforced-partials';
|
|
3
|
+
import type { RenderContentVariantsProps } from '../render-content-variants/render-content-variants.types';
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
content?: Nullable<BuilderContent>;
|
|
12
|
-
model?: string;
|
|
13
|
-
data?: { [key: string]: any };
|
|
14
|
-
context?: BuilderRenderContext;
|
|
15
|
-
apiKey: string;
|
|
16
|
-
apiVersion?: ApiVersion;
|
|
17
|
-
customComponents?: RegisteredComponent[];
|
|
18
|
-
canTrack?: boolean;
|
|
19
|
-
locale?: string;
|
|
20
|
-
/** @deprecated use `enrich` instead **/
|
|
21
|
-
includeRefs?: boolean;
|
|
22
|
-
enrich?: boolean;
|
|
5
|
+
interface InternalRenderProps {
|
|
23
6
|
/**
|
|
24
7
|
* TO-DO: improve qwik generator to not remap this name for non-HTML tags, then name it `className`
|
|
25
8
|
*/
|
|
26
|
-
classNameProp
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
isSsrAbTest?: boolean;
|
|
9
|
+
classNameProp: string | undefined;
|
|
10
|
+
showContent: boolean;
|
|
11
|
+
isSsrAbTest: boolean;
|
|
30
12
|
}
|
|
31
13
|
|
|
14
|
+
export type RenderContentProps = InternalRenderProps &
|
|
15
|
+
EnforcePartials<RenderContentVariantsProps>;
|
|
16
|
+
|
|
32
17
|
export interface BuilderComponentStateChange {
|
|
33
18
|
state: BuilderRenderState;
|
|
34
19
|
ref: {
|
|
@@ -5,7 +5,11 @@ import type { BuilderContent } from '../../types/builder-content';
|
|
|
5
5
|
import type { Target } from '../../types/targets';
|
|
6
6
|
|
|
7
7
|
export const getVariants = (content: Nullable<BuilderContent>) =>
|
|
8
|
-
Object.values(content?.variations || {})
|
|
8
|
+
Object.values(content?.variations || {}).map((variant) => ({
|
|
9
|
+
...variant,
|
|
10
|
+
testVariationId: variant.id,
|
|
11
|
+
id: content?.id,
|
|
12
|
+
}));
|
|
9
13
|
|
|
10
14
|
export const checkShouldRunVariants = ({
|
|
11
15
|
canTrack,
|
|
@@ -16,17 +20,24 @@ export const checkShouldRunVariants = ({
|
|
|
16
20
|
}) => {
|
|
17
21
|
const hasVariants = getVariants(content).length > 0;
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
/**
|
|
24
|
+
* We cannot SSR in React-Native.
|
|
25
|
+
*/
|
|
26
|
+
if (TARGET === 'reactNative') return false;
|
|
22
27
|
|
|
23
|
-
if (!
|
|
24
|
-
|
|
25
|
-
}
|
|
28
|
+
if (!hasVariants) return false;
|
|
29
|
+
if (!canTrack) return false;
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
/**
|
|
32
|
+
* For Vue 2 and Vue 3, we need to (initially) render the variants. This is to avoid hydration mismatch errors.
|
|
33
|
+
* Unlike React, Vue's hydration checks are shallow and do not check the attributes/contents of each element, so we
|
|
34
|
+
* are able to modify the `hidden` HTML attributes and `display` CSS properties without causing a hydration mismatch error.
|
|
35
|
+
*
|
|
36
|
+
* NOTE: after the app is hydrated, we strip the variants from the DOM (on mount) to reduce the amount of HTML in the DOM.
|
|
37
|
+
*/
|
|
38
|
+
if (TARGET === 'vue2' || TARGET === 'vue3') return true;
|
|
39
|
+
|
|
40
|
+
if (isBrowser()) return false;
|
|
30
41
|
|
|
31
42
|
return true;
|
|
32
43
|
};
|
|
@@ -107,18 +118,15 @@ function bldrAbTest(
|
|
|
107
118
|
|
|
108
119
|
const winningVariantId = getAndSetVariantId();
|
|
109
120
|
|
|
110
|
-
const styleEl = document.
|
|
111
|
-
|
|
112
|
-
) as HTMLStyleElement;
|
|
121
|
+
const styleEl = document.currentScript
|
|
122
|
+
?.previousElementSibling as HTMLStyleElement;
|
|
113
123
|
|
|
114
124
|
/**
|
|
115
125
|
* For React to work, we need hydration to match SSR, so we completely remove this node and the styles tag.
|
|
116
126
|
*/
|
|
117
127
|
if (isHydrationTarget) {
|
|
118
128
|
styleEl.remove();
|
|
119
|
-
const thisScriptEl = document.
|
|
120
|
-
`variants-script-${contentId}`
|
|
121
|
-
);
|
|
129
|
+
const thisScriptEl = document.currentScript;
|
|
122
130
|
thisScriptEl?.remove();
|
|
123
131
|
} else {
|
|
124
132
|
/* update styles to hide all variants except the winning variant */
|
|
@@ -131,7 +139,6 @@ function bldrAbTest(
|
|
|
131
139
|
})
|
|
132
140
|
.join('');
|
|
133
141
|
|
|
134
|
-
/* TO-DO: check if this actually updates the style */
|
|
135
142
|
styleEl.innerHTML = newStyleStr;
|
|
136
143
|
}
|
|
137
144
|
}
|
|
@@ -162,10 +169,7 @@ function bldrCntntScrpt(
|
|
|
162
169
|
const cookieName = `builder.tests.${defaultContentId}`;
|
|
163
170
|
const variantId = getCookie(cookieName);
|
|
164
171
|
|
|
165
|
-
|
|
166
|
-
const parentDiv = document.querySelector(
|
|
167
|
-
`[builder-content-id="${variantContentId}"]`
|
|
168
|
-
);
|
|
172
|
+
const parentDiv = document.currentScript?.parentElement;
|
|
169
173
|
|
|
170
174
|
const variantIsDefaultContent = variantContentId === defaultContentId;
|
|
171
175
|
|
|
@@ -204,10 +208,7 @@ function bldrCntntScrpt(
|
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
const getIsHydrationTarget = (target: Target) =>
|
|
207
|
-
target === 'react' ||
|
|
208
|
-
target === 'reactNative' ||
|
|
209
|
-
target === 'vue3' ||
|
|
210
|
-
target === 'vue2';
|
|
211
|
+
target === 'react' || target === 'reactNative';
|
|
211
212
|
|
|
212
213
|
const isHydrationTarget = getIsHydrationTarget(TARGET);
|
|
213
214
|
|
|
@@ -217,32 +218,36 @@ const isHydrationTarget = getIsHydrationTarget(TARGET);
|
|
|
217
218
|
*
|
|
218
219
|
* So we hardcode the function names here, and then use those names in the script string to make sure the function names are consistent.
|
|
219
220
|
*/
|
|
220
|
-
const AB_TEST_FN_NAME = '
|
|
221
|
-
const CONTENT_FN_NAME = '
|
|
221
|
+
const AB_TEST_FN_NAME = 'builderIoAbTest';
|
|
222
|
+
const CONTENT_FN_NAME = 'builderIoRenderContent';
|
|
223
|
+
|
|
224
|
+
export const getScriptString = () => {
|
|
225
|
+
const fnStr = bldrAbTest.toString().replace(/\s+/g, ' ');
|
|
226
|
+
const fnStr2 = bldrCntntScrpt.toString().replace(/\s+/g, ' ');
|
|
227
|
+
|
|
228
|
+
return `
|
|
229
|
+
window.${AB_TEST_FN_NAME} = ${fnStr}
|
|
230
|
+
window.${CONTENT_FN_NAME} = ${fnStr2}
|
|
231
|
+
`;
|
|
232
|
+
};
|
|
222
233
|
|
|
223
234
|
export const getVariantsScriptString = (
|
|
224
235
|
variants: VariantData[],
|
|
225
236
|
contentId: string
|
|
226
237
|
) => {
|
|
227
|
-
const fnStr = bldrAbTest.toString().replace(/\s+/g, ' ');
|
|
228
|
-
const fnStr2 = bldrCntntScrpt.toString().replace(/\s+/g, ' ');
|
|
229
|
-
|
|
230
238
|
return `
|
|
231
|
-
|
|
232
|
-
const ${CONTENT_FN_NAME} = ${fnStr2}
|
|
233
|
-
${AB_TEST_FN_NAME}("${contentId}", ${JSON.stringify(
|
|
239
|
+
window.${AB_TEST_FN_NAME}("${contentId}",${JSON.stringify(
|
|
234
240
|
variants
|
|
235
|
-
)}, ${isHydrationTarget})
|
|
236
|
-
`;
|
|
241
|
+
)}, ${isHydrationTarget})`;
|
|
237
242
|
};
|
|
238
243
|
|
|
239
244
|
export const getRenderContentScriptString = ({
|
|
240
|
-
parentContentId,
|
|
241
245
|
contentId,
|
|
246
|
+
variationId,
|
|
242
247
|
}: {
|
|
248
|
+
variationId: string;
|
|
243
249
|
contentId: string;
|
|
244
|
-
parentContentId: string;
|
|
245
250
|
}) => {
|
|
246
251
|
return `
|
|
247
|
-
|
|
252
|
+
window.${CONTENT_FN_NAME}("${variationId}", "${contentId}", ${isHydrationTarget})`;
|
|
248
253
|
};
|
|
@@ -1,83 +1,118 @@
|
|
|
1
1
|
<script context="module" lang="ts">
|
|
2
|
-
type VariantsProviderProps =
|
|
2
|
+
type VariantsProviderProps = RenderContentVariantsProps & {
|
|
3
|
+
/**
|
|
4
|
+
* For internal use only. Do not provide this prop.
|
|
5
|
+
*/
|
|
6
|
+
__isNestedRender?: boolean;
|
|
7
|
+
};
|
|
3
8
|
</script>
|
|
4
9
|
|
|
5
10
|
<script lang="ts">
|
|
11
|
+
import { onMount } from "svelte";
|
|
12
|
+
|
|
6
13
|
import {
|
|
7
14
|
checkShouldRunVariants,
|
|
15
|
+
getScriptString,
|
|
8
16
|
getVariants,
|
|
9
17
|
getVariantsScriptString,
|
|
10
18
|
} from "./helpers";
|
|
11
19
|
import RenderContent from "../render-content/render-content.svelte";
|
|
12
|
-
import type { RenderContentProps } from "../render-content/render-content.types";
|
|
13
20
|
import { getDefaultCanTrack } from "../../helpers/canTrack";
|
|
14
|
-
import
|
|
21
|
+
import InlinedStyles from "../inlined-styles.svelte";
|
|
15
22
|
import { handleABTestingSync } from "../../helpers/ab-tests";
|
|
23
|
+
import InlinedScript from "../inlined-script.svelte";
|
|
24
|
+
import { TARGET } from "../../constants/target";
|
|
25
|
+
import type { RenderContentVariantsProps } from "./render-content-variants.types";
|
|
16
26
|
|
|
17
|
-
export let content: VariantsProviderProps["content"];
|
|
18
27
|
export let canTrack: VariantsProviderProps["canTrack"];
|
|
28
|
+
export let content: VariantsProviderProps["content"];
|
|
29
|
+
export let __isNestedRender: VariantsProviderProps["__isNestedRender"];
|
|
30
|
+
export let model: VariantsProviderProps["model"];
|
|
31
|
+
export let data: VariantsProviderProps["data"];
|
|
32
|
+
export let context: VariantsProviderProps["context"];
|
|
19
33
|
export let apiKey: VariantsProviderProps["apiKey"];
|
|
20
34
|
export let apiVersion: VariantsProviderProps["apiVersion"];
|
|
21
35
|
export let customComponents: VariantsProviderProps["customComponents"];
|
|
22
|
-
export let
|
|
36
|
+
export let locale: VariantsProviderProps["locale"];
|
|
37
|
+
export let includeRefs: VariantsProviderProps["includeRefs"];
|
|
38
|
+
export let enrich: VariantsProviderProps["enrich"];
|
|
23
39
|
|
|
40
|
+
let shouldRenderVariants = checkShouldRunVariants({
|
|
41
|
+
canTrack: getDefaultCanTrack(canTrack),
|
|
42
|
+
content: content,
|
|
43
|
+
});
|
|
24
44
|
let variantScriptStr = getVariantsScriptString(
|
|
25
45
|
getVariants(content).map((value) => ({
|
|
26
|
-
id: value.
|
|
46
|
+
id: value.testVariationId!,
|
|
27
47
|
testRatio: value.testRatio,
|
|
28
48
|
})),
|
|
29
49
|
content?.id || ""
|
|
30
50
|
);
|
|
31
|
-
let shouldRenderVariants = checkShouldRunVariants({
|
|
32
|
-
canTrack: getDefaultCanTrack(canTrack),
|
|
33
|
-
content: content,
|
|
34
|
-
});
|
|
35
51
|
let hideVariantsStyleString = getVariants(content)
|
|
36
|
-
.map((value) => `.variant-${value.
|
|
52
|
+
.map((value) => `.variant-${value.testVariationId} { display: none; } `)
|
|
37
53
|
.join("");
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
|
|
55
|
+
onMount(() => {
|
|
56
|
+
/**
|
|
57
|
+
* We unmount the non-winning variants post-hydration in Vue.
|
|
58
|
+
*/
|
|
59
|
+
if (TARGET === "vue2" || TARGET === "vue3") {
|
|
60
|
+
shouldRenderVariants = false;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
47
63
|
</script>
|
|
48
64
|
|
|
65
|
+
{#if !__isNestedRender && TARGET !== "reactNative"}
|
|
66
|
+
<InlinedScript scriptStr={getScriptString()} />
|
|
67
|
+
{/if}
|
|
68
|
+
|
|
49
69
|
{#if shouldRenderVariants}
|
|
50
|
-
<
|
|
70
|
+
<InlinedStyles
|
|
51
71
|
id={`variants-styles-${content?.id}`}
|
|
52
72
|
styles={hideVariantsStyleString}
|
|
53
73
|
/>
|
|
54
74
|
|
|
55
|
-
<
|
|
56
|
-
>{@html variantScriptStr}</svelte:element
|
|
57
|
-
>
|
|
75
|
+
<InlinedScript scriptStr={variantScriptStr} />
|
|
58
76
|
|
|
59
|
-
{#each getVariants(content) as variant (variant.
|
|
77
|
+
{#each getVariants(content) as variant (variant.testVariationId)}
|
|
60
78
|
<RenderContent
|
|
61
79
|
content={variant}
|
|
80
|
+
showContent={false}
|
|
81
|
+
classNameProp={undefined}
|
|
82
|
+
{model}
|
|
83
|
+
{data}
|
|
84
|
+
{context}
|
|
62
85
|
{apiKey}
|
|
63
86
|
{apiVersion}
|
|
64
|
-
{canTrack}
|
|
65
87
|
{customComponents}
|
|
66
|
-
|
|
67
|
-
|
|
88
|
+
{canTrack}
|
|
89
|
+
{locale}
|
|
90
|
+
{includeRefs}
|
|
91
|
+
{enrich}
|
|
68
92
|
isSsrAbTest={shouldRenderVariants}
|
|
69
93
|
/>
|
|
70
94
|
{/each}
|
|
71
95
|
{/if}
|
|
72
96
|
|
|
73
97
|
<RenderContent
|
|
98
|
+
{...{}}
|
|
99
|
+
content={shouldRenderVariants
|
|
100
|
+
? content
|
|
101
|
+
: handleABTestingSync({
|
|
102
|
+
item: content,
|
|
103
|
+
canTrack: getDefaultCanTrack(canTrack),
|
|
104
|
+
})}
|
|
105
|
+
classNameProp={`variant-${content?.id}`}
|
|
106
|
+
showContent={true}
|
|
74
107
|
{model}
|
|
75
|
-
|
|
108
|
+
{data}
|
|
109
|
+
{context}
|
|
76
110
|
{apiKey}
|
|
77
111
|
{apiVersion}
|
|
78
|
-
{canTrack}
|
|
79
112
|
{customComponents}
|
|
80
|
-
|
|
81
|
-
|
|
113
|
+
{canTrack}
|
|
114
|
+
{locale}
|
|
115
|
+
{includeRefs}
|
|
116
|
+
{enrich}
|
|
82
117
|
isSsrAbTest={shouldRenderVariants}
|
|
83
118
|
/>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BuilderRenderContext,
|
|
3
|
+
RegisteredComponent,
|
|
4
|
+
} from '../../context/types';
|
|
5
|
+
import type { ApiVersion } from '../../types/api-version';
|
|
6
|
+
import type { BuilderContent } from '../../types/builder-content';
|
|
7
|
+
import type { Nullable } from '../../types/typescript';
|
|
8
|
+
|
|
9
|
+
export interface RenderContentVariantsProps {
|
|
10
|
+
content?: Nullable<BuilderContent>;
|
|
11
|
+
model?: string;
|
|
12
|
+
data?: { [key: string]: any };
|
|
13
|
+
context?: BuilderRenderContext;
|
|
14
|
+
apiKey: string;
|
|
15
|
+
apiVersion?: ApiVersion;
|
|
16
|
+
customComponents?: RegisteredComponent[];
|
|
17
|
+
canTrack?: boolean;
|
|
18
|
+
locale?: string;
|
|
19
|
+
/** @deprecated use `enrich` instead **/
|
|
20
|
+
includeRefs?: boolean;
|
|
21
|
+
enrich?: boolean;
|
|
22
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.4.
|
|
1
|
+
export const SDK_VERSION = "0.4.5"
|
|
@@ -118,7 +118,7 @@ export async function _track(eventProps: EventProps) {
|
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
return fetch(`https://builder.io/api/v1/track`, {
|
|
121
|
+
return fetch(`https://cdn.builder.io/api/v1/track`, {
|
|
122
122
|
method: 'POST',
|
|
123
123
|
body: JSON.stringify({
|
|
124
124
|
events: [await createEvent(eventProps)],
|