@vectoriox/iox-builder 1.4.16 → 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)
@@ -1484,10 +1518,12 @@ var TraitInputType;
1484
1518
  TraitInputType["DirectionalSize"] = "directionalSize";
1485
1519
  TraitInputType["SelectButton"] = "selectButton";
1486
1520
  TraitInputType["Scrub"] = "scrub";
1521
+ TraitInputType["Range"] = "range";
1487
1522
  TraitInputType["Icon"] = "icon";
1488
1523
  TraitInputType["Media"] = "media";
1489
1524
  TraitInputType["FontFamily"] = "fontFamily";
1490
1525
  TraitInputType["GridTemplate"] = "gridTemplate";
1526
+ TraitInputType["SectionLabel"] = "sectionLabel";
1491
1527
  })(TraitInputType || (TraitInputType = {}));
1492
1528
  function generateNodeId() {
1493
1529
  return Math.random().toString(36).substr(2, 9);
@@ -1547,6 +1583,8 @@ function resolveTraitControllerType(type) {
1547
1583
  case TraitInputType.DirectionalSize: return 'directionalSize';
1548
1584
  case TraitInputType.SelectButton: return 'selectButton';
1549
1585
  case TraitInputType.Scrub: return 'scrub';
1586
+ case TraitInputType.Range: return 'range';
1587
+ case TraitInputType.SectionLabel: return 'sectionLabel';
1550
1588
  case TraitInputType.Icon: return 'icon';
1551
1589
  case TraitInputType.Media: return 'media';
1552
1590
  case TraitInputType.FontFamily: return 'select';
@@ -1559,6 +1597,7 @@ function resolveTraitOptions(trait) {
1559
1597
  trait.type === TraitInputType.DirectionalSize ||
1560
1598
  trait.type === TraitInputType.SelectButton ||
1561
1599
  trait.type === TraitInputType.Scrub ||
1600
+ trait.type === TraitInputType.Range ||
1562
1601
  trait.type === TraitInputType.Media) {
1563
1602
  return trait.options;
1564
1603
  }
@@ -1756,36 +1795,41 @@ class EffectsGroupStyleConfig extends GroupStyleConfig {
1756
1795
  'grab', 'grabbing', 'crosshair', 'zoom-in', 'zoom-out', 'none',
1757
1796
  ], 'auto'),
1758
1797
  // ── Shadow ────────────────────────────────────────────
1798
+ new TraitConfig('_sep_shadow', 'Shadow', TraitInputType.SectionLabel),
1759
1799
  new TraitConfig('boxShadow', 'Box Shadow', TraitInputType.Text, undefined, ''),
1760
1800
  new TraitConfig('textShadow', 'Text Shadow', TraitInputType.Text, undefined, ''),
1761
1801
  // ── Transform (virtual — composed to CSS transform: …) ─
1802
+ new TraitConfig('_sep_transform', 'Transform', TraitInputType.SectionLabel),
1762
1803
  new TraitConfig('translateX', 'TX', TraitInputType.Scrub, { min: -2000, max: 2000, step: 1, units: UNITS_ALL }, '0px', true),
1763
1804
  new TraitConfig('translateY', 'TY', TraitInputType.Scrub, { min: -2000, max: 2000, step: 1, units: UNITS_ALL }, '0px', true),
1764
- new TraitConfig('scaleX', 'SX', TraitInputType.Scrub, { min: 0, max: 5, step: 0.01, units: [''] }, '1', true),
1765
- new TraitConfig('scaleY', 'SY', TraitInputType.Scrub, { min: 0, max: 5, step: 0.01, units: [''] }, '1', true),
1766
- new TraitConfig('rotate', 'Rot', TraitInputType.Scrub, { min: -360, max: 360, step: 1, units: UNITS_DEG }, '0deg', true),
1767
- new TraitConfig('skewX', 'SkX', TraitInputType.Scrub, { min: -180, max: 180, step: 1, units: UNITS_DEG }, '0deg', true),
1768
- new TraitConfig('skewY', 'SkY', TraitInputType.Scrub, { min: -180, max: 180, step: 1, units: UNITS_DEG }, '0deg', true),
1805
+ new TraitConfig('scaleX', 'Scale X', TraitInputType.Range, { min: 0, max: 3, step: 0.01, showExtremes: false, showValue: true, compact: true }, '1'),
1806
+ new TraitConfig('scaleY', 'Scale Y', TraitInputType.Range, { min: 0, max: 3, step: 0.01, showExtremes: false, showValue: true, compact: true }, '1'),
1807
+ new TraitConfig('rotate', 'Rotate', TraitInputType.Scrub, { min: -360, max: 360, step: 1, units: UNITS_DEG }, '0deg', true),
1808
+ new TraitConfig('skewX', 'Skew X', TraitInputType.Scrub, { min: -180, max: 180, step: 1, units: UNITS_DEG }, '0deg', true),
1809
+ new TraitConfig('skewY', 'Skew Y', TraitInputType.Scrub, { min: -180, max: 180, step: 1, units: UNITS_DEG }, '0deg', true),
1769
1810
  // ── Filter (virtual — composed to CSS filter: …) ──────
1811
+ new TraitConfig('_sep_filter', 'Filter', TraitInputType.SectionLabel),
1770
1812
  new TraitConfig('filterBlur', 'Blur', TraitInputType.Scrub, { min: 0, max: 50, step: 1, units: ['px'] }, '0px', true),
1771
- new TraitConfig('filterBrightness', 'Bright', TraitInputType.Scrub, { min: 0, max: 3, step: 0.05, units: [''] }, '1', true),
1772
- new TraitConfig('filterContrast', 'Contr', TraitInputType.Scrub, { min: 0, max: 3, step: 0.05, units: [''] }, '1', true),
1773
- new TraitConfig('filterGrayscale', 'Gray', TraitInputType.Scrub, { min: 0, max: 1, step: 0.05, units: [''] }, '0', true),
1774
- new TraitConfig('filterSaturate', 'Sat', TraitInputType.Scrub, { min: 0, max: 3, step: 0.05, units: [''] }, '1', true),
1775
- new TraitConfig('filterHueRotate', 'Hue', TraitInputType.Scrub, { min: 0, max: 360, step: 1, units: UNITS_DEG }, '0deg', true),
1776
- new TraitConfig('filterSepia', 'Sepia', TraitInputType.Scrub, { min: 0, max: 1, step: 0.05, units: [''] }, '0', true),
1777
- new TraitConfig('filterInvert', 'Invert', TraitInputType.Scrub, { min: 0, max: 1, step: 0.05, units: [''] }, '0', true),
1813
+ new TraitConfig('filterHueRotate', 'Hue Rotate', TraitInputType.Scrub, { min: 0, max: 360, step: 1, units: UNITS_DEG }, '0deg', true),
1814
+ new TraitConfig('filterBrightness', 'Brightness', TraitInputType.Range, { min: 0, max: 3, step: 0.05, showExtremes: false, showValue: true, compact: true }, '1'),
1815
+ new TraitConfig('filterContrast', 'Contrast', TraitInputType.Range, { min: 0, max: 3, step: 0.05, showExtremes: false, showValue: true, compact: true }, '1'),
1816
+ new TraitConfig('filterSaturate', 'Saturate', TraitInputType.Range, { min: 0, max: 3, step: 0.05, showExtremes: false, showValue: true, compact: true }, '1'),
1817
+ new TraitConfig('filterGrayscale', 'Grayscale', TraitInputType.Range, { min: 0, max: 1, step: 0.05, showExtremes: false, showValue: true, compact: true }, '0'),
1818
+ new TraitConfig('filterSepia', 'Sepia', TraitInputType.Range, { min: 0, max: 1, step: 0.05, showExtremes: false, showValue: true, compact: true }, '0'),
1819
+ new TraitConfig('filterInvert', 'Invert', TraitInputType.Range, { min: 0, max: 1, step: 0.05, showExtremes: false, showValue: true, compact: true }, '0'),
1778
1820
  // ── Backdrop filter (virtual — composed to CSS backdrop-filter: …)
1779
- new TraitConfig('backdropBlur', 'B.Blur', TraitInputType.Scrub, { min: 0, max: 50, step: 1, units: ['px'] }, '0px', true),
1780
- new TraitConfig('backdropBrightness', 'B.Bri', TraitInputType.Scrub, { min: 0, max: 3, step: 0.05, units: [''] }, '1', true),
1781
- new TraitConfig('backdropContrast', 'B.Con', TraitInputType.Scrub, { min: 0, max: 3, step: 0.05, units: [''] }, '1', true),
1782
- new TraitConfig('backdropSaturate', 'B.Sat', TraitInputType.Scrub, { min: 0, max: 3, step: 0.05, units: [''] }, '1', true),
1821
+ new TraitConfig('_sep_backdrop', 'Backdrop', TraitInputType.SectionLabel),
1822
+ new TraitConfig('backdropBlur', 'Blur', TraitInputType.Scrub, { min: 0, max: 50, step: 1, units: ['px'] }, '0px', true),
1823
+ new TraitConfig('backdropBrightness', 'Brightness', TraitInputType.Range, { min: 0, max: 3, step: 0.05, showExtremes: false, showValue: true, compact: true }, '1', true),
1824
+ new TraitConfig('backdropContrast', 'Contrast', TraitInputType.Range, { min: 0, max: 3, step: 0.05, showExtremes: false, showValue: true, compact: true }, '1', true),
1825
+ new TraitConfig('backdropSaturate', 'Saturate', TraitInputType.Range, { min: 0, max: 3, step: 0.05, showExtremes: false, showValue: true, compact: true }, '1', true),
1783
1826
  // ── Transition (virtual — composed to CSS transition: all …) ──
1784
- new TraitConfig('transitionDuration', 'Duration', TraitInputType.Scrub, { min: 0, max: 3000, step: 50, units: ['ms'] }, '0ms'),
1827
+ new TraitConfig('_sep_transition', 'Transition', TraitInputType.SectionLabel),
1828
+ new TraitConfig('transitionDuration', 'Duration', TraitInputType.Scrub, { min: 0, max: 3000, step: 50, units: ['ms'] }, '0ms', true),
1829
+ new TraitConfig('transitionDelay', 'Delay', TraitInputType.Scrub, { min: 0, max: 2000, step: 50, units: ['ms'] }, '0ms', true),
1785
1830
  new TraitConfig('transitionTimingFunction', 'Easing', TraitInputType.Select, [
1786
1831
  'ease', 'linear', 'ease-in', 'ease-out', 'ease-in-out',
1787
1832
  ], 'ease'),
1788
- new TraitConfig('transitionDelay', 'Delay', TraitInputType.Scrub, { min: 0, max: 2000, step: 50, units: ['ms'] }, '0ms'),
1789
1833
  ]);
1790
1834
  }
1791
1835
  }