Skip to content

Commit d75f64e

Browse files
chore: set up basic package config and readme
1 parent 31a326e commit d75f64e

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

packages/signal-polyfill/package.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "signal-polyfill",
3+
"version": "0.1.0",
4+
"description": "A polyfill for the TC39 Signals proposal.",
5+
"main": "dist/index.js",
6+
"type": "module",
7+
"types": "dist/index.d.ts",
8+
"scripts": {
9+
"build": "tsc -b tsconfig.json",
10+
"watch": "tsc -b tsconfig.json -watch"
11+
},
12+
"author": "EisenbergEffect",
13+
"license": "MIT"
14+
}

packages/signal-polyfill/readme.md

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Signal Polyfill
2+
3+
A "signal" is a proposed first-class JavaScript data type that enables one-way data flow through cells of state or computations derived from other data.
4+
5+
This is a polyfill for the `Signal` API that makes these capabilities available in browsers that don't yet support them natively.
6+
7+
# Examples
8+
9+
## Using signals
10+
11+
```js
12+
import { Signal } from "signal-polyfill";
13+
import { effect } from "./effect.js";
14+
15+
const counter = new Signal.State(0);
16+
const isEven = new Signal.Computed(() => (counter.get() & 1) == 0);
17+
const parity = new Signal.Computed(() => isEven.get() ? "even" : "odd");
18+
19+
effect(() => console.log(parity.get()));
20+
21+
setInterval(() => counter.set(counter.get() + 1), 1000);
22+
```
23+
24+
> [!NOTE]
25+
> The signal proposal does not include an `effect` API, since such APIs are often deeply integrated with rendering and batch strategies that are highly framework/library dependent. However, the proposal does seek to define a set of primitives that library authors can use to implement their own effects.
26+
27+
### Creating a simple effect
28+
29+
```js
30+
import { Signal } from "signal-polyfill";
31+
32+
let needsEnqueue = false;
33+
34+
const w = new Signal.subtle.Watcher(() => {
35+
if (needsEnqueue) {
36+
needsEnqueue = false;
37+
queueMicrotask.enqueue(processPending);
38+
}
39+
});
40+
41+
function processPending() {
42+
needsEnqueue = true;
43+
44+
for (const s of w.getPending()) {
45+
s.get();
46+
}
47+
48+
w.watch();
49+
}
50+
51+
export function effect(callback) {
52+
let onUnwatch;
53+
const computed = new Signal.Computed(() => onUnwatch = callback(), {
54+
[Signal.subtle.unwatched]() {
55+
typeof onUnwatch === "function" && onUnwatch();
56+
}
57+
});
58+
59+
w.watch(computed);
60+
computed.get();
61+
62+
return () => w.unwatch(computed);
63+
}
64+
```
65+
66+
> [!IMPORTANT]
67+
> The `Signal.subtle` APIs are so named in order to communicate that their correct use requires careful attention to detail. These APIs are not targeted at application-level code, but rather at framework/library authors.

0 commit comments

Comments
 (0)