@builder.io/sdk-solid 0.12.5 → 0.12.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -6,6 +6,23 @@ interface JSONObject$1 {
6
6
  }
7
7
  interface JSONArray$1 extends Array<JSONValue$1> {
8
8
  }
9
+ interface AnimationStep {
10
+ styles: {
11
+ [key: string]: string;
12
+ };
13
+ delay?: number;
14
+ }
15
+ interface BuilderAnimation {
16
+ elementId: string;
17
+ trigger: string;
18
+ steps: AnimationStep[];
19
+ duration: number;
20
+ delay?: number;
21
+ easing?: string;
22
+ id?: string;
23
+ repeat?: boolean;
24
+ thresholdPercent?: number;
25
+ }
9
26
  /** @todo typedoc this */
10
27
  interface BuilderBlock {
11
28
  '@type': '@builder.io/sdk:Element';
@@ -54,7 +71,7 @@ interface BuilderBlock {
54
71
  collection: string;
55
72
  itemName?: string;
56
73
  } | null;
57
- animations?: any[];
74
+ animations?: BuilderAnimation[];
58
75
  style?: Partial<CSSStyleDeclaration>;
59
76
  href?: string;
60
77
  /**
@@ -244,27 +244,43 @@ var runInBrowser = ({
244
244
  builder,
245
245
  context,
246
246
  event,
247
- state: flattenState(rootState, localState, rootSetState)
247
+ state: flattenState({
248
+ rootState,
249
+ localState,
250
+ rootSetState
251
+ })
248
252
  });
249
253
  return new Function(...functionArgs.map(([name]) => name), code)(...functionArgs.map(([, value]) => value));
250
254
  };
251
- function flattenState(rootState, localState, rootSetState) {
252
- if (rootState === localState) {
253
- throw new Error("rootState === localState");
254
- }
255
+ function flattenState({
256
+ rootState,
257
+ localState,
258
+ rootSetState
259
+ }) {
255
260
  return new Proxy(rootState, {
256
- get: (_, prop) => {
261
+ get: (target, prop) => {
257
262
  if (localState && prop in localState) {
258
263
  return localState[prop];
259
264
  }
260
- return rootState[prop];
265
+ const val = target[prop];
266
+ if (typeof val === "object") {
267
+ return flattenState({
268
+ rootState: val,
269
+ localState: void 0,
270
+ rootSetState: rootSetState ? (subState) => {
271
+ target[prop] = subState;
272
+ rootSetState(target);
273
+ } : void 0
274
+ });
275
+ }
276
+ return val;
261
277
  },
262
- set: (_, prop, value) => {
278
+ set: (target, prop, value) => {
263
279
  if (localState && prop in localState) {
264
280
  throw new Error("Writing to local state is not allowed as it is read-only.");
265
281
  }
266
- rootState[prop] = value;
267
- rootSetState?.(rootState);
282
+ target[prop] = value;
283
+ rootSetState?.(target);
268
284
  return true;
269
285
  }
270
286
  });
@@ -407,6 +423,212 @@ function getProcessedBlock({
407
423
  }
408
424
  }
409
425
 
426
+ // src/components/block/animator.ts
427
+ function throttle(func, wait, options = {}) {
428
+ let context;
429
+ let args;
430
+ let result;
431
+ let timeout = null;
432
+ let previous = 0;
433
+ const later = function() {
434
+ previous = options.leading === false ? 0 : Date.now();
435
+ timeout = null;
436
+ result = func.apply(context, args);
437
+ if (!timeout)
438
+ context = args = null;
439
+ };
440
+ return function() {
441
+ const now = Date.now();
442
+ if (!previous && options.leading === false)
443
+ previous = now;
444
+ const remaining = wait - (now - previous);
445
+ context = this;
446
+ args = arguments;
447
+ if (remaining <= 0 || remaining > wait) {
448
+ if (timeout) {
449
+ clearTimeout(timeout);
450
+ timeout = null;
451
+ }
452
+ previous = now;
453
+ result = func.apply(context, args);
454
+ if (!timeout)
455
+ context = args = null;
456
+ } else if (!timeout && options.trailing !== false) {
457
+ timeout = setTimeout(later, remaining);
458
+ }
459
+ return result;
460
+ };
461
+ }
462
+ function assign(target, ..._args) {
463
+ const to = Object(target);
464
+ for (let index = 1; index < arguments.length; index++) {
465
+ const nextSource = arguments[index];
466
+ if (nextSource != null) {
467
+ for (const nextKey in nextSource) {
468
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
469
+ to[nextKey] = nextSource[nextKey];
470
+ }
471
+ }
472
+ }
473
+ }
474
+ return to;
475
+ }
476
+ var camelCaseToKebabCase = (str) => str ? str.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`) : "";
477
+ function bindAnimations(animations) {
478
+ for (const animation of animations) {
479
+ switch (animation.trigger) {
480
+ case "pageLoad":
481
+ triggerAnimation(animation);
482
+ break;
483
+ case "hover":
484
+ bindHoverAnimation(animation);
485
+ break;
486
+ case "scrollInView":
487
+ bindScrollInViewAnimation(animation);
488
+ break;
489
+ }
490
+ }
491
+ }
492
+ function warnElementNotPresent(id) {
493
+ console.warn(`Cannot animate element: element with ID ${id} not found!`);
494
+ }
495
+ function augmentAnimation(animation, element) {
496
+ const stylesUsed = getAllStylesUsed(animation);
497
+ const computedStyle = getComputedStyle(element);
498
+ const firstStyles = animation.steps[0].styles;
499
+ const lastStyles = animation.steps[animation.steps.length - 1].styles;
500
+ const bothStyles = [firstStyles, lastStyles];
501
+ for (const styles of bothStyles) {
502
+ for (const style of stylesUsed) {
503
+ if (!(style in styles)) {
504
+ styles[style] = computedStyle[style];
505
+ }
506
+ }
507
+ }
508
+ }
509
+ function getAllStylesUsed(animation) {
510
+ const properties = [];
511
+ for (const step of animation.steps) {
512
+ for (const key in step.styles) {
513
+ if (properties.indexOf(key) === -1) {
514
+ properties.push(key);
515
+ }
516
+ }
517
+ }
518
+ return properties;
519
+ }
520
+ function triggerAnimation(animation) {
521
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
522
+ if (!elements.length) {
523
+ warnElementNotPresent(animation.elementId || animation.id || "");
524
+ return;
525
+ }
526
+ Array.from(elements).forEach((element) => {
527
+ augmentAnimation(animation, element);
528
+ element.style.transition = "none";
529
+ element.style.transitionDelay = "0";
530
+ assign(element.style, animation.steps[0].styles);
531
+ setTimeout(() => {
532
+ element.style.transition = `all ${animation.duration}s ${camelCaseToKebabCase(animation.easing)}`;
533
+ if (animation.delay) {
534
+ element.style.transitionDelay = animation.delay + "s";
535
+ }
536
+ assign(element.style, animation.steps[1].styles);
537
+ setTimeout(() => {
538
+ element.style.transition = "";
539
+ element.style.transitionDelay = "";
540
+ }, (animation.delay || 0) * 1e3 + animation.duration * 1e3 + 100);
541
+ });
542
+ });
543
+ }
544
+ function bindHoverAnimation(animation) {
545
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
546
+ if (!elements.length) {
547
+ warnElementNotPresent(animation.elementId || animation.id || "");
548
+ return;
549
+ }
550
+ Array.from(elements).forEach((element) => {
551
+ augmentAnimation(animation, element);
552
+ const defaultState = animation.steps[0].styles;
553
+ const hoverState = animation.steps[1].styles;
554
+ function attachDefaultState() {
555
+ assign(element.style, defaultState);
556
+ }
557
+ function attachHoverState() {
558
+ assign(element.style, hoverState);
559
+ }
560
+ attachDefaultState();
561
+ element.addEventListener("mouseenter", attachHoverState);
562
+ element.addEventListener("mouseleave", attachDefaultState);
563
+ setTimeout(() => {
564
+ element.style.transition = `all ${animation.duration}s ${camelCaseToKebabCase(animation.easing)}`;
565
+ if (animation.delay) {
566
+ element.style.transitionDelay = animation.delay + "s";
567
+ }
568
+ });
569
+ });
570
+ }
571
+ function bindScrollInViewAnimation(animation) {
572
+ const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ""));
573
+ if (!elements.length) {
574
+ warnElementNotPresent(animation.elementId || animation.id || "");
575
+ return;
576
+ }
577
+ Array.from(elements).forEach((element) => {
578
+ augmentAnimation(animation, element);
579
+ let triggered = false;
580
+ let pendingAnimation = false;
581
+ function immediateOnScroll() {
582
+ if (!triggered && isScrolledIntoView(element)) {
583
+ triggered = true;
584
+ pendingAnimation = true;
585
+ setTimeout(() => {
586
+ assign(element.style, animation.steps[1].styles);
587
+ if (!animation.repeat) {
588
+ document.removeEventListener("scroll", onScroll);
589
+ }
590
+ setTimeout(() => {
591
+ pendingAnimation = false;
592
+ if (!animation.repeat) {
593
+ element.style.transition = "";
594
+ element.style.transitionDelay = "";
595
+ }
596
+ }, (animation.duration + (animation.delay || 0)) * 1e3 + 100);
597
+ });
598
+ } else if (animation.repeat && triggered && !pendingAnimation && !isScrolledIntoView(element)) {
599
+ triggered = false;
600
+ assign(element.style, animation.steps[0].styles);
601
+ }
602
+ }
603
+ const onScroll = throttle(immediateOnScroll, 200, {
604
+ leading: false
605
+ });
606
+ function isScrolledIntoView(elem) {
607
+ const rect = elem.getBoundingClientRect();
608
+ const windowHeight = window.innerHeight;
609
+ const thresholdPercent = (animation.thresholdPercent || 0) / 100;
610
+ const threshold = thresholdPercent * windowHeight;
611
+ return rect.bottom > threshold && rect.top < windowHeight - threshold;
612
+ }
613
+ const defaultState = animation.steps[0].styles;
614
+ function attachDefaultState() {
615
+ assign(element.style, defaultState);
616
+ }
617
+ attachDefaultState();
618
+ setTimeout(() => {
619
+ element.style.transition = `all ${animation.duration}s ${camelCaseToKebabCase(animation.easing)}`;
620
+ if (animation.delay) {
621
+ element.style.transitionDelay = animation.delay + "s";
622
+ }
623
+ });
624
+ document.addEventListener("scroll", onScroll, {
625
+ capture: true,
626
+ passive: true
627
+ });
628
+ immediateOnScroll();
629
+ });
630
+ }
631
+
410
632
  // src/components/block/block.helpers.ts
411
633
  var getComponent = ({
412
634
  block,
@@ -982,6 +1204,16 @@ function Block(props) {
982
1204
  isInteractive: !blockComponent()?.isRSC
983
1205
  };
984
1206
  }
1207
+ onMount(() => {
1208
+ const blockId = processedBlock().id;
1209
+ const animations = processedBlock().animations;
1210
+ if (animations && blockId) {
1211
+ bindAnimations(animations.filter((item) => item.trigger !== "hover").map((animation) => ({
1212
+ ...animation,
1213
+ elementId: blockId
1214
+ })));
1215
+ }
1216
+ });
985
1217
  return createComponent(Show, {
986
1218
  get when() {
987
1219
  return canShowBlock();
@@ -3394,7 +3626,7 @@ var getInteractionPropertiesForEvent = (event) => {
3394
3626
  };
3395
3627
 
3396
3628
  // src/constants/sdk-version.ts
3397
- var SDK_VERSION = "0.12.5";
3629
+ var SDK_VERSION = "0.12.7";
3398
3630
 
3399
3631
  // src/functions/register.ts
3400
3632
  var registry = {};
@@ -3601,6 +3833,10 @@ function EnableEditor(props) {
3601
3833
  setForceReRenderCount(forceReRenderCount() + 1);
3602
3834
  break;
3603
3835
  }
3836
+ case "builder.triggerAnimation": {
3837
+ triggerAnimation(data.data);
3838
+ break;
3839
+ }
3604
3840
  case "builder.contentUpdate": {
3605
3841
  const messageContent = data.data;
3606
3842
  const key = messageContent.key || messageContent.alias || messageContent.entry || messageContent.modelName;
@@ -3771,7 +4007,7 @@ function EnableEditor(props) {
3771
4007
  function onUpdateFn_2() {
3772
4008
  evaluateJsCode();
3773
4009
  }
3774
- createEffect(on(() => [props.builderContextSignal.content?.data?.jsCode, props.builderContextSignal.rootState], onUpdateFn_2));
4010
+ createEffect(on(() => [props.builderContextSignal.content?.data?.jsCode], onUpdateFn_2));
3775
4011
  function onUpdateFn_3() {
3776
4012
  runHttpRequests();
3777
4013
  }