diff --git a/typescript/package-lock.json b/typescript/package-lock.json
index 90377b0d1..f69de1451 100644
--- a/typescript/package-lock.json
+++ b/typescript/package-lock.json
@@ -931,6 +931,10 @@
"resolved": "packages/common-html",
"link": true
},
+ "node_modules/@commontools/common-propagator": {
+ "resolved": "packages/common-propagator",
+ "link": true
+ },
"node_modules/@commontools/common-ui": {
"resolved": "packages/common-ui",
"link": true
@@ -1059,10 +1063,12 @@
"cpu": [
"ppc64"
],
+ "dev": true,
"optional": true,
"os": [
"aix"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1074,10 +1080,12 @@
"cpu": [
"arm"
],
+ "dev": true,
"optional": true,
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1089,10 +1097,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1104,10 +1114,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1119,10 +1131,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1134,10 +1148,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1149,10 +1165,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1164,10 +1182,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1179,10 +1199,12 @@
"cpu": [
"arm"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1194,10 +1216,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1209,10 +1233,12 @@
"cpu": [
"ia32"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1224,10 +1250,12 @@
"cpu": [
"loong64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1239,10 +1267,12 @@
"cpu": [
"mips64el"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1254,10 +1284,12 @@
"cpu": [
"ppc64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1269,10 +1301,12 @@
"cpu": [
"riscv64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1284,10 +1318,12 @@
"cpu": [
"s390x"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1299,10 +1335,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1314,10 +1352,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"netbsd"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1329,10 +1369,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"openbsd"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1344,10 +1386,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"sunos"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1359,10 +1403,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1374,10 +1420,12 @@
"cpu": [
"ia32"
],
+ "dev": true,
"optional": true,
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1389,10 +1437,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">=12"
}
@@ -1562,7 +1612,7 @@
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
@@ -2571,10 +2621,12 @@
"cpu": [
"arm"
],
+ "dev": true,
"optional": true,
"os": [
"android"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.18.0",
@@ -2583,10 +2635,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"android"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.18.0",
@@ -2595,10 +2649,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"darwin"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.18.0",
@@ -2607,10 +2663,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"darwin"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.18.0",
@@ -2619,10 +2677,12 @@
"cpu": [
"arm"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.18.0",
@@ -2631,10 +2691,12 @@
"cpu": [
"arm"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.18.0",
@@ -2643,10 +2705,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.18.0",
@@ -2655,10 +2719,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.18.0",
@@ -2667,10 +2733,12 @@
"cpu": [
"ppc64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.18.0",
@@ -2679,10 +2747,12 @@
"cpu": [
"riscv64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.18.0",
@@ -2691,10 +2761,12 @@
"cpu": [
"s390x"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.18.0",
@@ -2703,10 +2775,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.18.0",
@@ -2715,10 +2789,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"linux"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.18.0",
@@ -2727,10 +2803,12 @@
"cpu": [
"arm64"
],
+ "dev": true,
"optional": true,
"os": [
"win32"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.18.0",
@@ -2739,10 +2817,12 @@
"cpu": [
"ia32"
],
+ "dev": true,
"optional": true,
"os": [
"win32"
- ]
+ ],
+ "peer": true
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.18.0",
@@ -2751,10 +2831,12 @@
"cpu": [
"x64"
],
+ "dev": true,
"optional": true,
"os": [
"win32"
- ]
+ ],
+ "peer": true
},
"node_modules/@rushstack/node-core-library": {
"version": "4.0.2",
@@ -4496,7 +4578,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "devOptional": true
+ "dev": true
},
"node_modules/builtin-modules": {
"version": "3.3.0",
@@ -5737,6 +5819,7 @@
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
@@ -6205,6 +6288,7 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -9275,6 +9359,7 @@
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz",
"integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==",
+ "dev": true,
"dependencies": {
"@types/estree": "1.0.5"
},
@@ -9595,7 +9680,7 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -9605,7 +9690,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "devOptional": true,
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -10038,7 +10123,7 @@
"version": "5.31.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.1.tgz",
"integrity": "sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -10056,7 +10141,7 @@
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "devOptional": true
+ "dev": true
},
"node_modules/text-decoder": {
"version": "1.1.0",
@@ -10328,6 +10413,7 @@
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz",
"integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==",
+ "dev": true,
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.39",
@@ -11089,11 +11175,11 @@
}
},
"packages/common-html": {
+ "name": "@commontools/common-html",
"version": "0.0.1",
"license": "UNLICENSED",
"dependencies": {
- "htmlparser2": "^9.1.0",
- "vite": "^5.3.3"
+ "htmlparser2": "^9.1.0"
},
"devDependencies": {
"@types/mocha": "^10.0.7",
@@ -11103,6 +11189,7 @@
"mocha": "^10.6.0",
"tslib": "^2.6.2",
"typescript": "^5.2.2",
+ "vite": "^5.3.3",
"wireit": "^0.14.4"
}
},
@@ -11130,6 +11217,28 @@
"wireit": "^0.14.4"
}
},
+ "packages/common-propagator": {
+ "name": "@commontools/common-propagator",
+ "version": "0.0.1",
+ "license": "UNLICENSED",
+ "devDependencies": {
+ "@types/mocha": "^10.0.7",
+ "@types/node": "^20.14.12",
+ "mocha": "^10.6.0",
+ "tslib": "^2.6.2",
+ "typescript": "^5.2.2",
+ "wireit": "^0.14.4"
+ }
+ },
+ "packages/common-propagator/node_modules/@types/node": {
+ "version": "20.14.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz",
+ "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
"packages/common-ui": {
"name": "@commontools/common-ui",
"version": "0.0.1",
diff --git a/typescript/package.json b/typescript/package.json
index 262e9ee81..ee05c2ae6 100644
--- a/typescript/package.json
+++ b/typescript/package.json
@@ -40,6 +40,7 @@
"./packages/common-html:build",
"./packages/common-frp:build",
"./packages/common-frp-lit:build",
+ "./packages/common-propagator:build",
"./packages/common-ui:build",
"./packages/llm-client:build",
"./common/data:build",
@@ -62,6 +63,7 @@
"./packages/common-html:clean",
"./packages/common-frp:clean",
"./packages/common-frp-lit:clean",
+ "./packages/common-propagator:clean",
"./packages/common-ui:clean",
"./packages/llm-client:clean",
"./common/data:clean",
diff --git a/typescript/packages/common-html/example/main.ts b/typescript/packages/common-html/example/main.ts
index 5d14f7021..24bccb69e 100644
--- a/typescript/packages/common-html/example/main.ts
+++ b/typescript/packages/common-html/example/main.ts
@@ -1,27 +1,23 @@
-import render, { setNodeSanitizer, setEventSanitizer } from "../src/render.js";
+import { cell } from "@commontools/common-propagator";
import view from "../src/view.js";
import html from "../src/html.js";
-import { state, stream } from "../src/state.js";
+import render from "../src/render.js";
import { setDebug } from "../src/logger.js";
setDebug(true);
-// setNodeSanitizer(...);
-// setEventSanitizer(...);
+const inputState = cell({ text: "Hello, world!" });
+const inputEvents = cell Hello world! Hello world! {{a.b.c}}{{text}}
-
+ {{input.text}}
+
=> {
+ const bigValue = big.get();
+
+ const small = cell(lens.get(bigValue));
+
+ const [cancel, addCancel] = useCancelGroup();
+
+ // Propagate writes from parent to child
+ const cancelBigToSmall = big.sink((bigValue, time) => {
+ small.send(lens.get(bigValue), time);
+ });
+ addCancel(cancelBigToSmall);
+
+ // Propagate writes from child to parent
+ const cancelSmallToBig = small.sink((smallValue, time) => {
+ const bigValue = big.get();
+ const currSmallValue = lens.get(bigValue);
+ if (currSmallValue !== smallValue) {
+ big.send(lens.update(bigValue, smallValue), time);
+ }
+ });
+ addCancel(cancelSmallToBig);
+
+ const cancellableSmall = small as CancellableCell;
+ cancellableSmall.cancel = cancel;
+
+ return cancellableSmall;
+};
+
+export const key =