route-graphics 1.40.0 → 1.42.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.
@@ -2770,6 +2770,9 @@ var normalizeKeyframes = (propertyConfig, path5, assertValue = assertNumber, nor
2770
2770
  const keyframePath = `${path5}.keyframes[${index}]`;
2771
2771
  assertPlainObject3(keyframe, keyframePath);
2772
2772
  assertValue(keyframe.value, `${keyframePath}.value`);
2773
+ if (keyframe.startValue !== void 0) {
2774
+ assertValue(keyframe.startValue, `${keyframePath}.startValue`);
2775
+ }
2773
2776
  assertNonNegativeSafeIntegerMilliseconds(
2774
2777
  keyframe.duration,
2775
2778
  `${keyframePath}.duration`
@@ -2793,6 +2796,7 @@ var normalizeKeyframes = (propertyConfig, path5, assertValue = assertNumber, nor
2793
2796
  }
2794
2797
  return {
2795
2798
  value: normalizeValue(keyframe.value),
2799
+ ...keyframe.startValue === void 0 ? {} : { startValue: normalizeValue(keyframe.startValue) },
2796
2800
  duration: keyframe.duration,
2797
2801
  easing: keyframe.easing ?? "linear",
2798
2802
  ...keyframe.delay > 0 ? { delay: keyframe.delay } : {},
@@ -3604,12 +3608,9 @@ var NO_AUDIO_PLAYBACK_POSITION_OPERATIONS = /* @__PURE__ */ new Set();
3604
3608
  var AUDIO_PLAYBACK_KEYS = /* @__PURE__ */ new Set(["commandId", "operation", "positionMs"]);
3605
3609
  var AUDIO_TRANSITION_TYPE = "audio-transition";
3606
3610
  var AUDIO_EFFECT_TYPES = /* @__PURE__ */ new Set([AUDIO_TRANSITION_TYPE]);
3611
+ var AUDIO_EFFECT_KEYS = /* @__PURE__ */ new Set(["id", "type", "targetId", "properties"]);
3607
3612
  var AUDIO_TRANSITION_PHASES = /* @__PURE__ */ new Set(["enter", "exit", "update"]);
3608
3613
  var AUDIO_TRANSITION_PROPERTIES = /* @__PURE__ */ new Set(["volume", "pan", "playbackRate"]);
3609
- var AUDIO_TRANSITION_PROPERTIES_BY_NODE_TYPE = {
3610
- "audio-channel": /* @__PURE__ */ new Set(["volume", "pan"]),
3611
- sound: /* @__PURE__ */ new Set(["volume", "pan", "playbackRate"])
3612
- };
3613
3614
  var AUDIO_TRANSITION_PROPERTY_RANGES = {
3614
3615
  volume: { min: 0, max: 100 },
3615
3616
  pan: { min: -1, max: 1 },
@@ -3619,6 +3620,7 @@ var AUDIO_EASINGS = new Set(SUPPORTED_EASING_NAMES);
3619
3620
  var AUDIO_TRANSITION_PHASE_KEYS = /* @__PURE__ */ new Set(["initialValue", "keyframes"]);
3620
3621
  var AUDIO_TRANSITION_KEYFRAME_KEYS = /* @__PURE__ */ new Set([
3621
3622
  "value",
3623
+ "startValue",
3622
3624
  "duration",
3623
3625
  "delay",
3624
3626
  "easing",
@@ -3729,7 +3731,7 @@ var normalizePlaybackCommand = (playback, path5, {
3729
3731
  ...requiresPosition ? { positionMs: playback.positionMs } : {}
3730
3732
  };
3731
3733
  };
3732
- var validateSound = (node, path5, ids, flattenedSounds, inlineTransitions, channelId = null) => {
3734
+ var validateSound = (node, path5, ids, flattenedSounds, channelId = null) => {
3733
3735
  assertNonEmptyString3(node.id, `${path5}.id`);
3734
3736
  assertUniqueId(ids, node.id, `${path5}.id`);
3735
3737
  assertNonEmptyString3(node.src, `${path5}.src`);
@@ -3753,16 +3755,8 @@ var validateSound = (node, path5, ids, flattenedSounds, inlineTransitions, chann
3753
3755
  }
3754
3756
  const playback = node.playback === void 0 ? void 0 : normalizePlaybackCommand(node.playback, `${path5}.playback`);
3755
3757
  if (node.transition !== void 0) {
3756
- inlineTransitions.set(
3757
- node.id,
3758
- validateInlineAudioTransition(node.transition, `${path5}.transition`, {
3759
- nodeType: "sound",
3760
- propertyValues: {
3761
- volume,
3762
- pan: node.pan ?? 0,
3763
- playbackRate: node.playbackRate ?? 1
3764
- }
3765
- })
3758
+ throw new Error(
3759
+ `Input error: ${path5}.transition is not supported. Use top-level audioEffects instead.`
3766
3760
  );
3767
3761
  }
3768
3762
  flattenedSounds.push({
@@ -3781,7 +3775,7 @@ var validateSound = (node, path5, ids, flattenedSounds, inlineTransitions, chann
3781
3775
  ...playback ? { playback } : {}
3782
3776
  });
3783
3777
  };
3784
- var validateChannel = (node, path5, ids, flattenedChannels, flattenedSounds, inlineTransitions) => {
3778
+ var validateChannel = (node, path5, ids, flattenedChannels, flattenedSounds) => {
3785
3779
  assertNonEmptyString3(node.id, `${path5}.id`);
3786
3780
  assertUniqueId(ids, node.id, `${path5}.id`);
3787
3781
  const volume = normalizeVolumeValue(node.volume, `${path5}.volume`);
@@ -3803,15 +3797,8 @@ var validateChannel = (node, path5, ids, flattenedChannels, flattenedSounds, inl
3803
3797
  positionOperations: NO_AUDIO_PLAYBACK_POSITION_OPERATIONS
3804
3798
  });
3805
3799
  if (node.transition !== void 0) {
3806
- inlineTransitions.set(
3807
- node.id,
3808
- validateInlineAudioTransition(node.transition, `${path5}.transition`, {
3809
- nodeType: "audio-channel",
3810
- propertyValues: {
3811
- volume,
3812
- pan: node.pan ?? 0
3813
- }
3814
- })
3800
+ throw new Error(
3801
+ `Input error: ${path5}.transition is not supported. Use top-level audioEffects instead.`
3815
3802
  );
3816
3803
  }
3817
3804
  flattenedChannels.push({
@@ -3850,14 +3837,7 @@ var validateChannel = (node, path5, ids, flattenedChannels, flattenedSounds, inl
3850
3837
  `Input error: ${childPath}.playback is not allowed when ${path5}.playback is present.`
3851
3838
  );
3852
3839
  }
3853
- validateSound(
3854
- child,
3855
- childPath,
3856
- ids,
3857
- flattenedSounds,
3858
- inlineTransitions,
3859
- node.id
3860
- );
3840
+ validateSound(child, childPath, ids, flattenedSounds, node.id);
3861
3841
  }
3862
3842
  };
3863
3843
  var validateAudioNodes = (audio, ids) => {
@@ -3866,7 +3846,6 @@ var validateAudioNodes = (audio, ids) => {
3866
3846
  }
3867
3847
  const flattenedChannels = [];
3868
3848
  const flattenedSounds = [];
3869
- const inlineTransitions = /* @__PURE__ */ new Map();
3870
3849
  const builtinNodeIds = /* @__PURE__ */ new Set();
3871
3850
  for (const [index, node] of audio.entries()) {
3872
3851
  const path5 = `audio[${index}]`;
@@ -3877,14 +3856,7 @@ var validateAudioNodes = (audio, ids) => {
3877
3856
  continue;
3878
3857
  }
3879
3858
  if (node.type === "audio-channel") {
3880
- validateChannel(
3881
- node,
3882
- path5,
3883
- ids,
3884
- flattenedChannels,
3885
- flattenedSounds,
3886
- inlineTransitions
3887
- );
3859
+ validateChannel(node, path5, ids, flattenedChannels, flattenedSounds);
3888
3860
  builtinNodeIds.add(node.id);
3889
3861
  for (const sound of flattenedSounds) {
3890
3862
  if (sound.channelId === node.id) {
@@ -3892,14 +3864,13 @@ var validateAudioNodes = (audio, ids) => {
3892
3864
  }
3893
3865
  }
3894
3866
  } else {
3895
- validateSound(node, path5, ids, flattenedSounds, inlineTransitions);
3867
+ validateSound(node, path5, ids, flattenedSounds);
3896
3868
  builtinNodeIds.add(node.id);
3897
3869
  }
3898
3870
  }
3899
3871
  return {
3900
3872
  channels: flattenedChannels,
3901
3873
  sounds: flattenedSounds,
3902
- inlineTransitions,
3903
3874
  builtinNodeIds,
3904
3875
  builtinNodeTypes: new Map(
3905
3876
  [...flattenedChannels, ...flattenedSounds].map((node) => [
@@ -3909,7 +3880,7 @@ var validateAudioNodes = (audio, ids) => {
3909
3880
  )
3910
3881
  };
3911
3882
  };
3912
- var validateTransitionPhase = (phase, path5, propertyName, { finalValue } = {}) => {
3883
+ var validateTransitionPhase = (phase, path5, propertyName) => {
3913
3884
  assertRecord(phase, path5);
3914
3885
  for (const key of Object.keys(phase)) {
3915
3886
  if (!AUDIO_TRANSITION_PHASE_KEYS.has(key)) {
@@ -3948,6 +3919,13 @@ var validateTransitionPhase = (phase, path5, propertyName, { finalValue } = {})
3948
3919
  `${keyframePath}.value`,
3949
3920
  keyframe.relative ? void 0 : AUDIO_TRANSITION_PROPERTY_RANGES[propertyName]
3950
3921
  );
3922
+ if (keyframe.startValue !== void 0) {
3923
+ assertFiniteNumber2(
3924
+ keyframe.startValue,
3925
+ `${keyframePath}.startValue`,
3926
+ keyframe.relative ? void 0 : AUDIO_TRANSITION_PROPERTY_RANGES[propertyName]
3927
+ );
3928
+ }
3951
3929
  if (keyframe.duration === void 0) {
3952
3930
  throw new Error(`Input error: ${keyframePath}.duration is required.`);
3953
3931
  }
@@ -3964,61 +3942,9 @@ var validateTransitionPhase = (phase, path5, propertyName, { finalValue } = {})
3964
3942
  }
3965
3943
  assertOptionalBoolean(keyframe.relative, `${keyframePath}.relative`);
3966
3944
  }
3967
- if (finalValue !== void 0) {
3968
- const finalKeyframe = phase.keyframes[phase.keyframes.length - 1];
3969
- if (finalKeyframe.relative === true) {
3970
- throw new Error(
3971
- `Input error: ${path5}.keyframes must end with an absolute value.`
3972
- );
3973
- }
3974
- if (finalKeyframe.value !== finalValue) {
3975
- throw new Error(
3976
- `Input error: ${path5}.keyframes must end at the node's declared ${propertyName} value ${finalValue}.`
3977
- );
3978
- }
3979
- }
3980
3945
  };
3981
- function validateInlineAudioTransition(transition, path5, { nodeType, propertyValues }) {
3982
- assertNonEmptyRecord(transition, path5);
3983
- const normalizedProperties = {};
3984
- for (const [phaseName, propertyTracks] of Object.entries(transition)) {
3985
- if (!AUDIO_TRANSITION_PHASES.has(phaseName)) {
3986
- throw new Error(
3987
- `Input error: unsupported inline audio transition phase "${phaseName}" at ${path5}.`
3988
- );
3989
- }
3990
- assertNonEmptyRecord(propertyTracks, `${path5}.${phaseName}`);
3991
- for (const [propertyName, track] of Object.entries(propertyTracks)) {
3992
- if (!AUDIO_TRANSITION_PROPERTIES.has(propertyName)) {
3993
- throw new Error(
3994
- `Input error: unsupported inline audio transition property "${propertyName}" at ${path5}.${phaseName}.`
3995
- );
3996
- }
3997
- if (!AUDIO_TRANSITION_PROPERTIES_BY_NODE_TYPE[nodeType].has(propertyName)) {
3998
- throw new Error(
3999
- `Input error: inline audio transition property "${propertyName}" is not supported for node type "${nodeType}" at ${path5}.${phaseName}.`
4000
- );
4001
- }
4002
- validateTransitionPhase(
4003
- track,
4004
- `${path5}.${phaseName}.${propertyName}`,
4005
- propertyName,
4006
- phaseName === "enter" || phaseName === "update" ? { finalValue: propertyValues[propertyName] } : {}
4007
- );
4008
- normalizedProperties[propertyName] ??= {};
4009
- normalizedProperties[propertyName][phaseName] = track;
4010
- }
4011
- }
4012
- return normalizedProperties;
4013
- }
4014
- var validateAudioTransition = (effect, path5, nodeTypes) => {
3946
+ var validateAudioTransition = (effect, path5) => {
4015
3947
  assertNonEmptyString3(effect.targetId, `${path5}.targetId`);
4016
- const targetType = nodeTypes.get(effect.targetId);
4017
- if (!targetType) {
4018
- throw new Error(
4019
- `Input error: ${path5}.targetId "${effect.targetId}" does not resolve to an audio node.`
4020
- );
4021
- }
4022
3948
  assertNonEmptyRecord(effect.properties, `${path5}.properties`);
4023
3949
  for (const [propertyName, propertyTransitions] of Object.entries(
4024
3950
  effect.properties
@@ -4028,11 +3954,6 @@ var validateAudioTransition = (effect, path5, nodeTypes) => {
4028
3954
  `Input error: unsupported audio transition property "${propertyName}" at ${path5}.properties.`
4029
3955
  );
4030
3956
  }
4031
- if (!AUDIO_TRANSITION_PROPERTIES_BY_NODE_TYPE[targetType].has(propertyName)) {
4032
- throw new Error(
4033
- `Input error: audio transition property "${propertyName}" is not supported for target type "${targetType}" at ${path5}.properties.`
4034
- );
4035
- }
4036
3957
  assertNonEmptyRecord(
4037
3958
  propertyTransitions,
4038
3959
  `${path5}.properties.${propertyName}`
@@ -4051,7 +3972,7 @@ var validateAudioTransition = (effect, path5, nodeTypes) => {
4051
3972
  }
4052
3973
  }
4053
3974
  };
4054
- var validateAudioEffects = (audioEffects, ids, nodeTypes) => {
3975
+ var validateAudioEffects = (audioEffects, ids) => {
4055
3976
  if (!Array.isArray(audioEffects)) {
4056
3977
  throw new Error("Input error: `audioEffects` must be an array.");
4057
3978
  }
@@ -4062,13 +3983,20 @@ var validateAudioEffects = (audioEffects, ids, nodeTypes) => {
4062
3983
  assertRecord(effect, path5);
4063
3984
  assertNonEmptyString3(effect.id, `${path5}.id`);
4064
3985
  assertUniqueId(ids, effect.id, `${path5}.id`);
3986
+ for (const key of Object.keys(effect)) {
3987
+ if (!AUDIO_EFFECT_KEYS.has(key)) {
3988
+ throw new Error(
3989
+ `Input error: unsupported audio effect field "${key}" at ${path5}.`
3990
+ );
3991
+ }
3992
+ }
4065
3993
  if (!AUDIO_EFFECT_TYPES.has(effect.type)) {
4066
3994
  throw new Error(
4067
3995
  `Input error: unsupported audio effect type "${effect.type}" at ${path5}.`
4068
3996
  );
4069
3997
  }
4070
3998
  if (effect.type === AUDIO_TRANSITION_TYPE) {
4071
- validateAudioTransition(effect, path5, nodeTypes);
3999
+ validateAudioTransition(effect, path5);
4072
4000
  if (transitionTargetIds.has(effect.targetId)) {
4073
4001
  throw new Error(
4074
4002
  `Input error: duplicate audio-transition targetId "${effect.targetId}" at ${path5}.targetId.`
@@ -4086,25 +4014,14 @@ var normalizeAudioRenderState = ({
4086
4014
  } = {}) => {
4087
4015
  const ids = /* @__PURE__ */ new Set();
4088
4016
  const flattened = validateAudioNodes(audio, ids);
4089
- const transitions = validateAudioEffects(
4090
- audioEffects,
4091
- ids,
4092
- flattened.builtinNodeTypes
4093
- );
4094
- for (const [targetId, properties] of flattened.inlineTransitions) {
4095
- if (transitions.has(targetId)) {
4096
- throw new Error(
4097
- `Input error: audio node "${targetId}" cannot define both inline transition and legacy audio-transition input.`
4098
- );
4099
- }
4100
- transitions.set(targetId, properties);
4101
- }
4017
+ const transitions = validateAudioEffects(audioEffects, ids);
4102
4018
  return {
4103
4019
  audio,
4104
4020
  audioEffects,
4105
4021
  channels: flattened.channels,
4106
4022
  sounds: flattened.sounds,
4107
- transitions
4023
+ transitions,
4024
+ effectById: new Map(audioEffects.map((effect) => [effect.id, effect]))
4108
4025
  };
4109
4026
  };
4110
4027
 
@@ -6152,6 +6069,19 @@ var compilePortableGsapAnimation = (rawAnimation, { sourcePath = "animation" } =
6152
6069
 
6153
6070
  // src/plugins/animations/timeline/compileLegacyTransition.js
6154
6071
  var toPortableFrameValue = (frame) => frame.relative ? { by: frame.value } : frame.value;
6072
+ var toPortableFrameStartValue = (frame) => frame.relative ? { by: frame.startValue } : frame.startValue;
6073
+ var toPortableFrameStep = (target, property, frame) => ({
6074
+ kind: frame.startValue === void 0 ? "to" : "fromTo",
6075
+ targets: target,
6076
+ overwrite: "none",
6077
+ ...frame.startValue === void 0 ? { values: { [property]: toPortableFrameValue(frame) } } : {
6078
+ from: { [property]: toPortableFrameStartValue(frame) },
6079
+ to: { [property]: toPortableFrameValue(frame) }
6080
+ },
6081
+ duration: frame.duration,
6082
+ ...frame.delay === void 0 ? {} : { delay: frame.delay },
6083
+ ...frame.easing === void 0 ? {} : { easing: frame.easing }
6084
+ });
6155
6085
  var addInitialTrackDelay = (config, delay = 0) => {
6156
6086
  if (delay === 0) return config;
6157
6087
  return {
@@ -6172,17 +6102,26 @@ var addLegacyTrack = (steps, { target, property, config }) => {
6172
6102
  });
6173
6103
  }
6174
6104
  if (config.keyframes.length > 0) {
6175
- children.push({
6176
- kind: "keyframes",
6177
- targets: target,
6178
- overwrite: "none",
6179
- frames: config.keyframes.map((frame) => ({
6180
- values: { [property]: toPortableFrameValue(frame) },
6181
- duration: frame.duration,
6182
- ...frame.delay === void 0 ? {} : { delay: frame.delay },
6183
- ...frame.easing === void 0 ? {} : { easing: frame.easing }
6184
- }))
6185
- });
6105
+ if (config.keyframes.some((frame) => frame.startValue !== void 0)) {
6106
+ children.push({
6107
+ kind: "sequence",
6108
+ steps: config.keyframes.map(
6109
+ (frame) => toPortableFrameStep(target, property, frame)
6110
+ )
6111
+ });
6112
+ } else {
6113
+ children.push({
6114
+ kind: "keyframes",
6115
+ targets: target,
6116
+ overwrite: "none",
6117
+ frames: config.keyframes.map((frame) => ({
6118
+ values: { [property]: toPortableFrameValue(frame) },
6119
+ duration: frame.duration,
6120
+ ...frame.delay === void 0 ? {} : { delay: frame.delay },
6121
+ ...frame.easing === void 0 ? {} : { easing: frame.easing }
6122
+ }))
6123
+ });
6124
+ }
6186
6125
  }
6187
6126
  if (children.length === 1) steps.push(children[0]);
6188
6127
  else if (children.length > 1)
@@ -6282,6 +6221,11 @@ var addRelativeValue = (property, expression) => ({
6282
6221
  right: expression
6283
6222
  } : expression
6284
6223
  });
6224
+ var resolveFrameStart = (property, frame, currentExpression) => {
6225
+ if (frame.startValue === void 0) return currentExpression;
6226
+ const authored = constant2(frame.startValue);
6227
+ return frame.relative ? addRelativeValue(property, authored) : toSubjectCoordinate(property, authored);
6228
+ };
6285
6229
  var toIterations = (playback = {}) => {
6286
6230
  if (playback.loop === true || playback.repeat === "infinite") return null;
6287
6231
  return (playback.repeat ?? 0) + 1;
@@ -6388,6 +6332,11 @@ var compileLegacyTweenAnimation = (animation, { sourcePath = "animation" } = {})
6388
6332
  frame.delay ?? 0,
6389
6333
  `${propertyPath}.keyframes[${index}].delay`
6390
6334
  );
6335
+ const startExpression = resolveFrameStart(
6336
+ property,
6337
+ frame,
6338
+ currentExpression
6339
+ );
6391
6340
  const authored = constant2(frame.value);
6392
6341
  const nextExpression = frame.relative ? addRelativeValue(property, authored) : toSubjectCoordinate(property, authored);
6393
6342
  clips.push({
@@ -6402,7 +6351,7 @@ var compileLegacyTweenAnimation = (animation, { sourcePath = "animation" } = {})
6402
6351
  duration: frame.duration,
6403
6352
  sampler: {
6404
6353
  kind: "interpolate",
6405
- from: currentExpression,
6354
+ from: startExpression,
6406
6355
  to: nextExpression,
6407
6356
  easing: getEasingId(frame.easing)
6408
6357
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "route-graphics",
3
- "version": "1.40.0",
3
+ "version": "1.42.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",