physics-animator 0.2.1 → 0.9.1

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.
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TweenAnimator = void 0;
4
+ exports.linearStep = linearStep;
5
+ exports.easeInOutStep = easeInOutStep;
6
+ exports.easeInStep = easeInStep;
7
+ exports.easeOutStep = easeOutStep;
8
+ const IFieldAnimator_js_1 = require("../IFieldAnimator.js");
9
+ const defaultParams = {
10
+ duration_s: 0.5, // default duration of the tween in seconds
11
+ easingFn: linearStep, // default easing function is linear
12
+ };
13
+ exports.TweenAnimator = {
14
+ createState(obj, field, target, params) {
15
+ return {
16
+ x0: obj[field], // initial value of the field
17
+ t0_ms: performance.now(), // time when the tween started in milliseconds
18
+ target: target,
19
+ velocity: 0,
20
+ ...(params ?? defaultParams),
21
+ };
22
+ },
23
+ updateState(state, object, field, target, params) {
24
+ state.target = target;
25
+ state.x0 = object[field]; // update the initial value of the field
26
+ state.t0_ms = performance.now(); // reset the start time of the tween
27
+ state.duration_s = params?.duration_s ?? defaultParams.duration_s; // update the duration of the tween
28
+ state.easingFn = params?.easingFn ?? defaultParams.easingFn; //
29
+ },
30
+ step(state, object, field, params, dt_s) {
31
+ // step the tween
32
+ let x = object[field];
33
+ params.easingFn(object, field, state.target, state, dt_s);
34
+ let x_new = object[field];
35
+ state.velocity = (x_new - x) / dt_s;
36
+ // remove the tween if it's complete
37
+ let deltaTime_s = (performance.now() - state.t0_ms) / 1000;
38
+ if (deltaTime_s >= state.duration_s) {
39
+ object[field] = state.target;
40
+ return IFieldAnimator_js_1.StepResult.Complete;
41
+ }
42
+ else {
43
+ return IFieldAnimator_js_1.StepResult.Continue;
44
+ }
45
+ }
46
+ };
47
+ function linearStep(object, field, target, params, dt_s) {
48
+ let dx = target - params.x0;
49
+ let t = (performance.now() - params.t0_ms) / 1000;
50
+ let u = t / params.duration_s;
51
+ let x_new = params.x0 + dx * u;
52
+ object[field] = x_new;
53
+ }
54
+ // cubic ease in out
55
+ function easeInOutStep(object, field, target, params, dt_s) {
56
+ let dx = target - params.x0;
57
+ let t = (performance.now() - params.t0_ms) / 1000;
58
+ let u = t / params.duration_s;
59
+ let x_new = params.x0 + dx * u * u * (3 - 2 * u);
60
+ object[field] = x_new;
61
+ }
62
+ function easeInStep(object, field, target, params, dt_s) {
63
+ let dx = target - params.x0;
64
+ let t = (performance.now() - params.t0_ms) / 1000;
65
+ let u = t / params.duration_s;
66
+ let x_new = params.x0 + dx * u * u * u;
67
+ object[field] = x_new;
68
+ }
69
+ function easeOutStep(object, field, target, params, dt_s) {
70
+ let dx = target - params.x0;
71
+ let t = (performance.now() - params.t0_ms) / 1000;
72
+ let u = t / params.duration_s;
73
+ let x_new = params.x0 + dx * (1 - Math.pow(1 - u, 3));
74
+ object[field] = x_new;
75
+ }
package/dist/cjs/index.js CHANGED
@@ -16,4 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./AnimationSequencer.js"), exports);
18
18
  __exportStar(require("./Animator.js"), exports);
19
- __exportStar(require("./Spring.js"), exports);
19
+ __exportStar(require("./IFieldAnimator.js"), exports);
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useSpringValue = useSpringValue;
4
- const react_1 = require("react");
5
- const useAnimator_js_1 = require("./useAnimator.js");
6
4
  const use_initializer_1 = require("use-initializer");
5
+ const useAnimator_js_1 = require("./useAnimator.js");
6
+ const react_1 = require("react");
7
7
  /**
8
8
  * A value that animates to a target value using a spring animation.
9
9
  * This will **not** cause a re-render when the value changes.
@@ -13,47 +13,17 @@ const use_initializer_1 = require("use-initializer");
13
13
  function useSpringValue(options, onChange) {
14
14
  const animator = (0, useAnimator_js_1.useAnimator)(options.animator);
15
15
  const springValue = (0, use_initializer_1.useInitializer)(() => {
16
- let value = structuredClone(options.initial);
17
16
  return {
18
- get value() {
19
- return value;
20
- },
21
- set value(newValue) {
22
- value = newValue;
23
- onChange(value);
24
- },
17
+ value: structuredClone(options.initial),
25
18
  };
26
19
  });
27
- const afterStepListener = (0, react_1.useRef)(null);
28
- switch (typeof options.initial) {
29
- case 'number':
30
- {
31
- animator.springTo(springValue, 'value', options.target, options);
32
- }
33
- break;
34
- default:
35
- {
36
- if (Array.isArray(options.initial)) {
37
- for (let i = 0; i < options.initial.length; i++) {
38
- animator.springTo(springValue.value, i, options.target[i], options);
39
- }
40
- }
41
- else {
42
- // assume object, iterate over keys
43
- for (const key in options.initial) {
44
- animator.springTo(springValue.value, key, options.target[key], options);
45
- }
46
- }
47
- if (!afterStepListener.current) {
48
- afterStepListener.current = animator.onAfterStep.addListener(() => {
49
- onChange(springValue.value);
50
- });
51
- animator.onAllComplete(springValue.value, () => {
52
- afterStepListener.current?.remove();
53
- afterStepListener.current = null;
54
- }, 'once');
55
- }
56
- }
57
- break;
58
- }
20
+ (0, react_1.useEffect)(() => {
21
+ let remove = animator.onChange(springValue, () => {
22
+ onChange(springValue.value);
23
+ }).remove;
24
+ return () => {
25
+ remove();
26
+ };
27
+ }, [springValue, onChange]);
28
+ animator.springTo(springValue, { value: options.target }, options);
59
29
  }
@@ -1,81 +1,80 @@
1
1
  import { EventSignal } from "@haxiomic/event-signal";
2
- import { Spring } from "./Spring.js";
3
- var AnimationType;
4
- (function (AnimationType) {
5
- AnimationType[AnimationType["Spring"] = 0] = "Spring";
6
- AnimationType[AnimationType["Tween"] = 1] = "Tween";
7
- })(AnimationType || (AnimationType = {}));
2
+ import { StepResult } from "./IFieldAnimator.js";
3
+ import { SpringAnimator } from "./animators/SpringAnimator.js";
4
+ import { easeInOutStep, easeInStep, easeOutStep, linearStep, TweenAnimator } from "./animators/TweenAnimator.js";
8
5
  /**
9
6
  * Physically based animation of numeric properties of objects
10
7
  *
11
8
  * Designed to avoid discontinuities for smooth animation in all conditions
12
9
  */
13
10
  export class Animator {
14
- onBeforeStep = new EventSignal();
15
- onAfterStep = new EventSignal();
16
- _onAnimationComplete = new EventSignal();
17
- _onObjectAnimationsComplete = new EventSignal();
18
11
  animations = new Map();
12
+ events = {
13
+ beforeStep: new EventSignal(),
14
+ afterStep: new EventSignal(),
15
+ completeField: new EventSignal(),
16
+ completeObject: new EventSignal(),
17
+ };
18
+ changeObjectEvents = new Map();
19
+ changeFieldEvents = new Map();
20
+ // we use these signals to coalesce object change events
21
+ beforeChange = new EventSignal();
22
+ afterChange = new EventSignal();
19
23
  constructor(onBeforeStep, onAfterStep) {
20
24
  if (onBeforeStep) {
21
- this.onBeforeStep.addListener(e => onBeforeStep(e.dt_s));
25
+ this.events.beforeStep.addListener(e => onBeforeStep(e.dt_s));
22
26
  }
23
27
  if (onAfterStep) {
24
- this.onAfterStep.addListener(e => onAfterStep(e.dt_s));
28
+ this.events.afterStep.addListener(e => onAfterStep(e.dt_s));
25
29
  }
26
30
  }
27
- springTo(object, field, target, params = { duration_s: 0.5 }) {
28
- if (params != null) {
29
- let spring = this.getAnimationOrCreate(object, field, AnimationType.Spring);
30
- // update the target and parameters
31
- spring.type = AnimationType.Spring;
32
- spring.target = target;
33
- spring.springParams = Spring.getPhysicsParameters(params);
34
- spring.step = null;
35
- }
36
- else {
37
- this.setTo(object, field, target);
38
- }
31
+ setTo(object, target) {
32
+ this.beforeChange.dispatch();
33
+ forObjectFieldsRecursive(object, target, (obj, field, targetValue) => {
34
+ this.setFieldTo(obj, field, targetValue);
35
+ this.dispatchChangeObjectEvent(obj);
36
+ });
37
+ this.afterChange.dispatch();
39
38
  }
40
- customTweenTo(object, field, target, duration_s, step) {
41
- let animation = this.getAnimationOrCreate(object, field, AnimationType.Tween);
42
- animation.type = AnimationType.Tween;
43
- animation.target = target;
44
- animation.tweenParams = {
45
- x0: object[field],
46
- t0_ms: performance.now(),
47
- duration_s: duration_s,
48
- };
49
- animation.step = step;
39
+ animateTo(object, target, animator = SpringAnimator, params = null) {
40
+ forObjectFieldsRecursive(object, target, (subObj, field, targetValue) => {
41
+ this.syncAnimation(subObj, field, targetValue, animator, params);
42
+ });
50
43
  }
51
- linearTo(object, field, target, duration_s) {
52
- this.customTweenTo(object, field, target, duration_s, Tween.linearStep);
44
+ springTo(object, target, params) {
45
+ this.animateTo(object, target, SpringAnimator, params);
53
46
  }
54
- easeInOutTo(object, field, target, duration_s) {
55
- this.customTweenTo(object, field, target, duration_s, Tween.easeInOutStep);
47
+ customTweenTo(object, target, duration_s, easingFn) {
48
+ this.animateTo(object, target, TweenAnimator, {
49
+ duration_s,
50
+ easingFn,
51
+ });
56
52
  }
57
- easeInTo(object, field, target, duration_s) {
58
- this.customTweenTo(object, field, target, duration_s, Tween.easeInStep);
53
+ linearTo(object, target, duration_s) {
54
+ this.customTweenTo(object, target, duration_s, linearStep);
59
55
  }
60
- easeOutTo(object, field, target, duration_s) {
61
- this.customTweenTo(object, field, target, duration_s, Tween.easeOutStep);
56
+ easeInOutTo(object, target, duration_s) {
57
+ this.customTweenTo(object, target, duration_s, easeInOutStep);
62
58
  }
63
- /**
64
- * Remove animation from the object and set the field to the target value
65
- */
66
- setTo(object, field, target) {
67
- this.remove(object, field);
68
- object[field] = target;
59
+ easeInTo(object, target, duration_s) {
60
+ this.customTweenTo(object, target, duration_s, easeInStep);
61
+ }
62
+ easeOutTo(object, target, duration_s) {
63
+ this.customTweenTo(object, target, duration_s, easeOutStep);
69
64
  }
70
- onComplete(object, field, callback) {
71
- return this._onAnimationComplete.addListener(e => {
65
+ onCompleteField(object, field, callback, once) {
66
+ let listener = this.events.completeField.addListener(e => {
72
67
  if (e.object === object && e.field === field) {
73
68
  callback(object, field);
69
+ if (once) {
70
+ listener.remove();
71
+ }
74
72
  }
75
73
  });
74
+ return listener;
76
75
  }
77
- onAllComplete(object, callback, once) {
78
- let listener = this._onObjectAnimationsComplete.addListener(e => {
76
+ onComplete(object, callback, once) {
77
+ const listener = this.events.completeObject.addListener(e => {
79
78
  if (e.object === object) {
80
79
  callback(object);
81
80
  if (once) {
@@ -85,65 +84,92 @@ export class Animator {
85
84
  });
86
85
  return listener;
87
86
  }
88
- _springState = { x: 0, targetX: 0, v: 0 };
89
- step(dt_s) {
90
- if (this.onBeforeStep.hasListeners()) {
91
- this.onBeforeStep.dispatch({ dt_s });
87
+ onChangeField(object, field, callback) {
88
+ // check if field is an object
89
+ if (typeof object[field] === 'object' && object[field] !== null) {
90
+ return this.onChange(object[field], (subObject) => {
91
+ callback(object, field);
92
+ });
92
93
  }
93
- let springState = this._springState;
94
+ else {
95
+ // add a listener for this field
96
+ return this.addChangeFieldListener(object, field, callback);
97
+ }
98
+ }
99
+ onChange(object, callback) {
100
+ // add a listener for this object and every sub-object
101
+ const removeCallbacks = new Array();
102
+ // coalesce events within a single step
103
+ let objectChanged = false;
104
+ removeCallbacks.push(this.beforeChange.addListener(() => {
105
+ objectChanged = false;
106
+ }).remove, this.afterChange.addListener(() => {
107
+ if (objectChanged) {
108
+ callback(object);
109
+ }
110
+ }).remove);
111
+ const subObjectChangedCallback = (subObject) => {
112
+ objectChanged = true;
113
+ };
114
+ enumerateObjects(object, (subObject) => {
115
+ let signal = this.changeObjectEvents.get(object);
116
+ if (signal == null) {
117
+ signal = new EventSignal();
118
+ this.changeObjectEvents.set(subObject, signal);
119
+ }
120
+ const subListener = signal.addListener(subObjectChangedCallback);
121
+ removeCallbacks.push(() => {
122
+ subListener.remove();
123
+ if (!signal.hasListeners()) {
124
+ this.changeObjectEvents.delete(object);
125
+ }
126
+ });
127
+ });
128
+ return {
129
+ remove: () => {
130
+ for (const remove of removeCallbacks) {
131
+ remove();
132
+ }
133
+ }
134
+ };
135
+ }
136
+ onBeforeStep(callback) {
137
+ return this.events.beforeStep.addListener(e => callback(e.dt_s));
138
+ }
139
+ onAfterStep(callback) {
140
+ return this.events.afterStep.addListener(e => callback(e.dt_s));
141
+ }
142
+ step(dt_s) {
143
+ this.events.beforeStep.dispatch({ dt_s });
144
+ this.beforeChange.dispatch();
94
145
  // step all animations
95
- this.animations.forEach((objectAnims, object) => {
96
- objectAnims.forEach((animation, field) => {
97
- switch (animation.type) {
98
- case AnimationType.Spring:
146
+ for (let [object, objectAnims] of this.animations.entries()) {
147
+ for (let [field, animation] of objectAnims.entries()) {
148
+ let result = animation.animator.step(animation.state, object, field, animation.params, dt_s);
149
+ // dispatch the field change event
150
+ this.dispatchChangeFieldEvent(object, field);
151
+ // handle animation completion
152
+ switch (result) {
153
+ case StepResult.Complete:
99
154
  {
100
- // step the spring
101
- springState.x = object[field];
102
- springState.targetX = animation.target;
103
- springState.v = animation.velocity;
104
- if (animation.springParams != null) {
105
- Spring.stepSpring(dt_s, springState, animation.springParams);
106
- }
107
- else {
108
- // instant transition: set to the target
109
- springState.x = springState.targetX;
110
- springState.v = 0;
111
- }
112
- // update the object
113
- object[field] = springState.x;
114
- animation.velocity = springState.v;
115
- // remove the spring if it's close enough to the target and velocity is close to 0
116
- if (Math.abs(springState.x - springState.targetX) < 0.0001 && Math.abs(springState.v) < 0.0001) {
117
- object[field] = animation.target;
118
- objectAnims.delete(field);
119
- this._onAnimationComplete.dispatch({ object, field });
120
- }
121
- }
122
- break;
123
- case AnimationType.Tween: {
124
- // step the tween
125
- let x = object[field];
126
- animation.step(object, field, animation.target, animation.tweenParams, dt_s);
127
- let x_new = object[field];
128
- animation.velocity = (x_new - x) / dt_s;
129
- // remove the tween if it's complete
130
- let deltaTime_s = (performance.now() - animation.tweenParams.t0_ms) / 1000;
131
- if (deltaTime_s >= animation.tweenParams.duration_s) {
132
- object[field] = animation.target;
133
155
  objectAnims.delete(field);
134
- this._onAnimationComplete.dispatch({ object, field });
156
+ this.events.completeField.dispatch({ object, field });
135
157
  }
136
158
  break;
137
- }
138
159
  }
139
- });
160
+ }
161
+ ;
162
+ // dispatch the object change event
163
+ this.dispatchChangeObjectEvent(object);
140
164
  // remove the object if it has no more springs
141
165
  if (objectAnims.size == 0) {
142
166
  this.animations.delete(object);
143
- this._onObjectAnimationsComplete.dispatch({ object });
167
+ this.events.completeObject.dispatch({ object });
144
168
  }
145
- });
146
- this.onAfterStep.dispatch({ dt_s });
169
+ }
170
+ ;
171
+ this.afterChange.dispatch();
172
+ this.events.afterStep.dispatch({ dt_s });
147
173
  }
148
174
  t_last = -1;
149
175
  tick() {
@@ -208,31 +234,106 @@ export class Animator {
208
234
  * Remove animation for this object and field if it exists
209
235
  * Does not change the value of the field
210
236
  */
211
- remove(object, field) {
212
- let objectSprings = this.animations.get(object);
213
- if (objectSprings != null) {
214
- objectSprings.delete(field);
237
+ remove(object, field, dispatchComplete = false) {
238
+ let objectAnimations = this.animations.get(object);
239
+ if (objectAnimations != null) {
240
+ objectAnimations.delete(field);
241
+ if (dispatchComplete) {
242
+ this.events.completeField.dispatch({ object, field });
243
+ }
215
244
  }
216
245
  // if there are no more springs for this object, remove it from the map
217
- if (objectSprings != null && objectSprings.size == 0) {
218
- this.animations.delete(object);
246
+ if (objectAnimations != null && objectAnimations.size == 0) {
247
+ this.removeObject(object, dispatchComplete);
219
248
  }
220
249
  }
221
250
  /**
222
251
  * Remove all animations for this object
223
252
  */
224
- removeObject(object) {
253
+ removeObject(object, dispatchComplete = false) {
225
254
  this.animations.delete(object);
255
+ if (dispatchComplete) {
256
+ this.events.completeObject.dispatch({ object });
257
+ }
226
258
  }
227
259
  /**
228
260
  * Remove all animations
229
261
  */
230
- removeAll() {
262
+ removeAll(dispatchComplete = false) {
263
+ for (let [object, objectAnimations] of this.animations.entries()) {
264
+ for (let field of objectAnimations.keys()) {
265
+ this.remove(object, field, dispatchComplete);
266
+ }
267
+ }
231
268
  this.animations.clear();
232
269
  }
233
- getVelocity(object, field) {
234
- let spring = this.getObjectAnimations(object).get(field);
235
- return spring?.velocity ?? 0;
270
+ getState(object, field) {
271
+ let animation = this.getObjectAnimations(object).get(field);
272
+ return animation?.state;
273
+ }
274
+ dispatchChangeObjectEvent(object) {
275
+ let signal = this.changeObjectEvents.get(object);
276
+ if (signal == null) {
277
+ return;
278
+ }
279
+ signal.dispatch(object);
280
+ }
281
+ dispatchChangeFieldEvent(object, field) {
282
+ const map = this.changeFieldEvents.get(object);
283
+ if (map == null) {
284
+ return;
285
+ }
286
+ let signal = map.get(field);
287
+ if (signal == null) {
288
+ return;
289
+ }
290
+ if (signal.hasListeners()) {
291
+ signal.dispatch({ object, field });
292
+ }
293
+ }
294
+ addChangeFieldListener(object, field, callback) {
295
+ const getOrCreateChangeFieldSignal = (object, field) => {
296
+ let map = this.changeFieldEvents.get(object);
297
+ if (map == null) {
298
+ map = new Map();
299
+ this.changeFieldEvents.set(object, map);
300
+ }
301
+ let signal = map.get(field);
302
+ if (signal == null) {
303
+ signal = new EventSignal();
304
+ map.set(field, signal);
305
+ }
306
+ return signal;
307
+ };
308
+ const signal = getOrCreateChangeFieldSignal(object, field);
309
+ const listener = signal.addListener((e) => {
310
+ callback(e.object, e.field);
311
+ });
312
+ return {
313
+ remove: () => {
314
+ listener.remove();
315
+ // cleanup
316
+ if (!signal.hasListeners()) {
317
+ let map = this.changeFieldEvents.get(object);
318
+ map?.delete(field);
319
+ if (map != null && map.size === 0) {
320
+ this.changeFieldEvents.delete(object);
321
+ }
322
+ }
323
+ }
324
+ };
325
+ }
326
+ /**
327
+ * Remove animation from the object and set the field to the target value
328
+ *
329
+ * This completes the animation immediately and dispatches the onComplete event
330
+ */
331
+ setFieldTo(object, field, targetValue) {
332
+ const dispatchComplete = true;
333
+ this.remove(object, field, dispatchComplete);
334
+ object[field] = targetValue;
335
+ // dispatch the field change event
336
+ this.dispatchChangeFieldEvent(object, field);
236
337
  }
237
338
  /**
238
339
  * Creates a new map if one doesn't already exist for the given object
@@ -249,58 +350,55 @@ export class Animator {
249
350
  /**
250
351
  * Creates a new spring if one doesn't already exist for the given object and field
251
352
  */
252
- getAnimationOrCreate(object, field, type) {
353
+ syncAnimation(object, field, targetValue, fieldAnimator, params = null) {
253
354
  let objectAnimations = this.getObjectAnimations(object);
254
355
  let animation = objectAnimations.get(field);
255
- if (animation == null) {
356
+ let animatorChanged = animation?.animator !== fieldAnimator;
357
+ if (animation == null || animatorChanged) {
256
358
  // create
257
359
  animation = {
258
- target: 0,
259
- type: type,
260
- springParams: null,
261
- tweenParams: null,
262
- velocity: 0,
263
- step: null
360
+ animator: fieldAnimator,
361
+ state: fieldAnimator.createState(object, field, targetValue, params),
362
+ params,
264
363
  };
265
364
  objectAnimations.set(field, animation);
266
365
  }
267
- animation.type = type;
366
+ else {
367
+ animation.params = params;
368
+ animation.animator.updateState(animation.state, object, field, targetValue, params);
369
+ }
268
370
  return animation;
269
371
  }
270
372
  }
271
- export var Tween;
272
- (function (Tween) {
273
- function linearStep(object, field, target, params, dt_s) {
274
- let dx = target - params.x0;
275
- let t = (performance.now() - params.t0_ms) / 1000;
276
- let u = t / params.duration_s;
277
- let x_new = params.x0 + dx * u;
278
- object[field] = x_new;
279
- }
280
- Tween.linearStep = linearStep;
281
- // cubic ease in out
282
- function easeInOutStep(object, field, target, params, dt_s) {
283
- let dx = target - params.x0;
284
- let t = (performance.now() - params.t0_ms) / 1000;
285
- let u = t / params.duration_s;
286
- let x_new = params.x0 + dx * u * u * (3 - 2 * u);
287
- object[field] = x_new;
288
- }
289
- Tween.easeInOutStep = easeInOutStep;
290
- function easeInStep(object, field, target, params, dt_s) {
291
- let dx = target - params.x0;
292
- let t = (performance.now() - params.t0_ms) / 1000;
293
- let u = t / params.duration_s;
294
- let x_new = params.x0 + dx * u * u * u;
295
- object[field] = x_new;
296
- }
297
- Tween.easeInStep = easeInStep;
298
- function easeOutStep(object, field, target, params, dt_s) {
299
- let dx = target - params.x0;
300
- let t = (performance.now() - params.t0_ms) / 1000;
301
- let u = t / params.duration_s;
302
- let x_new = params.x0 + dx * (1 - Math.pow(1 - u, 3));
303
- object[field] = x_new;
304
- }
305
- Tween.easeOutStep = easeOutStep;
306
- })(Tween || (Tween = {}));
373
+ function forObjectFieldsRecursive(sourceObj, targetObj, callback) {
374
+ for (let field in targetObj) {
375
+ if (Object.prototype.hasOwnProperty.call(targetObj, field)) {
376
+ let targetValue = targetObj[field];
377
+ if (typeof targetValue === 'object') {
378
+ forObjectFieldsRecursive(sourceObj[field], targetValue, callback);
379
+ }
380
+ else {
381
+ callback(sourceObj, field, targetValue);
382
+ }
383
+ }
384
+ }
385
+ }
386
+ function enumerateObjects(input, callback) {
387
+ // Call callback for the current object if it's an object or array
388
+ if (typeof input === 'object' && input !== null) {
389
+ callback(input);
390
+ // Recursively enumerate nested objects
391
+ if (Array.isArray(input)) {
392
+ for (const item of input) {
393
+ enumerateObjects(item, callback);
394
+ }
395
+ }
396
+ else {
397
+ for (const key in input) {
398
+ if (input.hasOwnProperty(key)) {
399
+ enumerateObjects(input[key], callback);
400
+ }
401
+ }
402
+ }
403
+ }
404
+ }
@@ -0,0 +1,5 @@
1
+ export var StepResult;
2
+ (function (StepResult) {
3
+ StepResult[StepResult["Continue"] = 0] = "Continue";
4
+ StepResult[StepResult["Complete"] = 1] = "Complete";
5
+ })(StepResult || (StepResult = {}));