route-graphics 1.46.1 → 1.48.0

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.
@@ -2624,6 +2624,9 @@ var RECT_STYLE_TWEEN_FIELDS = /* @__PURE__ */ new Set([
2624
2624
  "border",
2625
2625
  "cornerRadius"
2626
2626
  ]);
2627
+ var NO_TRACKS = Symbol("no animation tracks");
2628
+ var EMPTY_MANUAL_TRACKS = { allowEmptyKeyframes: true };
2629
+ var MANUAL_TRACK_FIELDS = /* @__PURE__ */ new Set(["initialValue", "keyframes"]);
2627
2630
  var assertPlainObject3 = (value, path5) => {
2628
2631
  if (!value || typeof value !== "object" || Array.isArray(value)) {
2629
2632
  throw new Error(`${path5} must be an object.`);
@@ -2762,16 +2765,23 @@ var normalizeAutoTween = (autoConfig, path5) => {
2762
2765
  ...autoConfig.delay > 0 ? { delay: autoConfig.delay } : {}
2763
2766
  };
2764
2767
  };
2765
- var normalizeKeyframes = (propertyConfig, path5, assertValue = assertNumber, normalizeValue = (value) => Array.isArray(value) ? [...value] : value) => {
2768
+ var normalizeKeyframes = (propertyConfig, path5, assertValue = assertNumber, normalizeValue = (value) => Array.isArray(value) ? [...value] : value, { allowEmptyKeyframes = false } = {}) => {
2766
2769
  assertPlainObject3(propertyConfig, path5);
2767
2770
  const normalized = {};
2768
2771
  if (propertyConfig.initialValue !== void 0) {
2769
2772
  assertValue(propertyConfig.initialValue, `${path5}.initialValue`);
2770
2773
  normalized.initialValue = normalizeValue(propertyConfig.initialValue);
2771
2774
  }
2772
- if (!Array.isArray(propertyConfig.keyframes) || propertyConfig.keyframes.length === 0) {
2775
+ if (!Array.isArray(propertyConfig.keyframes)) {
2773
2776
  throw new Error(`${path5}.keyframes must be a non-empty array.`);
2774
2777
  }
2778
+ if (propertyConfig.keyframes.length === 0) {
2779
+ if (!allowEmptyKeyframes) {
2780
+ throw new Error(`${path5}.keyframes must be a non-empty array.`);
2781
+ }
2782
+ assertKnownFields2(propertyConfig, MANUAL_TRACK_FIELDS, path5);
2783
+ return NO_TRACKS;
2784
+ }
2775
2785
  normalized.keyframes = propertyConfig.keyframes.map((keyframe, index) => {
2776
2786
  const keyframePath = `${path5}.keyframes[${index}]`;
2777
2787
  assertPlainObject3(keyframe, keyframePath);
@@ -2811,14 +2821,15 @@ var normalizeKeyframes = (propertyConfig, path5, assertValue = assertNumber, nor
2811
2821
  });
2812
2822
  return normalized;
2813
2823
  };
2814
- var normalizeShaderTweenMap = (tween, path5) => {
2824
+ var normalizeShaderTweenMap = (tween, path5, options = {}) => {
2815
2825
  assertPlainObject3(tween, path5);
2826
+ const { allowEmptyMap = false, ...keyframeOptions } = options;
2816
2827
  const entries = Object.entries(tween);
2817
- if (entries.length === 0) {
2828
+ if (entries.length === 0 && !allowEmptyMap) {
2818
2829
  throw new Error(`${path5} must define at least one parameter.`);
2819
2830
  }
2820
2831
  return Object.fromEntries(
2821
- entries.map(([parameter, config]) => {
2832
+ entries.flatMap(([parameter, config]) => {
2822
2833
  if (parameter === "uTime" || parameter === "time") {
2823
2834
  throw new Error(
2824
2835
  `${path5}.${parameter} is read-only. Animate a custom parameter instead.`
@@ -2834,18 +2845,18 @@ var normalizeShaderTweenMap = (tween, path5) => {
2834
2845
  `${path5}.${parameter} must be progress or match ${SHADER_PARAMETER_PATTERN.source}.`
2835
2846
  );
2836
2847
  }
2837
- return [
2838
- parameter === "progress" ? "uProgress" : parameter,
2839
- normalizeKeyframes(
2840
- config,
2841
- `${path5}.${parameter}`,
2842
- parameter === "progress" ? assertShaderProgressValue : assertShaderTweenValue
2843
- )
2844
- ];
2848
+ const normalized = normalizeKeyframes(
2849
+ config,
2850
+ `${path5}.${parameter}`,
2851
+ parameter === "progress" ? assertShaderProgressValue : assertShaderTweenValue,
2852
+ void 0,
2853
+ keyframeOptions
2854
+ );
2855
+ return normalized === NO_TRACKS ? [] : [[parameter === "progress" ? "uProgress" : parameter, normalized]];
2845
2856
  })
2846
2857
  );
2847
2858
  };
2848
- var normalizeUpdatePropertyConfig = (propertyConfig, path5) => {
2859
+ var normalizeUpdatePropertyConfig = (propertyConfig, path5, options = {}) => {
2849
2860
  assertPlainObject3(propertyConfig, path5);
2850
2861
  const hasKeyframes = propertyConfig.keyframes !== void 0;
2851
2862
  const hasAuto = propertyConfig.auto !== void 0;
@@ -2865,7 +2876,13 @@ var normalizeUpdatePropertyConfig = (propertyConfig, path5) => {
2865
2876
  auto: normalizeAutoTween(propertyConfig.auto, `${path5}.auto`)
2866
2877
  };
2867
2878
  }
2868
- return normalizeKeyframes(propertyConfig, path5);
2879
+ return normalizeKeyframes(
2880
+ propertyConfig,
2881
+ path5,
2882
+ void 0,
2883
+ void 0,
2884
+ options
2885
+ );
2869
2886
  };
2870
2887
  var normalizeColorValue = (value, path5) => {
2871
2888
  if (typeof value !== "string" || value.length === 0) {
@@ -2877,10 +2894,10 @@ var normalizeColorValue = (value, path5) => {
2877
2894
  throw new Error(`${path5} must be a valid color.`);
2878
2895
  }
2879
2896
  };
2880
- var normalizeColorPropertyConfig = (propertyConfig, path5) => {
2897
+ var normalizeColorPropertyConfig = (propertyConfig, path5, options = {}) => {
2881
2898
  assertPlainObject3(propertyConfig, path5);
2882
2899
  if (propertyConfig.auto !== void 0) {
2883
- return normalizeUpdatePropertyConfig(propertyConfig, path5);
2900
+ return normalizeUpdatePropertyConfig(propertyConfig, path5, options);
2884
2901
  }
2885
2902
  for (const [index, keyframe] of (propertyConfig.keyframes ?? []).entries()) {
2886
2903
  if (keyframe?.relative === true) {
@@ -2895,25 +2912,26 @@ var normalizeColorPropertyConfig = (propertyConfig, path5) => {
2895
2912
  (value, valuePath) => {
2896
2913
  normalizeColorValue(value, valuePath);
2897
2914
  },
2898
- normalizeColorValue
2915
+ normalizeColorValue,
2916
+ options
2899
2917
  );
2900
2918
  };
2901
2919
  var normalizeRectPointTween = (point, path5, prefix) => {
2902
2920
  assertPlainObject3(point, path5);
2903
2921
  assertKnownFields2(point, /* @__PURE__ */ new Set(["x", "y"]), path5);
2904
- const entries = Object.entries(point);
2905
- if (entries.length === 0) {
2906
- throw new Error(`${path5} must define x or y.`);
2907
- }
2908
2922
  return Object.fromEntries(
2909
- entries.map(([axis, config]) => [
2910
- `${prefix}.${axis}`,
2911
- normalizeUpdatePropertyConfig(config, `${path5}.${axis}`)
2912
- ])
2923
+ Object.entries(point).flatMap(([axis, config]) => {
2924
+ const normalized = normalizeUpdatePropertyConfig(
2925
+ config,
2926
+ `${path5}.${axis}`,
2927
+ EMPTY_MANUAL_TRACKS
2928
+ );
2929
+ return normalized === NO_TRACKS ? [] : [[`${prefix}.${axis}`, normalized]];
2930
+ })
2913
2931
  );
2914
2932
  };
2915
2933
  var normalizeRectFillStopsTween = (stops, path5) => {
2916
- if (!Array.isArray(stops) || stops.length === 0) {
2934
+ if (!Array.isArray(stops)) {
2917
2935
  throw new Error(`${path5} must be a non-empty array.`);
2918
2936
  }
2919
2937
  const indices = /* @__PURE__ */ new Set();
@@ -2933,17 +2951,28 @@ var normalizeRectFillStopsTween = (stops, path5) => {
2933
2951
  if (stop.offset === void 0 && stop.color === void 0) {
2934
2952
  throw new Error(`${itemPath} must define offset or color.`);
2935
2953
  }
2936
- return {
2937
- ...stop.offset === void 0 ? {} : {
2938
- [`rect.fill.stops.${stop.index}.offset`]: normalizeUpdatePropertyConfig(
2939
- stop.offset,
2940
- `${itemPath}.offset`
2941
- )
2942
- },
2943
- ...stop.color === void 0 ? {} : {
2944
- [`rect.fill.stops.${stop.index}.color`]: normalizeColorPropertyConfig(stop.color, `${itemPath}.color`)
2954
+ const stopTracks = {};
2955
+ if (stop.offset !== void 0) {
2956
+ const offset = normalizeUpdatePropertyConfig(
2957
+ stop.offset,
2958
+ `${itemPath}.offset`,
2959
+ EMPTY_MANUAL_TRACKS
2960
+ );
2961
+ if (offset !== NO_TRACKS) {
2962
+ stopTracks[`rect.fill.stops.${stop.index}.offset`] = offset;
2945
2963
  }
2946
- };
2964
+ }
2965
+ if (stop.color !== void 0) {
2966
+ const color = normalizeColorPropertyConfig(
2967
+ stop.color,
2968
+ `${itemPath}.color`,
2969
+ EMPTY_MANUAL_TRACKS
2970
+ );
2971
+ if (color !== NO_TRACKS) {
2972
+ stopTracks[`rect.fill.stops.${stop.index}.color`] = color;
2973
+ }
2974
+ }
2975
+ return stopTracks;
2947
2976
  })
2948
2977
  );
2949
2978
  };
@@ -2965,53 +2994,67 @@ var normalizeRectFillTween = (fill, path5) => {
2965
2994
  ]),
2966
2995
  path5
2967
2996
  );
2968
- if (Object.keys(fill).length === 0) {
2969
- throw new Error(`${path5} must define at least one property.`);
2997
+ const normalized = {};
2998
+ if (fill.color !== void 0) {
2999
+ const color = normalizeColorPropertyConfig(
3000
+ fill.color,
3001
+ `${path5}.color`,
3002
+ EMPTY_MANUAL_TRACKS
3003
+ );
3004
+ if (color !== NO_TRACKS) {
3005
+ normalized["rect.fill.color"] = color;
3006
+ }
3007
+ }
3008
+ for (const [point, prefix] of [
3009
+ ["start", "rect.fill.start"],
3010
+ ["end", "rect.fill.end"],
3011
+ ["innerCenter", "rect.fill.innerCenter"],
3012
+ ["outerCenter", "rect.fill.outerCenter"]
3013
+ ]) {
3014
+ if (fill[point] !== void 0) {
3015
+ Object.assign(
3016
+ normalized,
3017
+ normalizeRectPointTween(fill[point], `${path5}.${point}`, prefix)
3018
+ );
3019
+ }
2970
3020
  }
2971
- return {
2972
- ...fill.color === void 0 ? {} : {
2973
- "rect.fill.color": normalizeColorPropertyConfig(
2974
- fill.color,
2975
- `${path5}.color`
2976
- )
2977
- },
2978
- ...fill.start === void 0 ? {} : normalizeRectPointTween(
2979
- fill.start,
2980
- `${path5}.start`,
2981
- "rect.fill.start"
2982
- ),
2983
- ...fill.end === void 0 ? {} : normalizeRectPointTween(fill.end, `${path5}.end`, "rect.fill.end"),
2984
- ...fill.innerCenter === void 0 ? {} : normalizeRectPointTween(
2985
- fill.innerCenter,
2986
- `${path5}.innerCenter`,
2987
- "rect.fill.innerCenter"
2988
- ),
2989
- ...fill.outerCenter === void 0 ? {} : normalizeRectPointTween(
2990
- fill.outerCenter,
2991
- `${path5}.outerCenter`,
2992
- "rect.fill.outerCenter"
2993
- ),
2994
- ...Object.fromEntries(
2995
- ["innerRadius", "outerRadius", "scale", "rotation"].filter((property) => fill[property] !== void 0).map((property) => [
2996
- `rect.fill.${property}`,
2997
- normalizeUpdatePropertyConfig(fill[property], `${path5}.${property}`)
2998
- ])
2999
- ),
3000
- ...fill.stops === void 0 ? {} : normalizeRectFillStopsTween(fill.stops, `${path5}.stops`)
3001
- };
3021
+ for (const property of ["innerRadius", "outerRadius", "scale", "rotation"]) {
3022
+ if (fill[property] === void 0) {
3023
+ continue;
3024
+ }
3025
+ const tracks = normalizeUpdatePropertyConfig(
3026
+ fill[property],
3027
+ `${path5}.${property}`,
3028
+ EMPTY_MANUAL_TRACKS
3029
+ );
3030
+ if (tracks !== NO_TRACKS) {
3031
+ normalized[`rect.fill.${property}`] = tracks;
3032
+ }
3033
+ }
3034
+ if (fill.stops !== void 0) {
3035
+ Object.assign(
3036
+ normalized,
3037
+ normalizeRectFillStopsTween(fill.stops, `${path5}.stops`)
3038
+ );
3039
+ }
3040
+ return normalized;
3002
3041
  };
3003
3042
  var normalizeRectBorderTween = (border, path5) => {
3004
3043
  assertPlainObject3(border, path5);
3005
3044
  assertKnownFields2(border, /* @__PURE__ */ new Set(["width", "color", "alpha"]), path5);
3006
- const entries = Object.entries(border);
3007
- if (entries.length === 0) {
3008
- throw new Error(`${path5} must define width, color, or alpha.`);
3009
- }
3010
3045
  return Object.fromEntries(
3011
- entries.map(([property, config]) => [
3012
- `rect.border.${property}`,
3013
- property === "color" ? normalizeColorPropertyConfig(config, `${path5}.${property}`) : normalizeUpdatePropertyConfig(config, `${path5}.${property}`)
3014
- ])
3046
+ Object.entries(border).flatMap(([property, config]) => {
3047
+ const normalized = property === "color" ? normalizeColorPropertyConfig(
3048
+ config,
3049
+ `${path5}.${property}`,
3050
+ EMPTY_MANUAL_TRACKS
3051
+ ) : normalizeUpdatePropertyConfig(
3052
+ config,
3053
+ `${path5}.${property}`,
3054
+ EMPTY_MANUAL_TRACKS
3055
+ );
3056
+ return normalized === NO_TRACKS ? [] : [[`rect.border.${property}`, normalized]];
3057
+ })
3015
3058
  );
3016
3059
  };
3017
3060
  var normalizeRectCornerRadiusTween = (cornerRadius, path5) => {
@@ -3024,36 +3067,44 @@ var normalizeRectCornerRadiusTween = (cornerRadius, path5) => {
3024
3067
  /* @__PURE__ */ new Set(["initialValue", "keyframes", "auto"]),
3025
3068
  path5
3026
3069
  );
3027
- const normalized = normalizeUpdatePropertyConfig(cornerRadius, path5);
3070
+ const normalized = normalizeUpdatePropertyConfig(
3071
+ cornerRadius,
3072
+ path5,
3073
+ EMPTY_MANUAL_TRACKS
3074
+ );
3075
+ if (normalized === NO_TRACKS) {
3076
+ return {};
3077
+ }
3028
3078
  return Object.fromEntries(
3029
3079
  cornerNames.map((corner) => [`rect.cornerRadius.${corner}`, normalized])
3030
3080
  );
3031
3081
  }
3032
3082
  assertKnownFields2(cornerRadius, new Set(cornerNames), path5);
3033
- const entries = Object.entries(cornerRadius);
3034
- if (entries.length === 0) {
3035
- throw new Error(`${path5} must define at least one corner.`);
3036
- }
3037
3083
  return Object.fromEntries(
3038
- entries.map(([corner, config]) => [
3039
- `rect.cornerRadius.${corner}`,
3040
- normalizeUpdatePropertyConfig(config, `${path5}.${corner}`)
3041
- ])
3084
+ Object.entries(cornerRadius).flatMap(([corner, config]) => {
3085
+ const normalized = normalizeUpdatePropertyConfig(
3086
+ config,
3087
+ `${path5}.${corner}`,
3088
+ EMPTY_MANUAL_TRACKS
3089
+ );
3090
+ return normalized === NO_TRACKS ? [] : [[`rect.cornerRadius.${corner}`, normalized]];
3091
+ })
3042
3092
  );
3043
3093
  };
3044
3094
  var normalizeRectStyleTween = (rectTween, path5) => {
3045
3095
  const normalized = {};
3046
- if (rectTween.width !== void 0) {
3047
- normalized["rect.width"] = normalizeUpdatePropertyConfig(
3048
- rectTween.width,
3049
- `${path5}.width`
3050
- );
3051
- }
3052
- if (rectTween.height !== void 0) {
3053
- normalized["rect.height"] = normalizeUpdatePropertyConfig(
3054
- rectTween.height,
3055
- `${path5}.height`
3096
+ for (const property of ["width", "height"]) {
3097
+ if (rectTween[property] === void 0) {
3098
+ continue;
3099
+ }
3100
+ const tracks = normalizeUpdatePropertyConfig(
3101
+ rectTween[property],
3102
+ `${path5}.${property}`,
3103
+ EMPTY_MANUAL_TRACKS
3056
3104
  );
3105
+ if (tracks !== NO_TRACKS) {
3106
+ normalized[`rect.${property}`] = tracks;
3107
+ }
3057
3108
  }
3058
3109
  if (rectTween.fill !== void 0) {
3059
3110
  Object.assign(
@@ -3078,7 +3129,8 @@ var normalizeRectStyleTween = (rectTween, path5) => {
3078
3129
  }
3079
3130
  return normalized;
3080
3131
  };
3081
- var normalizeTweenMap = (tween, path5, allowedProperties, propertyNormalizer = normalizeKeyframes) => {
3132
+ var normalizeSurfacePropertyConfig = (propertyConfig, path5, options) => normalizeKeyframes(propertyConfig, path5, void 0, void 0, options);
3133
+ var normalizeTweenMap = (tween, path5, allowedProperties, propertyNormalizer = normalizeSurfacePropertyConfig, options = EMPTY_MANUAL_TRACKS) => {
3082
3134
  assertPlainObject3(tween, path5);
3083
3135
  if (tween.x !== void 0 && tween.translateX !== void 0) {
3084
3136
  throw new Error(`${path5} cannot define both x and translateX.`);
@@ -3086,29 +3138,33 @@ var normalizeTweenMap = (tween, path5, allowedProperties, propertyNormalizer = n
3086
3138
  if (tween.y !== void 0 && tween.translateY !== void 0) {
3087
3139
  throw new Error(`${path5} cannot define both y and translateY.`);
3088
3140
  }
3089
- const normalizedEntries = Object.entries(tween).map(([property, config]) => {
3090
- if (!allowedProperties.has(property)) {
3091
- throw new Error(
3092
- `${path5}.${property} is not a supported animation property.`
3141
+ return Object.fromEntries(
3142
+ Object.entries(tween).flatMap(([property, config]) => {
3143
+ if (!allowedProperties.has(property)) {
3144
+ throw new Error(
3145
+ `${path5}.${property} is not a supported animation property.`
3146
+ );
3147
+ }
3148
+ const normalizedProperty = propertyNormalizer(
3149
+ config,
3150
+ `${path5}.${property}`,
3151
+ options
3093
3152
  );
3094
- }
3095
- return [property, propertyNormalizer(config, `${path5}.${property}`)];
3096
- });
3097
- if (normalizedEntries.length === 0) {
3098
- throw new Error(`${path5} must define at least one property.`);
3099
- }
3100
- return Object.fromEntries(normalizedEntries);
3153
+ return normalizedProperty === NO_TRACKS ? [] : [[property, normalizedProperty]];
3154
+ })
3155
+ );
3101
3156
  };
3102
3157
  var normalizeFilterTweens = (filters, path5) => {
3103
3158
  assertPlainObject3(filters, path5);
3104
- const entries = Object.entries(filters);
3105
- if (entries.length === 0) {
3106
- throw new Error(`${path5} must target at least one filter.`);
3107
- }
3108
3159
  return Object.fromEntries(
3109
- entries.map(([filterId, tween]) => {
3160
+ Object.entries(filters).flatMap(([filterId, tween]) => {
3110
3161
  assertString(filterId, `${path5} filter id`);
3111
- return [filterId, normalizeShaderTweenMap(tween, `${path5}.${filterId}`)];
3162
+ const tweenTracks = normalizeShaderTweenMap(
3163
+ tween,
3164
+ `${path5}.${filterId}`,
3165
+ { allowEmptyMap: true, allowEmptyKeyframes: true }
3166
+ );
3167
+ return Object.keys(tweenTracks).length === 0 ? [] : [[filterId, tweenTracks]];
3112
3168
  })
3113
3169
  );
3114
3170
  };
@@ -3125,26 +3181,31 @@ var normalizeUpdateTween = (tween, path5) => {
3125
3181
  ([property]) => !RECT_STYLE_TWEEN_FIELDS.has(property)
3126
3182
  )
3127
3183
  );
3128
- const normalized = {};
3184
+ const tracks = {};
3129
3185
  if (Object.keys(elementTween).length > 0) {
3130
- normalized.tween = normalizeTweenMap(
3131
- elementTween,
3132
- path5,
3133
- UPDATE_TWEEN_PROPERTIES,
3134
- normalizeUpdatePropertyConfig
3186
+ Object.assign(
3187
+ tracks,
3188
+ normalizeTweenMap(
3189
+ elementTween,
3190
+ path5,
3191
+ UPDATE_TWEEN_PROPERTIES,
3192
+ normalizeUpdatePropertyConfig,
3193
+ EMPTY_MANUAL_TRACKS
3194
+ )
3135
3195
  );
3136
3196
  }
3137
3197
  if (Object.keys(rectTween).length > 0) {
3138
- normalized.tween = {
3139
- ...normalized.tween,
3140
- ...normalizeRectStyleTween(rectTween, path5)
3141
- };
3198
+ Object.assign(tracks, normalizeRectStyleTween(rectTween, path5));
3142
3199
  }
3143
- if (filters !== void 0) {
3144
- normalized.filterTweens = normalizeFilterTweens(filters, `${path5}.filters`);
3200
+ const normalized = {};
3201
+ if (Object.keys(tracks).length > 0) {
3202
+ normalized.tween = tracks;
3145
3203
  }
3146
- if (normalized.tween === void 0 && normalized.filterTweens === void 0) {
3147
- throw new Error(`${path5} must define an element property or filters.`);
3204
+ if (filters !== void 0) {
3205
+ const filterTweens = normalizeFilterTweens(filters, `${path5}.filters`);
3206
+ if (Object.keys(filterTweens).length > 0) {
3207
+ normalized.filterTweens = filterTweens;
3208
+ }
3148
3209
  }
3149
3210
  return normalized;
3150
3211
  };
@@ -3290,6 +3351,9 @@ var normalizeReplaceSide = (side, path5) => {
3290
3351
  if (side.mask !== void 0) {
3291
3352
  throw new Error(`${path5}.mask is not valid. Define mask on ${path5}.`);
3292
3353
  }
3354
+ if (side.tween === void 0 && Object.keys(side).length > 0) {
3355
+ throw new Error(`${path5} must define tween.`);
3356
+ }
3293
3357
  const normalized = {};
3294
3358
  if (side.tween !== void 0) {
3295
3359
  normalized.tween = normalizeTweenMap(
@@ -3298,18 +3362,27 @@ var normalizeReplaceSide = (side, path5) => {
3298
3362
  TRANSITION_TWEEN_PROPERTIES
3299
3363
  );
3300
3364
  }
3301
- if (Object.keys(normalized).length === 0) {
3302
- throw new Error(`${path5} must define tween.`);
3365
+ if (!normalized.tween || Object.keys(normalized.tween).length === 0) {
3366
+ assertKnownFields2(side, /* @__PURE__ */ new Set(["tween"]), path5);
3303
3367
  }
3304
3368
  return normalized;
3305
3369
  };
3306
3370
  var normalizeReplacePayload = (animation, path5) => {
3371
+ if (animation.prev === void 0 && animation.next === void 0 && animation.mask === void 0 && animation.compositor === void 0) {
3372
+ throw new Error(`${path5} must define prev, next, mask, or compositor.`);
3373
+ }
3307
3374
  const normalized = {};
3308
3375
  if (animation.prev !== void 0) {
3309
- normalized.prev = normalizeReplaceSide(animation.prev, `${path5}.prev`);
3376
+ const prev = normalizeReplaceSide(animation.prev, `${path5}.prev`);
3377
+ if (prev.tween && Object.keys(prev.tween).length > 0) {
3378
+ normalized.prev = prev;
3379
+ }
3310
3380
  }
3311
3381
  if (animation.next !== void 0) {
3312
- normalized.next = normalizeReplaceSide(animation.next, `${path5}.next`);
3382
+ const next = normalizeReplaceSide(animation.next, `${path5}.next`);
3383
+ if (next.tween && Object.keys(next.tween).length > 0) {
3384
+ normalized.next = next;
3385
+ }
3313
3386
  }
3314
3387
  if (animation.mask !== void 0) {
3315
3388
  normalized.mask = normalizeMasks(animation.mask, `${path5}.mask`);
@@ -3334,9 +3407,6 @@ var normalizeReplacePayload = (animation, path5) => {
3334
3407
  );
3335
3408
  }
3336
3409
  }
3337
- if (normalized.prev === void 0 && normalized.next === void 0 && normalized.mask === void 0 && normalized.compositor === void 0) {
3338
- throw new Error(`${path5} must define prev, next, mask, or compositor.`);
3339
- }
3340
3410
  return normalized;
3341
3411
  };
3342
3412
  var assertLegacyFieldAbsent = (value, path5, message) => {
@@ -3348,7 +3418,7 @@ var normalizeAnimations = (animations = []) => {
3348
3418
  if (!Array.isArray(animations)) {
3349
3419
  throw new Error("Input error: `animations` must be an array.");
3350
3420
  }
3351
- const normalized = animations.map((animation, index) => {
3421
+ const normalizedEntries = animations.map((animation, index) => {
3352
3422
  const path5 = `animations[${index}]`;
3353
3423
  assertPlainObject3(animation, path5);
3354
3424
  assertString(animation.id, `${path5}.id`);
@@ -3422,6 +3492,11 @@ var normalizeAnimations = (animations = []) => {
3422
3492
  if (animation.tween !== void 0 && animation.gsap !== void 0) {
3423
3493
  throw new Error(`${path5} cannot define both tween and gsap.`);
3424
3494
  }
3495
+ if (animation.tween === void 0 && animation.gsap === void 0) {
3496
+ throw new Error(
3497
+ `${path5} must define exactly one of tween or gsap for an update animation.`
3498
+ );
3499
+ }
3425
3500
  if (animation.tween !== void 0) {
3426
3501
  Object.assign(
3427
3502
  normalizedAnimation,
@@ -3435,11 +3510,6 @@ var normalizeAnimations = (animations = []) => {
3435
3510
  "update"
3436
3511
  );
3437
3512
  }
3438
- if (normalizedAnimation.tween === void 0 && normalizedAnimation.filterTweens === void 0 && normalizedAnimation.gsap === void 0) {
3439
- throw new Error(
3440
- `${path5} must define exactly one of tween or gsap for an update animation.`
3441
- );
3442
- }
3443
3513
  if (animation.replace !== void 0) {
3444
3514
  throw new Error(
3445
3515
  `${path5}.replace is no longer supported. Define \`prev\`, \`next\`, or \`mask\` directly on the animation.`
@@ -3465,7 +3535,7 @@ var normalizeAnimations = (animations = []) => {
3465
3535
  `${path5}.compositor is only valid for transition animations.`
3466
3536
  );
3467
3537
  }
3468
- return normalizedAnimation;
3538
+ return normalizedAnimation.tween === void 0 && normalizedAnimation.filterTweens === void 0 && normalizedAnimation.gsap === void 0 ? null : normalizedAnimation;
3469
3539
  }
3470
3540
  if (animation.tween !== void 0) {
3471
3541
  throw new Error(`${path5}.tween is not valid for transition animations.`);
@@ -3535,11 +3605,15 @@ var normalizeAnimations = (animations = []) => {
3535
3605
  if (normalizedReplace.compositor !== void 0) {
3536
3606
  normalizedAnimation.compositor = normalizedReplace.compositor;
3537
3607
  }
3538
- return normalizedAnimation;
3608
+ return Object.keys(normalizedReplace).length === 0 ? null : normalizedAnimation;
3539
3609
  });
3610
+ const normalized = normalizedEntries.filter(
3611
+ (animation) => animation !== null
3612
+ );
3540
3613
  const animationIds = /* @__PURE__ */ new Map();
3541
3614
  const transitionTargets = /* @__PURE__ */ new Map();
3542
- for (const [index, animation] of normalized.entries()) {
3615
+ for (const [index, animation] of normalizedEntries.entries()) {
3616
+ if (animation === null) continue;
3543
3617
  const priorIdIndex = animationIds.get(animation.id);
3544
3618
  if (priorIdIndex !== void 0) {
3545
3619
  throw new Error(
@@ -6589,10 +6663,12 @@ var inspectTimelineDefinition = ({
6589
6663
  );
6590
6664
  }
6591
6665
  const state = normalizeRenderState(rawState);
6592
- const indexedAnimations = state.animations.map((animation, index) => ({
6593
- animation,
6594
- index
6595
- }));
6666
+ const indexedAnimations = (rawState.animations ?? []).flatMap(
6667
+ (raw, index) => {
6668
+ const [animation] = normalizeAnimations([raw]);
6669
+ return animation ? [{ animation, index }] : [];
6670
+ }
6671
+ );
6596
6672
  const selected = animationId ? indexedAnimations.filter(({ animation }) => animation.id === animationId) : indexedAnimations;
6597
6673
  if (animationId && selected.length === 0) {
6598
6674
  throw new Error(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "route-graphics",
3
- "version": "1.46.1",
3
+ "version": "1.48.0",
4
4
  "description": "A 2D graphics rendering interface that takes JSON input and renders pixels using PixiJS",
5
5
  "main": "dist/RouteGraphics.js",
6
6
  "type": "module",
@@ -71,6 +71,7 @@
71
71
  },
72
72
  "devDependencies": {
73
73
  "@vitest/coverage-v8": "^4.0.8",
74
+ "ajv": "8.17.1",
74
75
  "canvas": "3.2.0",
75
76
  "esbuild": "^0.25.6",
76
77
  "husky": "^9.1.7",