@builder.io/sdk-solid 5.1.0 → 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.
package/lib/node/dev.jsx CHANGED
@@ -208,213 +208,365 @@ 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
211
+ // src/constants/sdk-version.ts
212
+ var SDK_VERSION = "5.1.1";
213
+
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
+ });
220
+
221
+ // src/helpers/nullable.ts
222
+ var checkIsDefined = (maybeT) => maybeT !== null && maybeT !== void 0;
223
+
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
+ };
235
+
236
+ // src/helpers/cookie.ts
237
+ var getCookieSync = ({
238
+ name,
239
+ canTrack
217
240
  }) => {
218
- return Object.entries({
219
- state,
220
- Builder: builder,
221
- // legacy
222
- builder,
223
- context,
224
- event
225
- });
241
+ try {
242
+ if (!canTrack) {
243
+ return void 0;
244
+ }
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;
249
+ }
226
250
  };
227
- var getBuilderGlobals = () => ({
228
- isEditing: isEditing(),
229
- isBrowser: isBrowser(),
230
- isServer: !isBrowser(),
231
- getUserAttributes: () => getUserAttributes()
232
- });
233
- var parseCode = (code, {
234
- isExpression = true
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
235
258
  }) => {
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;
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;
242
265
  };
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;
266
+ var setCookie = async ({
267
+ name,
268
+ value,
269
+ expires,
270
+ canTrack
271
+ }) => {
272
+ try {
273
+ if (!canTrack) {
274
+ return;
273
275
  }
276
+ const cookie = createCookieString({
277
+ name,
278
+ value,
279
+ expires
280
+ });
281
+ document.cookie = cookie;
282
+ } catch (err) {
283
+ logger.warn("[COOKIE] SET error: ", err?.message || err);
284
+ }
285
+ };
286
+
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);
274
292
  });
275
293
  }
294
+ function uuid() {
295
+ return uuidv4().replace(/-/g, "");
296
+ }
276
297
 
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
298
+ // src/helpers/sessionId.ts
299
+ var SESSION_LOCAL_STORAGE_KEY = "builderSessionId";
300
+ var getSessionId = async ({
301
+ canTrack
286
302
  }) => {
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
- };
299
-
300
- // src/constants/sdk-name.ts
301
- var SDK_NAME_FOR_TARGET = (() => {
302
- switch (TARGET) {
303
- case "rsc":
304
- return "react-nextjs";
305
- case "reactNative":
306
- return "react-native";
307
- default:
308
- return TARGET;
303
+ if (!canTrack) {
304
+ return void 0;
309
305
  }
310
- })();
311
- var SDK_NAME = `@builder.io/sdk-${SDK_NAME_FOR_TARGET}`;
312
-
313
- // src/functions/fast-clone.ts
314
- var fastClone = (obj) => JSON.parse(JSON.stringify(obj));
315
-
316
- // src/functions/set.ts
317
- var set = (obj, _path, value) => {
318
- if (Object(obj) !== obj) {
319
- return obj;
306
+ const sessionId = await getCookie({
307
+ name: SESSION_LOCAL_STORAGE_KEY,
308
+ canTrack
309
+ });
310
+ if (checkIsDefined(sessionId)) {
311
+ return sessionId;
312
+ } else {
313
+ const newSessionId = createSessionId();
314
+ setSessionId({
315
+ id: newSessionId,
316
+ canTrack
317
+ });
318
+ return newSessionId;
320
319
  }
321
- const path = Array.isArray(_path) ? _path : _path.toString().match(/[^.[\]]+/g);
322
- 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;
323
- return obj;
324
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
+ });
325
330
 
326
- // src/functions/evaluate/node-runtime/safeDynamicRequire.ts
327
- import { createRequire } from "node:module";
328
- var noop = () => {
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);
340
+ }
341
+ return void 0;
342
+ } catch (err) {
343
+ console.debug("[LocalStorage] GET error: ", err);
344
+ return void 0;
345
+ }
329
346
  };
330
- var safeDynamicRequire = noop;
331
- try {
332
- safeDynamicRequire = createRequire(import.meta.url);
333
- } catch (error) {
347
+ var setLocalStorageItem = ({
348
+ key,
349
+ canTrack,
350
+ value
351
+ }) => {
334
352
  try {
335
- safeDynamicRequire = eval("require");
336
- } catch (error2) {
353
+ if (canTrack) {
354
+ getLocalStorage()?.setItem(key, value);
355
+ }
356
+ } catch (err) {
357
+ console.debug("[LocalStorage] SET error: ", err);
337
358
  }
338
- }
359
+ };
339
360
 
340
- // src/functions/evaluate/node-runtime/node-runtime.ts
341
- var getSyncValName = (key) => `bldr_${key}_sync`;
342
- var BUILDER_SET_STATE_NAME = "BUILDER_SET_STATE";
343
- var INJECTED_IVM_GLOBAL = "BUILDER_IVM";
344
- var REF_TO_PROXY_FN = `
345
- var refToProxy = (obj) => {
346
- if (typeof obj !== 'object' || obj === null) {
347
- return obj;
348
- }
349
- return new Proxy({}, {
350
- get(target, key) {
351
- if (key === 'copySync') {
352
- return () => obj.copySync();
353
- }
354
- const val = obj.getSync(key);
355
- if (typeof val?.getSync === 'function') {
356
- return refToProxy(val);
357
- }
358
- return val;
359
- },
360
- set(target, key, value) {
361
- const v = typeof value === 'object' ? new ${INJECTED_IVM_GLOBAL}.Reference(value) : value;
362
- obj.setSync(key, v);
363
- ${BUILDER_SET_STATE_NAME}(key, value)
364
- },
365
- deleteProperty(target, key) {
366
- obj.deleteSync(key);
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;
368
+ }
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;
382
+ }
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);
367
399
  }
368
- })
400
+ }
369
401
  }
370
- `;
371
- var processCode = ({
372
- code,
373
- args
402
+
403
+ // src/functions/track/index.ts
404
+ var getTrackingEventData = async ({
405
+ canTrack
374
406
  }) => {
375
- const fnArgs = args.map(([name]) => `var ${name} = refToProxy(${getSyncValName(name)}); `).join("");
376
- return `
377
- ${REF_TO_PROXY_FN}
378
- ${fnArgs}
379
- function theFunction() {
380
- ${code}
407
+ if (!canTrack) {
408
+ return {
409
+ visitorId: void 0,
410
+ sessionId: void 0
411
+ };
412
+ }
413
+ const sessionId = await getSessionId({
414
+ canTrack
415
+ });
416
+ const visitorId = getVisitorId({
417
+ canTrack
418
+ });
419
+ return {
420
+ sessionId,
421
+ visitorId
422
+ };
423
+ };
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
443
+ }
444
+ });
445
+ async function _track({
446
+ apiHost,
447
+ ...eventProps
448
+ }) {
449
+ if (!eventProps.apiKey) {
450
+ logger.error("Missing API key for track call. Please provide your API key.");
451
+ return;
452
+ }
453
+ if (!eventProps.canTrack) {
454
+ return;
455
+ }
456
+ if (isEditing()) {
457
+ return;
458
+ }
459
+ if (!(isBrowser() || TARGET === "reactNative")) {
460
+ return;
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
+ });
381
478
  }
479
+ var track = (args) => _track({
480
+ ...args,
481
+ canTrack: true
482
+ });
382
483
 
383
- const output = theFunction()
384
-
385
- if (typeof output === 'object' && output !== null) {
386
- return JSON.stringify(output.copySync ? output.copySync() : output);
387
- } else {
388
- return output;
389
- }
390
- `;
391
- };
392
- var IVM_INSTANCE = null;
393
- var IVM_OPTIONS = {
394
- memoryLimit: 128
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
+ });
395
499
  };
396
- var SHOULD_MENTION_INITIALIZE_SCRIPT = SDK_NAME === "@builder.io/sdk-react-nextjs" || SDK_NAME === "@builder.io/sdk-react" || SDK_NAME === "@builder.io/sdk-qwik" || SDK_NAME === "@builder.io/sdk-vue";
397
- var getIvm = () => {
398
- try {
399
- if (IVM_INSTANCE)
400
- return IVM_INSTANCE;
401
- const dynRequiredIvm = safeDynamicRequire("isolated-vm");
402
- if (dynRequiredIvm)
403
- return dynRequiredIvm;
404
- } catch (error2) {
405
- logger.error("isolated-vm import error.", error2);
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;
508
+ }
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
+ } : {}
520
+ }
521
+ });
406
522
  }
407
- const ERROR_MESSAGE = `${MSG_PREFIX}could not import \`isolated-vm\` module for safe script execution on a Node server.
408
-
409
- SOLUTION: In a server-only execution path within your application, do one of the following:
410
-
411
- ${SHOULD_MENTION_INITIALIZE_SCRIPT ? `- import and call \`initializeNodeRuntime()\` from "${SDK_NAME}/node/init".` : ""}
412
- - add the following import: \`await import('isolated-vm')\`.
413
-
414
- For more information, visit https://builder.io/c/docs/integration-tips#enabling-data-bindings-in-node-environments`;
415
- throw new Error(ERROR_MESSAGE);
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;
416
533
  };
417
- var runInNode = ({
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
553
+ });
554
+ }
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.");
560
+ }
561
+ target[prop] = value;
562
+ rootSetState?.(target);
563
+ return true;
564
+ }
565
+ });
566
+ }
567
+
568
+ // src/functions/evaluate/browser-runtime/browser.ts
569
+ var runInBrowser = ({
418
570
  code,
419
571
  builder,
420
572
  context,
@@ -423,20 +575,159 @@ var runInNode = ({
423
575
  rootSetState,
424
576
  rootState
425
577
  }) => {
426
- const ivm = getIvm();
427
- let isolate;
428
- try {
429
- isolate = new ivm.Isolate(IVM_OPTIONS);
430
- const isolateContext = isolate.createContextSync();
431
- const jail = isolateContext.global;
432
- jail.setSync("global", jail.derefInto());
433
- jail.setSync("log", function(...logArgs) {
434
- console.log(...logArgs);
435
- });
436
- jail.setSync(INJECTED_IVM_GLOBAL, ivm);
437
- const state = fastClone({
438
- ...rootState,
439
- ...localState
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));
589
+ };
590
+
591
+ // src/constants/sdk-name.ts
592
+ var SDK_NAME_FOR_TARGET = (() => {
593
+ switch (TARGET) {
594
+ case "rsc":
595
+ return "react-nextjs";
596
+ case "reactNative":
597
+ return "react-native";
598
+ default:
599
+ return TARGET;
600
+ }
601
+ })();
602
+ var SDK_NAME = `@builder.io/sdk-${SDK_NAME_FOR_TARGET}`;
603
+
604
+ // src/functions/fast-clone.ts
605
+ var fastClone = (obj) => JSON.parse(JSON.stringify(obj));
606
+
607
+ // src/functions/set.ts
608
+ var set = (obj, _path, value) => {
609
+ if (Object(obj) !== obj) {
610
+ return obj;
611
+ }
612
+ const path = Array.isArray(_path) ? _path : _path.toString().match(/[^.[\]]+/g);
613
+ 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;
614
+ return obj;
615
+ };
616
+
617
+ // src/functions/evaluate/node-runtime/safeDynamicRequire.ts
618
+ import { createRequire } from "node:module";
619
+ var noop = () => {
620
+ };
621
+ var safeDynamicRequire = noop;
622
+ try {
623
+ safeDynamicRequire = createRequire(import.meta.url);
624
+ } catch (error) {
625
+ try {
626
+ safeDynamicRequire = eval("require");
627
+ } catch (error2) {
628
+ }
629
+ }
630
+
631
+ // src/functions/evaluate/node-runtime/node-runtime.ts
632
+ var getSyncValName = (key) => `bldr_${key}_sync`;
633
+ var BUILDER_SET_STATE_NAME = "BUILDER_SET_STATE";
634
+ var INJECTED_IVM_GLOBAL = "BUILDER_IVM";
635
+ var REF_TO_PROXY_FN = `
636
+ var refToProxy = (obj) => {
637
+ if (typeof obj !== 'object' || obj === null) {
638
+ return obj;
639
+ }
640
+ return new Proxy({}, {
641
+ get(target, key) {
642
+ if (key === 'copySync') {
643
+ return () => obj.copySync();
644
+ }
645
+ const val = obj.getSync(key);
646
+ if (typeof val?.getSync === 'function') {
647
+ return refToProxy(val);
648
+ }
649
+ return val;
650
+ },
651
+ set(target, key, value) {
652
+ const v = typeof value === 'object' ? new ${INJECTED_IVM_GLOBAL}.Reference(value) : value;
653
+ obj.setSync(key, v);
654
+ ${BUILDER_SET_STATE_NAME}(key, value)
655
+ },
656
+ deleteProperty(target, key) {
657
+ obj.deleteSync(key);
658
+ }
659
+ })
660
+ }
661
+ `;
662
+ var processCode = ({
663
+ code,
664
+ args
665
+ }) => {
666
+ const fnArgs = args.map(([name]) => `var ${name} = refToProxy(${getSyncValName(name)}); `).join("");
667
+ return `
668
+ ${REF_TO_PROXY_FN}
669
+ ${fnArgs}
670
+ function theFunction() {
671
+ ${code}
672
+ }
673
+
674
+ const output = theFunction()
675
+
676
+ if (typeof output === 'object' && output !== null) {
677
+ return JSON.stringify(output.copySync ? output.copySync() : output);
678
+ } else {
679
+ return output;
680
+ }
681
+ `;
682
+ };
683
+ var IVM_INSTANCE = null;
684
+ var IVM_OPTIONS = {
685
+ memoryLimit: 128
686
+ };
687
+ var SHOULD_MENTION_INITIALIZE_SCRIPT = SDK_NAME === "@builder.io/sdk-react-nextjs" || SDK_NAME === "@builder.io/sdk-react" || SDK_NAME === "@builder.io/sdk-qwik" || SDK_NAME === "@builder.io/sdk-vue";
688
+ var getIvm = () => {
689
+ try {
690
+ if (IVM_INSTANCE)
691
+ return IVM_INSTANCE;
692
+ const dynRequiredIvm = safeDynamicRequire("isolated-vm");
693
+ if (dynRequiredIvm)
694
+ return dynRequiredIvm;
695
+ } catch (error2) {
696
+ logger.error("isolated-vm import error.", error2);
697
+ }
698
+ const ERROR_MESSAGE = `${MSG_PREFIX}could not import \`isolated-vm\` module for safe script execution on a Node server.
699
+
700
+ SOLUTION: In a server-only execution path within your application, do one of the following:
701
+
702
+ ${SHOULD_MENTION_INITIALIZE_SCRIPT ? `- import and call \`initializeNodeRuntime()\` from "${SDK_NAME}/node/init".` : ""}
703
+ - add the following import: \`await import('isolated-vm')\`.
704
+
705
+ For more information, visit https://builder.io/c/docs/integration-tips#enabling-data-bindings-in-node-environments`;
706
+ throw new Error(ERROR_MESSAGE);
707
+ };
708
+ var runInNode = ({
709
+ code,
710
+ builder,
711
+ context,
712
+ event,
713
+ localState,
714
+ rootSetState,
715
+ rootState
716
+ }) => {
717
+ const ivm = getIvm();
718
+ let isolate;
719
+ try {
720
+ isolate = new ivm.Isolate(IVM_OPTIONS);
721
+ const isolateContext = isolate.createContextSync();
722
+ const jail = isolateContext.global;
723
+ jail.setSync("global", jail.derefInto());
724
+ jail.setSync("log", function(...logArgs) {
725
+ console.log(...logArgs);
726
+ });
727
+ jail.setSync(INJECTED_IVM_GLOBAL, ivm);
728
+ const state = fastClone({
729
+ ...rootState,
730
+ ...localState
440
731
  });
441
732
  const args = getFunctionArguments({
442
733
  builder,
@@ -479,9 +770,6 @@ var runInNode = ({
479
770
  }
480
771
  };
481
772
 
482
- // src/helpers/nullable.ts
483
- var checkIsDefined = (maybeT) => maybeT !== null && maybeT !== void 0;
484
-
485
773
  // src/functions/is-node-runtime.ts
486
774
  function isNodeRuntime() {
487
775
  return typeof process !== "undefined" && checkIsDefined(process?.versions?.node);
@@ -526,7 +814,8 @@ function evaluate({
526
814
  rootState,
527
815
  rootSetState,
528
816
  event,
529
- isExpression = true
817
+ isExpression = true,
818
+ trackingContext
530
819
  }) {
531
820
  if (code.trim() === "") {
532
821
  return void 0;
@@ -542,7 +831,7 @@ function evaluate({
542
831
  code: parseCode(code, {
543
832
  isExpression
544
833
  }),
545
- builder: getBuilderGlobals(),
834
+ builder: getBuilderGlobals(trackingContext),
546
835
  context,
547
836
  event,
548
837
  rootSetState,
@@ -791,801 +1080,538 @@ function throttle(func, wait, options = {}) {
791
1080
  previous = now;
792
1081
  result = func.apply(context, args);
793
1082
  if (!timeout)
794
- context = args = null;
795
- } else if (!timeout && options.trailing !== false) {
796
- timeout = setTimeout(later, remaining);
797
- }
798
- return result;
799
- };
800
- }
801
- function assign(target, ..._args) {
802
- const to = Object(target);
803
- for (let index = 1; index < arguments.length; index++) {
804
- const nextSource = arguments[index];
805
- if (nextSource != null) {
806
- for (const nextKey in nextSource) {
807
- if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
808
- to[nextKey] = nextSource[nextKey];
809
- }
810
- }
811
- }
812
- }
813
- return to;
814
- }
815
- function bindAnimations(animations) {
816
- if (TARGET === "reactNative") {
817
- return;
818
- }
819
- for (const animation of animations) {
820
- switch (animation.trigger) {
821
- case "pageLoad":
822
- triggerAnimation(animation);
823
- break;
824
- case "scrollInView":
825
- bindScrollInViewAnimation(animation);
826
- break;
827
- }
828
- }
829
- }
830
- function warnElementNotPresent(id) {
831
- console.warn(`Cannot animate element: element with ID ${id} not found!`);
832
- }
833
- function augmentAnimation(animation, element) {
834
- const stylesUsed = getAllStylesUsed(animation);
835
- const computedStyle = getComputedStyle(element);
836
- const firstStyles = animation.steps[0].styles;
837
- const lastStyles = animation.steps[animation.steps.length - 1].styles;
838
- const bothStyles = [firstStyles, lastStyles];
839
- for (const styles of bothStyles) {
840
- for (const style of stylesUsed) {
841
- if (!(style in styles)) {
842
- styles[style] = computedStyle[style];
843
- }
844
- }
845
- }
846
- }
847
- function getAllStylesUsed(animation) {
848
- const properties = [];
849
- for (const step of animation.steps) {
850
- for (const key in step.styles) {
851
- if (properties.indexOf(key) === -1) {
852
- properties.push(key);
853
- }
854
- }
855
- }
856
- return properties;
857
- }
858
- function triggerAnimation(animation) {
859
- const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
860
- if (!elements.length) {
861
- warnElementNotPresent(animation.elementId || animation.id || "");
862
- return;
863
- }
864
- Array.from(elements).forEach((element) => {
865
- augmentAnimation(animation, element);
866
- element.style.transition = "none";
867
- element.style.transitionDelay = "0";
868
- assign(element.style, animation.steps[0].styles);
869
- setTimeout(() => {
870
- element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
871
- if (animation.delay) {
872
- element.style.transitionDelay = animation.delay + "s";
873
- }
874
- assign(element.style, animation.steps[1].styles);
875
- setTimeout(() => {
876
- element.style.transition = "";
877
- element.style.transitionDelay = "";
878
- }, (animation.delay || 0) * 1e3 + animation.duration * 1e3 + 100);
879
- });
880
- });
881
- }
882
- function bindScrollInViewAnimation(animation) {
883
- const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
884
- if (!elements.length) {
885
- warnElementNotPresent(animation.elementId || animation.id || "");
886
- return;
887
- }
888
- Array.from(elements).forEach((element) => {
889
- augmentAnimation(animation, element);
890
- let triggered = false;
891
- let pendingAnimation = false;
892
- function immediateOnScroll() {
893
- if (!triggered && isScrolledIntoView(element)) {
894
- triggered = true;
895
- pendingAnimation = true;
896
- setTimeout(() => {
897
- assign(element.style, animation.steps[1].styles);
898
- if (!animation.repeat) {
899
- document.removeEventListener("scroll", onScroll);
900
- }
901
- setTimeout(() => {
902
- pendingAnimation = false;
903
- if (!animation.repeat) {
904
- element.style.transition = "";
905
- element.style.transitionDelay = "";
906
- }
907
- }, (animation.duration + (animation.delay || 0)) * 1e3 + 100);
908
- });
909
- } else if (animation.repeat && triggered && !pendingAnimation && !isScrolledIntoView(element)) {
910
- triggered = false;
911
- assign(element.style, animation.steps[0].styles);
912
- }
913
- }
914
- const onScroll = throttle(immediateOnScroll, 200, {
915
- leading: false
916
- });
917
- function isScrolledIntoView(elem) {
918
- const rect = elem.getBoundingClientRect();
919
- const windowHeight = window.innerHeight;
920
- const thresholdPercent = (animation.thresholdPercent || 0) / 100;
921
- const threshold = thresholdPercent * windowHeight;
922
- return rect.bottom > threshold && rect.top < windowHeight - threshold;
923
- }
924
- const defaultState = animation.steps[0].styles;
925
- function attachDefaultState() {
926
- assign(element.style, defaultState);
927
- }
928
- attachDefaultState();
929
- setTimeout(() => {
930
- element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
931
- if (animation.delay) {
932
- element.style.transitionDelay = animation.delay + "s";
933
- }
934
- });
935
- document.addEventListener("scroll", onScroll, {
936
- capture: true,
937
- passive: true
938
- });
939
- immediateOnScroll();
940
- });
941
- }
942
-
943
- // src/helpers/css.ts
944
- var convertStyleMapToCSSArray = (style) => {
945
- const cssProps = Object.entries(style).map(([key, value]) => {
946
- if (typeof value === "string") {
947
- return `${camelToKebabCase(key)}: ${value};`;
948
- } else {
949
- return void 0;
950
- }
951
- });
952
- return cssProps.filter(checkIsDefined);
953
- };
954
- var convertStyleMapToCSS = (style) => convertStyleMapToCSSArray(style).join("\n");
955
- var createCssClass = ({
956
- mediaQuery,
957
- className,
958
- styles
959
- }) => {
960
- const cssClass = `.${className} {
961
- ${convertStyleMapToCSS(styles)}
962
- }`;
963
- if (mediaQuery) {
964
- return `${mediaQuery} {
965
- ${cssClass}
966
- }`;
967
- } else {
968
- return cssClass;
969
- }
970
- };
971
-
972
- // src/functions/transform-style-property.ts
973
- function transformStyleProperty({
974
- style
975
- }) {
976
- return style;
977
- }
978
-
979
- // src/functions/get-style.ts
980
- var getStyle = ({
981
- block,
982
- context
983
- }) => {
984
- return mapStyleObjToStrIfNeeded(transformStyleProperty({
985
- style: block.style || {},
986
- context,
987
- block
988
- }));
989
- };
990
- function mapStyleObjToStrIfNeeded(style) {
991
- switch (TARGET) {
992
- case "svelte":
993
- case "vue":
994
- case "solid":
995
- case "angular":
996
- return convertStyleMapToCSSArray(style).join(" ");
997
- case "qwik":
998
- case "reactNative":
999
- case "react":
1000
- case "rsc":
1001
- return style;
1002
- }
1003
- }
1004
-
1005
- // src/components/block/block.helpers.ts
1006
- var checkIsComponentRestricted = (component, model) => {
1007
- if (!component)
1008
- return true;
1009
- if (!model)
1010
- return false;
1011
- return component.models && component.models.length > 0 && !component.models.includes(model);
1012
- };
1013
- var getComponent = ({
1014
- block,
1015
- registeredComponents,
1016
- model
1017
- }) => {
1018
- const componentName = block.component?.name;
1019
- if (!componentName) {
1020
- return null;
1021
- }
1022
- const ref = registeredComponents[componentName];
1023
- if (!ref || checkIsComponentRestricted(ref, model)) {
1024
- console.warn(`
1025
- Could not find a registered component named "${componentName}".
1026
- If you registered it, is the file that registered it imported by the file that needs to render it?`);
1027
- return void 0;
1028
- } else {
1029
- return ref;
1030
- }
1031
- };
1032
- var getRepeatItemData = ({
1033
- block,
1034
- context
1035
- }) => {
1036
- const {
1037
- repeat,
1038
- ...blockWithoutRepeat
1039
- } = block;
1040
- if (!repeat?.collection) {
1041
- return void 0;
1042
- }
1043
- const itemsArray = evaluate({
1044
- code: repeat.collection,
1045
- localState: context.localState,
1046
- rootState: context.rootState,
1047
- rootSetState: context.rootSetState,
1048
- context: context.context
1049
- });
1050
- if (!Array.isArray(itemsArray)) {
1051
- return void 0;
1052
- }
1053
- const collectionName = repeat.collection.split(".").pop();
1054
- const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
1055
- const repeatArray = itemsArray.map((item, index) => ({
1056
- context: {
1057
- ...context,
1058
- localState: {
1059
- ...context.localState,
1060
- $index: index,
1061
- $item: item,
1062
- [itemNameToUse]: item,
1063
- [`$${itemNameToUse}Index`]: index
1064
- }
1065
- },
1066
- block: blockWithoutRepeat
1067
- }));
1068
- return repeatArray;
1069
- };
1070
- var provideLinkComponent = (block, linkComponent) => {
1071
- if (block?.shouldReceiveBuilderProps?.builderLinkComponent)
1072
- return {
1073
- builderLinkComponent: linkComponent
1074
- };
1075
- return {};
1076
- };
1077
- var provideRegisteredComponents = (block, registeredComponents, model) => {
1078
- if (block?.shouldReceiveBuilderProps?.builderComponents) {
1079
- const filteredRegisteredComponents = Object.fromEntries(Object.entries(registeredComponents).filter(([_, component]) => {
1080
- return !checkIsComponentRestricted(component, model);
1081
- }));
1082
- return {
1083
- builderComponents: filteredRegisteredComponents
1084
- };
1085
- }
1086
- return {};
1087
- };
1088
- var provideBuilderBlock = (block, builderBlock) => {
1089
- if (block?.shouldReceiveBuilderProps?.builderBlock)
1090
- return {
1091
- builderBlock
1092
- };
1093
- return {};
1094
- };
1095
- var provideBuilderContext = (block, context) => {
1096
- if (block?.shouldReceiveBuilderProps?.builderContext)
1097
- return {
1098
- builderContext: context
1099
- };
1100
- return {};
1101
- };
1102
- var generateKey = (index) => {
1103
- return index.toString();
1104
- };
1105
-
1106
- // src/functions/event-handler-name.ts
1107
- function capitalizeFirstLetter(string) {
1108
- return string.charAt(0).toUpperCase() + string.slice(1);
1109
- }
1110
- var getEventHandlerName = (key) => `on${capitalizeFirstLetter(key)}`;
1111
-
1112
- // src/functions/get-block-actions-handler.ts
1113
- var createEventHandler = (value, options) => (event) => evaluate({
1114
- code: value,
1115
- context: options.context,
1116
- localState: options.localState,
1117
- rootState: options.rootState,
1118
- rootSetState: options.rootSetState,
1119
- event,
1120
- isExpression: false
1121
- });
1122
-
1123
- // src/functions/get-block-actions.ts
1124
- function getBlockActions(options) {
1125
- const obj = {};
1126
- const optionActions = options.block.actions ?? {};
1127
- for (const key in optionActions) {
1128
- if (!optionActions.hasOwnProperty(key)) {
1129
- continue;
1130
- }
1131
- const value = optionActions[key];
1132
- let eventHandlerName = getEventHandlerName(key);
1133
- if (options.stripPrefix) {
1134
- switch (TARGET) {
1135
- case "vue":
1136
- eventHandlerName = eventHandlerName.replace("v-on:", "");
1137
- break;
1138
- case "svelte":
1139
- eventHandlerName = eventHandlerName.replace("on:", "");
1140
- break;
1141
- }
1142
- }
1143
- obj[eventHandlerName] = createEventHandler(value, options);
1144
- }
1145
- return obj;
1146
- }
1147
-
1148
- // src/functions/transform-block-properties.ts
1149
- function transformBlockProperties({
1150
- properties
1151
- }) {
1152
- return properties;
1153
- }
1154
-
1155
- // src/functions/get-block-properties.ts
1156
- var extractRelevantRootBlockProperties = (block) => {
1157
- return {
1158
- href: block.href
1159
- };
1160
- };
1161
- function getBlockProperties({
1162
- block,
1163
- context
1164
- }) {
1165
- const properties = {
1166
- ...extractRelevantRootBlockProperties(block),
1167
- ...block.properties,
1168
- "builder-id": block.id,
1169
- style: getStyle({
1170
- block,
1171
- context
1172
- }),
1173
- [getClassPropName()]: [block.id, "builder-block", block.class, block.properties?.class].filter(Boolean).join(" ")
1174
- };
1175
- return transformBlockProperties({
1176
- properties,
1177
- context,
1178
- block
1179
- });
1180
- }
1181
-
1182
- // src/components/block/components/block-wrapper.tsx
1183
- function BlockWrapper(props) {
1184
- return <><Dynamic_renderer_default
1185
- TagName={props.Wrapper}
1186
- attributes={getBlockProperties({
1187
- block: props.block,
1188
- context: props.context
1189
- })}
1190
- actionAttributes={getBlockActions({
1191
- block: props.block,
1192
- rootState: props.context.rootState,
1193
- rootSetState: props.context.rootSetState,
1194
- localState: props.context.localState,
1195
- context: props.context.context,
1196
- stripPrefix: true
1197
- })}
1198
- >{props.children}</Dynamic_renderer_default></>;
1199
- }
1200
- var Block_wrapper_default = BlockWrapper;
1201
-
1202
- // src/components/block/components/component-ref/component-ref.tsx
1203
- import { Show as Show3, For, createSignal as createSignal3 } from "solid-js";
1204
- import { Dynamic as Dynamic4 } from "solid-js/web";
1205
-
1206
- // src/components/block/components/interactive-element.tsx
1207
- import { Show as Show2, on, createEffect, createMemo as createMemo2, createSignal as createSignal2 } from "solid-js";
1208
- import { Dynamic as Dynamic3 } from "solid-js/web";
1209
-
1210
- // src/functions/is-previewing.ts
1211
- function isPreviewing(search) {
1212
- const searchToUse = search || (isBrowser() ? window.location.search : void 0);
1213
- if (!searchToUse) {
1214
- return false;
1215
- }
1216
- const normalizedSearch = getSearchString(searchToUse);
1217
- return Boolean(normalizedSearch.indexOf("builder.preview=") !== -1);
1218
- }
1219
-
1220
- // src/functions/register-component.ts
1221
- var createRegisterComponentMessage = (info) => ({
1222
- type: "builder.registerComponent",
1223
- data: serializeIncludingFunctions(info)
1224
- });
1225
- var serializeFn = (fnValue) => {
1226
- const fnStr = fnValue.toString().trim();
1227
- const isArrowWithoutParens = /^[a-zA-Z0-9_]+\s*=>/i.test(fnStr);
1228
- const appendFunction = !fnStr.startsWith("function") && !fnStr.startsWith("async") && !fnStr.startsWith("(") && !isArrowWithoutParens;
1229
- return `return (${appendFunction ? "function " : ""}${fnStr}).apply(this, arguments)`;
1230
- };
1231
- function serializeIncludingFunctions(info) {
1232
- return JSON.parse(JSON.stringify(info, (key, value) => {
1233
- if (typeof value === "function") {
1234
- return serializeFn(value);
1083
+ context = args = null;
1084
+ } else if (!timeout && options.trailing !== false) {
1085
+ timeout = setTimeout(later, remaining);
1235
1086
  }
1236
- return value;
1237
- }));
1087
+ return result;
1088
+ };
1238
1089
  }
1239
-
1240
- // src/functions/register.ts
1241
- var registry = {};
1242
- function register(type, info) {
1243
- if (type === "plugin") {
1244
- info = serializeIncludingFunctions(info);
1245
- }
1246
- let typeList = registry[type];
1247
- if (!typeList) {
1248
- typeList = registry[type] = [];
1249
- }
1250
- typeList.push(info);
1251
- if (isBrowser()) {
1252
- const message = {
1253
- type: "builder.register",
1254
- data: {
1255
- type,
1256
- info
1257
- }
1258
- };
1259
- try {
1260
- parent.postMessage(message, "*");
1261
- if (parent !== window) {
1262
- window.postMessage(message, "*");
1090
+ function assign(target, ..._args) {
1091
+ const to = Object(target);
1092
+ for (let index = 1; index < arguments.length; index++) {
1093
+ const nextSource = arguments[index];
1094
+ if (nextSource != null) {
1095
+ for (const nextKey in nextSource) {
1096
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
1097
+ to[nextKey] = nextSource[nextKey];
1098
+ }
1263
1099
  }
1264
- } catch (err) {
1265
- console.debug("Could not postmessage", err);
1266
1100
  }
1267
1101
  }
1102
+ return to;
1268
1103
  }
1269
- function registerAction(action) {
1270
- if (isBrowser()) {
1271
- const actionClone = JSON.parse(JSON.stringify(action));
1272
- if (action.action) {
1273
- actionClone.action = action.action.toString();
1104
+ function bindAnimations(animations) {
1105
+ if (TARGET === "reactNative") {
1106
+ return;
1107
+ }
1108
+ for (const animation of animations) {
1109
+ switch (animation.trigger) {
1110
+ case "pageLoad":
1111
+ triggerAnimation(animation);
1112
+ break;
1113
+ case "scrollInView":
1114
+ bindScrollInViewAnimation(animation);
1115
+ break;
1274
1116
  }
1275
- window.parent?.postMessage({
1276
- type: "builder.registerAction",
1277
- data: actionClone
1278
- }, "*");
1279
1117
  }
1280
1118
  }
1281
-
1282
- // src/functions/set-editor-settings.ts
1283
- var settings = {};
1284
- function setEditorSettings(newSettings) {
1285
- if (isBrowser()) {
1286
- Object.assign(settings, newSettings);
1287
- const message = {
1288
- type: "builder.settingsChange",
1289
- data: settings
1290
- };
1291
- parent.postMessage(message, "*");
1292
- }
1119
+ function warnElementNotPresent(id) {
1120
+ console.warn(`Cannot animate element: element with ID ${id} not found!`);
1293
1121
  }
1294
-
1295
- // src/functions/get-builder-search-params/index.ts
1296
- var BUILDER_SEARCHPARAMS_PREFIX = "builder.";
1297
- var BUILDER_OPTIONS_PREFIX = "options.";
1298
- var getBuilderSearchParams = (_options) => {
1299
- if (!_options) {
1300
- return {};
1122
+ function augmentAnimation(animation, element) {
1123
+ const stylesUsed = getAllStylesUsed(animation);
1124
+ const computedStyle = getComputedStyle(element);
1125
+ const firstStyles = animation.steps[0].styles;
1126
+ const lastStyles = animation.steps[animation.steps.length - 1].styles;
1127
+ const bothStyles = [firstStyles, lastStyles];
1128
+ for (const styles of bothStyles) {
1129
+ for (const style of stylesUsed) {
1130
+ if (!(style in styles)) {
1131
+ styles[style] = computedStyle[style];
1132
+ }
1133
+ }
1301
1134
  }
1302
- const options = normalizeSearchParams(_options);
1303
- const newOptions = {};
1304
- Object.keys(options).forEach((key) => {
1305
- if (key.startsWith(BUILDER_SEARCHPARAMS_PREFIX)) {
1306
- const trimmedKey = key.replace(BUILDER_SEARCHPARAMS_PREFIX, "").replace(BUILDER_OPTIONS_PREFIX, "");
1307
- newOptions[trimmedKey] = options[key];
1135
+ }
1136
+ function getAllStylesUsed(animation) {
1137
+ const properties = [];
1138
+ for (const step of animation.steps) {
1139
+ for (const key in step.styles) {
1140
+ if (properties.indexOf(key) === -1) {
1141
+ properties.push(key);
1142
+ }
1308
1143
  }
1309
- });
1310
- return newOptions;
1311
- };
1312
- var getBuilderSearchParamsFromWindow = () => {
1313
- if (!isBrowser()) {
1314
- return {};
1315
1144
  }
1316
- const searchParams = new URLSearchParams(window.location.search);
1317
- return getBuilderSearchParams(searchParams);
1318
- };
1319
-
1320
- // src/constants/sdk-version.ts
1321
- var SDK_VERSION = "5.1.0";
1322
-
1323
- // src/helpers/sdk-headers.ts
1324
- var getSdkHeaders = () => ({
1325
- "X-Builder-SDK": TARGET,
1326
- "X-Builder-SDK-GEN": "2",
1327
- "X-Builder-SDK-Version": SDK_VERSION
1328
- });
1329
-
1330
- // src/helpers/url.ts
1331
- var getTopLevelDomain = (host) => {
1332
- if (host === "localhost" || host === "127.0.0.1") {
1333
- return host;
1145
+ return properties;
1146
+ }
1147
+ function triggerAnimation(animation) {
1148
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
1149
+ if (!elements.length) {
1150
+ warnElementNotPresent(animation.elementId || animation.id || "");
1151
+ return;
1334
1152
  }
1335
- const parts = host.split(".");
1336
- if (parts.length > 2) {
1337
- return parts.slice(1).join(".");
1153
+ Array.from(elements).forEach((element) => {
1154
+ augmentAnimation(animation, element);
1155
+ element.style.transition = "none";
1156
+ element.style.transitionDelay = "0";
1157
+ assign(element.style, animation.steps[0].styles);
1158
+ setTimeout(() => {
1159
+ element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
1160
+ if (animation.delay) {
1161
+ element.style.transitionDelay = animation.delay + "s";
1162
+ }
1163
+ assign(element.style, animation.steps[1].styles);
1164
+ setTimeout(() => {
1165
+ element.style.transition = "";
1166
+ element.style.transitionDelay = "";
1167
+ }, (animation.delay || 0) * 1e3 + animation.duration * 1e3 + 100);
1168
+ });
1169
+ });
1170
+ }
1171
+ function bindScrollInViewAnimation(animation) {
1172
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
1173
+ if (!elements.length) {
1174
+ warnElementNotPresent(animation.elementId || animation.id || "");
1175
+ return;
1338
1176
  }
1339
- return host;
1340
- };
1341
-
1342
- // src/helpers/cookie.ts
1343
- var getCookieSync = ({
1344
- name,
1345
- canTrack
1346
- }) => {
1347
- try {
1348
- if (!canTrack) {
1349
- return void 0;
1177
+ Array.from(elements).forEach((element) => {
1178
+ augmentAnimation(animation, element);
1179
+ let triggered = false;
1180
+ let pendingAnimation = false;
1181
+ function immediateOnScroll() {
1182
+ if (!triggered && isScrolledIntoView(element)) {
1183
+ triggered = true;
1184
+ pendingAnimation = true;
1185
+ setTimeout(() => {
1186
+ assign(element.style, animation.steps[1].styles);
1187
+ if (!animation.repeat) {
1188
+ document.removeEventListener("scroll", onScroll);
1189
+ }
1190
+ setTimeout(() => {
1191
+ pendingAnimation = false;
1192
+ if (!animation.repeat) {
1193
+ element.style.transition = "";
1194
+ element.style.transitionDelay = "";
1195
+ }
1196
+ }, (animation.duration + (animation.delay || 0)) * 1e3 + 100);
1197
+ });
1198
+ } else if (animation.repeat && triggered && !pendingAnimation && !isScrolledIntoView(element)) {
1199
+ triggered = false;
1200
+ assign(element.style, animation.steps[0].styles);
1201
+ }
1350
1202
  }
1351
- return document.cookie.split("; ").find((row) => row.startsWith(`${name}=`))?.split("=")[1];
1352
- } catch (err) {
1353
- logger.warn("[COOKIE] GET error: ", err?.message || err);
1354
- return void 0;
1355
- }
1356
- };
1357
- var getCookie = async (args) => getCookieSync(args);
1358
- var stringifyCookie = (cookie) => cookie.map(([key, value]) => value ? `${key}=${value}` : key).filter(checkIsDefined).join("; ");
1359
- var SECURE_CONFIG = [["secure", ""], ["SameSite", "None"]];
1360
- var createCookieString = ({
1361
- name,
1362
- value,
1363
- expires
1364
- }) => {
1365
- const secure = isBrowser() ? location.protocol === "https:" : true;
1366
- const secureObj = secure ? SECURE_CONFIG : [[]];
1367
- const expiresObj = expires ? [["expires", expires.toUTCString()]] : [[]];
1368
- const cookieValue = [[name, value], ...expiresObj, ["path", "/"], ["domain", getTopLevelDomain(window.location.hostname)], ...secureObj];
1369
- const cookie = stringifyCookie(cookieValue);
1370
- return cookie;
1371
- };
1372
- var setCookie = async ({
1373
- name,
1374
- value,
1375
- expires,
1376
- canTrack
1377
- }) => {
1378
- try {
1379
- if (!canTrack) {
1380
- return;
1203
+ const onScroll = throttle(immediateOnScroll, 200, {
1204
+ leading: false
1205
+ });
1206
+ function isScrolledIntoView(elem) {
1207
+ const rect = elem.getBoundingClientRect();
1208
+ const windowHeight = window.innerHeight;
1209
+ const thresholdPercent = (animation.thresholdPercent || 0) / 100;
1210
+ const threshold = thresholdPercent * windowHeight;
1211
+ return rect.bottom > threshold && rect.top < windowHeight - threshold;
1381
1212
  }
1382
- const cookie = createCookieString({
1383
- name,
1384
- value,
1385
- expires
1213
+ const defaultState = animation.steps[0].styles;
1214
+ function attachDefaultState() {
1215
+ assign(element.style, defaultState);
1216
+ }
1217
+ attachDefaultState();
1218
+ setTimeout(() => {
1219
+ element.style.transition = `all ${animation.duration}s ${camelToKebabCase(animation.easing)}`;
1220
+ if (animation.delay) {
1221
+ element.style.transitionDelay = animation.delay + "s";
1222
+ }
1386
1223
  });
1387
- document.cookie = cookie;
1388
- } catch (err) {
1389
- logger.warn("[COOKIE] SET error: ", err?.message || err);
1390
- }
1391
- };
1392
-
1393
- // src/helpers/uuid.ts
1394
- function uuidv4() {
1395
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
1396
- const r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
1397
- return v.toString(16);
1224
+ document.addEventListener("scroll", onScroll, {
1225
+ capture: true,
1226
+ passive: true
1227
+ });
1228
+ immediateOnScroll();
1398
1229
  });
1399
1230
  }
1400
- function uuid() {
1401
- return uuidv4().replace(/-/g, "");
1402
- }
1403
1231
 
1404
- // src/helpers/sessionId.ts
1405
- var SESSION_LOCAL_STORAGE_KEY = "builderSessionId";
1406
- var getSessionId = async ({
1407
- canTrack
1408
- }) => {
1409
- if (!canTrack) {
1410
- return void 0;
1411
- }
1412
- const sessionId = await getCookie({
1413
- name: SESSION_LOCAL_STORAGE_KEY,
1414
- canTrack
1232
+ // src/helpers/css.ts
1233
+ var convertStyleMapToCSSArray = (style) => {
1234
+ const cssProps = Object.entries(style).map(([key, value]) => {
1235
+ if (typeof value === "string") {
1236
+ return `${camelToKebabCase(key)}: ${value};`;
1237
+ } else {
1238
+ return void 0;
1239
+ }
1415
1240
  });
1416
- if (checkIsDefined(sessionId)) {
1417
- return sessionId;
1241
+ return cssProps.filter(checkIsDefined);
1242
+ };
1243
+ var convertStyleMapToCSS = (style) => convertStyleMapToCSSArray(style).join("\n");
1244
+ var createCssClass = ({
1245
+ mediaQuery,
1246
+ className,
1247
+ styles
1248
+ }) => {
1249
+ const cssClass = `.${className} {
1250
+ ${convertStyleMapToCSS(styles)}
1251
+ }`;
1252
+ if (mediaQuery) {
1253
+ return `${mediaQuery} {
1254
+ ${cssClass}
1255
+ }`;
1418
1256
  } else {
1419
- const newSessionId = createSessionId();
1420
- setSessionId({
1421
- id: newSessionId,
1422
- canTrack
1423
- });
1424
- return newSessionId;
1257
+ return cssClass;
1425
1258
  }
1426
1259
  };
1427
- var createSessionId = () => uuid();
1428
- var setSessionId = ({
1429
- id,
1430
- canTrack
1431
- }) => setCookie({
1432
- name: SESSION_LOCAL_STORAGE_KEY,
1433
- value: id,
1434
- canTrack
1435
- });
1436
1260
 
1437
- // src/helpers/localStorage.ts
1438
- var getLocalStorage = () => isBrowser() && typeof localStorage !== "undefined" ? localStorage : void 0;
1439
- var getLocalStorageItem = ({
1440
- key,
1441
- canTrack
1261
+ // src/functions/transform-style-property.ts
1262
+ function transformStyleProperty({
1263
+ style
1264
+ }) {
1265
+ return style;
1266
+ }
1267
+
1268
+ // src/functions/get-style.ts
1269
+ var getStyle = ({
1270
+ block,
1271
+ context
1442
1272
  }) => {
1443
- try {
1444
- if (canTrack) {
1445
- return getLocalStorage()?.getItem(key);
1446
- }
1447
- return void 0;
1448
- } catch (err) {
1449
- console.debug("[LocalStorage] GET error: ", err);
1450
- return void 0;
1273
+ return mapStyleObjToStrIfNeeded(transformStyleProperty({
1274
+ style: block.style || {},
1275
+ context,
1276
+ block
1277
+ }));
1278
+ };
1279
+ function mapStyleObjToStrIfNeeded(style) {
1280
+ switch (TARGET) {
1281
+ case "svelte":
1282
+ case "vue":
1283
+ case "solid":
1284
+ case "angular":
1285
+ return convertStyleMapToCSSArray(style).join(" ");
1286
+ case "qwik":
1287
+ case "reactNative":
1288
+ case "react":
1289
+ case "rsc":
1290
+ return style;
1451
1291
  }
1292
+ }
1293
+
1294
+ // src/components/block/block.helpers.ts
1295
+ var checkIsComponentRestricted = (component, model) => {
1296
+ if (!component)
1297
+ return true;
1298
+ if (!model)
1299
+ return false;
1300
+ return component.models && component.models.length > 0 && !component.models.includes(model);
1452
1301
  };
1453
- var setLocalStorageItem = ({
1454
- key,
1455
- canTrack,
1456
- value
1302
+ var getComponent = ({
1303
+ block,
1304
+ registeredComponents,
1305
+ model
1457
1306
  }) => {
1458
- try {
1459
- if (canTrack) {
1460
- getLocalStorage()?.setItem(key, value);
1461
- }
1462
- } catch (err) {
1463
- console.debug("[LocalStorage] SET error: ", err);
1307
+ const componentName = block.component?.name;
1308
+ if (!componentName) {
1309
+ return null;
1310
+ }
1311
+ const ref = registeredComponents[componentName];
1312
+ if (!ref || checkIsComponentRestricted(ref, model)) {
1313
+ console.warn(`
1314
+ Could not find a registered component named "${componentName}".
1315
+ If you registered it, is the file that registered it imported by the file that needs to render it?`);
1316
+ return void 0;
1317
+ } else {
1318
+ return ref;
1464
1319
  }
1465
1320
  };
1466
-
1467
- // src/helpers/visitorId.ts
1468
- var VISITOR_LOCAL_STORAGE_KEY = "builderVisitorId";
1469
- var getVisitorId = ({
1470
- canTrack
1321
+ var getRepeatItemData = ({
1322
+ block,
1323
+ context
1471
1324
  }) => {
1472
- if (!canTrack) {
1325
+ const {
1326
+ repeat,
1327
+ ...blockWithoutRepeat
1328
+ } = block;
1329
+ if (!repeat?.collection) {
1473
1330
  return void 0;
1474
1331
  }
1475
- const visitorId = getLocalStorageItem({
1476
- key: VISITOR_LOCAL_STORAGE_KEY,
1477
- canTrack
1332
+ const itemsArray = evaluate({
1333
+ code: repeat.collection,
1334
+ localState: context.localState,
1335
+ rootState: context.rootState,
1336
+ rootSetState: context.rootSetState,
1337
+ context: context.context
1478
1338
  });
1479
- if (checkIsDefined(visitorId)) {
1480
- return visitorId;
1481
- } else {
1482
- const newVisitorId = createVisitorId();
1483
- setVisitorId({
1484
- id: newVisitorId,
1485
- canTrack
1486
- });
1487
- return newVisitorId;
1339
+ if (!Array.isArray(itemsArray)) {
1340
+ return void 0;
1341
+ }
1342
+ const collectionName = repeat.collection.split(".").pop();
1343
+ const itemNameToUse = repeat.itemName || (collectionName ? collectionName + "Item" : "item");
1344
+ const repeatArray = itemsArray.map((item, index) => ({
1345
+ context: {
1346
+ ...context,
1347
+ localState: {
1348
+ ...context.localState,
1349
+ $index: index,
1350
+ $item: item,
1351
+ [itemNameToUse]: item,
1352
+ [`$${itemNameToUse}Index`]: index
1353
+ }
1354
+ },
1355
+ block: blockWithoutRepeat
1356
+ }));
1357
+ return repeatArray;
1358
+ };
1359
+ var provideLinkComponent = (block, linkComponent) => {
1360
+ if (block?.shouldReceiveBuilderProps?.builderLinkComponent)
1361
+ return {
1362
+ builderLinkComponent: linkComponent
1363
+ };
1364
+ return {};
1365
+ };
1366
+ var provideRegisteredComponents = (block, registeredComponents, model) => {
1367
+ if (block?.shouldReceiveBuilderProps?.builderComponents) {
1368
+ const filteredRegisteredComponents = Object.fromEntries(Object.entries(registeredComponents).filter(([_, component]) => {
1369
+ return !checkIsComponentRestricted(component, model);
1370
+ }));
1371
+ return {
1372
+ builderComponents: filteredRegisteredComponents
1373
+ };
1488
1374
  }
1375
+ return {};
1489
1376
  };
1490
- var createVisitorId = () => uuid();
1491
- var setVisitorId = ({
1492
- id,
1493
- canTrack
1494
- }) => setLocalStorageItem({
1495
- key: VISITOR_LOCAL_STORAGE_KEY,
1496
- value: id,
1497
- canTrack
1377
+ var provideBuilderBlock = (block, builderBlock) => {
1378
+ if (block?.shouldReceiveBuilderProps?.builderBlock)
1379
+ return {
1380
+ builderBlock
1381
+ };
1382
+ return {};
1383
+ };
1384
+ var provideBuilderContext = (block, context) => {
1385
+ if (block?.shouldReceiveBuilderProps?.builderContext)
1386
+ return {
1387
+ builderContext: context
1388
+ };
1389
+ return {};
1390
+ };
1391
+ var generateKey = (index) => {
1392
+ return index.toString();
1393
+ };
1394
+
1395
+ // src/functions/event-handler-name.ts
1396
+ function capitalizeFirstLetter(string) {
1397
+ return string.charAt(0).toUpperCase() + string.slice(1);
1398
+ }
1399
+ var getEventHandlerName = (key) => `on${capitalizeFirstLetter(key)}`;
1400
+
1401
+ // src/functions/get-block-actions-handler.ts
1402
+ var createEventHandler = (value, options) => (event) => evaluate({
1403
+ code: value,
1404
+ context: options.context,
1405
+ localState: options.localState,
1406
+ rootState: options.rootState,
1407
+ rootSetState: options.rootSetState,
1408
+ event,
1409
+ isExpression: false,
1410
+ trackingContext: options.trackingContext
1498
1411
  });
1499
1412
 
1500
- // src/functions/log-fetch.ts
1501
- function logFetch(url) {
1502
- if (typeof process !== "undefined" && process.env?.DEBUG) {
1503
- if (String(process.env.DEBUG) == "true") {
1504
- logger.log(url);
1413
+ // src/functions/get-block-actions.ts
1414
+ function getBlockActions(options) {
1415
+ const obj = {};
1416
+ const optionActions = options.block.actions ?? {};
1417
+ for (const key in optionActions) {
1418
+ if (!optionActions.hasOwnProperty(key)) {
1419
+ continue;
1420
+ }
1421
+ const value = optionActions[key];
1422
+ let eventHandlerName = getEventHandlerName(key);
1423
+ if (options.stripPrefix) {
1424
+ switch (TARGET) {
1425
+ case "vue":
1426
+ eventHandlerName = eventHandlerName.replace("v-on:", "");
1427
+ break;
1428
+ case "svelte":
1429
+ eventHandlerName = eventHandlerName.replace("on:", "");
1430
+ break;
1431
+ }
1505
1432
  }
1433
+ obj[eventHandlerName] = createEventHandler(value, options);
1506
1434
  }
1435
+ return obj;
1507
1436
  }
1508
1437
 
1509
- // src/functions/track/index.ts
1510
- var getTrackingEventData = async ({
1511
- canTrack
1512
- }) => {
1513
- if (!canTrack) {
1514
- return {
1515
- visitorId: void 0,
1516
- sessionId: void 0
1517
- };
1518
- }
1519
- const sessionId = await getSessionId({
1520
- canTrack
1521
- });
1522
- const visitorId = getVisitorId({
1523
- canTrack
1524
- });
1438
+ // src/functions/transform-block-properties.ts
1439
+ function transformBlockProperties({
1440
+ properties
1441
+ }) {
1442
+ return properties;
1443
+ }
1444
+
1445
+ // src/functions/get-block-properties.ts
1446
+ var extractRelevantRootBlockProperties = (block) => {
1525
1447
  return {
1526
- sessionId,
1527
- visitorId
1448
+ href: block.href
1528
1449
  };
1529
1450
  };
1530
- var createEvent = async ({
1531
- type: eventType,
1532
- canTrack,
1533
- apiKey,
1534
- metadata,
1535
- ...properties
1536
- }) => ({
1537
- type: eventType,
1538
- data: {
1539
- ...properties,
1540
- metadata: {
1541
- url: location.href,
1542
- ...metadata
1543
- },
1544
- ...await getTrackingEventData({
1545
- canTrack
1451
+ function getBlockProperties({
1452
+ block,
1453
+ context
1454
+ }) {
1455
+ const properties = {
1456
+ ...extractRelevantRootBlockProperties(block),
1457
+ ...block.properties,
1458
+ "builder-id": block.id,
1459
+ style: getStyle({
1460
+ block,
1461
+ context
1546
1462
  }),
1547
- userAttributes: getUserAttributes(),
1548
- ownerId: apiKey
1463
+ [getClassPropName()]: [block.id, "builder-block", block.class, block.properties?.class].filter(Boolean).join(" ")
1464
+ };
1465
+ return transformBlockProperties({
1466
+ properties,
1467
+ context,
1468
+ block
1469
+ });
1470
+ }
1471
+
1472
+ // src/components/block/components/block-wrapper.tsx
1473
+ function BlockWrapper(props) {
1474
+ return <><Dynamic_renderer_default
1475
+ TagName={props.Wrapper}
1476
+ attributes={getBlockProperties({
1477
+ block: props.block,
1478
+ context: props.context
1479
+ })}
1480
+ actionAttributes={getBlockActions({
1481
+ block: props.block,
1482
+ rootState: props.context.rootState,
1483
+ rootSetState: props.context.rootSetState,
1484
+ localState: props.context.localState,
1485
+ context: props.context.context,
1486
+ stripPrefix: true,
1487
+ trackingContext: {
1488
+ apiKey: props.context.apiKey,
1489
+ canTrack: props.context.canTrack ?? true,
1490
+ contentId: props.context.content?.id,
1491
+ variationId: props.context.content?.testVariationId
1492
+ }
1493
+ })}
1494
+ >{props.children}</Dynamic_renderer_default></>;
1495
+ }
1496
+ var Block_wrapper_default = BlockWrapper;
1497
+
1498
+ // src/components/block/components/component-ref/component-ref.tsx
1499
+ import { Show as Show3, For, createSignal as createSignal3 } from "solid-js";
1500
+ import { Dynamic as Dynamic4 } from "solid-js/web";
1501
+
1502
+ // src/components/block/components/interactive-element.tsx
1503
+ import { Show as Show2, on, createEffect, createMemo as createMemo2, createSignal as createSignal2 } from "solid-js";
1504
+ import { Dynamic as Dynamic3 } from "solid-js/web";
1505
+
1506
+ // src/functions/is-previewing.ts
1507
+ function isPreviewing(search) {
1508
+ const searchToUse = search || (isBrowser() ? window.location.search : void 0);
1509
+ if (!searchToUse) {
1510
+ return false;
1549
1511
  }
1512
+ const normalizedSearch = getSearchString(searchToUse);
1513
+ return Boolean(normalizedSearch.indexOf("builder.preview=") !== -1);
1514
+ }
1515
+
1516
+ // src/functions/register-component.ts
1517
+ var createRegisterComponentMessage = (info) => ({
1518
+ type: "builder.registerComponent",
1519
+ data: serializeIncludingFunctions(info)
1550
1520
  });
1551
- async function _track({
1552
- apiHost,
1553
- ...eventProps
1554
- }) {
1555
- if (!eventProps.apiKey) {
1556
- logger.error("Missing API key for track call. Please provide your API key.");
1557
- return;
1521
+ var serializeFn = (fnValue) => {
1522
+ const fnStr = fnValue.toString().trim();
1523
+ const isArrowWithoutParens = /^[a-zA-Z0-9_]+\s*=>/i.test(fnStr);
1524
+ const appendFunction = !fnStr.startsWith("function") && !fnStr.startsWith("async") && !fnStr.startsWith("(") && !isArrowWithoutParens;
1525
+ return `return (${appendFunction ? "function " : ""}${fnStr}).apply(this, arguments)`;
1526
+ };
1527
+ function serializeIncludingFunctions(info) {
1528
+ return JSON.parse(JSON.stringify(info, (key, value) => {
1529
+ if (typeof value === "function") {
1530
+ return serializeFn(value);
1531
+ }
1532
+ return value;
1533
+ }));
1534
+ }
1535
+
1536
+ // src/functions/register.ts
1537
+ var registry = {};
1538
+ function register(type, info) {
1539
+ if (type === "plugin") {
1540
+ info = serializeIncludingFunctions(info);
1558
1541
  }
1559
- if (!eventProps.canTrack) {
1560
- return;
1542
+ let typeList = registry[type];
1543
+ if (!typeList) {
1544
+ typeList = registry[type] = [];
1561
1545
  }
1562
- if (isEditing()) {
1563
- return;
1546
+ typeList.push(info);
1547
+ if (isBrowser()) {
1548
+ const message = {
1549
+ type: "builder.register",
1550
+ data: {
1551
+ type,
1552
+ info
1553
+ }
1554
+ };
1555
+ try {
1556
+ parent.postMessage(message, "*");
1557
+ if (parent !== window) {
1558
+ window.postMessage(message, "*");
1559
+ }
1560
+ } catch (err) {
1561
+ console.debug("Could not postmessage", err);
1562
+ }
1564
1563
  }
1565
- if (!(isBrowser() || TARGET === "reactNative")) {
1566
- return;
1564
+ }
1565
+ function registerAction(action) {
1566
+ if (isBrowser()) {
1567
+ const actionClone = JSON.parse(JSON.stringify(action));
1568
+ if (action.action) {
1569
+ actionClone.action = action.action.toString();
1570
+ }
1571
+ window.parent?.postMessage({
1572
+ type: "builder.registerAction",
1573
+ data: actionClone
1574
+ }, "*");
1567
1575
  }
1568
- const baseUrl = apiHost || "https://cdn.builder.io";
1569
- const url = `${baseUrl}/api/v1/track`;
1570
- logFetch(url);
1571
- return fetch(url, {
1572
- method: "POST",
1573
- body: JSON.stringify({
1574
- events: [await createEvent(eventProps)]
1575
- }),
1576
- headers: {
1577
- "content-type": "application/json",
1578
- ...getSdkHeaders()
1579
- },
1580
- mode: "cors"
1581
- }).catch((err) => {
1582
- console.error("Failed to track: ", err);
1583
- });
1584
1576
  }
1585
- var track = (args) => _track({
1586
- ...args,
1587
- canTrack: true
1588
- });
1577
+
1578
+ // src/functions/set-editor-settings.ts
1579
+ var settings = {};
1580
+ function setEditorSettings(newSettings) {
1581
+ if (isBrowser()) {
1582
+ Object.assign(settings, newSettings);
1583
+ const message = {
1584
+ type: "builder.settingsChange",
1585
+ data: settings
1586
+ };
1587
+ parent.postMessage(message, "*");
1588
+ }
1589
+ }
1590
+
1591
+ // src/functions/get-builder-search-params/index.ts
1592
+ var BUILDER_SEARCHPARAMS_PREFIX = "builder.";
1593
+ var BUILDER_OPTIONS_PREFIX = "options.";
1594
+ var getBuilderSearchParams = (_options) => {
1595
+ if (!_options) {
1596
+ return {};
1597
+ }
1598
+ const options = normalizeSearchParams(_options);
1599
+ const newOptions = {};
1600
+ Object.keys(options).forEach((key) => {
1601
+ if (key.startsWith(BUILDER_SEARCHPARAMS_PREFIX)) {
1602
+ const trimmedKey = key.replace(BUILDER_SEARCHPARAMS_PREFIX, "").replace(BUILDER_OPTIONS_PREFIX, "");
1603
+ newOptions[trimmedKey] = options[key];
1604
+ }
1605
+ });
1606
+ return newOptions;
1607
+ };
1608
+ var getBuilderSearchParamsFromWindow = () => {
1609
+ if (!isBrowser()) {
1610
+ return {};
1611
+ }
1612
+ const searchParams = new URLSearchParams(window.location.search);
1613
+ return getBuilderSearchParams(searchParams);
1614
+ };
1589
1615
 
1590
1616
  // src/functions/is-from-trusted-host.ts
1591
1617
  var DEFAULT_TRUSTED_HOSTS = ["*.beta.builder.io", "beta.builder.io", "builder.io", "localhost", "qa.builder.io"];
@@ -2329,7 +2355,13 @@ function InteractiveElement(props) {
2329
2355
  rootState: props.context.rootState,
2330
2356
  rootSetState: props.context.rootSetState,
2331
2357
  localState: props.context.localState,
2332
- context: props.context.context
2358
+ context: props.context.context,
2359
+ trackingContext: {
2360
+ apiKey: props.context.apiKey,
2361
+ canTrack: props.context.canTrack ?? true,
2362
+ contentId: props.context.content?.id,
2363
+ variationId: props.context.content?.testVariationId
2364
+ }
2333
2365
  })
2334
2366
  } : {};
2335
2367
  });