@davidcal/frosth 1.4.0 → 1.6.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Frosth - Yet another UI framework
2
2
 
3
- **Latest version**: v1.4.0
3
+ **Latest version**: v1.6.0
4
4
 
5
5
  ## Motivation
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@davidcal/frosth",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Async-first CRUD-last UI framework that treats encapsulation as a solved problem.",
5
5
  "type": "module",
6
6
  "main": "./src/sigew.js",
@@ -0,0 +1,37 @@
1
+ export const create_producer = () => {
2
+ const result = {};
3
+
4
+ const subscriptions = new Set();
5
+
6
+ const create_stream = () => {
7
+ const result = {};
8
+
9
+ result.subscribe = (handler) => {
10
+ subscriptions.add(handler);
11
+
12
+ const unsubscribe = () => {
13
+ subscriptions.delete(handler);
14
+ };
15
+
16
+ return { unsubscribe };
17
+ };
18
+
19
+ return result;
20
+ };
21
+
22
+ result.emit = (calldata) => {
23
+ return result.emit_many([calldata]);
24
+ };
25
+
26
+ result.emit_many = (calldatas) => {
27
+ for (const calldata of calldatas) {
28
+ for (const handler of subscriptions) {
29
+ handler(calldata);
30
+ }
31
+ }
32
+ };
33
+
34
+ result.stream = create_stream();
35
+
36
+ return result;
37
+ };
@@ -106,7 +106,7 @@ class Self {
106
106
  this._parent._children.delete(this);
107
107
  }
108
108
 
109
- for (const handle_dispose of this._dispose_handlers) {
109
+ for (const handle_dispose of this._dispose_handlers.toReversed()) {
110
110
  handle_dispose();
111
111
  }
112
112
  }
@@ -33,5 +33,18 @@ export const create_stream = () => {
33
33
  beacon.fire();
34
34
  };
35
35
 
36
+ result.emit_many = (bodies) => {
37
+ for (const body of bodies) {
38
+ const activity = {
39
+ seq: activity_seq++,
40
+ body,
41
+ };
42
+
43
+ outstanding_activities.push(activity);
44
+ }
45
+
46
+ beacon.fire();
47
+ };
48
+
36
49
  return result;
37
50
  };
@@ -0,0 +1,34 @@
1
+ export const create_wrapper_stream = (stream, handle) => {
2
+ const result = {};
3
+
4
+ const subscriptions = new Set();
5
+
6
+ let upstream;
7
+
8
+ result.subscribe = (handler) => {
9
+ subscriptions.add(handler);
10
+
11
+ if (upstream === undefined) {
12
+ upstream = stream.subscribe((calldata) => {
13
+ handle(calldata, (new_calldata) => {
14
+ for (const handler of subscriptions) {
15
+ handler(new_calldata);
16
+ }
17
+ });
18
+ });
19
+ }
20
+
21
+ const unsubscribe = () => {
22
+ if (subscriptions.size === 1) {
23
+ upstream.unsubscribe();
24
+ upstream = undefined;
25
+ }
26
+
27
+ subscriptions.delete(handler);
28
+ };
29
+
30
+ return { unsubscribe };
31
+ };
32
+
33
+ return result;
34
+ };
@@ -0,0 +1,9 @@
1
+ import { create_wrapper_stream } from "./create_wrapper_stream.js";
2
+
3
+ export const stream_filter = (stream, predicate) =>
4
+ create_wrapper_stream(stream, (calldata, emit) => {
5
+ if (predicate(calldata)) {
6
+ emit(calldata);
7
+ }
8
+ })
9
+ ;
@@ -0,0 +1,41 @@
1
+ import { create_signal } from "./create_signal.js";
2
+
3
+ export const stream_latest = (stream, initial) => {
4
+ const signal = create_signal(() => initial);
5
+
6
+ let upstream = undefined;
7
+ const registered = new Set();
8
+
9
+ const consider_acquiring = () => {
10
+ if (upstream !== undefined) {
11
+ return;
12
+ }
13
+
14
+ upstream = stream.subscribe((calldata) => {
15
+ signal.set(() => calldata);
16
+ });
17
+ };
18
+
19
+ const consider_releasing = () => {
20
+ if (registered.size !== 0) {
21
+ return;
22
+ }
23
+
24
+ upstream.unsubscribe();
25
+ upstream = undefined;
26
+ };
27
+
28
+ return (self) => {
29
+ if (self._is_effectfully_useful() && !registered.has(self)) {
30
+ registered.add(self);
31
+ consider_acquiring();
32
+
33
+ self.on_dispose(() => {
34
+ registered.delete(self);
35
+ consider_releasing();
36
+ });
37
+ }
38
+
39
+ return signal(self);
40
+ };
41
+ };
@@ -0,0 +1,7 @@
1
+ import { create_wrapper_stream } from "./create_wrapper_stream.js";
2
+
3
+ export const stream_map = (stream, mapper) =>
4
+ create_wrapper_stream(stream, (calldata, emit) => {
5
+ emit(mapper(calldata));
6
+ })
7
+ ;
@@ -0,0 +1,10 @@
1
+ import { create_wrapper_stream } from "./create_wrapper_stream.js";
2
+
3
+ export const stream_reduce = (stream, reducer, initial) => {
4
+ let acc = initial;
5
+
6
+ return create_wrapper_stream(stream, (calldata, emit) => {
7
+ acc = reducer(acc, calldata);
8
+ emit(acc);
9
+ });
10
+ };