@vectoriox/iox-builder 1.4.17 → 1.4.18

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.
@@ -1097,6 +1097,16 @@ class InteractionEngineService {
1097
1097
  return;
1098
1098
  const cleanups = [];
1099
1099
  for (const ix of node.interactions) {
1100
+ // For entrance-type triggers, freeze the target at the animation's
1101
+ // starting frame immediately so it is never briefly visible before
1102
+ // the trigger fires (avoids the flash-then-animate flicker).
1103
+ if (ix.trigger === 'pageLoad' || ix.trigger === 'viewportEnter') {
1104
+ for (const action of ix.actions) {
1105
+ const target = this.resolveTarget(node, action);
1106
+ if (target)
1107
+ this.applyPreState(target, action);
1108
+ }
1109
+ }
1100
1110
  const cleanup = this.attachInteraction(node, ix, ref.element);
1101
1111
  cleanups.push({ node, interaction: ix, cleanup });
1102
1112
  }
@@ -1111,11 +1121,14 @@ class InteractionEngineService {
1111
1121
  entry.cleanup();
1112
1122
  }
1113
1123
  this.attached.delete(node);
1114
- // Cancelling Web Animations removes fill:'forwards' committed styles,
1115
- // returning the element to its natural CSS state.
1124
+ // Cancel Web Animations and strip any inline pre-state styles that
1125
+ // were applied by applyPreState() so the element returns to its natural CSS state.
1116
1126
  const ref = this.overlayService.getNodeRef(node);
1117
1127
  if (ref) {
1118
1128
  ref.element.getAnimations().forEach(a => a.cancel());
1129
+ ref.element.style.removeProperty('opacity');
1130
+ ref.element.style.removeProperty('transform');
1131
+ ref.element.style.removeProperty('visibility');
1119
1132
  }
1120
1133
  }
1121
1134
  /** Re-attach interactions after they have been edited in the panel. */
@@ -1234,13 +1247,34 @@ class InteractionEngineService {
1234
1247
  const { keyframes } = this.buildAnimation(action);
1235
1248
  if (!keyframes.length)
1236
1249
  return;
1250
+ // 'both' = backwards (holds first keyframe during delay) + forwards (holds last keyframe after end).
1251
+ // This eliminates any flicker during the delay period.
1237
1252
  element.animate(keyframes, {
1238
1253
  duration: action.duration,
1239
1254
  delay: action.delay,
1240
1255
  easing: action.easing,
1241
- fill: 'forwards',
1256
+ fill: 'both',
1242
1257
  });
1243
1258
  }
1259
+ /**
1260
+ * Freeze an element at the animation's starting frame immediately, before any
1261
+ * trigger fires. Without this, entrance animations (fadeIn, moveUp, …) show the
1262
+ * element at its natural visible state for the time between mount and trigger —
1263
+ * causing a visible-then-disappear-then-animate flicker.
1264
+ *
1265
+ * Only call this for triggers that will eventually animate the element in
1266
+ * (pageLoad, viewportEnter). Click/hover triggers must NOT pre-hide the element
1267
+ * because the element should remain normally visible until interacted with.
1268
+ */
1269
+ applyPreState(element, action) {
1270
+ const { keyframes } = this.buildAnimation(action);
1271
+ if (!keyframes.length)
1272
+ return;
1273
+ const first = keyframes[0];
1274
+ for (const [prop, val] of Object.entries(first)) {
1275
+ element.style[prop] = String(val);
1276
+ }
1277
+ }
1244
1278
  reverseAction(element, action) {
1245
1279
  const { keyframes } = this.buildAnimation(action);
1246
1280
  if (!keyframes.length)