@builder.io/sdk-svelte 0.0.5 → 0.0.7

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 (59) hide show
  1. package/package/--package.json +2 -1
  2. package/package/blocks/button/button.svelte +2 -2
  3. package/package/blocks/columns/columns.svelte +1 -2
  4. package/package/blocks/columns/component-info.js +2 -2
  5. package/package/blocks/embed/component-info.js +2 -2
  6. package/package/blocks/form/form.svelte +1 -1
  7. package/package/blocks/image/component-info.js +2 -2
  8. package/package/blocks/img/img.svelte +1 -1
  9. package/package/blocks/section/section.svelte +1 -1
  10. package/package/blocks/submit-button/submit-button.svelte +1 -1
  11. package/package/blocks/symbol/symbol.svelte +4 -7
  12. package/package/blocks/util.d.ts +4 -1
  13. package/package/blocks/util.js +13 -4
  14. package/package/blocks/video/video.svelte +1 -1
  15. package/package/components/render-block/block-styles.svelte +5 -3
  16. package/package/components/render-block/render-block.svelte +9 -9
  17. package/package/components/render-block/render-component.svelte +1 -2
  18. package/package/components/render-content/builder-editing.svelte +4 -0
  19. package/package/components/render-content/builder-editing.svelte.d.ts +14 -0
  20. package/package/components/render-content/render-content.svelte +14 -10
  21. package/package/components/render-inlined-styles.svelte +3 -3
  22. package/package/constants/device-sizes.d.ts +12 -1
  23. package/package/constants/device-sizes.js +27 -1
  24. package/package/functions/get-content/index.js +5 -2
  25. package/package/functions/get-content/types.d.ts +4 -0
  26. package/package/functions/register-component.js +1 -13
  27. package/package/functions/track.d.ts +35 -5
  28. package/package/functions/track.js +5 -4
  29. package/package/index.d.ts +4 -1
  30. package/package/index.js +2 -1
  31. package/package/scripts/init-editing.js +6 -0
  32. package/package/types/builder-content.d.ts +7 -0
  33. package/package.json +1 -1
  34. package/src/blocks/button/button.svelte +2 -2
  35. package/src/blocks/columns/columns.svelte +1 -2
  36. package/src/blocks/columns/component-info.ts +2 -2
  37. package/src/blocks/embed/component-info.ts +2 -2
  38. package/src/blocks/form/form.svelte +1 -1
  39. package/src/blocks/image/component-info.ts +2 -2
  40. package/src/blocks/img/img.svelte +1 -1
  41. package/src/blocks/section/section.svelte +1 -1
  42. package/src/blocks/submit-button/submit-button.svelte +1 -1
  43. package/src/blocks/symbol/symbol.svelte +4 -7
  44. package/src/blocks/util.ts +18 -6
  45. package/src/blocks/video/video.svelte +1 -1
  46. package/src/components/render-block/block-styles.svelte +16 -3
  47. package/src/components/render-block/render-block.svelte +9 -9
  48. package/src/components/render-block/render-component.svelte +1 -2
  49. package/src/components/render-content/builder-editing.svelte +4 -0
  50. package/src/components/render-content/render-content.svelte +14 -10
  51. package/src/components/render-inlined-styles.svelte +3 -3
  52. package/src/constants/device-sizes.ts +39 -2
  53. package/src/functions/get-content/index.ts +6 -1
  54. package/src/functions/get-content/types.ts +5 -0
  55. package/src/functions/register-component.ts +1 -18
  56. package/src/functions/track.ts +45 -11
  57. package/src/index.ts +4 -1
  58. package/src/scripts/init-editing.ts +6 -0
  59. package/src/types/builder-content.ts +7 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.0.4",
4
+ "version": "0.0.6",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -72,6 +72,7 @@
72
72
  "./components/render-block/render-repeated-block.svelte": "./components/render-block/render-repeated-block.svelte",
73
73
  "./components/render-block/types": "./components/render-block/types.js",
74
74
  "./components/render-blocks.svelte": "./components/render-blocks.svelte",
75
+ "./components/render-content/builder-editing.svelte": "./components/render-content/builder-editing.svelte",
75
76
  "./components/render-content/components/render-styles.svelte": "./components/render-content/components/render-styles.svelte",
76
77
  "./components/render-content": "./components/render-content/index.js",
77
78
  "./components/render-content/render-content.svelte": "./components/render-content/render-content.svelte",
@@ -8,15 +8,15 @@ export let openLinkInNewTab;
8
8
 
9
9
  {#if link}
10
10
  <a
11
- {...attributes}
12
11
  role="button"
12
+ {...attributes}
13
13
  href={link}
14
14
  target={openLinkInNewTab ? "_blank" : undefined}
15
15
  >
16
16
  {text}
17
17
  </a>
18
18
  {:else}
19
- <button {...attributes} class="button">
19
+ <button class="button" {...attributes}>
20
20
  {text}
21
21
  </button>
22
22
  {/if}
@@ -1,7 +1,6 @@
1
1
  <script context="module"></script>
2
2
 
3
3
  <script>import RenderBlocks from "../../components/render-blocks.svelte";
4
- import { markMutable } from "../../functions/mark-mutable";
5
4
  export let space;
6
5
  export let columns;
7
6
  export let stackColumnsAt;
@@ -71,7 +70,7 @@ $: columnCssVars = () => {
71
70
  class="builder-column div-2"
72
71
  >
73
72
  <RenderBlocks
74
- blocks={markMutable(column.blocks)}
73
+ blocks={column.blocks}
75
74
  path={`component.options.columns.${index}.blocks`}
76
75
  parent={builderBlock.id}
77
76
  styleProp={{
@@ -1,4 +1,4 @@
1
- import { markSerializable } from '../util.js';
1
+ import { serializeFn } from '../util.js';
2
2
  export const componentInfo = {
3
3
  // TODO: ways to statically preprocess JSON for references, functions, etc
4
4
  name: 'Columns',
@@ -188,7 +188,7 @@ export const componentInfo = {
188
188
  ],
189
189
  },
190
190
  ],
191
- onChange: markSerializable((options) => {
191
+ onChange: serializeFn((options) => {
192
192
  function clearWidths() {
193
193
  columns.forEach((col) => {
194
194
  col.delete('width');
@@ -1,4 +1,4 @@
1
- import { markSerializable } from '../util.js';
1
+ import { serializeFn } from '../util.js';
2
2
  export const componentInfo = {
3
3
  name: 'Embed',
4
4
  static: true,
@@ -10,7 +10,7 @@ export const componentInfo = {
10
10
  required: true,
11
11
  defaultValue: '',
12
12
  helperText: 'e.g. enter a youtube url, google map, etc',
13
- onChange: markSerializable((options) => {
13
+ onChange: serializeFn((options) => {
14
14
  const url = options.get('url');
15
15
  if (url) {
16
16
  options.set('content', 'Loading...');
@@ -217,7 +217,6 @@ let formErrorMessage = "";
217
217
  </script>
218
218
 
219
219
  <form
220
- {...attributes}
221
220
  {validate}
222
221
  bind:this={formRef}
223
222
  action={!sendWithJs && action}
@@ -226,6 +225,7 @@ let formErrorMessage = "";
226
225
  on:submit={(event) => {
227
226
  onSubmit(event);
228
227
  }}
228
+ {...attributes}
229
229
  >
230
230
  {#if builderBlock && builderBlock.children}
231
231
  {#each builderBlock?.children as block}
@@ -1,4 +1,4 @@
1
- import { markSerializable } from '../util.js';
1
+ import { serializeFn } from '../util.js';
2
2
  export const componentInfo = {
3
3
  name: 'Image',
4
4
  static: true,
@@ -19,7 +19,7 @@ export const componentInfo = {
19
19
  allowedFileTypes: ['jpeg', 'jpg', 'png', 'svg'],
20
20
  required: true,
21
21
  defaultValue: 'https://cdn.builder.io/api/v1/image/assets%2Fpwgjf0RoYWbdnJSbpBAjXNRMe9F2%2Ffb27a7c790324294af8be1c35fe30f4d',
22
- onChange: markSerializable((options) => {
22
+ onChange: serializeFn((options) => {
23
23
  const DEFAULT_ASPECT_RATIO = 0.7041;
24
24
  options.delete('srcset');
25
25
  options.delete('noWebp');
@@ -20,7 +20,6 @@ function mitosis_styling(node, vars) {
20
20
  </script>
21
21
 
22
22
  <img
23
- {...attributes}
24
23
  use:mitosis_styling={{
25
24
  objectFit: backgroundSize || "cover",
26
25
  objectPosition: backgroundPosition || "center",
@@ -28,4 +27,5 @@ function mitosis_styling(node, vars) {
28
27
  key={(isEditing() && imgSrc) || "default-key"}
29
28
  alt={altText}
30
29
  src={imgSrc || image}
30
+ {...attributes}
31
31
  />
@@ -15,12 +15,12 @@ function mitosis_styling(node, vars) {
15
15
  </script>
16
16
 
17
17
  <section
18
- {...attributes}
19
18
  use:mitosis_styling={maxWidth && typeof maxWidth === "number"
20
19
  ? {
21
20
  maxWidth: maxWidth,
22
21
  }
23
22
  : undefined}
23
+ {...attributes}
24
24
  >
25
25
  <slot />
26
26
  </section>
@@ -4,6 +4,6 @@
4
4
  export let text;
5
5
  </script>
6
6
 
7
- <button {...attributes} type="submit">
7
+ <button type="submit" {...attributes}>
8
8
  {text}
9
9
  </button>
@@ -4,7 +4,6 @@
4
4
  import RenderContent from "../../components/render-content/render-content.svelte";
5
5
  import BuilderContext from "../../context/builder.context.js";
6
6
  import { getContent } from "../../functions/get-content/index.js";
7
- import { markMutable } from "../../functions/mark-mutable";
8
7
  export let symbol;
9
8
  export let attributes;
10
9
  let builderContext = getContext(BuilderContext.key);
@@ -52,15 +51,13 @@ $: onUpdateFn_0(...[symbol, fetchedContent]);
52
51
  <RenderContent
53
52
  apiKey={builderContext.apiKey}
54
53
  context={builderContext.context}
55
- customComponents={markMutable(
56
- Object.values(builderContext.registeredComponents)
57
- )}
58
- data={markMutable({
54
+ customComponents={Object.values(builderContext.registeredComponents)}
55
+ data={{
59
56
  ...symbol?.data,
60
57
  ...builderContext.state,
61
58
  ...symbol?.content?.data?.state,
62
- })}
59
+ }}
63
60
  model={symbol?.model}
64
- content={markMutable(contentToUse())}
61
+ content={contentToUse()}
65
62
  />
66
63
  </div>
@@ -1 +1,4 @@
1
- export declare function markSerializable<FN extends (...args: any[]) => any>(fn: FN): FN;
1
+ /**
2
+ * Input attributes that are functions must be converted to strings before being serialized to JSON.
3
+ */
4
+ export declare const serializeFn: (fnValue: Function) => string;
@@ -1,4 +1,13 @@
1
- export function markSerializable(fn) {
2
- fn.__qwik_serializable__ = true;
3
- return fn;
4
- }
1
+ /**
2
+ * Input attributes that are functions must be converted to strings before being serialized to JSON.
3
+ */
4
+ // eslint-disable-next-line @typescript-eslint/ban-types
5
+ export const serializeFn = (fnValue) => {
6
+ const fnStr = fnValue.toString().trim();
7
+ // we need to account for a few different fn syntaxes:
8
+ // 1. `function name(args) => {code}`
9
+ // 2. `name(args) => {code}`
10
+ // 3. `(args) => {}`
11
+ const appendFunction = !fnStr.startsWith('function') && !fnStr.startsWith('(');
12
+ return `return (${appendFunction ? 'function ' : ''}${fnStr}).apply(this, arguments)`;
13
+ };
@@ -58,7 +58,6 @@ $: spreadProps = () => {
58
58
  </script>
59
59
 
60
60
  <video
61
- {...spreadProps()}
62
61
  use:mitosis_styling={{
63
62
  width: "100%",
64
63
  height: "100%",
@@ -69,6 +68,7 @@ $: spreadProps = () => {
69
68
  // not have the video overflow
70
69
  borderRadius: 1,
71
70
  }}
71
+ {...spreadProps()}
72
72
  src={video || "no-src"}
73
73
  poster={posterImage}
74
74
  />
@@ -1,6 +1,6 @@
1
1
  <script context="module"></script>
2
2
 
3
- <script>import { getMaxWidthQueryForSize } from "../../constants/device-sizes.js";
3
+ <script>import { getMaxWidthQueryForSize, getSizesForBreakpoints, } from "../../constants/device-sizes.js";
4
4
  import { TARGET } from "../../constants/target.js";
5
5
  import { getProcessedBlock } from "../../functions/get-processed-block.js";
6
6
  import { createCssClass } from "../../helpers/css.js";
@@ -17,6 +17,8 @@ $: useBlock = () => {
17
17
  };
18
18
  $: css = () => {
19
19
  const styles = useBlock().responsiveStyles;
20
+ const content = context.content;
21
+ const sizesWithUpdatedBreakpoints = getSizesForBreakpoints(content?.meta?.breakpoints || {});
20
22
  const largeStyles = styles?.large;
21
23
  const mediumStyles = styles?.medium;
22
24
  const smallStyles = styles?.small;
@@ -31,14 +33,14 @@ $: css = () => {
31
33
  ? createCssClass({
32
34
  className,
33
35
  styles: mediumStyles,
34
- mediaQuery: getMaxWidthQueryForSize("medium"),
36
+ mediaQuery: getMaxWidthQueryForSize("medium", sizesWithUpdatedBreakpoints),
35
37
  })
36
38
  : "";
37
39
  const smallStylesClass = smallStyles
38
40
  ? createCssClass({
39
41
  className,
40
42
  styles: smallStyles,
41
- mediaQuery: getMaxWidthQueryForSize("small"),
43
+ mediaQuery: getMaxWidthQueryForSize("small", sizesWithUpdatedBreakpoints),
42
44
  })
43
45
  : "";
44
46
  return [largeStylesClass, mediumStylesClass, smallStylesClass].join(" ");
@@ -38,7 +38,7 @@ $: component = () => {
38
38
  return ref;
39
39
  }
40
40
  };
41
- $: tagName = () => {
41
+ $: tag = () => {
42
42
  return getBlockTag(useBlock());
43
43
  };
44
44
  $: useBlock = () => {
@@ -74,7 +74,7 @@ $: shouldWrap = () => {
74
74
  };
75
75
  $: renderComponentProps = () => {
76
76
  return {
77
- blockChildren: children(),
77
+ blockChildren: useChildren(),
78
78
  componentRef: component?.()?.component,
79
79
  componentOptions: {
80
80
  ...getBlockComponentOptions(useBlock()),
@@ -91,7 +91,7 @@ $: renderComponentProps = () => {
91
91
  context: childrenContext(),
92
92
  };
93
93
  };
94
- $: children = () => {
94
+ $: useChildren = () => {
95
95
  // TO-DO: When should `canHaveChildren` dictate rendering?
96
96
  // This is currently commented out because some Builder components (e.g. Box) do not have `canHaveChildren: true`,
97
97
  // but still receive and need to render children.
@@ -106,7 +106,7 @@ $: childrenWithoutParentComponent = () => {
106
106
  * blocks, and the children will be repeated within those blocks.
107
107
  */
108
108
  const shouldRenderChildrenOutsideRef = !component?.()?.component && !repeatItemData();
109
- return shouldRenderChildrenOutsideRef ? children() : [];
109
+ return shouldRenderChildrenOutsideRef ? useChildren() : [];
110
110
  };
111
111
  $: repeatItemData = () => {
112
112
  /**
@@ -177,18 +177,18 @@ $: renderComponentTag = () => {
177
177
  </script>
178
178
 
179
179
  {#if shouldWrap()}
180
- {#if isEmptyHtmlElement(tagName())}
181
- <svelte:element this={tagName()} {...attributes()} />
180
+ {#if isEmptyHtmlElement(tag())}
181
+ <svelte:element this={tag()} {...attributes()} />
182
182
  {/if}
183
183
 
184
- {#if !isEmptyHtmlElement(tagName()) && repeatItemData()}
184
+ {#if !isEmptyHtmlElement(tag()) && repeatItemData()}
185
185
  {#each repeatItemData() as data, index (index)}
186
186
  <RenderRepeatedBlock repeatContext={data.context} block={data.block} />
187
187
  {/each}
188
188
  {/if}
189
189
 
190
- {#if !isEmptyHtmlElement(tagName()) && !repeatItemData()}
191
- <svelte:element this={tagName()} {...attributes()}>
190
+ {#if !isEmptyHtmlElement(tag()) && !repeatItemData()}
191
+ <svelte:element this={tag()} {...attributes()}>
192
192
  <svelte:component
193
193
  this={renderComponentTag()}
194
194
  {...renderComponentProps()}
@@ -2,7 +2,6 @@
2
2
 
3
3
  <script>import BlockStyles from "./block-styles.svelte";
4
4
  import RenderBlock from "./render-block.svelte";
5
- import { markPropsMutable } from "../../functions/mark-mutable.js";
6
5
  export let componentRef;
7
6
  export let componentOptions;
8
7
  export let blockChildren;
@@ -10,7 +9,7 @@ export let context;
10
9
  </script>
11
10
 
12
11
  {#if componentRef}
13
- <svelte:component this={componentRef} {...markPropsMutable(componentOptions)}>
12
+ <svelte:component this={componentRef} {...componentOptions}>
14
13
  {#each blockChildren as child ("render-block-" + child.id)}
15
14
  <RenderBlock block={child} {context} />
16
15
  {/each}
@@ -0,0 +1,4 @@
1
+ <script>"use strict";
2
+ </script>
3
+
4
+ <div />
@@ -0,0 +1,14 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {};
4
+ events: {
5
+ [evt: string]: CustomEvent<any>;
6
+ };
7
+ slots: {};
8
+ };
9
+ export declare type BuilderEditingProps = typeof __propDef.props;
10
+ export declare type BuilderEditingEvents = typeof __propDef.events;
11
+ export declare type BuilderEditingSlots = typeof __propDef.slots;
12
+ export default class BuilderEditing extends SvelteComponentTyped<BuilderEditingProps, BuilderEditingEvents, BuilderEditingSlots> {
13
+ }
14
+ export {};
@@ -11,11 +11,10 @@ import { isBrowser } from "../../functions/is-browser.js";
11
11
  import { isEditing } from "../../functions/is-editing.js";
12
12
  import { isPreviewing } from "../../functions/is-previewing.js";
13
13
  import { components, createRegisterComponentMessage, } from "../../functions/register-component.js";
14
- import { track } from "../../functions/track.js";
14
+ import { _track } from "../../functions/track.js";
15
15
  import RenderBlocks from "../render-blocks.svelte";
16
16
  import RenderContentStyles from "./components/render-styles.svelte";
17
17
  import { registerInsertMenu, setupBrowserForEditing, } from "../../scripts/init-editing.js";
18
- import { markMutable } from "../../functions/mark-mutable.js";
19
18
  export let content;
20
19
  export let data;
21
20
  export let canTrack;
@@ -77,11 +76,14 @@ function evaluateJsCode() {
77
76
  }
78
77
  function onClick(_event) {
79
78
  if (useContent()) {
80
- track({
79
+ const variationId = useContent?.()?.testVariationId;
80
+ const contentId = useContent?.()?.id;
81
+ _track({
81
82
  type: "click",
82
83
  canTrack: canTrackToUse(),
83
- contentId: useContent?.()?.id,
84
- orgId: apiKey,
84
+ contentId,
85
+ apiKey: apiKey,
86
+ variationId: variationId !== contentId ? variationId : undefined,
85
87
  });
86
88
  }
87
89
  }
@@ -193,7 +195,6 @@ onMount(() => {
193
195
  if (isBrowser()) {
194
196
  if (isEditing()) {
195
197
  forceReRenderCount = forceReRenderCount + 1;
196
- // QWIK-REPLACE: _useMutableProps
197
198
  registerInsertMenu();
198
199
  setupBrowserForEditing();
199
200
  Object.values(allRegisteredComponents()).forEach((registeredComponent) => {
@@ -204,11 +205,14 @@ onMount(() => {
204
205
  window.addEventListener("builder:component:stateChangeListenerActivated", emitStateUpdate);
205
206
  }
206
207
  if (useContent()) {
207
- track({
208
+ const variationId = useContent?.()?.testVariationId;
209
+ const contentId = useContent?.()?.id;
210
+ _track({
208
211
  type: "impression",
209
212
  canTrack: canTrackToUse(),
210
- contentId: useContent?.()?.id,
211
- orgId: apiKey,
213
+ contentId,
214
+ apiKey: apiKey,
215
+ variationId: variationId !== contentId ? variationId : undefined,
212
216
  });
213
217
  }
214
218
  // override normal content in preview mode
@@ -269,7 +273,7 @@ onDestroy(() => {
269
273
  />
270
274
  {/if}
271
275
  <RenderBlocks
272
- blocks={markMutable(useContent?.()?.data?.blocks)}
276
+ blocks={useContent?.()?.data?.blocks}
273
277
  key={forceReRenderCount}
274
278
  />
275
279
  </div>
@@ -3,9 +3,9 @@
3
3
  <script>import { TARGET } from "../constants/target.js";
4
4
  export let styles;
5
5
  $: injectedStyleScript = () => {
6
- return `<${tagName()}>${styles}</${tagName()}>`;
6
+ return `<${tag()}>${styles}</${tag()}>`;
7
7
  };
8
- $: tagName = () => {
8
+ $: tag = () => {
9
9
  // NOTE: we have to obfusctate the name of the tag due to a limitation in the svelte-preprocessor plugin.
10
10
  // https://github.com/sveltejs/vite-plugin-svelte/issues/315#issuecomment-1109000027
11
11
  return "sty" + "le";
@@ -15,5 +15,5 @@ $: tagName = () => {
15
15
  {#if TARGET === "svelte"}
16
16
  {@html injectedStyleScript()}
17
17
  {:else}
18
- <svelte:element this={tagName()}>{styles}</svelte:element>
18
+ <svelte:element this={tag()}>{styles}</svelte:element>
19
19
  {/if}
@@ -1,2 +1,13 @@
1
1
  export declare type SizeName = 'large' | 'medium' | 'small';
2
- export declare const getMaxWidthQueryForSize: (size: SizeName) => string;
2
+ interface Size {
3
+ min: number;
4
+ default: number;
5
+ max: number;
6
+ }
7
+ export declare const getMaxWidthQueryForSize: (size: SizeName, sizeValues?: Record<SizeName, Size>) => string;
8
+ interface Breakpoints {
9
+ small?: number;
10
+ medium?: number;
11
+ }
12
+ export declare const getSizesForBreakpoints: ({ small, medium }: Breakpoints) => Record<SizeName, Size>;
13
+ export {};
@@ -1,3 +1,4 @@
1
+ import { fastClone } from '../functions/fast-clone';
1
2
  const SIZES = {
2
3
  small: {
3
4
  min: 320,
@@ -15,4 +16,29 @@ const SIZES = {
15
16
  max: 1200,
16
17
  },
17
18
  };
18
- export const getMaxWidthQueryForSize = (size) => `@media (max-width: ${SIZES[size].max}px)`;
19
+ export const getMaxWidthQueryForSize = (size, sizeValues = SIZES) => `@media (max-width: ${sizeValues[size].max}px)`;
20
+ export const getSizesForBreakpoints = ({ small, medium }) => {
21
+ const newSizes = fastClone(SIZES); // Note: this helps to get a deep clone of fields like small, medium etc
22
+ if (!small || !medium) {
23
+ return newSizes;
24
+ }
25
+ const smallMin = Math.floor(small / 2);
26
+ newSizes.small = {
27
+ max: small,
28
+ min: smallMin,
29
+ default: smallMin + 1,
30
+ };
31
+ const mediumMin = newSizes.small.max + 1;
32
+ newSizes.medium = {
33
+ max: medium,
34
+ min: mediumMin,
35
+ default: mediumMin + 1,
36
+ };
37
+ const largeMin = newSizes.medium.max + 1;
38
+ newSizes.large = {
39
+ max: 2000,
40
+ min: largeMin,
41
+ default: largeMin + 1,
42
+ };
43
+ return newSizes;
44
+ };
@@ -6,8 +6,11 @@ export async function getContent(options) {
6
6
  return (await getAllContent({ ...options, limit: 1 })).results[0] || null;
7
7
  }
8
8
  export const generateContentUrl = (options) => {
9
- const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, } = options;
10
- const url = new URL(`https://cdn.builder.io/api/v2/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}`);
9
+ const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, } = options;
10
+ if (!apiKey) {
11
+ throw new Error('Missing API key');
12
+ }
13
+ const url = new URL(`https://cdn.builder.io/api/v2/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}`);
11
14
  const queryOptions = {
12
15
  ...getBuilderSearchParamsFromWindow(),
13
16
  ...normalizeSearchParams(options.options || {}),
@@ -28,4 +28,8 @@ export interface GetContentOptions {
28
28
  * Defaults to `true`.
29
29
  */
30
30
  canTrack?: boolean;
31
+ /**
32
+ * Include references in the response. Defaults to `true`.
33
+ */
34
+ includeRefs?: boolean;
31
35
  }
@@ -1,3 +1,4 @@
1
+ import { serializeFn } from '../blocks/util.js';
1
2
  import { fastClone } from './fast-clone.js';
2
3
  /**
3
4
  * @deprecated. Use the `customComponents` prop in RenderContent instead to provide your custom components to the builder SDK.
@@ -16,19 +17,6 @@ export const createRegisterComponentMessage = ({ component: _, ...info }) => ({
16
17
  data: prepareComponentInfoToSend(info),
17
18
  });
18
19
  const serializeValue = (value) => typeof value === 'function' ? serializeFn(value) : fastClone(value);
19
- /**
20
- * Input attributes that are functions must be converted to strings before being serialized to JSON.
21
- */
22
- // eslint-disable-next-line @typescript-eslint/ban-types
23
- const serializeFn = (fnValue) => {
24
- const fnStr = fnValue.toString().trim();
25
- // we need to account for a few different fn syntaxes:
26
- // 1. `function name(args) => {code}`
27
- // 2. `name(args) => {code}`
28
- // 3. `(args) => {}`
29
- const appendFunction = !fnStr.startsWith('function') && !fnStr.startsWith('(');
30
- return `return (${appendFunction ? 'function ' : ''}${fnStr}).apply(this, arguments)`;
31
- };
32
20
  const prepareComponentInfoToSend = ({ inputs, ...info }) => ({
33
21
  ...fastClone(info),
34
22
  inputs: inputs?.map((input) => Object.entries(input).reduce((acc, [key, value]) => ({
@@ -2,20 +2,50 @@ import type { CanTrack } from '../types/can-track.js';
2
2
  interface Event {
3
3
  type: 'click' | 'impression';
4
4
  data: {
5
+ /**
6
+ * (Optional) The content's ID. Useful if this event pertains to a specific piece of content.
7
+ */
5
8
  contentId?: string;
9
+ /**
10
+ * This is the ID of the space that the content belongs to.
11
+ */
6
12
  ownerId: string;
13
+ /**
14
+ * Stringified JSON object containing any additional metadata you want to track.
15
+ */
7
16
  metadata?: string;
17
+ /**
18
+ * Session ID of the user. This is provided by the SDK by checking session storage.
19
+ */
8
20
  sessionId: string | undefined;
21
+ /**
22
+ * Visitor ID of the user. This is provided by the SDK by checking cookies.
23
+ */
9
24
  visitorId: string | undefined;
25
+ /**
26
+ * (Optional) If running an A/B test, the ID of the variation that the user is in.
27
+ */
28
+ variationId?: string;
10
29
  [index: string]: any;
11
30
  };
12
31
  }
13
- declare type EventProperties = {
14
- type: Event['type'];
15
- orgId: Event['data']['ownerId'];
16
- contentId: Event['data']['contentId'];
32
+ declare type EventProperties = Pick<Event, 'type'> & Pick<Event['data'], 'contentId' | 'variationId'> & {
33
+ /**
34
+ * Your organization's API key.
35
+ */
36
+ apiKey: Event['data']['ownerId'];
37
+ /**
38
+ * (Optional) metadata that you want to provide with your event.
39
+ */
40
+ metadata?: {
41
+ [index: string]: any;
42
+ };
43
+ /**
44
+ * (Optional) Any additional (non-metadata) properties to add to the event.
45
+ */
17
46
  [index: string]: any;
18
47
  };
19
48
  export declare type EventProps = EventProperties & CanTrack;
20
- export declare function track(eventProps: EventProps): Promise<void | Response>;
49
+ export declare function _track(eventProps: EventProps): Promise<void | Response>;
50
+ export declare const track: (args: EventProperties) => Promise<void | Response>;
21
51
  export {};
@@ -14,16 +14,16 @@ const getTrackingEventData = async ({ canTrack, }) => {
14
14
  visitorId,
15
15
  };
16
16
  };
17
- const createEvent = async ({ type: eventType, canTrack, orgId, contentId, ...properties }) => ({
17
+ const createEvent = async ({ type: eventType, canTrack, apiKey, metadata, ...properties }) => ({
18
18
  type: eventType,
19
19
  data: {
20
20
  ...properties,
21
+ metadata: JSON.stringify(metadata),
21
22
  ...(await getTrackingEventData({ canTrack })),
22
- ownerId: orgId,
23
- contentId,
23
+ ownerId: apiKey,
24
24
  },
25
25
  });
26
- export async function track(eventProps) {
26
+ export async function _track(eventProps) {
27
27
  if (!eventProps.canTrack) {
28
28
  return;
29
29
  }
@@ -46,3 +46,4 @@ export async function track(eventProps) {
46
46
  console.error('Failed to track: ', err);
47
47
  });
48
48
  }
49
+ export const track = (args) => _track({ ...args, canTrack: true });
@@ -1,4 +1,4 @@
1
- import './index-helpers/top-of-file.js';
1
+ export * from './index-helpers/top-of-file.js';
2
2
  import './scripts/init-editing.js';
3
3
  export * from './index-helpers/blocks-exports.js';
4
4
  export * from './functions/is-editing.js';
@@ -8,3 +8,6 @@ export * from './functions/register.js';
8
8
  export * from './functions/set-editor-settings.js';
9
9
  export * from './functions/get-content/index.js';
10
10
  export * from './functions/get-builder-search-params/index.js';
11
+ export { track } from './functions/track';
12
+ export type { RegisteredComponent } from './context/types';
13
+ export type { ComponentInfo } from './types/components';
package/package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import './index-helpers/top-of-file.js';
1
+ export * from './index-helpers/top-of-file.js';
2
2
  import './scripts/init-editing.js';
3
3
  export * from './index-helpers/blocks-exports.js';
4
4
  export * from './functions/is-editing.js';
@@ -8,3 +8,4 @@ export * from './functions/register.js';
8
8
  export * from './functions/set-editor-settings.js';
9
9
  export * from './functions/get-content/index.js';
10
10
  export * from './functions/get-builder-search-params/index.js';
11
+ export { track } from './functions/track';