@vectoriox/iox-builder 1.4.20 → 1.4.21
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.
|
@@ -1088,6 +1088,14 @@ class InteractionEngineService {
|
|
|
1088
1088
|
constructor(overlayService) {
|
|
1089
1089
|
this.overlayService = overlayService;
|
|
1090
1090
|
this.attached = new Map();
|
|
1091
|
+
/** Elements that have had pre-state applied (hidden by attach). */
|
|
1092
|
+
this.preStatedElements = new Set();
|
|
1093
|
+
/** Action types that animate an element from hidden → visible. */
|
|
1094
|
+
this.ENTRANCE_TYPES = new Set([
|
|
1095
|
+
'fadeIn', 'moveUp', 'moveDown', 'moveLeft', 'moveRight', 'scaleIn', 'show',
|
|
1096
|
+
]);
|
|
1097
|
+
/** Action types that animate an element from visible → hidden. */
|
|
1098
|
+
this.EXIT_TYPES = new Set(['fadeOut', 'scaleOut', 'hide']);
|
|
1091
1099
|
}
|
|
1092
1100
|
/** Wire all interactions for a node to its rendered DOM element. */
|
|
1093
1101
|
attach(node) {
|
|
@@ -1098,11 +1106,12 @@ class InteractionEngineService {
|
|
|
1098
1106
|
return;
|
|
1099
1107
|
const cleanups = [];
|
|
1100
1108
|
for (const ix of node.interactions) {
|
|
1101
|
-
//
|
|
1102
|
-
//
|
|
1103
|
-
//
|
|
1104
|
-
|
|
1105
|
-
|
|
1109
|
+
// Apply pre-state to targets of ANY entrance animation so the element
|
|
1110
|
+
// starts hidden regardless of whether the trigger is automatic (pageLoad,
|
|
1111
|
+
// viewportEnter) or user-driven (click). Without this, a click-triggered
|
|
1112
|
+
// fadeIn on a menu overlay would start the overlay fully visible.
|
|
1113
|
+
for (const action of ix.actions) {
|
|
1114
|
+
if (this.ENTRANCE_TYPES.has(action.type)) {
|
|
1106
1115
|
const target = this.resolveTarget(node, action);
|
|
1107
1116
|
if (target)
|
|
1108
1117
|
this.applyPreState(target, action);
|
|
@@ -1127,9 +1136,20 @@ class InteractionEngineService {
|
|
|
1127
1136
|
const ref = this.overlayService.getNodeRef(node);
|
|
1128
1137
|
if (ref) {
|
|
1129
1138
|
ref.element.getAnimations().forEach(a => a.cancel());
|
|
1130
|
-
ref.element
|
|
1131
|
-
|
|
1132
|
-
|
|
1139
|
+
this.clearInlineAnimationStyles(ref.element);
|
|
1140
|
+
}
|
|
1141
|
+
// Also clean up pre-state on any target elements this node was animating.
|
|
1142
|
+
if (node.interactions) {
|
|
1143
|
+
for (const ix of node.interactions) {
|
|
1144
|
+
for (const action of ix.actions) {
|
|
1145
|
+
const target = this.resolveTarget(node, action);
|
|
1146
|
+
if (target && this.preStatedElements.has(target)) {
|
|
1147
|
+
target.getAnimations().forEach(a => a.cancel());
|
|
1148
|
+
this.clearInlineAnimationStyles(target);
|
|
1149
|
+
this.preStatedElements.delete(target);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1133
1153
|
}
|
|
1134
1154
|
}
|
|
1135
1155
|
/** Re-attach interactions after they have been edited in the panel. */
|
|
@@ -1249,23 +1269,35 @@ class InteractionEngineService {
|
|
|
1249
1269
|
if (!keyframes.length)
|
|
1250
1270
|
return;
|
|
1251
1271
|
// 'both' = backwards (holds first keyframe during delay) + forwards (holds last keyframe after end).
|
|
1252
|
-
|
|
1253
|
-
element.animate(keyframes, {
|
|
1272
|
+
const anim = element.animate(keyframes, {
|
|
1254
1273
|
duration: action.duration,
|
|
1255
1274
|
delay: action.delay,
|
|
1256
1275
|
easing: action.easing,
|
|
1257
1276
|
fill: 'both',
|
|
1258
1277
|
});
|
|
1278
|
+
if (this.ENTRANCE_TYPES.has(action.type)) {
|
|
1279
|
+
// Once the entrance animation finishes the element is fully visible —
|
|
1280
|
+
// restore pointer events so it can be interacted with.
|
|
1281
|
+
anim.finished.then(() => {
|
|
1282
|
+
element.style.removeProperty('pointer-events');
|
|
1283
|
+
}).catch(() => { });
|
|
1284
|
+
}
|
|
1285
|
+
else if (this.EXIT_TYPES.has(action.type)) {
|
|
1286
|
+
// Once the exit animation finishes the element is invisible —
|
|
1287
|
+
// disable pointer events so it doesn't silently block clicks underneath it.
|
|
1288
|
+
anim.finished.then(() => {
|
|
1289
|
+
element.style.setProperty('pointer-events', 'none');
|
|
1290
|
+
}).catch(() => { });
|
|
1291
|
+
}
|
|
1259
1292
|
}
|
|
1260
1293
|
/**
|
|
1261
1294
|
* Freeze an element at the animation's starting frame immediately, before any
|
|
1262
|
-
* trigger fires.
|
|
1263
|
-
*
|
|
1264
|
-
* causing a visible-then-disappear-then-animate flicker.
|
|
1295
|
+
* trigger fires. Called for ALL entrance-type actions regardless of trigger so
|
|
1296
|
+
* that a click-triggered fadeIn on a menu overlay also starts it hidden.
|
|
1265
1297
|
*
|
|
1266
|
-
*
|
|
1267
|
-
*
|
|
1268
|
-
*
|
|
1298
|
+
* Also sets pointer-events:none so the invisible element does not block clicks
|
|
1299
|
+
* on other content beneath it. Pointer events are restored in executeAction()
|
|
1300
|
+
* once the entrance animation finishes.
|
|
1269
1301
|
*/
|
|
1270
1302
|
applyPreState(element, action) {
|
|
1271
1303
|
const { keyframes } = this.buildAnimation(action);
|
|
@@ -1275,6 +1307,18 @@ class InteractionEngineService {
|
|
|
1275
1307
|
for (const [prop, val] of Object.entries(first)) {
|
|
1276
1308
|
element.style[prop] = String(val);
|
|
1277
1309
|
}
|
|
1310
|
+
// Invisible element must not intercept pointer events.
|
|
1311
|
+
const opacity = first['opacity'];
|
|
1312
|
+
if (opacity === '0' || opacity === 0) {
|
|
1313
|
+
element.style.setProperty('pointer-events', 'none');
|
|
1314
|
+
}
|
|
1315
|
+
this.preStatedElements.add(element);
|
|
1316
|
+
}
|
|
1317
|
+
clearInlineAnimationStyles(element) {
|
|
1318
|
+
element.style.removeProperty('opacity');
|
|
1319
|
+
element.style.removeProperty('transform');
|
|
1320
|
+
element.style.removeProperty('visibility');
|
|
1321
|
+
element.style.removeProperty('pointer-events');
|
|
1278
1322
|
}
|
|
1279
1323
|
reverseAction(element, action) {
|
|
1280
1324
|
const { keyframes } = this.buildAnimation(action);
|