@builder.io/sdk-svelte 0.1.2 → 0.1.3-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/package/--package.json +3 -3
  2. package/package/CHANGELOG.md +5 -0
  3. package/package/blocks/BaseText.svelte +1 -1
  4. package/package/blocks/button/button.svelte +1 -1
  5. package/package/blocks/columns/columns.svelte +3 -3
  6. package/package/blocks/custom-code/custom-code.svelte +1 -1
  7. package/package/blocks/embed/embed.svelte +2 -3
  8. package/package/blocks/form/form.svelte +1 -1
  9. package/package/blocks/fragment/fragment.svelte +1 -1
  10. package/package/blocks/image/image.svelte +1 -2
  11. package/package/blocks/img/img.svelte +1 -1
  12. package/package/blocks/input/input.svelte +1 -1
  13. package/package/blocks/raw-text/raw-text.svelte +1 -1
  14. package/package/blocks/section/section.svelte +1 -1
  15. package/package/blocks/select/select.svelte +1 -1
  16. package/package/blocks/submit-button/submit-button.svelte +1 -1
  17. package/package/blocks/symbol/symbol.svelte +4 -2
  18. package/package/blocks/text/text.svelte +1 -1
  19. package/package/blocks/textarea/textarea.svelte +1 -1
  20. package/package/blocks/video/video.svelte +1 -1
  21. package/package/components/render-block/block-styles.svelte +1 -1
  22. package/package/components/render-block/render-block.helpers.d.ts +11 -0
  23. package/package/components/render-block/render-block.helpers.js +58 -0
  24. package/package/components/render-block/render-block.svelte +33 -109
  25. package/package/components/render-block/render-component.svelte +1 -1
  26. package/package/components/render-block/render-repeated-block.svelte +7 -19
  27. package/package/components/render-blocks.svelte +1 -1
  28. package/package/components/render-content/builder-editing.svelte +1 -1
  29. package/package/components/render-content/components/render-styles.svelte +3 -3
  30. package/package/components/render-content/render-content.svelte +52 -53
  31. package/package/components/render-inlined-styles.svelte +1 -1
  32. package/package/functions/track/helpers.d.ts +5 -0
  33. package/package/functions/track/helpers.js +56 -0
  34. package/package/functions/{track.d.ts → track/index.d.ts} +5 -10
  35. package/package/functions/{track.js → track/index.js} +11 -6
  36. package/package/index.d.ts +1 -1
  37. package/package/index.js +1 -1
  38. package/package.json +1 -1
  39. package/src/blocks/BaseText.svelte +2 -2
  40. package/src/blocks/button/button.svelte +1 -6
  41. package/src/blocks/columns/columns.svelte +3 -3
  42. package/src/blocks/custom-code/custom-code.svelte +1 -1
  43. package/src/blocks/embed/embed.svelte +1 -3
  44. package/src/blocks/form/form.svelte +2 -7
  45. package/src/blocks/fragment/fragment.svelte +1 -1
  46. package/src/blocks/image/image.svelte +1 -2
  47. package/src/blocks/img/img.svelte +1 -6
  48. package/src/blocks/input/input.svelte +1 -6
  49. package/src/blocks/raw-text/raw-text.svelte +1 -1
  50. package/src/blocks/section/section.svelte +1 -6
  51. package/src/blocks/select/select.svelte +1 -6
  52. package/src/blocks/submit-button/submit-button.svelte +1 -6
  53. package/src/blocks/symbol/symbol.svelte +5 -8
  54. package/src/blocks/text/text.svelte +1 -1
  55. package/src/blocks/textarea/textarea.svelte +1 -6
  56. package/src/blocks/video/video.svelte +1 -6
  57. package/src/components/render-block/block-styles.svelte +1 -1
  58. package/src/components/render-block/render-block.helpers.ts +85 -0
  59. package/src/components/render-block/render-block.svelte +41 -118
  60. package/src/components/render-block/render-component.svelte +1 -1
  61. package/src/components/render-block/render-repeated-block.svelte +8 -20
  62. package/src/components/render-blocks.svelte +2 -2
  63. package/src/components/render-content/builder-editing.svelte +1 -1
  64. package/src/components/render-content/components/render-styles.svelte +5 -3
  65. package/src/components/render-content/render-content.svelte +58 -64
  66. package/src/components/render-inlined-styles.svelte +1 -1
  67. package/src/functions/track/helpers.ts +67 -0
  68. package/src/functions/{track.ts → track/index.ts} +16 -17
  69. package/src/index.ts +1 -1
  70. package/package/components/render-block/render-component-with-context.svelte +0 -32
  71. package/package/components/render-block/render-component-with-context.svelte.d.ts +0 -19
  72. package/src/components/render-block/render-component-with-context.svelte +0 -38
@@ -11,7 +11,7 @@
11
11
  BuilderContent,
12
12
  } from "../../types/builder-content.js";
13
13
 
14
- import type { Dictionary, Nullable } from "../../types/typescript.js";
14
+ import type { Nullable } from "../../types/typescript.js";
15
15
 
16
16
  export type RenderContentProps = {
17
17
  content?: Nullable<BuilderContent>;
@@ -41,13 +41,7 @@
41
41
  </script>
42
42
 
43
43
  <script lang="ts">
44
- import {
45
- afterUpdate,
46
- getContext,
47
- onDestroy,
48
- onMount,
49
- setContext,
50
- } from "svelte";
44
+ import { onDestroy, onMount, setContext } from "svelte";
51
45
 
52
46
  import { getDefaultRegisteredComponents } from "../../constants/builder-registered-components.js";
53
47
  import { TARGET } from "../../constants/target.js";
@@ -61,10 +55,10 @@
61
55
  components,
62
56
  createRegisterComponentMessage,
63
57
  } from "../../functions/register-component.js";
64
- import { _track } from "../../functions/track.js";
58
+ import { _track } from "../../functions/track/index.js";
65
59
  import RenderBlocks from "../render-blocks.svelte";
66
60
  import RenderContentStyles from "./components/render-styles.svelte";
67
- import BuilderContext from "../../context/builder.context.js";
61
+ import builderContext from "../../context/builder.context.js";
68
62
  import {
69
63
  registerInsertMenu,
70
64
  setupBrowserForEditing,
@@ -81,7 +75,7 @@
81
75
  export let apiKey: RenderContentProps["apiKey"];
82
76
  export let includeRefs: RenderContentProps["includeRefs"];
83
77
 
84
- setContext(BuilderContext.key, {
78
+ setContext(builderContext.key, {
85
79
  get content() {
86
80
  return useContent();
87
81
  },
@@ -89,13 +83,13 @@
89
83
  return contentState();
90
84
  },
91
85
  get context() {
92
- return contextContext();
86
+ return contextContext;
93
87
  },
94
88
  get apiKey() {
95
89
  return apiKey;
96
90
  },
97
91
  get registeredComponents() {
98
- return allRegisteredComponents();
92
+ return allRegisteredComponents;
99
93
  },
100
94
  });
101
95
 
@@ -141,7 +135,7 @@
141
135
  if (jsCode) {
142
136
  evaluate({
143
137
  code: jsCode,
144
- context: contextContext(),
138
+ context: contextContext,
145
139
  state: contentState(),
146
140
  });
147
141
  }
@@ -152,7 +146,7 @@
152
146
  const contentId = useContent?.()?.id;
153
147
  _track({
154
148
  type: "click",
155
- canTrack: canTrackToUse(),
149
+ canTrack: canTrackToUse,
156
150
  contentId,
157
151
  apiKey: apiKey,
158
152
  variationId: variationId !== contentId ? variationId : undefined,
@@ -163,7 +157,7 @@
163
157
  return expression.replace(/{{([^}]+)}}/g, (_match, group) =>
164
158
  evaluate({
165
159
  code: group,
166
- context: contextContext(),
160
+ context: contextContext,
167
161
  state: contentState(),
168
162
  })
169
163
  );
@@ -185,7 +179,7 @@
185
179
  function runHttpRequests() {
186
180
  const requests = useContent?.()?.data?.httpRequests ?? {};
187
181
  Object.entries(requests).forEach(([key, url]) => {
188
- if (url && (!httpReqsData()[key] || isEditing())) {
182
+ if (url && (!httpReqsData[key] || isEditing())) {
189
183
  const evaluatedUrl = evalExpression(url);
190
184
  handleRequest({
191
185
  url: evaluatedUrl,
@@ -212,7 +206,7 @@
212
206
  if (!content && !overrideContent) {
213
207
  return undefined;
214
208
  }
215
- const mergedContent = {
209
+ return {
216
210
  ...content,
217
211
  ...overrideContent,
218
212
  data: {
@@ -229,10 +223,6 @@
229
223
  content?.meta?.breakpoints,
230
224
  },
231
225
  };
232
- return mergedContent;
233
- };
234
- $: canTrackToUse = () => {
235
- return checkIsDefined(canTrack) ? canTrack : true;
236
226
  };
237
227
  $: contentState = () => {
238
228
  return {
@@ -246,32 +236,6 @@
246
236
  ...overrideState,
247
237
  };
248
238
  };
249
- $: contextContext = () => {
250
- return context || {};
251
- };
252
- $: allRegisteredComponents = () => {
253
- const allComponentsArray = [
254
- ...getDefaultRegisteredComponents(),
255
- // While this `components` object is deprecated, we must maintain support for it.
256
- // Since users are able to override our default components, we need to make sure that we do not break such
257
- // existing usage.
258
- // This is why we spread `components` after the default Builder.io components, but before the `customComponents`,
259
- // which is the new standard way of providing custom components, and must therefore take precedence.
260
- ...components,
261
- ...(customComponents || []),
262
- ];
263
- const allComponents = allComponentsArray.reduce(
264
- (acc, curr) => ({
265
- ...acc,
266
- [curr.name]: curr,
267
- }),
268
- {}
269
- );
270
- return allComponents;
271
- };
272
- $: httpReqsData = () => {
273
- return {};
274
- };
275
239
  $: shouldRenderContentStyles = () => {
276
240
  return Boolean(
277
241
  (useContent?.()?.data?.cssCode ||
@@ -286,7 +250,26 @@
286
250
  let overrideContent = null;
287
251
  let update = 0;
288
252
  let useBreakpoints = null;
253
+ let canTrackToUse = checkIsDefined(canTrack) ? canTrack : true;
289
254
  let overrideState = {};
255
+ let contextContext = context || {};
256
+ let allRegisteredComponents = [
257
+ ...getDefaultRegisteredComponents(),
258
+ // While this `components` object is deprecated, we must maintain support for it.
259
+ // Since users are able to override our default components, we need to make sure that we do not break such
260
+ // existing usage.
261
+ // This is why we spread `components` after the default Builder.io components, but before the `props.customComponents`,
262
+ // which is the new standard way of providing custom components, and must therefore take precedence.
263
+ ...components,
264
+ ...(customComponents || []),
265
+ ].reduce(
266
+ (acc, curr) => ({
267
+ ...acc,
268
+ [curr.name]: curr,
269
+ }),
270
+ {}
271
+ );
272
+ let httpReqsData = {};
290
273
 
291
274
  onMount(() => {
292
275
  if (!apiKey) {
@@ -310,7 +293,7 @@
310
293
  }
311
294
  : {}),
312
295
  });
313
- Object.values(allRegisteredComponents()).forEach(
296
+ Object.values(allRegisteredComponents).forEach(
314
297
  (registeredComponent) => {
315
298
  const message = createRegisterComponentMessage(registeredComponent);
316
299
  window.parent?.postMessage(message, "*");
@@ -327,7 +310,7 @@
327
310
  const contentId = useContent?.()?.id;
328
311
  _track({
329
312
  type: "impression",
330
- canTrack: canTrackToUse(),
313
+ canTrack: canTrackToUse,
331
314
  contentId,
332
315
  apiKey: apiKey,
333
316
  variationId: variationId !== contentId ? variationId : undefined,
@@ -337,19 +320,30 @@
337
320
  // override normal content in preview mode
338
321
  if (isPreviewing()) {
339
322
  const searchParams = new URL(location.href).searchParams;
340
- if (model && searchParams.get("builder.preview") === model) {
341
- const previewApiKey =
342
- searchParams.get("apiKey") || searchParams.get("builder.space");
343
- if (previewApiKey) {
344
- getContent({
345
- model: model,
346
- apiKey: previewApiKey,
347
- }).then((content) => {
348
- if (content) {
349
- overrideContent = content;
350
- }
351
- });
352
- }
323
+ const searchParamPreview = searchParams.get("builder.preview");
324
+ const previewApiKey =
325
+ searchParams.get("apiKey") || searchParams.get("builder.space");
326
+
327
+ /**
328
+ * Make sure that:
329
+ * - the preview model name is the same as the one we're rendering, since there can be multiple models rendered
330
+ * at the same time, e.g. header/page/footer.
331
+ * - the API key is the same, since we don't want to preview content from other organizations.
332
+ *
333
+ * TO-DO: should we check that the preview item ID is the same as the initial one being rendered? Or would
334
+ * this break scenarios where the item is not published yet?
335
+ *
336
+ * TO-DO: should we only update the state when there is a change?
337
+ **/
338
+ if (searchParamPreview === model && previewApiKey === apiKey) {
339
+ getContent({
340
+ model: model,
341
+ apiKey: apiKey,
342
+ }).then((content) => {
343
+ if (content) {
344
+ overrideContent = content;
345
+ }
346
+ });
353
347
  }
354
348
  }
355
349
  evaluateJsCode();
@@ -402,4 +396,4 @@
402
396
  key={forceReRenderCount}
403
397
  />
404
398
  </div>
405
- {/if}
399
+ {/if}
@@ -23,4 +23,4 @@
23
23
  {@html injectedStyleScript()}
24
24
  {:else}
25
25
  <svelte:element this={tag()}>{styles}</svelte:element>
26
- {/if}
26
+ {/if}
@@ -0,0 +1,67 @@
1
+ import { TARGET } from '../../constants/target';
2
+ import type { Nullable } from '../../helpers/nullable';
3
+ import { isBrowser } from '../is-browser';
4
+
5
+ const getLocation = (): Nullable<URL> => {
6
+ if (TARGET === 'reactNative') {
7
+ return null;
8
+ } else if (isBrowser()) {
9
+ const parsedLocation = new URL(location.href);
10
+
11
+ // IE11 bug with parsed path being empty string
12
+ // causes issues with our user targeting
13
+ if (parsedLocation.pathname === '') {
14
+ parsedLocation.pathname = '/';
15
+ }
16
+
17
+ return parsedLocation;
18
+ } else {
19
+ console.warn('Cannot get location for tracking in non-browser environment');
20
+ return null;
21
+ }
22
+ };
23
+
24
+ const getUserAgent = () =>
25
+ (typeof navigator === 'object' && navigator.userAgent) || '';
26
+
27
+ export const getUserAttributes = () => {
28
+ const userAgent = getUserAgent();
29
+
30
+ const isMobile = {
31
+ Android() {
32
+ return userAgent.match(/Android/i);
33
+ },
34
+ BlackBerry() {
35
+ return userAgent.match(/BlackBerry/i);
36
+ },
37
+ iOS() {
38
+ return userAgent.match(/iPhone|iPod/i);
39
+ },
40
+ Opera() {
41
+ return userAgent.match(/Opera Mini/i);
42
+ },
43
+ Windows() {
44
+ return userAgent.match(/IEMobile/i) || userAgent.match(/WPDesktop/i);
45
+ },
46
+ any() {
47
+ return (
48
+ isMobile.Android() ||
49
+ isMobile.BlackBerry() ||
50
+ isMobile.iOS() ||
51
+ isMobile.Opera() ||
52
+ isMobile.Windows() ||
53
+ TARGET === 'reactNative'
54
+ );
55
+ },
56
+ };
57
+
58
+ const isTablet = userAgent.match(/Tablet|iPad/i);
59
+
60
+ const url = getLocation();
61
+
62
+ return {
63
+ urlPath: url?.pathname,
64
+ host: url?.host || url?.hostname,
65
+ device: isTablet ? 'tablet' : isMobile.any() ? 'mobile' : 'desktop',
66
+ };
67
+ };
@@ -1,9 +1,11 @@
1
- import { TARGET } from '../constants/target.js';
2
- import { getSessionId } from '../helpers/sessionId.js';
3
- import { getVisitorId } from '../helpers/visitorId.js';
4
- import type { CanTrack } from '../types/can-track.js';
5
- import { isBrowser } from './is-browser.js';
6
- import { isEditing } from './is-editing.js';
1
+ import { TARGET } from '../../constants/target.js';
2
+ import { getSessionId } from '../../helpers/sessionId.js';
3
+ import { getVisitorId } from '../../helpers/visitorId.js';
4
+ import type { CanTrack } from '../../types/can-track.js';
5
+ import type { Dictionary } from '../../types/typescript.js';
6
+ import { isBrowser } from '../is-browser.js';
7
+ import { isEditing } from '../is-editing.js';
8
+ import { getUserAttributes } from './helpers.js';
7
9
 
8
10
  interface Event {
9
11
  /**
@@ -22,9 +24,9 @@ interface Event {
22
24
  */
23
25
  ownerId: string;
24
26
  /**
25
- * Stringified JSON object containing any additional metadata you want to track.
27
+ * (Optional) metadata that you want to provide with your event.
26
28
  */
27
- metadata?: string;
29
+ metadata?: Dictionary<any>;
28
30
  /**
29
31
  * Session ID of the user. This is provided by the SDK by checking session storage.
30
32
  */
@@ -63,18 +65,11 @@ const getTrackingEventData = async ({
63
65
  };
64
66
 
65
67
  type EventProperties = Pick<Event, 'type'> &
66
- Pick<Event['data'], 'contentId' | 'variationId'> & {
68
+ Pick<Event['data'], 'contentId' | 'variationId' | 'metadata'> & {
67
69
  /**
68
70
  * Your organization's API key.
69
71
  */
70
72
  apiKey: Event['data']['ownerId'];
71
- /**
72
- * (Optional) metadata that you want to provide with your event.
73
- */
74
- metadata?: {
75
- [index: string]: any;
76
- };
77
-
78
73
  /**
79
74
  * (Optional) Any additional (non-metadata) properties to add to the event.
80
75
  */
@@ -93,8 +88,12 @@ const createEvent = async ({
93
88
  type: eventType,
94
89
  data: {
95
90
  ...properties,
96
- metadata: JSON.stringify(metadata),
91
+ metadata: {
92
+ url: location.href,
93
+ ...metadata,
94
+ },
97
95
  ...(await getTrackingEventData({ canTrack })),
96
+ userAttributes: getUserAttributes(),
98
97
  ownerId: apiKey,
99
98
  },
100
99
  });
package/src/index.ts CHANGED
@@ -10,6 +10,6 @@ export * from './functions/register.js';
10
10
  export * from './functions/set-editor-settings.js';
11
11
  export * from './functions/get-content/index.js';
12
12
  export * from './functions/get-builder-search-params/index.js';
13
- export { track } from './functions/track';
13
+ export { track } from './functions/track/index.js';
14
14
  export type { RegisteredComponent } from './context/types';
15
15
  export type { ComponentInfo } from './types/components';
@@ -1,32 +0,0 @@
1
- <script context="module"></script>
2
-
3
- <script>import { setContext } from "svelte";
4
- import BuilderContext from "../../context/builder.context.js";
5
- import RenderComponent from "./render-component.svelte";
6
- export let componentRef;
7
- export let componentOptions;
8
- export let blockChildren;
9
- export let context;
10
- setContext(BuilderContext.key, {
11
- get content() {
12
- return context.content;
13
- },
14
- get state() {
15
- return context.state;
16
- },
17
- get context() {
18
- return context.context;
19
- },
20
- get apiKey() {
21
- return context.apiKey;
22
- },
23
- get registeredComponents() {
24
- return context.registeredComponents;
25
- },
26
- get inheritedStyles() {
27
- return context.inheritedStyles;
28
- },
29
- });
30
- </script>
31
-
32
- <RenderComponent {componentRef} {componentOptions} {blockChildren} {context} />
@@ -1,19 +0,0 @@
1
- import { SvelteComponentTyped } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- componentRef: RenderComponentProps;
5
- componentOptions: RenderComponentProps;
6
- blockChildren: RenderComponentProps;
7
- context: RenderComponentProps;
8
- };
9
- events: {
10
- [evt: string]: CustomEvent<any>;
11
- };
12
- slots: {};
13
- };
14
- export declare type RenderComponentWithContextProps = typeof __propDef.props;
15
- export declare type RenderComponentWithContextEvents = typeof __propDef.events;
16
- export declare type RenderComponentWithContextSlots = typeof __propDef.slots;
17
- export default class RenderComponentWithContext extends SvelteComponentTyped<RenderComponentWithContextProps, RenderComponentWithContextEvents, RenderComponentWithContextSlots> {
18
- }
19
- export {};
@@ -1,38 +0,0 @@
1
- <script context="module" lang="ts">
2
- import type { RenderComponentProps } from "./render-component";
3
- </script>
4
-
5
- <script lang="ts">
6
- import { getContext, setContext } from "svelte";
7
-
8
- import BuilderContext from "../../context/builder.context.js";
9
- import RenderComponent from "./render-component.svelte";
10
-
11
- export let componentRef: RenderComponentProps["componentRef"];
12
- export let componentOptions: RenderComponentProps["componentOptions"];
13
- export let blockChildren: RenderComponentProps["blockChildren"];
14
- export let context: RenderComponentProps["context"];
15
-
16
- setContext(BuilderContext.key, {
17
- get content() {
18
- return context.content;
19
- },
20
- get state() {
21
- return context.state;
22
- },
23
- get context() {
24
- return context.context;
25
- },
26
- get apiKey() {
27
- return context.apiKey;
28
- },
29
- get registeredComponents() {
30
- return context.registeredComponents;
31
- },
32
- get inheritedStyles() {
33
- return context.inheritedStyles;
34
- },
35
- });
36
- </script>
37
-
38
- <RenderComponent {componentRef} {componentOptions} {blockChildren} {context} />