shouldTransition method

bool shouldTransition(
  1. String property,
  2. String? prevValue,
  3. String nextValue
)

Implementation

bool shouldTransition(String property, String? prevValue, String nextValue) {
  if (DebugFlags.shouldLogTransitionForProp(property)) {
    cssLogger.info('[transition][check] property=$property prev=${prevValue ?? 'null'} next=$nextValue');
  }

  // Custom properties (CSS variables) are not animatable. Their changes may
  // indirectly drive transitions on animatable properties (e.g., transform)
  // via the CSSVariableMixin path. Skip here to avoid confusing logs.
  if (CSSVariable.isCSSSVariableProperty(property)) {
    return false;
  }
  // When begin propertyValue is AUTO, skip animation and trigger style update directly.
  prevValue = (prevValue == null || prevValue.isEmpty) ? CSSInitialValues[property] : prevValue;
  // If the serialized values are identical, skip scheduling here. Var-driven
  // changes may be handled by the CSSVariableMixin path that schedules a
  // transition with an explicit prev substitution.
  if (prevValue == nextValue) {
    if (DebugFlags.shouldLogTransitionForProp(property)) {
      cssLogger.info('[transition][check] property=$property skip: same-serialized');
    }
    return false;
  }
  if (CSSLength.isAuto(prevValue) || CSSLength.isAuto(nextValue)) {
    if (DebugFlags.shouldLogTransitionForProp(property)) {
      cssLogger.info('[transition][check] property=$property skip: auto');
    }
    return false;
  }

  // Transition does not work when renderBoxModel has not been layout yet
  // or when we don't have a transition handler for this property.
  final bool hasRenderBoxModel = hasRenderBox();
  final bool hasBoxSize = isBoxModelHaveSize();
  final bool hasHandler = CSSTransitionHandlers[property] != null;

  if (!hasRenderBoxModel || !hasBoxSize || !hasHandler) {
    if (DebugFlags.shouldLogTransitionForProp(property)) {
      final String reason;
      if (!hasRenderBoxModel || !hasBoxSize) {
        reason = 'no-layout (hasRenderBox=$hasRenderBoxModel hasSize=$hasBoxSize)';
      } else {
        reason = 'no-handler';
      }
      cssLogger.info('[transition][check] property=$property skip: $reason');
    }
    return false;
  }

  final String key = _canonicalTransitionKey(property);
  final bool configured = effectiveTransitions.containsKey(key) || effectiveTransitions.containsKey(ALL);
  if (!configured) {
    if (DebugFlags.shouldLogTransitionForProp(property)) {
      cssLogger
          .info('[transition][check] property=$property skip: not-configured (key=$key)');
    }
    return false;
  }
  if (DebugFlags.shouldLogTransitionForProp(property)) {
    final List? opts = effectiveTransitions[key] ?? effectiveTransitions[ALL];
    cssLogger.info(
        '[transition][check] property=$property key=$key opts=${opts != null ? '{duration: ${opts[0]}, easing: ${opts[1]}, delay: ${opts[2]}}' : 'null'}');
  }
  bool shouldTransition = false;
  // Transition will be disabled when all transition has transitionDuration as 0.
  effectiveTransitions.forEach((String transitionKey, List transitionOptions) {
    int? duration = CSSTime.parseTime(transitionOptions[0]);
    if (duration != null && duration != 0) {
      shouldTransition = true;
    }
  });
  if (DebugFlags.shouldLogTransitionForProp(property)) {
    cssLogger.info(
        '[transition][check] property=$property configured key=$key result=$shouldTransition');
  }
  return shouldTransition;
}