• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bordoley / reactive-js / 13532879980

25 Feb 2025 11:17PM UTC coverage: 97.821% (-0.3%) from 98.168%
13532879980

push

github

bordoley
improve spring api to allow for more control. misc other fixes

881 of 947 branches covered (93.03%)

Branch coverage included in aggregate %.

6 of 16 new or added lines in 2 files covered. (37.5%)

2 existing lines in 1 file now uncovered.

5179 of 5248 relevant lines covered (98.69%)

6618.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

29.63
/src/concurrent/Streamable/__private__/Streamable.spring.ts
1
import {
3✔
2
  include,
3
  init,
4
  mixInstanceFactory,
5
  props,
6
} from "../../../__internal__/mixins.js";
7
import * as Iterable from "../../../computations/Iterable.js";
3✔
8
import {
3✔
9
  AnimationStreamLike,
10
  AnimationStreamLike_animation,
11
  DeferredObservableLike,
12
  DeferredObservableWithSideEffectsLike,
13
  PauseableLike_resume,
14
  PureRunnableLike,
15
  SchedulerLike,
16
  StreamableLike,
17
  StreamableLike_stream,
18
} from "../../../concurrent.js";
19
import * as Publisher from "../../../events/Publisher.js";
3✔
20
import { EventListenerLike_notify, EventSourceLike } from "../../../events.js";
3✔
21
import {
3✔
22
  Function1,
23
  Tuple2,
24
  compose,
25
  isNumber,
26
  isReadonlyArray,
27
  none,
28
  pipe,
29
  returns,
30
  scale,
31
  tuple,
32
} from "../../../functions.js";
33
import * as Disposable from "../../../utils/Disposable.js";
3✔
34
import { BackpressureStrategy } from "../../../utils.js";
35
import * as Observable from "../../Observable.js";
3✔
36
import * as PauseableScheduler from "../../PauseableScheduler.js";
3✔
37
import type * as Streamable from "../../Streamable.js";
38
import * as Subject from "../../Subject.js";
3✔
39
import DelegatingPauseableMixin from "../../__mixins__/DelegatingPauseableMixin.js";
3✔
40
import StreamMixin from "../../__mixins__/StreamMixin.js";
3✔
41

42
const SpringStream_create: (
43
  initialValue: number,
44
  scheduler: SchedulerLike,
45
  animationScheduler: SchedulerLike,
46
  springOptions?: {
47
    readonly stiffness?: number;
48
    readonly damping?: number;
49
    readonly precision?: number;
50
  },
51
  options?: {
52
    readonly backpressureStrategy?: BackpressureStrategy;
53
    readonly replay?: number;
54
    readonly capacity?: number;
55
  },
56
) => AnimationStreamLike<
57
  Function1<
58
    number,
59
    | number
60
    | { from: number; to: number | ReadonlyArray<number> }
61
    | ReadonlyArray<number>
62
  >,
63
  number
64
> = /*@__PURE__*/ (() => {
3✔
65
  type TProperties = {
66
    [AnimationStreamLike_animation]: EventSourceLike<number>;
67
  };
68

69
  return mixInstanceFactory(
3✔
70
    include(StreamMixin(), DelegatingPauseableMixin),
71
    function AnimationStream(
72
      instance: TProperties,
73
      initialValue: number,
74
      scheduler: SchedulerLike,
75
      animationScheduler: SchedulerLike,
76
      springOptions?: {
77
        readonly stiffness?: number;
78
        readonly damping?: number;
79
        readonly precision?: number;
80
      },
81
      options?: {
82
        readonly backpressureStrategy?: BackpressureStrategy;
83
        readonly replay?: number;
84
        readonly capacity?: number;
85
      },
86
    ): AnimationStreamLike<
87
      Function1<number, number | ReadonlyArray<number>>,
88
      number
89
    > {
UNCOV
90
      const pauseableScheduler = PauseableScheduler.create(animationScheduler);
×
91

92
      const publisher = (instance[AnimationStreamLike_animation] =
×
93
        Publisher.create<number>());
94

95
      const accFeedbackStream = Subject.create<number>({ replay: 1 });
×
96

97
      const operator: Function1<
98
        DeferredObservableLike<
99
          Function1<
100
            number,
101
            | number
102
            | { from: number; to: number | ReadonlyArray<number> }
103
            | ReadonlyArray<number>
104
          >
105
        >,
106
        DeferredObservableWithSideEffectsLike<boolean>
107
      > = compose(
×
108
        Observable.withLatestFrom<
109
          Function1<
110
            number,
111
            | number
112
            | { from: number; to: number | ReadonlyArray<number> }
113
            | ReadonlyArray<number>
114
          >,
115
          number,
116
          Tuple2<
117
            | number
118
            | ReadonlyArray<number>
119
            | { from: number; to: number | ReadonlyArray<number> },
120
            number
121
          >
UNCOV
122
        >(accFeedbackStream, (updater, acc) => tuple(updater(acc), acc)),
×
123
        Observable.switchMap<
124
          Tuple2<
125
            | number
126
            | ReadonlyArray<number>
127
            | { from: number; to: number | ReadonlyArray<number> },
128
            number
129
          >,
130
          boolean
131
        >(
132
          ([updated, acc]) => {
133
            const initialValue =
NEW
134
              isNumber(updated) || isReadonlyArray(updated)
×
135
                ? acc
136
                : updated.from;
137

NEW
138
            const destinations = isNumber(updated)
×
139
              ? [updated]
140
              : isReadonlyArray(updated)
×
141
                ? updated
142
                : isNumber(updated.to)
×
143
                  ? [updated.to]
144
                  : updated.to;
145

NEW
146
            const sources = pipe(
×
147
              destinations,
148
              Iterable.scan<number, Tuple2<number, number>>(
NEW
149
                ([, prev], v) => tuple(prev, v),
×
150
                returns(tuple(initialValue, initialValue)),
151
              ),
152
              Iterable.reduce(
153
                (animations: Array<PureRunnableLike<number>>, [prev, next]) => {
NEW
154
                  if (prev !== next) {
×
NEW
155
                    animations.push(
×
156
                      pipe(
157
                        Observable.spring(springOptions),
158
                        Observable.map(scale(prev, next)),
159
                      ),
160
                    );
161
                  }
NEW
162
                  return animations;
×
163
                },
NEW
164
                (): Array<PureRunnableLike<number>> => [],
×
165
              ),
166
            );
167

NEW
168
            return sources.length > 0
×
169
              ? pipe(
170
                  sources,
NEW
171
                  x => Observable.concatMany<number>(x),
×
172
                  Observable.notify(publisher),
173
                  Observable.notify(accFeedbackStream),
174
                  Observable.ignoreElements(),
175
                  Observable.subscribeOn(pauseableScheduler),
176
                  Observable.startWith<boolean>(true),
177
                  Observable.endWith<boolean>(false),
178
                )
179
              : Observable.empty();
180
          },
181

182
          {
183
            innerType: Observable.DeferredObservableWithSideEffectsType,
184
          },
185
        ),
186
      );
187

188
      init(
×
189
        StreamMixin<
190
          Function1<number, number | ReadonlyArray<number>>,
191
          boolean
192
        >(),
193
        instance,
194
        operator,
195
        scheduler,
196
        options,
197
      );
198

199
      init(DelegatingPauseableMixin, instance, pauseableScheduler);
×
200

201
      pipe(
×
202
        instance,
203
        Disposable.add(publisher),
204
        Disposable.add(accFeedbackStream),
205
        Disposable.add(pauseableScheduler),
206
      );
207

208
      instance[PauseableLike_resume]();
×
209

210
      accFeedbackStream[EventListenerLike_notify](initialValue);
×
211

212
      return instance;
×
213
    },
214
    props<TProperties>({
215
      [AnimationStreamLike_animation]: none,
216
    }),
217
  );
218
})();
219

220
const Streamable_spring: Streamable.Signature["spring"] = (
3✔
221
  initialValue: number,
222
  creationOptions?: {
223
    readonly animationScheduler?: SchedulerLike;
224
    readonly stiffness?: number;
225
    readonly damping?: number;
226
    readonly precision?: number;
227
  },
228
): StreamableLike<
229
  Function1<
230
    number,
231
    | number
232
    | { from: number; to: number | ReadonlyArray<number> }
233
    | ReadonlyArray<number>
234
  >,
235
  boolean,
236
  AnimationStreamLike<Function1<number, number | ReadonlyArray<number>>, number>
237
> => ({
×
238
  [StreamableLike_stream]: (scheduler, options) =>
239
    SpringStream_create(
×
240
      initialValue,
241
      scheduler,
242
      creationOptions?.animationScheduler ?? scheduler,
×
243
      creationOptions,
244
      options,
245
    ),
246
});
247

248
export default Streamable_spring;
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc