Skip to content

Commit 07d331b

Browse files
feat: #232 transform template signals usage into effects and templates
1 parent a4fb350 commit 07d331b

File tree

14 files changed

+371
-71
lines changed

14 files changed

+371
-71
lines changed

docs/components/sandbox/signal-counter.jsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ export default class SignalCounter extends HTMLElement {
1818

1919
increment() {
2020
this.count.set(this.count.get() + 1);
21-
console.log('increment', this.count.get());
2221
}
2322

2423
decrement() {
2524
this.count.set(this.count.get() - 1);
26-
console.log('decrement', this.count.get());
25+
}
26+
27+
double() {
28+
this.count.set(this.count.get() * 2);
2729
}
2830

2931
render() {
@@ -33,7 +35,9 @@ export default class SignalCounter extends HTMLElement {
3335
<div>
3436
<button onclick={this.increment}>Increment (+)</button>
3537
<button onclick={this.decrement}>Decrement (-)</button>
36-
<button onclick={() => this.count.set(this.count.get() * 2)}>Double (++)</button>
38+
{/* TODO: inline version breaks with effects */}
39+
{/* <button onclick={() => this.count.set(this.count.get() * 2)}>Double (++)</button> */}
40+
<button onclick={this.double}>Double (++)</button>
3741
<span>
3842
The count is {count.get()} ({parity.get()})
3943
</span>

docs/pages/sandbox.html

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
<script type="importmap">
4747
{
4848
"imports": {
49-
"signal-polyfill": "../node_modules/signal-polyfill/dist/index.js"
49+
"signal-polyfill": "../node_modules/signal-polyfill/dist/index.js",
50+
"wc-compiler/effect": "../node_modules/wc-compiler/src/effect.js"
5051
}
5152
}
5253
</script>
@@ -55,6 +56,19 @@
5556

5657
globalThis.Signal = Signal;
5758
</script>
59+
<script type="module">
60+
// NOTE: `Signal` has to be defined first
61+
import { effect } from 'wc-compiler/effect';
62+
globalThis.effect = effect;
63+
64+
globalThis._wcc = function (strings, ...values) {
65+
let str = '';
66+
strings.forEach((string, i) => {
67+
str += string + (values[i] === 0 ? '0' : values[i] || '');
68+
});
69+
return str;
70+
};
71+
</script>
5872
<script>
5973
function randomReset() {
6074
return Math.floor(Math.random() * 100);
@@ -67,7 +81,9 @@
6781
// const counterTsxDsdResetButton = document.getElementById('counter-tsx-dsd-reset');
6882

6983
signalCounterJsxResetButton.addEventListener('click', () => {
70-
document.querySelector('sb-signal-counter-jsx').setAttribute('count', randomReset());
84+
document.querySelectorAll('sb-signal-counter-jsx').forEach((el) => {
85+
el.setAttribute('count', randomReset());
86+
});
7187
});
7288

7389
// counterJsxResetButton.addEventListener('click', () => {
@@ -92,6 +108,7 @@ <h1>WCC Sandbox</h1>
92108

93109
<h2>JSX + inferredObservability</h2>
94110

111+
<sb-signal-counter-jsx count="0"></sb-signal-counter-jsx>
95112
<sb-signal-counter-jsx count="3"></sb-signal-counter-jsx>
96113

97114
<button class="reset" id="signal-counter-reset">Random Reset</button>

greenwood.config.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
1-
import type { Config } from '@greenwood/cli';
1+
import type { Config, CopyPlugin } from '@greenwood/cli';
22
import { greenwoodPluginMarkdown } from '@greenwood/plugin-markdown';
33
import { greenwoodPluginImportJsx } from '@greenwood/plugin-import-jsx';
44
import { greenwoodPluginCssModules } from '@greenwood/plugin-css-modules';
55
import { greenwoodPluginImportRaw } from '@greenwood/plugin-import-raw';
6+
import fs from 'node:fs';
7+
8+
// TODO: this does not run in dev :/
9+
function copyEffectPlugin(): CopyPlugin {
10+
console.log('herere???');
11+
return {
12+
type: 'copy',
13+
name: 'plugin-copy-wcc-effect',
14+
provider: async () => {
15+
console.log('copy???');
16+
return [
17+
{
18+
// copy a file
19+
from: new URL('./src/effect.js', import.meta.url),
20+
to: new URL('./node_modules/wc-compiler/src/effect.js', import.meta.url),
21+
},
22+
];
23+
},
24+
};
25+
}
26+
27+
fs.copyFileSync(
28+
new URL('./src/effect.js', import.meta.url),
29+
new URL('./node_modules/wc-compiler/src/effect.js', import.meta.url),
30+
);
631

732
const config: Config = {
833
activeContent: true,
@@ -12,6 +37,7 @@ const config: Config = {
1237
importAttributes: ['css'],
1338
},
1439
plugins: [
40+
// copyEffectPlugin(),
1541
greenwoodPluginImportRaw(),
1642
greenwoodPluginCssModules(),
1743
greenwoodPluginImportJsx(),

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"./register": "./src/register.js",
1818
"./dom-shim": "./src/dom-shim.js",
1919
"./jsx-loader": "./src/jsx-loader.js",
20-
"./jsx-runtime": "./src/jsx-runtime.ts"
20+
"./jsx-runtime": "./src/jsx-runtime.ts",
21+
"./effect": "./src/effect.js"
2122
},
2223
"author": "Owen Buckley <owen@thegreenhouse.io>",
2324
"keywords": [

src/effect.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// https://github.com/proposal-signals/signal-polyfill?tab=readme-ov-file#creating-a-simple-effect
2+
import { Signal } from 'signal-polyfill';
3+
4+
let needsEnqueue = true;
5+
6+
const w = new Signal.subtle.Watcher(() => {
7+
if (needsEnqueue) {
8+
needsEnqueue = false;
9+
queueMicrotask(processPending);
10+
}
11+
});
12+
13+
function processPending() {
14+
needsEnqueue = true;
15+
16+
for (const s of w.getPending()) {
17+
s.get();
18+
}
19+
20+
w.watch();
21+
}
22+
23+
export function effect(callback) {
24+
let cleanup;
25+
26+
const computed = new Signal.Computed(() => {
27+
typeof cleanup === 'function' && cleanup();
28+
cleanup = callback();
29+
});
30+
31+
w.watch(computed);
32+
computed.get();
33+
34+
return () => {
35+
w.unwatch(computed);
36+
typeof cleanup === 'function' && cleanup();
37+
cleanup = undefined;
38+
};
39+
}

0 commit comments

Comments
 (0)