@builder.io/sdk-solid 5.0.1 → 5.1.1

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.
@@ -208,1215 +208,1241 @@ var getUserAttributes = () => {
208
208
  };
209
209
  };
210
210
 
211
- // src/functions/evaluate/helpers.ts
212
- var getFunctionArguments = ({
213
- builder,
214
- context,
215
- event,
216
- state
217
- }) => {
218
- return Object.entries({
219
- state,
220
- Builder: builder,
221
- // legacy
222
- builder,
223
- context,
224
- event
225
- });
226
- };
227
- var getBuilderGlobals = () => ({
228
- isEditing: isEditing(),
229
- isBrowser: isBrowser(),
230
- isServer: !isBrowser(),
231
- getUserAttributes: () => getUserAttributes()
232
- });
233
- var parseCode = (code, {
234
- isExpression = true
235
- }) => {
236
- const useReturn = (
237
- // we disable this for cases where we definitely don't want a return
238
- isExpression && !(code.includes(";") || code.includes(" return ") || code.trim().startsWith("return "))
239
- );
240
- const useCode = useReturn ? `return (${code});` : code;
241
- return useCode;
242
- };
243
- function flattenState({
244
- rootState,
245
- localState,
246
- rootSetState
247
- }) {
248
- return new Proxy(rootState, {
249
- get: (target, prop) => {
250
- if (localState && prop in localState) {
251
- return localState[prop];
252
- }
253
- const val = target[prop];
254
- if (typeof val === "object" && val !== null) {
255
- return flattenState({
256
- rootState: val,
257
- localState: void 0,
258
- rootSetState: rootSetState ? (subState) => {
259
- target[prop] = subState;
260
- rootSetState(target);
261
- } : void 0
262
- });
263
- }
264
- return val;
265
- },
266
- set: (target, prop, value) => {
267
- if (localState && prop in localState) {
268
- throw new Error("Writing to local state is not allowed as it is read-only.");
269
- }
270
- target[prop] = value;
271
- rootSetState?.(target);
272
- return true;
273
- }
274
- });
275
- }
211
+ // src/constants/sdk-version.ts
212
+ var SDK_VERSION = "5.1.1";
276
213
 
277
- // src/functions/evaluate/browser-runtime/browser.ts
278
- var runInBrowser = ({
279
- code,
280
- builder,
281
- context,
282
- event,
283
- localState,
284
- rootSetState,
285
- rootState
286
- }) => {
287
- const functionArgs = getFunctionArguments({
288
- builder,
289
- context,
290
- event,
291
- state: flattenState({
292
- rootState,
293
- localState,
294
- rootSetState
295
- })
296
- });
297
- return new Function(...functionArgs.map(([name]) => name), code)(...functionArgs.map(([, value]) => value));
298
- };
214
+ // src/helpers/sdk-headers.ts
215
+ var getSdkHeaders = () => ({
216
+ "X-Builder-SDK": TARGET,
217
+ "X-Builder-SDK-GEN": "2",
218
+ "X-Builder-SDK-Version": SDK_VERSION
219
+ });
299
220
 
300
221
  // src/helpers/nullable.ts
301
222
  var checkIsDefined = (maybeT) => maybeT !== null && maybeT !== void 0;
302
223
 
303
- // src/functions/is-node-runtime.ts
304
- function isNodeRuntime() {
305
- return typeof process !== "undefined" && checkIsDefined(process?.versions?.node);
306
- }
224
+ // src/helpers/url.ts
225
+ var getTopLevelDomain = (host) => {
226
+ if (host === "localhost" || host === "127.0.0.1") {
227
+ return host;
228
+ }
229
+ const parts = host.split(".");
230
+ if (parts.length > 2) {
231
+ return parts.slice(1).join(".");
232
+ }
233
+ return host;
234
+ };
307
235
 
308
- // src/functions/evaluate/should-force-browser-runtime-in-node.ts
309
- var shouldForceBrowserRuntimeInNode = ({
310
- shouldLogWarning
236
+ // src/helpers/cookie.ts
237
+ var getCookieSync = ({
238
+ name,
239
+ canTrack
311
240
  }) => {
312
- if (!isNodeRuntime())
313
- return false;
314
- const isArm64 = process.arch === "arm64";
315
- const isNode20 = process.version.startsWith("v20");
316
- const hasNoNodeSnapshotNodeOption = process.env.NODE_OPTIONS?.includes("--no-node-snapshot");
317
- if (isArm64 && isNode20 && !hasNoNodeSnapshotNodeOption) {
318
- if (shouldLogWarning) {
319
- logger.log(`Skipping usage of \`isolated-vm\` to avoid crashes in Node v20 on an arm64 machine.
320
- If you would like to use the \`isolated-vm\` package on this machine, please provide the \`NODE_OPTIONS=--no-node-snapshot\` config to your Node process.
321
- See https://github.com/BuilderIO/builder/blob/main/packages/sdks/README.md#node-v20--m1-macs-apple-silicon-support for more information.
322
- `);
241
+ try {
242
+ if (!canTrack) {
243
+ return void 0;
323
244
  }
324
- return true;
245
+ return document.cookie.split("; ").find((row) => row.startsWith(`${name}=`))?.split("=")[1];
246
+ } catch (err) {
247
+ logger.warn("[COOKIE] GET error: ", err?.message || err);
248
+ return void 0;
325
249
  }
326
- return false;
327
250
  };
328
-
329
- // src/functions/evaluate/choose-eval.ts
330
- var chooseBrowserOrServerEval = (args) => isBrowser() || shouldForceBrowserRuntimeInNode({
331
- shouldLogWarning: true
332
- }) ? runInBrowser(args) : runInBrowser(args);
333
-
334
- // src/functions/evaluate/evaluate.ts
335
- var STATE_GETTER_REGEX = /^(return )?(\s*)?state(?<getPath>(\.\w+)+)(\s*);?$/;
336
- var VIRTUAL_INDEX_REGEX = /(\s)*var(\s)+_virtual_index(\s)*=(\s)*state(?<getPath>(\.\w+)+)(\s*);?(\s)*return(\s)*_virtual_index(\s)*/;
337
- var getSimpleExpressionGetPath = (code) => {
338
- return STATE_GETTER_REGEX.exec(code.trim())?.groups?.getPath?.slice(1) || VIRTUAL_INDEX_REGEX.exec(code.trim())?.groups?.getPath?.slice(1);
251
+ var getCookie = async (args) => getCookieSync(args);
252
+ var stringifyCookie = (cookie) => cookie.map(([key, value]) => value ? `${key}=${value}` : key).filter(checkIsDefined).join("; ");
253
+ var SECURE_CONFIG = [["secure", ""], ["SameSite", "None"]];
254
+ var createCookieString = ({
255
+ name,
256
+ value,
257
+ expires
258
+ }) => {
259
+ const secure = isBrowser() ? location.protocol === "https:" : true;
260
+ const secureObj = secure ? SECURE_CONFIG : [[]];
261
+ const expiresObj = expires ? [["expires", expires.toUTCString()]] : [[]];
262
+ const cookieValue = [[name, value], ...expiresObj, ["path", "/"], ["domain", getTopLevelDomain(window.location.hostname)], ...secureObj];
263
+ const cookie = stringifyCookie(cookieValue);
264
+ return cookie;
339
265
  };
340
- function evaluate({
341
- code,
342
- context,
343
- localState,
344
- rootState,
345
- rootSetState,
346
- event,
347
- isExpression = true
348
- }) {
349
- if (code.trim() === "") {
350
- return void 0;
351
- }
352
- const getPath = getSimpleExpressionGetPath(code.trim());
353
- if (getPath) {
354
- return get({
355
- ...rootState,
356
- ...localState
357
- }, getPath);
358
- }
359
- const args = {
360
- code: parseCode(code, {
361
- isExpression
362
- }),
363
- builder: getBuilderGlobals(),
364
- context,
365
- event,
366
- rootSetState,
367
- rootState,
368
- localState
369
- };
266
+ var setCookie = async ({
267
+ name,
268
+ value,
269
+ expires,
270
+ canTrack
271
+ }) => {
370
272
  try {
371
- const newEval = chooseBrowserOrServerEval(args);
372
- return newEval;
373
- } catch (e) {
374
- logger.error("Failed code evaluation: " + e.message, {
375
- code
273
+ if (!canTrack) {
274
+ return;
275
+ }
276
+ const cookie = createCookieString({
277
+ name,
278
+ value,
279
+ expires
376
280
  });
377
- return void 0;
378
- }
379
- }
380
-
381
- // src/functions/get-block-component-options.ts
382
- function getBlockComponentOptions(block, context) {
383
- return {
384
- ...block.component?.options,
385
- ...block.options,
386
- ...evaluateTextComponentTextOption(block, context)
387
- };
388
- }
389
- var evaluateTextComponentTextOption = (block, context) => {
390
- if (block.component?.name === "Text" && block.component.options?.text && typeof block.component.options.text === "string") {
391
- return {
392
- ...block.component.options,
393
- text: block.component.options.text.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
394
- code: group,
395
- context,
396
- localState: context.localState,
397
- rootState: context.rootState,
398
- rootSetState: context.rootSetState
399
- }))
400
- };
281
+ document.cookie = cookie;
282
+ } catch (err) {
283
+ logger.warn("[COOKIE] SET error: ", err?.message || err);
401
284
  }
402
285
  };
403
286
 
404
- // src/helpers/omit.ts
405
- function omit(obj, ...values) {
406
- const newObject = Object.assign({}, obj);
407
- for (const key of values) {
408
- delete newObject[key];
409
- }
410
- return newObject;
287
+ // src/helpers/uuid.ts
288
+ function uuidv4() {
289
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
290
+ const r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
291
+ return v.toString(16);
292
+ });
293
+ }
294
+ function uuid() {
295
+ return uuidv4().replace(/-/g, "");
411
296
  }
412
297
 
413
- // src/functions/traverse.ts
414
- function traverse(obj, callback, parent2 = null, key = null, visited = /* @__PURE__ */ new WeakSet()) {
415
- if (obj == null || typeof obj !== "object") {
416
- callback(obj, (newValue) => {
417
- if (parent2 !== null && key !== null) {
418
- parent2[key] = newValue;
419
- }
420
- });
421
- return;
422
- }
423
- if (visited.has(obj)) {
424
- return;
298
+ // src/helpers/sessionId.ts
299
+ var SESSION_LOCAL_STORAGE_KEY = "builderSessionId";
300
+ var getSessionId = async ({
301
+ canTrack
302
+ }) => {
303
+ if (!canTrack) {
304
+ return void 0;
425
305
  }
426
- visited.add(obj);
427
- if (Array.isArray(obj)) {
428
- obj.forEach((item, index) => {
429
- const update = (newValue) => {
430
- obj[index] = newValue;
431
- };
432
- callback(item, update);
433
- traverse(item, callback, obj, index, visited);
434
- });
306
+ const sessionId = await getCookie({
307
+ name: SESSION_LOCAL_STORAGE_KEY,
308
+ canTrack
309
+ });
310
+ if (checkIsDefined(sessionId)) {
311
+ return sessionId;
435
312
  } else {
436
- Object.entries(obj).forEach(([key2, value]) => {
437
- const update = (newValue) => {
438
- obj[key2] = newValue;
439
- };
440
- callback(value, update);
441
- traverse(value, callback, obj, key2, visited);
313
+ const newSessionId = createSessionId();
314
+ setSessionId({
315
+ id: newSessionId,
316
+ canTrack
442
317
  });
318
+ return newSessionId;
443
319
  }
444
- }
320
+ };
321
+ var createSessionId = () => uuid();
322
+ var setSessionId = ({
323
+ id,
324
+ canTrack
325
+ }) => setCookie({
326
+ name: SESSION_LOCAL_STORAGE_KEY,
327
+ value: id,
328
+ canTrack
329
+ });
445
330
 
446
- // src/functions/extract-localized-values.ts
447
- function isLocalizedField(value) {
448
- return value && typeof value === "object" && value["@type"] === "@builder.io/core:LocalizedValue";
449
- }
450
- function containsLocalizedValues(data) {
451
- if (!data || !Object.getOwnPropertyNames(data).length) {
452
- return false;
453
- }
454
- let hasLocalizedValues = false;
455
- traverse(data, (value) => {
456
- if (isLocalizedField(value)) {
457
- hasLocalizedValues = true;
458
- return;
331
+ // src/helpers/localStorage.ts
332
+ var getLocalStorage = () => isBrowser() && typeof localStorage !== "undefined" ? localStorage : void 0;
333
+ var getLocalStorageItem = ({
334
+ key,
335
+ canTrack
336
+ }) => {
337
+ try {
338
+ if (canTrack) {
339
+ return getLocalStorage()?.getItem(key);
459
340
  }
460
- });
461
- return hasLocalizedValues;
462
- }
463
- function extractLocalizedValues(data, locale) {
464
- if (!data || !Object.getOwnPropertyNames(data).length) {
465
- return {};
341
+ return void 0;
342
+ } catch (err) {
343
+ console.debug("[LocalStorage] GET error: ", err);
344
+ return void 0;
466
345
  }
467
- traverse(data, (value, update) => {
468
- if (isLocalizedField(value)) {
469
- update(value[locale] ?? void 0);
470
- }
471
- });
472
- return data;
473
- }
474
- function resolveLocalizedValues(block, locale) {
475
- if (block.component?.options && containsLocalizedValues(block.component?.options)) {
476
- if (!locale) {
477
- console.warn("[Builder.io] In order to use localized fields in Builder, you must pass a locale prop to the BuilderComponent or to options object while fetching the content to resolve localized fields. Learn more: https://www.builder.io/c/docs/localization-inline#targeting-and-inline-localization");
346
+ };
347
+ var setLocalStorageItem = ({
348
+ key,
349
+ canTrack,
350
+ value
351
+ }) => {
352
+ try {
353
+ if (canTrack) {
354
+ getLocalStorage()?.setItem(key, value);
478
355
  }
479
- block.component.options = extractLocalizedValues(block.component.options, locale ?? "Default");
480
- }
481
- return block;
482
- }
483
-
484
- // src/functions/fast-clone.ts
485
- var fastClone = (obj) => JSON.parse(JSON.stringify(obj));
486
-
487
- // src/functions/set.ts
488
- var set = (obj, _path, value) => {
489
- if (Object(obj) !== obj) {
490
- return obj;
356
+ } catch (err) {
357
+ console.debug("[LocalStorage] SET error: ", err);
491
358
  }
492
- const path = Array.isArray(_path) ? _path : _path.toString().match(/[^.[\]]+/g);
493
- path.slice(0, -1).reduce((a, c, i) => Object(a[c]) === a[c] ? a[c] : a[c] = Math.abs(Number(path[i + 1])) >> 0 === +path[i + 1] ? [] : {}, obj)[path[path.length - 1]] = value;
494
- return obj;
495
359
  };
496
360
 
497
- // src/functions/transform-block.ts
498
- function transformBlock(block) {
499
- return block;
500
- }
501
-
502
- // src/functions/get-processed-block.ts
503
- function deepCloneWithConditions(obj) {
504
- if (obj === null || typeof obj !== "object") {
505
- return obj;
506
- }
507
- if (Array.isArray(obj)) {
508
- return obj.map((item) => deepCloneWithConditions(item));
361
+ // src/helpers/visitorId.ts
362
+ var VISITOR_LOCAL_STORAGE_KEY = "builderVisitorId";
363
+ var getVisitorId = ({
364
+ canTrack
365
+ }) => {
366
+ if (!canTrack) {
367
+ return void 0;
509
368
  }
510
- if (obj["@type"] === "@builder.io/sdk:Element") {
511
- return obj;
369
+ const visitorId = getLocalStorageItem({
370
+ key: VISITOR_LOCAL_STORAGE_KEY,
371
+ canTrack
372
+ });
373
+ if (checkIsDefined(visitorId)) {
374
+ return visitorId;
375
+ } else {
376
+ const newVisitorId = createVisitorId();
377
+ setVisitorId({
378
+ id: newVisitorId,
379
+ canTrack
380
+ });
381
+ return newVisitorId;
512
382
  }
513
- const clonedObj = {};
514
- for (const key in obj) {
515
- if (key !== "meta" && Object.prototype.hasOwnProperty.call(obj, key)) {
516
- clonedObj[key] = deepCloneWithConditions(obj[key]);
383
+ };
384
+ var createVisitorId = () => uuid();
385
+ var setVisitorId = ({
386
+ id,
387
+ canTrack
388
+ }) => setLocalStorageItem({
389
+ key: VISITOR_LOCAL_STORAGE_KEY,
390
+ value: id,
391
+ canTrack
392
+ });
393
+
394
+ // src/functions/log-fetch.ts
395
+ function logFetch(url) {
396
+ if (typeof process !== "undefined" && process.env?.DEBUG) {
397
+ if (String(process.env.DEBUG) == "true") {
398
+ logger.log(url);
517
399
  }
518
400
  }
519
- return clonedObj;
520
401
  }
521
- var IS_SDK_WITHOUT_CACHED_PROCESSED_BLOCK = ["svelte", "vue", "angular", "qwik", "solid"].includes(TARGET);
522
- var getCopy = (block) => {
523
- if (IS_SDK_WITHOUT_CACHED_PROCESSED_BLOCK) {
524
- const copy = fastClone(block);
525
- const copied = {
526
- ...copy,
527
- properties: {
528
- ...copy.properties
529
- },
530
- actions: {
531
- ...copy.actions
532
- }
533
- };
534
- return copied;
535
- } else {
536
- const copy = deepCloneWithConditions(omit(block, "children", "meta"));
402
+
403
+ // src/functions/track/index.ts
404
+ var getTrackingEventData = async ({
405
+ canTrack
406
+ }) => {
407
+ if (!canTrack) {
537
408
  return {
538
- ...copy,
539
- properties: {
540
- ...copy.properties
541
- },
542
- actions: {
543
- ...copy.actions
544
- },
545
- children: block.children,
546
- meta: block.meta
409
+ visitorId: void 0,
410
+ sessionId: void 0
547
411
  };
548
412
  }
413
+ const sessionId = await getSessionId({
414
+ canTrack
415
+ });
416
+ const visitorId = getVisitorId({
417
+ canTrack
418
+ });
419
+ return {
420
+ sessionId,
421
+ visitorId
422
+ };
549
423
  };
550
- var evaluateBindings = ({
551
- block,
552
- context,
553
- localState,
554
- rootState,
555
- rootSetState
556
- }) => {
557
- if (!block.bindings) {
558
- return block;
559
- }
560
- const copied = getCopy(block);
561
- for (const binding in block.bindings) {
562
- const expression = block.bindings[binding];
563
- const value = evaluate({
564
- code: expression,
565
- localState,
566
- rootState,
567
- rootSetState,
568
- context
569
- });
570
- set(copied, binding, value);
424
+ var createEvent = async ({
425
+ type: eventType,
426
+ canTrack,
427
+ apiKey,
428
+ metadata,
429
+ ...properties
430
+ }) => ({
431
+ type: eventType,
432
+ data: {
433
+ ...properties,
434
+ metadata: {
435
+ url: location.href,
436
+ ...metadata
437
+ },
438
+ ...await getTrackingEventData({
439
+ canTrack
440
+ }),
441
+ userAttributes: getUserAttributes(),
442
+ ownerId: apiKey
571
443
  }
572
- return copied;
573
- };
574
- function getProcessedBlock({
575
- block,
576
- context,
577
- localState,
578
- rootState,
579
- rootSetState
444
+ });
445
+ async function _track({
446
+ apiHost,
447
+ ...eventProps
580
448
  }) {
581
- let transformedBlock = transformBlock(block);
582
- transformedBlock = evaluateBindings({
583
- block: transformedBlock,
584
- localState,
585
- rootState,
586
- rootSetState,
587
- context
588
- });
589
- transformedBlock = resolveLocalizedValues(transformedBlock, rootState.locale);
590
- return transformedBlock;
591
- }
592
-
593
- // src/functions/camel-to-kebab-case.ts
594
- var camelToKebabCase = (str) => str ? str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase() : "";
595
-
596
- // src/components/block/animator.ts
597
- function throttle(func, wait, options = {}) {
598
- let context;
599
- let args;
600
- let result;
601
- let timeout = null;
602
- let previous = 0;
603
- const later = function() {
604
- previous = options.leading === false ? 0 : Date.now();
605
- timeout = null;
606
- result = func.apply(context, args);
607
- if (!timeout)
608
- context = args = null;
609
- };
610
- return function() {
611
- const now = Date.now();
612
- if (!previous && options.leading === false)
613
- previous = now;
614
- const remaining = wait - (now - previous);
615
- context = this;
616
- args = arguments;
617
- if (remaining <= 0 || remaining > wait) {
618
- if (timeout) {
619
- clearTimeout(timeout);
620
- timeout = null;
621
- }
622
- previous = now;
623
- result = func.apply(context, args);
624
- if (!timeout)
625
- context = args = null;
626
- } else if (!timeout && options.trailing !== false) {
627
- timeout = setTimeout(later, remaining);
628
- }
629
- return result;
630
- };
631
- }
632
- function assign(target, ..._args) {
633
- const to = Object(target);
634
- for (let index = 1; index < arguments.length; index++) {
635
- const nextSource = arguments[index];
636
- if (nextSource != null) {
637
- for (const nextKey in nextSource) {
638
- if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
639
- to[nextKey] = nextSource[nextKey];
640
- }
641
- }
642
- }
449
+ if (!eventProps.apiKey) {
450
+ logger.error("Missing API key for track call. Please provide your API key.");
451
+ return;
643
452
  }
644
- return to;
645
- }
646
- function bindAnimations(animations) {
647
- if (TARGET === "reactNative") {
453
+ if (!eventProps.canTrack) {
648
454
  return;
649
455
  }
650
- for (const animation of animations) {
651
- switch (animation.trigger) {
652
- case "pageLoad":
653
- triggerAnimation(animation);
654
- break;
655
- case "scrollInView":
656
- bindScrollInViewAnimation(animation);
657
- break;
658
- }
456
+ if (isEditing()) {
457
+ return;
659
458
  }
660
- }
661
- function warnElementNotPresent(id) {
662
- console.warn(`Cannot animate element: element with ID ${id} not found!`);
663
- }
664
- function augmentAnimation(animation, element) {
665
- const stylesUsed = getAllStylesUsed(animation);
666
- const computedStyle = getComputedStyle(element);
667
- const firstStyles = animation.steps[0].styles;
668
- const lastStyles = animation.steps[animation.steps.length - 1].styles;
669
- const bothStyles = [firstStyles, lastStyles];
670
- for (const styles of bothStyles) {
671
- for (const style of stylesUsed) {
672
- if (!(style in styles)) {
673
- styles[style] = computedStyle[style];
674
- }
675
- }
459
+ if (!(isBrowser() || TARGET === "reactNative")) {
460
+ return;
676
461
  }
462
+ const baseUrl = apiHost || "https://cdn.builder.io";
463
+ const url = `${baseUrl}/api/v1/track`;
464
+ logFetch(url);
465
+ return fetch(url, {
466
+ method: "POST",
467
+ body: JSON.stringify({
468
+ events: [await createEvent(eventProps)]
469
+ }),
470
+ headers: {
471
+ "content-type": "application/json",
472
+ ...getSdkHeaders()
473
+ },
474
+ mode: "cors"
475
+ }).catch((err) => {
476
+ console.error("Failed to track: ", err);
477
+ });
677
478
  }
678
- function getAllStylesUsed(animation) {
679
- const properties = [];
680
- for (const step of animation.steps) {
681
- for (const key in step.styles) {
682
- if (properties.indexOf(key) === -1) {
683
- properties.push(key);
684
- }
479
+ var track = (args) => _track({
480
+ ...args,
481
+ canTrack: true
482
+ });
483
+
484
+ // src/functions/evaluate/helpers.ts
485
+ var getFunctionArguments = ({
486
+ builder,
487
+ context,
488
+ event,
489
+ state
490
+ }) => {
491
+ return Object.entries({
492
+ state,
493
+ Builder: builder,
494
+ // legacy
495
+ builder,
496
+ context,
497
+ event
498
+ });
499
+ };
500
+ var getBuilderGlobals = (trackingContext) => ({
501
+ isEditing: isEditing(),
502
+ isBrowser: isBrowser(),
503
+ isServer: !isBrowser(),
504
+ getUserAttributes: () => getUserAttributes(),
505
+ trackConversion: (amount, customProperties) => {
506
+ if (!trackingContext?.apiKey || trackingContext?.canTrack === false) {
507
+ return;
685
508
  }
686
- }
687
- return properties;
688
- }
689
- function triggerAnimation(animation) {
690
- const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
691
- if (!elements.length) {
692
- warnElementNotPresent(animation.elementId || animation.id || "");
693
- return;
694
- }
695
- Array.from(elements).forEach((element) => {
696
- augmentAnimation(animation, element);
697
- element.style.transition = "none";
698
- element.style.transitionDelay = "0";
699
- assign(element.style, animation.steps[0].styles);
700
- setTimeout(() => {
701
- element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
702
- if (animation.delay) {
703
- element.style.transitionDelay = animation.delay + "s";
509
+ _track({
510
+ type: "conversion",
511
+ apiKey: trackingContext.apiKey,
512
+ canTrack: trackingContext.canTrack ?? true,
513
+ contentId: trackingContext.contentId,
514
+ variationId: trackingContext.variationId !== trackingContext.contentId ? trackingContext.variationId : void 0,
515
+ metadata: {
516
+ ...customProperties || {},
517
+ ...amount !== void 0 ? {
518
+ amount
519
+ } : {}
704
520
  }
705
- assign(element.style, animation.steps[1].styles);
706
- setTimeout(() => {
707
- element.style.transition = "";
708
- element.style.transitionDelay = "";
709
- }, (animation.delay || 0) * 1e3 + animation.duration * 1e3 + 100);
710
521
  });
711
- });
712
- }
713
- function bindScrollInViewAnimation(animation) {
714
- const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
715
- if (!elements.length) {
716
- warnElementNotPresent(animation.elementId || animation.id || "");
717
- return;
718
522
  }
719
- Array.from(elements).forEach((element) => {
720
- augmentAnimation(animation, element);
721
- let triggered = false;
722
- let pendingAnimation = false;
723
- function immediateOnScroll() {
724
- if (!triggered && isScrolledIntoView(element)) {
725
- triggered = true;
726
- pendingAnimation = true;
727
- setTimeout(() => {
728
- assign(element.style, animation.steps[1].styles);
729
- if (!animation.repeat) {
730
- document.removeEventListener("scroll", onScroll);
731
- }
732
- setTimeout(() => {
733
- pendingAnimation = false;
734
- if (!animation.repeat) {
735
- element.style.transition = "";
736
- element.style.transitionDelay = "";
737
- }
738
- }, (animation.duration + (animation.delay || 0)) * 1e3 + 100);
523
+ });
524
+ var parseCode = (code, {
525
+ isExpression = true
526
+ }) => {
527
+ const useReturn = (
528
+ // we disable this for cases where we definitely don't want a return
529
+ isExpression && !(code.includes(";") || code.includes(" return ") || code.trim().startsWith("return "))
530
+ );
531
+ const useCode = useReturn ? `return (${code});` : code;
532
+ return useCode;
533
+ };
534
+ function flattenState({
535
+ rootState,
536
+ localState,
537
+ rootSetState
538
+ }) {
539
+ return new Proxy(rootState, {
540
+ get: (target, prop) => {
541
+ if (localState && prop in localState) {
542
+ return localState[prop];
543
+ }
544
+ const val = target[prop];
545
+ if (typeof val === "object" && val !== null) {
546
+ return flattenState({
547
+ rootState: val,
548
+ localState: void 0,
549
+ rootSetState: rootSetState ? (subState) => {
550
+ target[prop] = subState;
551
+ rootSetState(target);
552
+ } : void 0
739
553
  });
740
- } else if (animation.repeat && triggered && !pendingAnimation && !isScrolledIntoView(element)) {
741
- triggered = false;
742
- assign(element.style, animation.steps[0].styles);
743
554
  }
744
- }
745
- const onScroll = throttle(immediateOnScroll, 200, {
746
- leading: false
747
- });
748
- function isScrolledIntoView(elem) {
749
- const rect = elem.getBoundingClientRect();
750
- const windowHeight = window.innerHeight;
751
- const thresholdPercent = (animation.thresholdPercent || 0) / 100;
752
- const threshold = thresholdPercent * windowHeight;
753
- return rect.bottom > threshold && rect.top < windowHeight - threshold;
754
- }
755
- const defaultState = animation.steps[0].styles;
756
- function attachDefaultState() {
757
- assign(element.style, defaultState);
758
- }
759
- attachDefaultState();
760
- setTimeout(() => {
761
- element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
762
- if (animation.delay) {
763
- element.style.transitionDelay = animation.delay + "s";
555
+ return val;
556
+ },
557
+ set: (target, prop, value) => {
558
+ if (localState && prop in localState) {
559
+ throw new Error("Writing to local state is not allowed as it is read-only.");
764
560
  }
765
- });
766
- document.addEventListener("scroll", onScroll, {
767
- capture: true,
768
- passive: true
769
- });
770
- immediateOnScroll();
561
+ target[prop] = value;
562
+ rootSetState?.(target);
563
+ return true;
564
+ }
771
565
  });
772
566
  }
773
567
 
774
- // src/helpers/css.ts
775
- var convertStyleMapToCSSArray = (style) => {
776
- const cssProps = Object.entries(style).map(([key, value]) => {
777
- if (typeof value === "string") {
778
- return `${camelToKebabCase(key)}: ${value};`;
779
- } else {
780
- return void 0;
781
- }
782
- });
783
- return cssProps.filter(checkIsDefined);
784
- };
785
- var convertStyleMapToCSS = (style) => convertStyleMapToCSSArray(style).join("\n");
786
- var createCssClass = ({
787
- mediaQuery,
788
- className,
789
- styles
568
+ // src/functions/evaluate/browser-runtime/browser.ts
569
+ var runInBrowser = ({
570
+ code,
571
+ builder,
572
+ context,
573
+ event,
574
+ localState,
575
+ rootSetState,
576
+ rootState
790
577
  }) => {
791
- const cssClass = `.${className} {
792
- ${convertStyleMapToCSS(styles)}
793
- }`;
794
- if (mediaQuery) {
795
- return `${mediaQuery} {
796
- ${cssClass}
797
- }`;
798
- } else {
799
- return cssClass;
800
- }
578
+ const functionArgs = getFunctionArguments({
579
+ builder,
580
+ context,
581
+ event,
582
+ state: flattenState({
583
+ rootState,
584
+ localState,
585
+ rootSetState
586
+ })
587
+ });
588
+ return new Function(...functionArgs.map(([name]) => name), code)(...functionArgs.map(([, value]) => value));
801
589
  };
802
590
 
803
- // src/functions/transform-style-property.ts
804
- function transformStyleProperty({
805
- style
806
- }) {
807
- return style;
591
+ // src/functions/is-node-runtime.ts
592
+ function isNodeRuntime() {
593
+ return typeof process !== "undefined" && checkIsDefined(process?.versions?.node);
808
594
  }
809
595
 
810
- // src/functions/get-style.ts
811
- var getStyle = ({
812
- block,
813
- context
596
+ // src/functions/evaluate/should-force-browser-runtime-in-node.ts
597
+ var shouldForceBrowserRuntimeInNode = ({
598
+ shouldLogWarning
814
599
  }) => {
815
- return mapStyleObjToStrIfNeeded(transformStyleProperty({
816
- style: block.style || {},
817
- context,
818
- block
819
- }));
820
- };
821
- function mapStyleObjToStrIfNeeded(style) {
822
- switch (TARGET) {
823
- case "svelte":
824
- case "vue":
825
- case "solid":
826
- case "angular":
827
- return convertStyleMapToCSSArray(style).join(" ");
828
- case "qwik":
829
- case "reactNative":
830
- case "react":
831
- case "rsc":
832
- return style;
600
+ if (!isNodeRuntime())
601
+ return false;
602
+ const isArm64 = process.arch === "arm64";
603
+ const isNode20 = process.version.startsWith("v20");
604
+ const hasNoNodeSnapshotNodeOption = process.env.NODE_OPTIONS?.includes("--no-node-snapshot");
605
+ if (isArm64 && isNode20 && !hasNoNodeSnapshotNodeOption) {
606
+ if (shouldLogWarning) {
607
+ logger.log(`Skipping usage of \`isolated-vm\` to avoid crashes in Node v20 on an arm64 machine.
608
+ If you would like to use the \`isolated-vm\` package on this machine, please provide the \`NODE_OPTIONS=--no-node-snapshot\` config to your Node process.
609
+ See https://github.com/BuilderIO/builder/blob/main/packages/sdks/README.md#node-v20--m1-macs-apple-silicon-support for more information.
610
+ `);
611
+ }
612
+ return true;
833
613
  }
834
- }
614
+ return false;
615
+ };
835
616
 
836
- // src/components/block/block.helpers.ts
837
- var checkIsComponentRestricted = (component, model) => {
838
- if (!component)
839
- return true;
840
- if (!model)
841
- return false;
842
- return component.models && component.models.length > 0 && !component.models.includes(model);
617
+ // src/functions/evaluate/choose-eval.ts
618
+ var chooseBrowserOrServerEval = (args) => isBrowser() || shouldForceBrowserRuntimeInNode({
619
+ shouldLogWarning: true
620
+ }) ? runInBrowser(args) : runInBrowser(args);
621
+
622
+ // src/functions/evaluate/evaluate.ts
623
+ var STATE_GETTER_REGEX = /^(return )?(\s*)?state(?<getPath>(\.\w+)+)(\s*);?$/;
624
+ var VIRTUAL_INDEX_REGEX = /(\s)*var(\s)+_virtual_index(\s)*=(\s)*state(?<getPath>(\.\w+)+)(\s*);?(\s)*return(\s)*_virtual_index(\s)*/;
625
+ var getSimpleExpressionGetPath = (code) => {
626
+ return STATE_GETTER_REGEX.exec(code.trim())?.groups?.getPath?.slice(1) || VIRTUAL_INDEX_REGEX.exec(code.trim())?.groups?.getPath?.slice(1);
843
627
  };
844
- var getComponent = ({
845
- block,
846
- registeredComponents,
847
- model
848
- }) => {
849
- const componentName = block.component?.name;
850
- if (!componentName) {
851
- return null;
852
- }
853
- const ref = registeredComponents[componentName];
854
- if (!ref || checkIsComponentRestricted(ref, model)) {
855
- console.warn(`
856
- Could not find a registered component named "${componentName}".
857
- If you registered it, is the file that registered it imported by the file that needs to render it?`);
628
+ function evaluate({
629
+ code,
630
+ context,
631
+ localState,
632
+ rootState,
633
+ rootSetState,
634
+ event,
635
+ isExpression = true,
636
+ trackingContext
637
+ }) {
638
+ if (code.trim() === "") {
858
639
  return void 0;
859
- } else {
860
- return ref;
861
640
  }
862
- };
863
- var getRepeatItemData = ({
864
- block,
865
- context
866
- }) => {
867
- const {
868
- repeat,
869
- ...blockWithoutRepeat
870
- } = block;
871
- if (!repeat?.collection) {
872
- return void 0;
641
+ const getPath = getSimpleExpressionGetPath(code.trim());
642
+ if (getPath) {
643
+ return get({
644
+ ...rootState,
645
+ ...localState
646
+ }, getPath);
873
647
  }
874
- const itemsArray = evaluate({
875
- code: repeat.collection,
876
- localState: context.localState,
877
- rootState: context.rootState,
878
- rootSetState: context.rootSetState,
879
- context: context.context
880
- });
881
- if (!Array.isArray(itemsArray)) {
648
+ const args = {
649
+ code: parseCode(code, {
650
+ isExpression
651
+ }),
652
+ builder: getBuilderGlobals(trackingContext),
653
+ context,
654
+ event,
655
+ rootSetState,
656
+ rootState,
657
+ localState
658
+ };
659
+ try {
660
+ const newEval = chooseBrowserOrServerEval(args);
661
+ return newEval;
662
+ } catch (e) {
663
+ logger.error("Failed code evaluation: " + e.message, {
664
+ code
665
+ });
882
666
  return void 0;
883
667
  }
884
- const collectionName = repeat.collection.split(".").pop();
885
- const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
886
- const repeatArray = itemsArray.map((item, index) => ({
887
- context: {
888
- ...context,
889
- localState: {
890
- ...context.localState,
891
- $index: index,
892
- $item: item,
893
- [itemNameToUse]: item,
894
- [`$${itemNameToUse}Index`]: index
895
- }
896
- },
897
- block: blockWithoutRepeat
898
- }));
899
- return repeatArray;
900
- };
901
- var provideLinkComponent = (block, linkComponent) => {
902
- if (block?.shouldReceiveBuilderProps?.builderLinkComponent)
903
- return {
904
- builderLinkComponent: linkComponent
905
- };
906
- return {};
907
- };
908
- var provideRegisteredComponents = (block, registeredComponents, model) => {
909
- if (block?.shouldReceiveBuilderProps?.builderComponents) {
910
- const filteredRegisteredComponents = Object.fromEntries(Object.entries(registeredComponents).filter(([_, component]) => {
911
- return !checkIsComponentRestricted(component, model);
912
- }));
668
+ }
669
+
670
+ // src/functions/get-block-component-options.ts
671
+ function getBlockComponentOptions(block, context) {
672
+ return {
673
+ ...block.component?.options,
674
+ ...block.options,
675
+ ...evaluateTextComponentTextOption(block, context)
676
+ };
677
+ }
678
+ var evaluateTextComponentTextOption = (block, context) => {
679
+ if (block.component?.name === "Text" && block.component.options?.text && typeof block.component.options.text === "string") {
913
680
  return {
914
- builderComponents: filteredRegisteredComponents
681
+ ...block.component.options,
682
+ text: block.component.options.text.replace(/{{([^}]+)}}/g, (_match, group) => evaluate({
683
+ code: group,
684
+ context,
685
+ localState: context.localState,
686
+ rootState: context.rootState,
687
+ rootSetState: context.rootSetState
688
+ }))
915
689
  };
916
690
  }
917
- return {};
918
- };
919
- var provideBuilderBlock = (block, builderBlock) => {
920
- if (block?.shouldReceiveBuilderProps?.builderBlock)
921
- return {
922
- builderBlock
923
- };
924
- return {};
925
- };
926
- var provideBuilderContext = (block, context) => {
927
- if (block?.shouldReceiveBuilderProps?.builderContext)
928
- return {
929
- builderContext: context
930
- };
931
- return {};
932
- };
933
- var generateKey = (index) => {
934
- return index.toString();
935
691
  };
936
692
 
937
- // src/functions/event-handler-name.ts
938
- function capitalizeFirstLetter(string) {
939
- return string.charAt(0).toUpperCase() + string.slice(1);
693
+ // src/helpers/omit.ts
694
+ function omit(obj, ...values) {
695
+ const newObject = Object.assign({}, obj);
696
+ for (const key of values) {
697
+ delete newObject[key];
698
+ }
699
+ return newObject;
700
+ }
701
+
702
+ // src/functions/traverse.ts
703
+ function traverse(obj, callback, parent2 = null, key = null, visited = /* @__PURE__ */ new WeakSet()) {
704
+ if (obj == null || typeof obj !== "object") {
705
+ callback(obj, (newValue) => {
706
+ if (parent2 !== null && key !== null) {
707
+ parent2[key] = newValue;
708
+ }
709
+ });
710
+ return;
711
+ }
712
+ if (visited.has(obj)) {
713
+ return;
714
+ }
715
+ visited.add(obj);
716
+ if (Array.isArray(obj)) {
717
+ obj.forEach((item, index) => {
718
+ const update = (newValue) => {
719
+ obj[index] = newValue;
720
+ };
721
+ callback(item, update);
722
+ traverse(item, callback, obj, index, visited);
723
+ });
724
+ } else {
725
+ Object.entries(obj).forEach(([key2, value]) => {
726
+ const update = (newValue) => {
727
+ obj[key2] = newValue;
728
+ };
729
+ callback(value, update);
730
+ traverse(value, callback, obj, key2, visited);
731
+ });
732
+ }
733
+ }
734
+
735
+ // src/functions/extract-localized-values.ts
736
+ function isLocalizedField(value) {
737
+ return value && typeof value === "object" && value["@type"] === "@builder.io/core:LocalizedValue";
738
+ }
739
+ function containsLocalizedValues(data) {
740
+ if (!data || !Object.getOwnPropertyNames(data).length) {
741
+ return false;
742
+ }
743
+ let hasLocalizedValues = false;
744
+ traverse(data, (value) => {
745
+ if (isLocalizedField(value)) {
746
+ hasLocalizedValues = true;
747
+ return;
748
+ }
749
+ });
750
+ return hasLocalizedValues;
751
+ }
752
+ function extractLocalizedValues(data, locale) {
753
+ if (!data || !Object.getOwnPropertyNames(data).length) {
754
+ return {};
755
+ }
756
+ traverse(data, (value, update) => {
757
+ if (isLocalizedField(value)) {
758
+ update(value[locale] ?? void 0);
759
+ }
760
+ });
761
+ return data;
762
+ }
763
+ function resolveLocalizedValues(block, locale) {
764
+ if (block.component?.options && containsLocalizedValues(block.component?.options)) {
765
+ if (!locale) {
766
+ console.warn("[Builder.io] In order to use localized fields in Builder, you must pass a locale prop to the BuilderComponent or to options object while fetching the content to resolve localized fields. Learn more: https://www.builder.io/c/docs/localization-inline#targeting-and-inline-localization");
767
+ }
768
+ block.component.options = extractLocalizedValues(block.component.options, locale ?? "Default");
769
+ }
770
+ return block;
940
771
  }
941
- var getEventHandlerName = (key) => `on${capitalizeFirstLetter(key)}`;
942
772
 
943
- // src/functions/get-block-actions-handler.ts
944
- var createEventHandler = (value, options) => (event) => evaluate({
945
- code: value,
946
- context: options.context,
947
- localState: options.localState,
948
- rootState: options.rootState,
949
- rootSetState: options.rootSetState,
950
- event,
951
- isExpression: false
952
- });
773
+ // src/functions/fast-clone.ts
774
+ var fastClone = (obj) => JSON.parse(JSON.stringify(obj));
953
775
 
954
- // src/functions/get-block-actions.ts
955
- function getBlockActions(options) {
956
- const obj = {};
957
- const optionActions = options.block.actions ?? {};
958
- for (const key in optionActions) {
959
- if (!optionActions.hasOwnProperty(key)) {
960
- continue;
961
- }
962
- const value = optionActions[key];
963
- let eventHandlerName = getEventHandlerName(key);
964
- if (options.stripPrefix) {
965
- switch (TARGET) {
966
- case "vue":
967
- eventHandlerName = eventHandlerName.replace("v-on:", "");
968
- break;
969
- case "svelte":
970
- eventHandlerName = eventHandlerName.replace("on:", "");
971
- break;
972
- }
973
- }
974
- obj[eventHandlerName] = createEventHandler(value, options);
776
+ // src/functions/set.ts
777
+ var set = (obj, _path, value) => {
778
+ if (Object(obj) !== obj) {
779
+ return obj;
975
780
  }
781
+ const path = Array.isArray(_path) ? _path : _path.toString().match(/[^.[\]]+/g);
782
+ path.slice(0, -1).reduce((a, c, i) => Object(a[c]) === a[c] ? a[c] : a[c] = Math.abs(Number(path[i + 1])) >> 0 === +path[i + 1] ? [] : {}, obj)[path[path.length - 1]] = value;
976
783
  return obj;
977
- }
784
+ };
978
785
 
979
- // src/functions/transform-block-properties.ts
980
- function transformBlockProperties({
981
- properties
982
- }) {
983
- return properties;
786
+ // src/functions/transform-block.ts
787
+ function transformBlock(block) {
788
+ return block;
984
789
  }
985
790
 
986
- // src/functions/get-block-properties.ts
987
- var extractRelevantRootBlockProperties = (block) => {
988
- return {
989
- href: block.href
990
- };
791
+ // src/functions/get-processed-block.ts
792
+ function deepCloneWithConditions(obj) {
793
+ if (obj === null || typeof obj !== "object") {
794
+ return obj;
795
+ }
796
+ if (Array.isArray(obj)) {
797
+ return obj.map((item) => deepCloneWithConditions(item));
798
+ }
799
+ if (obj["@type"] === "@builder.io/sdk:Element") {
800
+ return obj;
801
+ }
802
+ const clonedObj = {};
803
+ for (const key in obj) {
804
+ if (key !== "meta" && Object.prototype.hasOwnProperty.call(obj, key)) {
805
+ clonedObj[key] = deepCloneWithConditions(obj[key]);
806
+ }
807
+ }
808
+ return clonedObj;
809
+ }
810
+ var IS_SDK_WITHOUT_CACHED_PROCESSED_BLOCK = ["svelte", "vue", "angular", "qwik", "solid"].includes(TARGET);
811
+ var getCopy = (block) => {
812
+ if (IS_SDK_WITHOUT_CACHED_PROCESSED_BLOCK) {
813
+ const copy = fastClone(block);
814
+ const copied = {
815
+ ...copy,
816
+ properties: {
817
+ ...copy.properties
818
+ },
819
+ actions: {
820
+ ...copy.actions
821
+ }
822
+ };
823
+ return copied;
824
+ } else {
825
+ const copy = deepCloneWithConditions(omit(block, "children", "meta"));
826
+ return {
827
+ ...copy,
828
+ properties: {
829
+ ...copy.properties
830
+ },
831
+ actions: {
832
+ ...copy.actions
833
+ },
834
+ children: block.children,
835
+ meta: block.meta
836
+ };
837
+ }
991
838
  };
992
- function getBlockProperties({
839
+ var evaluateBindings = ({
993
840
  block,
994
- context
995
- }) {
996
- const properties = {
997
- ...extractRelevantRootBlockProperties(block),
998
- ...block.properties,
999
- "builder-id": block.id,
1000
- style: getStyle({
1001
- block,
841
+ context,
842
+ localState,
843
+ rootState,
844
+ rootSetState
845
+ }) => {
846
+ if (!block.bindings) {
847
+ return block;
848
+ }
849
+ const copied = getCopy(block);
850
+ for (const binding in block.bindings) {
851
+ const expression = block.bindings[binding];
852
+ const value = evaluate({
853
+ code: expression,
854
+ localState,
855
+ rootState,
856
+ rootSetState,
1002
857
  context
1003
- }),
1004
- [getClassPropName()]: [block.id, "builder-block", block.class, block.properties?.class].filter(Boolean).join(" ")
1005
- };
1006
- return transformBlockProperties({
1007
- properties,
1008
- context,
1009
- block
858
+ });
859
+ set(copied, binding, value);
860
+ }
861
+ return copied;
862
+ };
863
+ function getProcessedBlock({
864
+ block,
865
+ context,
866
+ localState,
867
+ rootState,
868
+ rootSetState
869
+ }) {
870
+ let transformedBlock = transformBlock(block);
871
+ transformedBlock = evaluateBindings({
872
+ block: transformedBlock,
873
+ localState,
874
+ rootState,
875
+ rootSetState,
876
+ context
1010
877
  });
878
+ transformedBlock = resolveLocalizedValues(transformedBlock, rootState.locale);
879
+ return transformedBlock;
1011
880
  }
1012
881
 
1013
- // src/components/block/components/block-wrapper.tsx
1014
- function BlockWrapper(props) {
1015
- return <><Dynamic_renderer_default
1016
- TagName={props.Wrapper}
1017
- attributes={getBlockProperties({
1018
- block: props.block,
1019
- context: props.context
1020
- })}
1021
- actionAttributes={getBlockActions({
1022
- block: props.block,
1023
- rootState: props.context.rootState,
1024
- rootSetState: props.context.rootSetState,
1025
- localState: props.context.localState,
1026
- context: props.context.context,
1027
- stripPrefix: true
1028
- })}
1029
- >{props.children}</Dynamic_renderer_default></>;
1030
- }
1031
- var Block_wrapper_default = BlockWrapper;
1032
-
1033
- // src/components/block/components/component-ref/component-ref.tsx
1034
- import { Show as Show3, For, createSignal as createSignal3 } from "solid-js";
1035
- import { Dynamic as Dynamic4 } from "solid-js/web";
1036
-
1037
- // src/components/block/components/interactive-element.tsx
1038
- import { Show as Show2, on, createEffect, createMemo as createMemo2, createSignal as createSignal2 } from "solid-js";
1039
- import { Dynamic as Dynamic3 } from "solid-js/web";
1040
-
1041
- // src/functions/is-previewing.ts
1042
- function isPreviewing(search) {
1043
- const searchToUse = search || (isBrowser() ? window.location.search : void 0);
1044
- if (!searchToUse) {
1045
- return false;
1046
- }
1047
- const normalizedSearch = getSearchString(searchToUse);
1048
- return Boolean(normalizedSearch.indexOf("builder.preview=") !== -1);
1049
- }
882
+ // src/functions/camel-to-kebab-case.ts
883
+ var camelToKebabCase = (str) => str ? str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase() : "";
1050
884
 
1051
- // src/functions/register-component.ts
1052
- var createRegisterComponentMessage = (info) => ({
1053
- type: "builder.registerComponent",
1054
- data: serializeIncludingFunctions(info)
1055
- });
1056
- var serializeFn = (fnValue) => {
1057
- const fnStr = fnValue.toString().trim();
1058
- const isArrowWithoutParens = /^[a-zA-Z0-9_]+\s*=>/i.test(fnStr);
1059
- const appendFunction = !fnStr.startsWith("function") && !fnStr.startsWith("async") && !fnStr.startsWith("(") && !isArrowWithoutParens;
1060
- return `return (${appendFunction ? "function " : ""}${fnStr}).apply(this, arguments)`;
1061
- };
1062
- function serializeIncludingFunctions(info) {
1063
- return JSON.parse(JSON.stringify(info, (key, value) => {
1064
- if (typeof value === "function") {
1065
- return serializeFn(value);
885
+ // src/components/block/animator.ts
886
+ function throttle(func, wait, options = {}) {
887
+ let context;
888
+ let args;
889
+ let result;
890
+ let timeout = null;
891
+ let previous = 0;
892
+ const later = function() {
893
+ previous = options.leading === false ? 0 : Date.now();
894
+ timeout = null;
895
+ result = func.apply(context, args);
896
+ if (!timeout)
897
+ context = args = null;
898
+ };
899
+ return function() {
900
+ const now = Date.now();
901
+ if (!previous && options.leading === false)
902
+ previous = now;
903
+ const remaining = wait - (now - previous);
904
+ context = this;
905
+ args = arguments;
906
+ if (remaining <= 0 || remaining > wait) {
907
+ if (timeout) {
908
+ clearTimeout(timeout);
909
+ timeout = null;
910
+ }
911
+ previous = now;
912
+ result = func.apply(context, args);
913
+ if (!timeout)
914
+ context = args = null;
915
+ } else if (!timeout && options.trailing !== false) {
916
+ timeout = setTimeout(later, remaining);
1066
917
  }
1067
- return value;
1068
- }));
918
+ return result;
919
+ };
1069
920
  }
1070
-
1071
- // src/functions/register.ts
1072
- var registry = {};
1073
- function register(type, info) {
1074
- if (type === "plugin") {
1075
- info = serializeIncludingFunctions(info);
1076
- }
1077
- let typeList = registry[type];
1078
- if (!typeList) {
1079
- typeList = registry[type] = [];
1080
- }
1081
- typeList.push(info);
1082
- if (isBrowser()) {
1083
- const message = {
1084
- type: "builder.register",
1085
- data: {
1086
- type,
1087
- info
1088
- }
1089
- };
1090
- try {
1091
- parent.postMessage(message, "*");
1092
- if (parent !== window) {
1093
- window.postMessage(message, "*");
921
+ function assign(target, ..._args) {
922
+ const to = Object(target);
923
+ for (let index = 1; index < arguments.length; index++) {
924
+ const nextSource = arguments[index];
925
+ if (nextSource != null) {
926
+ for (const nextKey in nextSource) {
927
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
928
+ to[nextKey] = nextSource[nextKey];
929
+ }
1094
930
  }
1095
- } catch (err) {
1096
- console.debug("Could not postmessage", err);
1097
931
  }
1098
932
  }
933
+ return to;
1099
934
  }
1100
- function registerAction(action) {
1101
- if (isBrowser()) {
1102
- const actionClone = JSON.parse(JSON.stringify(action));
1103
- if (action.action) {
1104
- actionClone.action = action.action.toString();
935
+ function bindAnimations(animations) {
936
+ if (TARGET === "reactNative") {
937
+ return;
938
+ }
939
+ for (const animation of animations) {
940
+ switch (animation.trigger) {
941
+ case "pageLoad":
942
+ triggerAnimation(animation);
943
+ break;
944
+ case "scrollInView":
945
+ bindScrollInViewAnimation(animation);
946
+ break;
1105
947
  }
1106
- window.parent?.postMessage({
1107
- type: "builder.registerAction",
1108
- data: actionClone
1109
- }, "*");
1110
948
  }
1111
949
  }
1112
-
1113
- // src/functions/set-editor-settings.ts
1114
- var settings = {};
1115
- function setEditorSettings(newSettings) {
1116
- if (isBrowser()) {
1117
- Object.assign(settings, newSettings);
1118
- const message = {
1119
- type: "builder.settingsChange",
1120
- data: settings
1121
- };
1122
- parent.postMessage(message, "*");
1123
- }
950
+ function warnElementNotPresent(id) {
951
+ console.warn(`Cannot animate element: element with ID ${id} not found!`);
1124
952
  }
1125
-
1126
- // src/functions/get-builder-search-params/index.ts
1127
- var BUILDER_SEARCHPARAMS_PREFIX = "builder.";
1128
- var BUILDER_OPTIONS_PREFIX = "options.";
1129
- var getBuilderSearchParams = (_options) => {
1130
- if (!_options) {
1131
- return {};
953
+ function augmentAnimation(animation, element) {
954
+ const stylesUsed = getAllStylesUsed(animation);
955
+ const computedStyle = getComputedStyle(element);
956
+ const firstStyles = animation.steps[0].styles;
957
+ const lastStyles = animation.steps[animation.steps.length - 1].styles;
958
+ const bothStyles = [firstStyles, lastStyles];
959
+ for (const styles of bothStyles) {
960
+ for (const style of stylesUsed) {
961
+ if (!(style in styles)) {
962
+ styles[style] = computedStyle[style];
963
+ }
964
+ }
1132
965
  }
1133
- const options = normalizeSearchParams(_options);
1134
- const newOptions = {};
1135
- Object.keys(options).forEach((key) => {
1136
- if (key.startsWith(BUILDER_SEARCHPARAMS_PREFIX)) {
1137
- const trimmedKey = key.replace(BUILDER_SEARCHPARAMS_PREFIX, "").replace(BUILDER_OPTIONS_PREFIX, "");
1138
- newOptions[trimmedKey] = options[key];
966
+ }
967
+ function getAllStylesUsed(animation) {
968
+ const properties = [];
969
+ for (const step of animation.steps) {
970
+ for (const key in step.styles) {
971
+ if (properties.indexOf(key) === -1) {
972
+ properties.push(key);
973
+ }
1139
974
  }
1140
- });
1141
- return newOptions;
1142
- };
1143
- var getBuilderSearchParamsFromWindow = () => {
1144
- if (!isBrowser()) {
1145
- return {};
1146
975
  }
1147
- const searchParams = new URLSearchParams(window.location.search);
1148
- return getBuilderSearchParams(searchParams);
1149
- };
1150
-
1151
- // src/constants/sdk-version.ts
1152
- var SDK_VERSION = "5.0.1";
1153
-
1154
- // src/helpers/sdk-headers.ts
1155
- var getSdkHeaders = () => ({
1156
- "X-Builder-SDK": TARGET,
1157
- "X-Builder-SDK-GEN": "2",
1158
- "X-Builder-SDK-Version": SDK_VERSION
1159
- });
1160
-
1161
- // src/helpers/url.ts
1162
- var getTopLevelDomain = (host) => {
1163
- if (host === "localhost" || host === "127.0.0.1") {
1164
- return host;
976
+ return properties;
977
+ }
978
+ function triggerAnimation(animation) {
979
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
980
+ if (!elements.length) {
981
+ warnElementNotPresent(animation.elementId || animation.id || "");
982
+ return;
1165
983
  }
1166
- const parts = host.split(".");
1167
- if (parts.length > 2) {
1168
- return parts.slice(1).join(".");
984
+ Array.from(elements).forEach((element) => {
985
+ augmentAnimation(animation, element);
986
+ element.style.transition = "none";
987
+ element.style.transitionDelay = "0";
988
+ assign(element.style, animation.steps[0].styles);
989
+ setTimeout(() => {
990
+ element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
991
+ if (animation.delay) {
992
+ element.style.transitionDelay = animation.delay + "s";
993
+ }
994
+ assign(element.style, animation.steps[1].styles);
995
+ setTimeout(() => {
996
+ element.style.transition = "";
997
+ element.style.transitionDelay = "";
998
+ }, (animation.delay || 0) * 1e3 + animation.duration * 1e3 + 100);
999
+ });
1000
+ });
1001
+ }
1002
+ function bindScrollInViewAnimation(animation) {
1003
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
1004
+ if (!elements.length) {
1005
+ warnElementNotPresent(animation.elementId || animation.id || "");
1006
+ return;
1169
1007
  }
1170
- return host;
1171
- };
1172
-
1173
- // src/helpers/cookie.ts
1174
- var getCookieSync = ({
1175
- name,
1176
- canTrack
1177
- }) => {
1178
- try {
1179
- if (!canTrack) {
1180
- return void 0;
1008
+ Array.from(elements).forEach((element) => {
1009
+ augmentAnimation(animation, element);
1010
+ let triggered = false;
1011
+ let pendingAnimation = false;
1012
+ function immediateOnScroll() {
1013
+ if (!triggered && isScrolledIntoView(element)) {
1014
+ triggered = true;
1015
+ pendingAnimation = true;
1016
+ setTimeout(() => {
1017
+ assign(element.style, animation.steps[1].styles);
1018
+ if (!animation.repeat) {
1019
+ document.removeEventListener("scroll", onScroll);
1020
+ }
1021
+ setTimeout(() => {
1022
+ pendingAnimation = false;
1023
+ if (!animation.repeat) {
1024
+ element.style.transition = "";
1025
+ element.style.transitionDelay = "";
1026
+ }
1027
+ }, (animation.duration + (animation.delay || 0)) * 1e3 + 100);
1028
+ });
1029
+ } else if (animation.repeat && triggered && !pendingAnimation && !isScrolledIntoView(element)) {
1030
+ triggered = false;
1031
+ assign(element.style, animation.steps[0].styles);
1032
+ }
1181
1033
  }
1182
- return document.cookie.split("; ").find((row) => row.startsWith(`${name}=`))?.split("=")[1];
1183
- } catch (err) {
1184
- logger.warn("[COOKIE] GET error: ", err?.message || err);
1185
- return void 0;
1186
- }
1187
- };
1188
- var getCookie = async (args) => getCookieSync(args);
1189
- var stringifyCookie = (cookie) => cookie.map(([key, value]) => value ? `${key}=${value}` : key).filter(checkIsDefined).join("; ");
1190
- var SECURE_CONFIG = [["secure", ""], ["SameSite", "None"]];
1191
- var createCookieString = ({
1192
- name,
1193
- value,
1194
- expires
1195
- }) => {
1196
- const secure = isBrowser() ? location.protocol === "https:" : true;
1197
- const secureObj = secure ? SECURE_CONFIG : [[]];
1198
- const expiresObj = expires ? [["expires", expires.toUTCString()]] : [[]];
1199
- const cookieValue = [[name, value], ...expiresObj, ["path", "/"], ["domain", getTopLevelDomain(window.location.hostname)], ...secureObj];
1200
- const cookie = stringifyCookie(cookieValue);
1201
- return cookie;
1202
- };
1203
- var setCookie = async ({
1204
- name,
1205
- value,
1206
- expires,
1207
- canTrack
1208
- }) => {
1209
- try {
1210
- if (!canTrack) {
1211
- return;
1034
+ const onScroll = throttle(immediateOnScroll, 200, {
1035
+ leading: false
1036
+ });
1037
+ function isScrolledIntoView(elem) {
1038
+ const rect = elem.getBoundingClientRect();
1039
+ const windowHeight = window.innerHeight;
1040
+ const thresholdPercent = (animation.thresholdPercent || 0) / 100;
1041
+ const threshold = thresholdPercent * windowHeight;
1042
+ return rect.bottom > threshold && rect.top < windowHeight - threshold;
1212
1043
  }
1213
- const cookie = createCookieString({
1214
- name,
1215
- value,
1216
- expires
1044
+ const defaultState = animation.steps[0].styles;
1045
+ function attachDefaultState() {
1046
+ assign(element.style, defaultState);
1047
+ }
1048
+ attachDefaultState();
1049
+ setTimeout(() => {
1050
+ element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
1051
+ if (animation.delay) {
1052
+ element.style.transitionDelay = animation.delay + "s";
1053
+ }
1217
1054
  });
1218
- document.cookie = cookie;
1219
- } catch (err) {
1220
- logger.warn("[COOKIE] SET error: ", err?.message || err);
1221
- }
1222
- };
1223
-
1224
- // src/helpers/uuid.ts
1225
- function uuidv4() {
1226
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
1227
- const r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
1228
- return v.toString(16);
1055
+ document.addEventListener("scroll", onScroll, {
1056
+ capture: true,
1057
+ passive: true
1058
+ });
1059
+ immediateOnScroll();
1229
1060
  });
1230
1061
  }
1231
- function uuid() {
1232
- return uuidv4().replace(/-/g, "");
1233
- }
1234
1062
 
1235
- // src/helpers/sessionId.ts
1236
- var SESSION_LOCAL_STORAGE_KEY = "builderSessionId";
1237
- var getSessionId = async ({
1238
- canTrack
1239
- }) => {
1240
- if (!canTrack) {
1241
- return void 0;
1242
- }
1243
- const sessionId = await getCookie({
1244
- name: SESSION_LOCAL_STORAGE_KEY,
1245
- canTrack
1063
+ // src/helpers/css.ts
1064
+ var convertStyleMapToCSSArray = (style) => {
1065
+ const cssProps = Object.entries(style).map(([key, value]) => {
1066
+ if (typeof value === "string") {
1067
+ return `${camelToKebabCase(key)}: ${value};`;
1068
+ } else {
1069
+ return void 0;
1070
+ }
1246
1071
  });
1247
- if (checkIsDefined(sessionId)) {
1248
- return sessionId;
1072
+ return cssProps.filter(checkIsDefined);
1073
+ };
1074
+ var convertStyleMapToCSS = (style) => convertStyleMapToCSSArray(style).join("\n");
1075
+ var createCssClass = ({
1076
+ mediaQuery,
1077
+ className,
1078
+ styles
1079
+ }) => {
1080
+ const cssClass = `.${className} {
1081
+ ${convertStyleMapToCSS(styles)}
1082
+ }`;
1083
+ if (mediaQuery) {
1084
+ return `${mediaQuery} {
1085
+ ${cssClass}
1086
+ }`;
1249
1087
  } else {
1250
- const newSessionId = createSessionId();
1251
- setSessionId({
1252
- id: newSessionId,
1253
- canTrack
1254
- });
1255
- return newSessionId;
1088
+ return cssClass;
1256
1089
  }
1257
1090
  };
1258
- var createSessionId = () => uuid();
1259
- var setSessionId = ({
1260
- id,
1261
- canTrack
1262
- }) => setCookie({
1263
- name: SESSION_LOCAL_STORAGE_KEY,
1264
- value: id,
1265
- canTrack
1266
- });
1267
1091
 
1268
- // src/helpers/localStorage.ts
1269
- var getLocalStorage = () => isBrowser() && typeof localStorage !== "undefined" ? localStorage : void 0;
1270
- var getLocalStorageItem = ({
1271
- key,
1272
- canTrack
1092
+ // src/functions/transform-style-property.ts
1093
+ function transformStyleProperty({
1094
+ style
1095
+ }) {
1096
+ return style;
1097
+ }
1098
+
1099
+ // src/functions/get-style.ts
1100
+ var getStyle = ({
1101
+ block,
1102
+ context
1273
1103
  }) => {
1274
- try {
1275
- if (canTrack) {
1276
- return getLocalStorage()?.getItem(key);
1277
- }
1278
- return void 0;
1279
- } catch (err) {
1280
- console.debug("[LocalStorage] GET error: ", err);
1281
- return void 0;
1104
+ return mapStyleObjToStrIfNeeded(transformStyleProperty({
1105
+ style: block.style || {},
1106
+ context,
1107
+ block
1108
+ }));
1109
+ };
1110
+ function mapStyleObjToStrIfNeeded(style) {
1111
+ switch (TARGET) {
1112
+ case "svelte":
1113
+ case "vue":
1114
+ case "solid":
1115
+ case "angular":
1116
+ return convertStyleMapToCSSArray(style).join(" ");
1117
+ case "qwik":
1118
+ case "reactNative":
1119
+ case "react":
1120
+ case "rsc":
1121
+ return style;
1282
1122
  }
1123
+ }
1124
+
1125
+ // src/components/block/block.helpers.ts
1126
+ var checkIsComponentRestricted = (component, model) => {
1127
+ if (!component)
1128
+ return true;
1129
+ if (!model)
1130
+ return false;
1131
+ return component.models && component.models.length > 0 && !component.models.includes(model);
1283
1132
  };
1284
- var setLocalStorageItem = ({
1285
- key,
1286
- canTrack,
1287
- value
1133
+ var getComponent = ({
1134
+ block,
1135
+ registeredComponents,
1136
+ model
1288
1137
  }) => {
1289
- try {
1290
- if (canTrack) {
1291
- getLocalStorage()?.setItem(key, value);
1292
- }
1293
- } catch (err) {
1294
- console.debug("[LocalStorage] SET error: ", err);
1138
+ const componentName = block.component?.name;
1139
+ if (!componentName) {
1140
+ return null;
1141
+ }
1142
+ const ref = registeredComponents[componentName];
1143
+ if (!ref || checkIsComponentRestricted(ref, model)) {
1144
+ console.warn(`
1145
+ Could not find a registered component named "${componentName}".
1146
+ If you registered it, is the file that registered it imported by the file that needs to render it?`);
1147
+ return void 0;
1148
+ } else {
1149
+ return ref;
1295
1150
  }
1296
1151
  };
1297
-
1298
- // src/helpers/visitorId.ts
1299
- var VISITOR_LOCAL_STORAGE_KEY = "builderVisitorId";
1300
- var getVisitorId = ({
1301
- canTrack
1152
+ var getRepeatItemData = ({
1153
+ block,
1154
+ context
1302
1155
  }) => {
1303
- if (!canTrack) {
1156
+ const {
1157
+ repeat,
1158
+ ...blockWithoutRepeat
1159
+ } = block;
1160
+ if (!repeat?.collection) {
1304
1161
  return void 0;
1305
1162
  }
1306
- const visitorId = getLocalStorageItem({
1307
- key: VISITOR_LOCAL_STORAGE_KEY,
1308
- canTrack
1163
+ const itemsArray = evaluate({
1164
+ code: repeat.collection,
1165
+ localState: context.localState,
1166
+ rootState: context.rootState,
1167
+ rootSetState: context.rootSetState,
1168
+ context: context.context
1309
1169
  });
1310
- if (checkIsDefined(visitorId)) {
1311
- return visitorId;
1312
- } else {
1313
- const newVisitorId = createVisitorId();
1314
- setVisitorId({
1315
- id: newVisitorId,
1316
- canTrack
1317
- });
1318
- return newVisitorId;
1170
+ if (!Array.isArray(itemsArray)) {
1171
+ return void 0;
1172
+ }
1173
+ const collectionName = repeat.collection.split(".").pop();
1174
+ const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
1175
+ const repeatArray = itemsArray.map((item, index) => ({
1176
+ context: {
1177
+ ...context,
1178
+ localState: {
1179
+ ...context.localState,
1180
+ $index: index,
1181
+ $item: item,
1182
+ [itemNameToUse]: item,
1183
+ [`$${itemNameToUse}Index`]: index
1184
+ }
1185
+ },
1186
+ block: blockWithoutRepeat
1187
+ }));
1188
+ return repeatArray;
1189
+ };
1190
+ var provideLinkComponent = (block, linkComponent) => {
1191
+ if (block?.shouldReceiveBuilderProps?.builderLinkComponent)
1192
+ return {
1193
+ builderLinkComponent: linkComponent
1194
+ };
1195
+ return {};
1196
+ };
1197
+ var provideRegisteredComponents = (block, registeredComponents, model) => {
1198
+ if (block?.shouldReceiveBuilderProps?.builderComponents) {
1199
+ const filteredRegisteredComponents = Object.fromEntries(Object.entries(registeredComponents).filter(([_, component]) => {
1200
+ return !checkIsComponentRestricted(component, model);
1201
+ }));
1202
+ return {
1203
+ builderComponents: filteredRegisteredComponents
1204
+ };
1319
1205
  }
1206
+ return {};
1320
1207
  };
1321
- var createVisitorId = () => uuid();
1322
- var setVisitorId = ({
1323
- id,
1324
- canTrack
1325
- }) => setLocalStorageItem({
1326
- key: VISITOR_LOCAL_STORAGE_KEY,
1327
- value: id,
1328
- canTrack
1208
+ var provideBuilderBlock = (block, builderBlock) => {
1209
+ if (block?.shouldReceiveBuilderProps?.builderBlock)
1210
+ return {
1211
+ builderBlock
1212
+ };
1213
+ return {};
1214
+ };
1215
+ var provideBuilderContext = (block, context) => {
1216
+ if (block?.shouldReceiveBuilderProps?.builderContext)
1217
+ return {
1218
+ builderContext: context
1219
+ };
1220
+ return {};
1221
+ };
1222
+ var generateKey = (index) => {
1223
+ return index.toString();
1224
+ };
1225
+
1226
+ // src/functions/event-handler-name.ts
1227
+ function capitalizeFirstLetter(string) {
1228
+ return string.charAt(0).toUpperCase() + string.slice(1);
1229
+ }
1230
+ var getEventHandlerName = (key) => `on${capitalizeFirstLetter(key)}`;
1231
+
1232
+ // src/functions/get-block-actions-handler.ts
1233
+ var createEventHandler = (value, options) => (event) => evaluate({
1234
+ code: value,
1235
+ context: options.context,
1236
+ localState: options.localState,
1237
+ rootState: options.rootState,
1238
+ rootSetState: options.rootSetState,
1239
+ event,
1240
+ isExpression: false,
1241
+ trackingContext: options.trackingContext
1329
1242
  });
1330
1243
 
1331
- // src/functions/log-fetch.ts
1332
- function logFetch(url) {
1333
- if (typeof process !== "undefined" && process.env?.DEBUG) {
1334
- if (String(process.env.DEBUG) == "true") {
1335
- logger.log(url);
1244
+ // src/functions/get-block-actions.ts
1245
+ function getBlockActions(options) {
1246
+ const obj = {};
1247
+ const optionActions = options.block.actions ?? {};
1248
+ for (const key in optionActions) {
1249
+ if (!optionActions.hasOwnProperty(key)) {
1250
+ continue;
1251
+ }
1252
+ const value = optionActions[key];
1253
+ let eventHandlerName = getEventHandlerName(key);
1254
+ if (options.stripPrefix) {
1255
+ switch (TARGET) {
1256
+ case "vue":
1257
+ eventHandlerName = eventHandlerName.replace("v-on:", "");
1258
+ break;
1259
+ case "svelte":
1260
+ eventHandlerName = eventHandlerName.replace("on:", "");
1261
+ break;
1262
+ }
1336
1263
  }
1264
+ obj[eventHandlerName] = createEventHandler(value, options);
1337
1265
  }
1266
+ return obj;
1338
1267
  }
1339
1268
 
1340
- // src/functions/track/index.ts
1341
- var getTrackingEventData = async ({
1342
- canTrack
1343
- }) => {
1344
- if (!canTrack) {
1345
- return {
1346
- visitorId: void 0,
1347
- sessionId: void 0
1348
- };
1349
- }
1350
- const sessionId = await getSessionId({
1351
- canTrack
1352
- });
1353
- const visitorId = getVisitorId({
1354
- canTrack
1355
- });
1269
+ // src/functions/transform-block-properties.ts
1270
+ function transformBlockProperties({
1271
+ properties
1272
+ }) {
1273
+ return properties;
1274
+ }
1275
+
1276
+ // src/functions/get-block-properties.ts
1277
+ var extractRelevantRootBlockProperties = (block) => {
1356
1278
  return {
1357
- sessionId,
1358
- visitorId
1279
+ href: block.href
1359
1280
  };
1360
1281
  };
1361
- var createEvent = async ({
1362
- type: eventType,
1363
- canTrack,
1364
- apiKey,
1365
- metadata,
1366
- ...properties
1367
- }) => ({
1368
- type: eventType,
1369
- data: {
1370
- ...properties,
1371
- metadata: {
1372
- url: location.href,
1373
- ...metadata
1374
- },
1375
- ...await getTrackingEventData({
1376
- canTrack
1282
+ function getBlockProperties({
1283
+ block,
1284
+ context
1285
+ }) {
1286
+ const properties = {
1287
+ ...extractRelevantRootBlockProperties(block),
1288
+ ...block.properties,
1289
+ "builder-id": block.id,
1290
+ style: getStyle({
1291
+ block,
1292
+ context
1377
1293
  }),
1378
- userAttributes: getUserAttributes(),
1379
- ownerId: apiKey
1294
+ [getClassPropName()]: [block.id, "builder-block", block.class, block.properties?.class].filter(Boolean).join(" ")
1295
+ };
1296
+ return transformBlockProperties({
1297
+ properties,
1298
+ context,
1299
+ block
1300
+ });
1301
+ }
1302
+
1303
+ // src/components/block/components/block-wrapper.tsx
1304
+ function BlockWrapper(props) {
1305
+ return <><Dynamic_renderer_default
1306
+ TagName={props.Wrapper}
1307
+ attributes={getBlockProperties({
1308
+ block: props.block,
1309
+ context: props.context
1310
+ })}
1311
+ actionAttributes={getBlockActions({
1312
+ block: props.block,
1313
+ rootState: props.context.rootState,
1314
+ rootSetState: props.context.rootSetState,
1315
+ localState: props.context.localState,
1316
+ context: props.context.context,
1317
+ stripPrefix: true,
1318
+ trackingContext: {
1319
+ apiKey: props.context.apiKey,
1320
+ canTrack: props.context.canTrack ?? true,
1321
+ contentId: props.context.content?.id,
1322
+ variationId: props.context.content?.testVariationId
1323
+ }
1324
+ })}
1325
+ >{props.children}</Dynamic_renderer_default></>;
1326
+ }
1327
+ var Block_wrapper_default = BlockWrapper;
1328
+
1329
+ // src/components/block/components/component-ref/component-ref.tsx
1330
+ import { Show as Show3, For, createSignal as createSignal3 } from "solid-js";
1331
+ import { Dynamic as Dynamic4 } from "solid-js/web";
1332
+
1333
+ // src/components/block/components/interactive-element.tsx
1334
+ import { Show as Show2, on, createEffect, createMemo as createMemo2, createSignal as createSignal2 } from "solid-js";
1335
+ import { Dynamic as Dynamic3 } from "solid-js/web";
1336
+
1337
+ // src/functions/is-previewing.ts
1338
+ function isPreviewing(search) {
1339
+ const searchToUse = search || (isBrowser() ? window.location.search : void 0);
1340
+ if (!searchToUse) {
1341
+ return false;
1380
1342
  }
1343
+ const normalizedSearch = getSearchString(searchToUse);
1344
+ return Boolean(normalizedSearch.indexOf("builder.preview=") !== -1);
1345
+ }
1346
+
1347
+ // src/functions/register-component.ts
1348
+ var createRegisterComponentMessage = (info) => ({
1349
+ type: "builder.registerComponent",
1350
+ data: serializeIncludingFunctions(info)
1381
1351
  });
1382
- async function _track({
1383
- apiHost,
1384
- ...eventProps
1385
- }) {
1386
- if (!eventProps.apiKey) {
1387
- logger.error("Missing API key for track call. Please provide your API key.");
1388
- return;
1352
+ var serializeFn = (fnValue) => {
1353
+ const fnStr = fnValue.toString().trim();
1354
+ const isArrowWithoutParens = /^[a-zA-Z0-9_]+\s*=>/i.test(fnStr);
1355
+ const appendFunction = !fnStr.startsWith("function") && !fnStr.startsWith("async") && !fnStr.startsWith("(") && !isArrowWithoutParens;
1356
+ return `return (${appendFunction ? "function " : ""}${fnStr}).apply(this, arguments)`;
1357
+ };
1358
+ function serializeIncludingFunctions(info) {
1359
+ return JSON.parse(JSON.stringify(info, (key, value) => {
1360
+ if (typeof value === "function") {
1361
+ return serializeFn(value);
1362
+ }
1363
+ return value;
1364
+ }));
1365
+ }
1366
+
1367
+ // src/functions/register.ts
1368
+ var registry = {};
1369
+ function register(type, info) {
1370
+ if (type === "plugin") {
1371
+ info = serializeIncludingFunctions(info);
1389
1372
  }
1390
- if (!eventProps.canTrack) {
1391
- return;
1373
+ let typeList = registry[type];
1374
+ if (!typeList) {
1375
+ typeList = registry[type] = [];
1392
1376
  }
1393
- if (isEditing()) {
1394
- return;
1377
+ typeList.push(info);
1378
+ if (isBrowser()) {
1379
+ const message = {
1380
+ type: "builder.register",
1381
+ data: {
1382
+ type,
1383
+ info
1384
+ }
1385
+ };
1386
+ try {
1387
+ parent.postMessage(message, "*");
1388
+ if (parent !== window) {
1389
+ window.postMessage(message, "*");
1390
+ }
1391
+ } catch (err) {
1392
+ console.debug("Could not postmessage", err);
1393
+ }
1395
1394
  }
1396
- if (!(isBrowser() || TARGET === "reactNative")) {
1397
- return;
1395
+ }
1396
+ function registerAction(action) {
1397
+ if (isBrowser()) {
1398
+ const actionClone = JSON.parse(JSON.stringify(action));
1399
+ if (action.action) {
1400
+ actionClone.action = action.action.toString();
1401
+ }
1402
+ window.parent?.postMessage({
1403
+ type: "builder.registerAction",
1404
+ data: actionClone
1405
+ }, "*");
1398
1406
  }
1399
- const baseUrl = apiHost || "https://cdn.builder.io";
1400
- const url = `${baseUrl}/api/v1/track`;
1401
- logFetch(url);
1402
- return fetch(url, {
1403
- method: "POST",
1404
- body: JSON.stringify({
1405
- events: [await createEvent(eventProps)]
1406
- }),
1407
- headers: {
1408
- "content-type": "application/json",
1409
- ...getSdkHeaders()
1410
- },
1411
- mode: "cors"
1412
- }).catch((err) => {
1413
- console.error("Failed to track: ", err);
1414
- });
1415
1407
  }
1416
- var track = (args) => _track({
1417
- ...args,
1418
- canTrack: true
1419
- });
1408
+
1409
+ // src/functions/set-editor-settings.ts
1410
+ var settings = {};
1411
+ function setEditorSettings(newSettings) {
1412
+ if (isBrowser()) {
1413
+ Object.assign(settings, newSettings);
1414
+ const message = {
1415
+ type: "builder.settingsChange",
1416
+ data: settings
1417
+ };
1418
+ parent.postMessage(message, "*");
1419
+ }
1420
+ }
1421
+
1422
+ // src/functions/get-builder-search-params/index.ts
1423
+ var BUILDER_SEARCHPARAMS_PREFIX = "builder.";
1424
+ var BUILDER_OPTIONS_PREFIX = "options.";
1425
+ var getBuilderSearchParams = (_options) => {
1426
+ if (!_options) {
1427
+ return {};
1428
+ }
1429
+ const options = normalizeSearchParams(_options);
1430
+ const newOptions = {};
1431
+ Object.keys(options).forEach((key) => {
1432
+ if (key.startsWith(BUILDER_SEARCHPARAMS_PREFIX)) {
1433
+ const trimmedKey = key.replace(BUILDER_SEARCHPARAMS_PREFIX, "").replace(BUILDER_OPTIONS_PREFIX, "");
1434
+ newOptions[trimmedKey] = options[key];
1435
+ }
1436
+ });
1437
+ return newOptions;
1438
+ };
1439
+ var getBuilderSearchParamsFromWindow = () => {
1440
+ if (!isBrowser()) {
1441
+ return {};
1442
+ }
1443
+ const searchParams = new URLSearchParams(window.location.search);
1444
+ return getBuilderSearchParams(searchParams);
1445
+ };
1420
1446
 
1421
1447
  // src/functions/is-from-trusted-host.ts
1422
1448
  var DEFAULT_TRUSTED_HOSTS = ["*.beta.builder.io", "beta.builder.io", "builder.io", "localhost", "qa.builder.io"];
@@ -2160,7 +2186,13 @@ function InteractiveElement(props) {
2160
2186
  rootState: props.context.rootState,
2161
2187
  rootSetState: props.context.rootSetState,
2162
2188
  localState: props.context.localState,
2163
- context: props.context.context
2189
+ context: props.context.context,
2190
+ trackingContext: {
2191
+ apiKey: props.context.apiKey,
2192
+ canTrack: props.context.canTrack ?? true,
2193
+ contentId: props.context.content?.id,
2194
+ variationId: props.context.content?.testVariationId
2195
+ }
2164
2196
  })
2165
2197
  } : {};
2166
2198
  });