@treenity/react 3.0.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/dist/AclEditor.d.ts +11 -0
- package/dist/AclEditor.d.ts.map +1 -0
- package/dist/AclEditor.js +152 -0
- package/dist/AclEditor.js.map +1 -0
- package/dist/App.d.ts +2 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +521 -0
- package/dist/App.js.map +1 -0
- package/dist/Inspector.d.ts +12 -0
- package/dist/Inspector.d.ts.map +1 -0
- package/dist/Inspector.js +360 -0
- package/dist/Inspector.js.map +1 -0
- package/dist/Tree.d.ts +16 -0
- package/dist/Tree.d.ts.map +1 -0
- package/dist/Tree.js +100 -0
- package/dist/Tree.js.map +1 -0
- package/dist/ViewPage.d.ts +5 -0
- package/dist/ViewPage.d.ts.map +1 -0
- package/dist/ViewPage.js +13 -0
- package/dist/ViewPage.js.map +1 -0
- package/dist/bind/computed.d.ts +9 -0
- package/dist/bind/computed.d.ts.map +1 -0
- package/dist/bind/computed.js +61 -0
- package/dist/bind/computed.js.map +1 -0
- package/dist/bind/engine.d.ts +3 -0
- package/dist/bind/engine.d.ts.map +1 -0
- package/dist/bind/engine.js +184 -0
- package/dist/bind/engine.js.map +1 -0
- package/dist/bind/eval.d.ts +13 -0
- package/dist/bind/eval.d.ts.map +1 -0
- package/dist/bind/eval.js +97 -0
- package/dist/bind/eval.js.map +1 -0
- package/dist/bind/hook.d.ts +8 -0
- package/dist/bind/hook.d.ts.map +1 -0
- package/dist/bind/hook.js +99 -0
- package/dist/bind/hook.js.map +1 -0
- package/dist/bind/parse.d.ts +19 -0
- package/dist/bind/parse.d.ts.map +1 -0
- package/dist/bind/parse.js +86 -0
- package/dist/bind/parse.js.map +1 -0
- package/dist/bind/pipes.d.ts +4 -0
- package/dist/bind/pipes.d.ts.map +1 -0
- package/dist/bind/pipes.js +43 -0
- package/dist/bind/pipes.js.map +1 -0
- package/dist/cache.d.ts +27 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +236 -0
- package/dist/cache.js.map +1 -0
- package/dist/client-tree.d.ts +9 -0
- package/dist/client-tree.d.ts.map +1 -0
- package/dist/client-tree.js +14 -0
- package/dist/client-tree.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +10 -0
- package/dist/client.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +8 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/accordion.js +18 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/badge.d.ts +10 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +19 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +31 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +7 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +37 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +14 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/drawer.js +35 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/input.d.ts +4 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +7 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +8 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/popover.d.ts +11 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/popover.js +26 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/progress.d.ts +5 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/progress.js +9 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/select.d.ts +16 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +39 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/slider.d.ts +5 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/slider.js +15 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +4 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/sonner.js +21 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/switch.d.ts +7 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +9 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +4 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +7 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +8 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +18 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/context/index.d.ts +31 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +98 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/hooks.d.ts +21 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +156 -0
- package/dist/hooks.js.map +1 -0
- package/dist/idb.d.ts +13 -0
- package/dist/idb.d.ts.map +1 -0
- package/dist/idb.js +67 -0
- package/dist/idb.js.map +1 -0
- package/dist/lib/minimd.d.ts +3 -0
- package/dist/lib/minimd.d.ts.map +1 -0
- package/dist/lib/minimd.js +97 -0
- package/dist/lib/minimd.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/load-client.d.ts +2 -0
- package/dist/load-client.d.ts.map +1 -0
- package/dist/load-client.js +6 -0
- package/dist/load-client.js.map +1 -0
- package/dist/main.d.ts +4 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -0
- package/dist/mods/editor-ui/client.d.ts +6 -0
- package/dist/mods/editor-ui/client.d.ts.map +1 -0
- package/dist/mods/editor-ui/client.js +8 -0
- package/dist/mods/editor-ui/client.js.map +1 -0
- package/dist/mods/editor-ui/default-view.d.ts +2 -0
- package/dist/mods/editor-ui/default-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/default-view.js +71 -0
- package/dist/mods/editor-ui/default-view.js.map +1 -0
- package/dist/mods/editor-ui/dir-view.d.ts +2 -0
- package/dist/mods/editor-ui/dir-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/dir-view.js +42 -0
- package/dist/mods/editor-ui/dir-view.js.map +1 -0
- package/dist/mods/editor-ui/form-fields.d.ts +6 -0
- package/dist/mods/editor-ui/form-fields.d.ts.map +1 -0
- package/dist/mods/editor-ui/form-fields.js +401 -0
- package/dist/mods/editor-ui/form-fields.js.map +1 -0
- package/dist/mods/editor-ui/layout-view.d.ts +2 -0
- package/dist/mods/editor-ui/layout-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/layout-view.js +22 -0
- package/dist/mods/editor-ui/layout-view.js.map +1 -0
- package/dist/mods/editor-ui/list-items.d.ts +2 -0
- package/dist/mods/editor-ui/list-items.d.ts.map +1 -0
- package/dist/mods/editor-ui/list-items.js +38 -0
- package/dist/mods/editor-ui/list-items.js.map +1 -0
- package/dist/mods/editor-ui/node-utils.d.ts +10 -0
- package/dist/mods/editor-ui/node-utils.d.ts.map +1 -0
- package/dist/mods/editor-ui/node-utils.js +76 -0
- package/dist/mods/editor-ui/node-utils.js.map +1 -0
- package/dist/mods/editor-ui/user-view.d.ts +2 -0
- package/dist/mods/editor-ui/user-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/user-view.js +47 -0
- package/dist/mods/editor-ui/user-view.js.map +1 -0
- package/dist/mods/treenity/client.d.ts +4 -0
- package/dist/mods/treenity/client.d.ts.map +1 -0
- package/dist/mods/treenity/client.js +6 -0
- package/dist/mods/treenity/client.js.map +1 -0
- package/dist/mods/treenity/groups/index.d.ts +2 -0
- package/dist/mods/treenity/groups/index.d.ts.map +1 -0
- package/dist/mods/treenity/groups/index.js +27 -0
- package/dist/mods/treenity/groups/index.js.map +1 -0
- package/dist/mods/treenity/preview.d.ts +6 -0
- package/dist/mods/treenity/preview.d.ts.map +1 -0
- package/dist/mods/treenity/preview.js +95 -0
- package/dist/mods/treenity/preview.js.map +1 -0
- package/dist/mods/treenity/ref-view.d.ts +2 -0
- package/dist/mods/treenity/ref-view.d.ts.map +1 -0
- package/dist/mods/treenity/ref-view.js +29 -0
- package/dist/mods/treenity/ref-view.js.map +1 -0
- package/dist/mods/treenity/schema-form.d.ts +2 -0
- package/dist/mods/treenity/schema-form.d.ts.map +1 -0
- package/dist/mods/treenity/schema-form.js +38 -0
- package/dist/mods/treenity/schema-form.js.map +1 -0
- package/dist/mods/treenity/seed.d.ts +2 -0
- package/dist/mods/treenity/seed.d.ts.map +1 -0
- package/dist/mods/treenity/seed.js +53 -0
- package/dist/mods/treenity/seed.js.map +1 -0
- package/dist/mods/treenity/server.d.ts +2 -0
- package/dist/mods/treenity/server.d.ts.map +1 -0
- package/dist/mods/treenity/server.js +2 -0
- package/dist/mods/treenity/server.js.map +1 -0
- package/dist/mods/treenity/type-view.d.ts +2 -0
- package/dist/mods/treenity/type-view.d.ts.map +1 -0
- package/dist/mods/treenity/type-view.js +36 -0
- package/dist/mods/treenity/type-view.js.map +1 -0
- package/dist/remote-tree.d.ts +6 -0
- package/dist/remote-tree.d.ts.map +1 -0
- package/dist/remote-tree.js +18 -0
- package/dist/remote-tree.js.map +1 -0
- package/dist/schema-loader.d.ts +19 -0
- package/dist/schema-loader.d.ts.map +1 -0
- package/dist/schema-loader.js +63 -0
- package/dist/schema-loader.js.map +1 -0
- package/dist/trpc.d.ts +187 -0
- package/dist/trpc.d.ts.map +1 -0
- package/dist/trpc.js +21 -0
- package/dist/trpc.js.map +1 -0
- package/package.json +88 -0
- package/src/AclEditor.tsx +330 -0
- package/src/App.tsx +775 -0
- package/src/CLAUDE.md +16 -0
- package/src/Inspector.tsx +857 -0
- package/src/Tree.tsx +237 -0
- package/src/ViewPage.tsx +45 -0
- package/src/bind/bind.test.ts +316 -0
- package/src/bind/computed.ts +64 -0
- package/src/bind/engine.ts +198 -0
- package/src/bind/eval.ts +108 -0
- package/src/bind/hook.ts +112 -0
- package/src/bind/parse.ts +104 -0
- package/src/bind/pipes.ts +71 -0
- package/src/cache.test.ts +139 -0
- package/src/cache.ts +244 -0
- package/src/client-tree.test.ts +116 -0
- package/src/client-tree.ts +24 -0
- package/src/client.ts +11 -0
- package/src/components/ui/accordion.tsx +63 -0
- package/src/components/ui/badge.tsx +27 -0
- package/src/components/ui/button.tsx +44 -0
- package/src/components/ui/checkbox.tsx +19 -0
- package/src/components/ui/dialog.tsx +156 -0
- package/src/components/ui/drawer.tsx +132 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/label.tsx +21 -0
- package/src/components/ui/popover.tsx +86 -0
- package/src/components/ui/progress.tsx +30 -0
- package/src/components/ui/select.tsx +189 -0
- package/src/components/ui/slider.tsx +62 -0
- package/src/components/ui/sonner.tsx +32 -0
- package/src/components/ui/switch.tsx +34 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/tooltip.tsx +56 -0
- package/src/context/index.tsx +131 -0
- package/src/context.ts +1 -0
- package/src/hooks.ts +208 -0
- package/src/idb.ts +80 -0
- package/src/index.html +14 -0
- package/src/lib/minimd.css +28 -0
- package/src/lib/minimd.ts +95 -0
- package/src/lib/utils.ts +6 -0
- package/src/load-client.ts +5 -0
- package/src/main.tsx +22 -0
- package/src/mods/editor-ui/CLAUDE.md +3 -0
- package/src/mods/editor-ui/client.ts +8 -0
- package/src/mods/editor-ui/default-view.tsx +148 -0
- package/src/mods/editor-ui/dir-view.tsx +91 -0
- package/src/mods/editor-ui/form-fields.tsx +861 -0
- package/src/mods/editor-ui/layout-view.tsx +62 -0
- package/src/mods/editor-ui/list-items.tsx +63 -0
- package/src/mods/editor-ui/node-utils.ts +84 -0
- package/src/mods/editor-ui/user-view.tsx +101 -0
- package/src/mods/treenity/CLAUDE.md +7 -0
- package/src/mods/treenity/client.ts +6 -0
- package/src/mods/treenity/groups/index.tsx +65 -0
- package/src/mods/treenity/preview.tsx +133 -0
- package/src/mods/treenity/ref-view.tsx +87 -0
- package/src/mods/treenity/schema-form.tsx +65 -0
- package/src/mods/treenity/seed.ts +56 -0
- package/src/mods/treenity/server.ts +1 -0
- package/src/mods/treenity/type-view.tsx +116 -0
- package/src/remote-tree.test.ts +142 -0
- package/src/remote-tree.ts +25 -0
- package/src/schema-loader.ts +84 -0
- package/src/style.css +1269 -0
- package/src/trpc.ts +27 -0
- package/src/vite-env.d.ts +3 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Computed store — separate reactive layer for $ref+$map resolved values
|
|
2
|
+
// Dual: valtio proxies for field-level React reactivity (useSnapshot),
|
|
3
|
+
// plus synchronous manual subs for bind engine and non-React consumers.
|
|
4
|
+
// Never persisted to IDB or server. No Meteor trap.
|
|
5
|
+
import { proxy, snapshot } from 'valtio/vanilla';
|
|
6
|
+
const proxies = new Map();
|
|
7
|
+
const subs = new Map();
|
|
8
|
+
function ensure(path) {
|
|
9
|
+
let p = proxies.get(path);
|
|
10
|
+
if (!p) {
|
|
11
|
+
p = proxy({});
|
|
12
|
+
proxies.set(path, p);
|
|
13
|
+
}
|
|
14
|
+
return p;
|
|
15
|
+
}
|
|
16
|
+
function fire(path) {
|
|
17
|
+
const s = subs.get(path);
|
|
18
|
+
if (s)
|
|
19
|
+
for (const cb of s)
|
|
20
|
+
cb();
|
|
21
|
+
}
|
|
22
|
+
export function getComputed(path) {
|
|
23
|
+
const p = proxies.get(path);
|
|
24
|
+
if (!p)
|
|
25
|
+
return undefined;
|
|
26
|
+
return snapshot(p);
|
|
27
|
+
}
|
|
28
|
+
/** Get the raw valtio proxy — for useSnapshot in hooks */
|
|
29
|
+
export function getComputedProxy(path) {
|
|
30
|
+
return proxies.get(path);
|
|
31
|
+
}
|
|
32
|
+
export function setComputed(path, field, value) {
|
|
33
|
+
const p = ensure(path);
|
|
34
|
+
if (Object.is(p[field], value))
|
|
35
|
+
return; // no-op if unchanged
|
|
36
|
+
p[field] = value;
|
|
37
|
+
fire(path); // synchronous for non-React consumers
|
|
38
|
+
}
|
|
39
|
+
export function clearComputed(path) {
|
|
40
|
+
const p = proxies.get(path);
|
|
41
|
+
if (p) {
|
|
42
|
+
for (const k of Object.keys(p))
|
|
43
|
+
delete p[k];
|
|
44
|
+
proxies.delete(path);
|
|
45
|
+
}
|
|
46
|
+
fire(path);
|
|
47
|
+
}
|
|
48
|
+
export function subscribeComputed(path, cb) {
|
|
49
|
+
if (!subs.has(path))
|
|
50
|
+
subs.set(path, new Set());
|
|
51
|
+
subs.get(path).add(cb);
|
|
52
|
+
return () => {
|
|
53
|
+
const s = subs.get(path);
|
|
54
|
+
if (s) {
|
|
55
|
+
s.delete(cb);
|
|
56
|
+
if (!s.size)
|
|
57
|
+
subs.delete(path);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=computed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computed.js","sourceRoot":"","sources":["../../src/bind/computed.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,uEAAuE;AACvE,wEAAwE;AACxE,oDAAoD;AAEpD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAIjD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmC,CAAC;AAC3D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC;AAEzC,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,GAAG,KAAK,CAA0B,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,IAAI,CAAC,IAAY;IACxB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,CAAC;QAAE,KAAK,MAAM,EAAE,IAAI,CAAC;YAAE,EAAE,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,OAAO,QAAQ,CAAC,CAAC,CAA4B,CAAC;AAChD,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa,EAAE,KAAc;IACrE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,qBAAqB;IAC7D,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IACjB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,sCAAsC;AACpD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,EAAO;IACrD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE;QACV,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,EAAE,CAAC;YACN,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACb,IAAI,CAAC,CAAC,CAAC,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/bind/engine.ts"],"names":[],"mappings":"AA4JA,0DAA0D;AAC1D,wBAAgB,eAAe,IAAI,MAAM,IAAI,CAwC5C"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Binding engine — scans cache for $ref+$map fields, subscribes to sources,
|
|
2
|
+
// evaluates on change, writes to computed store.
|
|
3
|
+
// Supports $ref: "." (self) and @/path.field ref args in $map expressions.
|
|
4
|
+
import * as cache from '#cache';
|
|
5
|
+
import { trpc } from '#trpc';
|
|
6
|
+
import { isRef } from '@treenity/core/core';
|
|
7
|
+
import { clearComputed, getComputed, setComputed } from './computed';
|
|
8
|
+
import { evaluateRef, extractArgPaths, hasOnce, isCollectionRef } from './eval';
|
|
9
|
+
// Active bindings: targetPath → field → { ref, unsub }
|
|
10
|
+
const active = new Map();
|
|
11
|
+
// Collection paths with active SSE watches
|
|
12
|
+
const watchedCollections = new Set();
|
|
13
|
+
// Single-node paths already fetched
|
|
14
|
+
const fetchedNodes = new Set();
|
|
15
|
+
const ctx = {
|
|
16
|
+
getNode: (p) => cache.get(p),
|
|
17
|
+
getChildren: (p) => cache.getChildren(p),
|
|
18
|
+
};
|
|
19
|
+
/** Fetch collection children from server into cache */
|
|
20
|
+
function fetchChildren(path) {
|
|
21
|
+
trpc.getChildren
|
|
22
|
+
.query({ path, watch: true, watchNew: true })
|
|
23
|
+
.then((r) => cache.putMany(r.items, path));
|
|
24
|
+
}
|
|
25
|
+
/** Ensure source data is in cache by fetching from server */
|
|
26
|
+
function ensureInCache(path, collection) {
|
|
27
|
+
if (collection) {
|
|
28
|
+
if (!watchedCollections.has(path)) {
|
|
29
|
+
watchedCollections.add(path);
|
|
30
|
+
fetchChildren(path);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (fetchedNodes.has(path))
|
|
35
|
+
return;
|
|
36
|
+
fetchedNodes.add(path);
|
|
37
|
+
trpc.get.query({ path }).then((n) => {
|
|
38
|
+
if (n)
|
|
39
|
+
cache.put(n);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function evaluate(targetPath, field, ref) {
|
|
44
|
+
// Resolve $ref: "." → actual target path before eval
|
|
45
|
+
const resolved = ref.$ref === '.' ? { ...ref, $ref: targetPath } : ref;
|
|
46
|
+
try {
|
|
47
|
+
const value = evaluateRef(resolved, ctx);
|
|
48
|
+
setComputed(targetPath, field, value);
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
console.warn(`[bind] eval error ${targetPath}.${field}:`, e);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function registerBinding(targetPath, field, ref) {
|
|
55
|
+
const once = hasOnce(ref);
|
|
56
|
+
const unsubs = [];
|
|
57
|
+
const cb = () => evaluate(targetPath, field, ref);
|
|
58
|
+
const mainPath = ref.$ref === '.' ? targetPath : ref.$ref;
|
|
59
|
+
const collection = isCollectionRef(ref);
|
|
60
|
+
if (mainPath !== targetPath) {
|
|
61
|
+
ensureInCache(mainPath, collection);
|
|
62
|
+
}
|
|
63
|
+
// `once` — evaluate once, no reactive subscription
|
|
64
|
+
if (!once) {
|
|
65
|
+
unsubs.push(collection
|
|
66
|
+
? cache.subscribeChildren(mainPath, cb)
|
|
67
|
+
: cache.subscribePath(mainPath, cb));
|
|
68
|
+
for (const argPath of extractArgPaths(ref)) {
|
|
69
|
+
unsubs.push(cache.subscribePath(argPath, cb));
|
|
70
|
+
ensureInCache(argPath, false);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!active.has(targetPath))
|
|
74
|
+
active.set(targetPath, new Map());
|
|
75
|
+
active.get(targetPath).set(field, { ref, unsub: () => unsubs.forEach(u => u()) });
|
|
76
|
+
evaluate(targetPath, field, ref);
|
|
77
|
+
}
|
|
78
|
+
function unregisterAll(targetPath) {
|
|
79
|
+
const bindings = active.get(targetPath);
|
|
80
|
+
if (!bindings)
|
|
81
|
+
return;
|
|
82
|
+
for (const { unsub } of bindings.values())
|
|
83
|
+
unsub();
|
|
84
|
+
active.delete(targetPath);
|
|
85
|
+
clearComputed(targetPath);
|
|
86
|
+
}
|
|
87
|
+
/** Scan a single node for $ref+$map fields, register/update bindings */
|
|
88
|
+
function scanNode(node) {
|
|
89
|
+
const path = node.$path;
|
|
90
|
+
const newRefs = new Map();
|
|
91
|
+
// Scan node-level fields
|
|
92
|
+
for (const [key, value] of Object.entries(node)) {
|
|
93
|
+
if (key.startsWith('$'))
|
|
94
|
+
continue;
|
|
95
|
+
if (isRef(value) && value.$map) {
|
|
96
|
+
newRefs.set(key, value);
|
|
97
|
+
}
|
|
98
|
+
// Scan sub-component fields
|
|
99
|
+
if (typeof value === 'object' && value !== null && '$type' in value) {
|
|
100
|
+
for (const [subKey, subVal] of Object.entries(value)) {
|
|
101
|
+
if (subKey.startsWith('$'))
|
|
102
|
+
continue;
|
|
103
|
+
if (isRef(subVal) && subVal.$map) {
|
|
104
|
+
newRefs.set(`${key}.${subKey}`, subVal);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const existing = active.get(path);
|
|
110
|
+
// No bindings before or after — nothing to do
|
|
111
|
+
if (!existing && newRefs.size === 0)
|
|
112
|
+
return;
|
|
113
|
+
// Remove stale bindings
|
|
114
|
+
if (existing) {
|
|
115
|
+
for (const [field, { unsub }] of existing) {
|
|
116
|
+
if (!newRefs.has(field)) {
|
|
117
|
+
unsub();
|
|
118
|
+
existing.delete(field);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (existing.size === 0 && newRefs.size === 0) {
|
|
122
|
+
active.delete(path);
|
|
123
|
+
clearComputed(path);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Register new/updated bindings
|
|
128
|
+
for (const [field, ref] of newRefs) {
|
|
129
|
+
const prev = existing?.get(field);
|
|
130
|
+
// Skip if same expression
|
|
131
|
+
if (prev && prev.ref.$ref === ref.$ref && prev.ref.$map === ref.$map)
|
|
132
|
+
continue;
|
|
133
|
+
// Unregister old
|
|
134
|
+
if (prev)
|
|
135
|
+
prev.unsub();
|
|
136
|
+
registerBinding(path, field, ref);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function handleRemove(path) {
|
|
140
|
+
unregisterAll(path);
|
|
141
|
+
}
|
|
142
|
+
/** Start the binding engine. Returns cleanup function. */
|
|
143
|
+
export function startBindEngine() {
|
|
144
|
+
// 1. Scan all existing nodes in cache
|
|
145
|
+
for (const [, node] of cache.raw()) {
|
|
146
|
+
scanNode(node);
|
|
147
|
+
}
|
|
148
|
+
// 2. Reactive: scan each node as it arrives/changes — instant, no polling
|
|
149
|
+
const unsubPut = cache.onNodePut((path) => {
|
|
150
|
+
const node = cache.get(path);
|
|
151
|
+
if (node)
|
|
152
|
+
scanNode(node);
|
|
153
|
+
});
|
|
154
|
+
// 3. Detect removed nodes — clean up stale bindings
|
|
155
|
+
const unsubGlobal = cache.subscribeGlobal(() => {
|
|
156
|
+
for (const path of active.keys()) {
|
|
157
|
+
if (!cache.get(path))
|
|
158
|
+
handleRemove(path);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
// Dev debug — inspect binding engine state from console
|
|
162
|
+
if (typeof window !== 'undefined') {
|
|
163
|
+
window.__bind = {
|
|
164
|
+
active: () => Object.fromEntries([...active].map(([k, v]) => [k, [...v.keys()]])),
|
|
165
|
+
watched: () => [...watchedCollections],
|
|
166
|
+
fetched: () => [...fetchedNodes],
|
|
167
|
+
computed: () => {
|
|
168
|
+
const result = {};
|
|
169
|
+
for (const p of active.keys())
|
|
170
|
+
result[p] = getComputed(p);
|
|
171
|
+
return result;
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return () => {
|
|
176
|
+
unsubPut();
|
|
177
|
+
unsubGlobal();
|
|
178
|
+
for (const path of [...active.keys()])
|
|
179
|
+
unregisterAll(path);
|
|
180
|
+
watchedCollections.clear();
|
|
181
|
+
fetchedNodes.clear();
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/bind/engine.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,iDAAiD;AACjD,2EAA2E;AAE3E,OAAO,KAAK,KAAK,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,KAAK,EAA2B,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAIhF,uDAAuD;AACvD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmD,CAAC;AAE1E,2CAA2C;AAC3C,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;AAC7C,oCAAoC;AACpC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;AAEvC,MAAM,GAAG,GAAG;IACV,OAAO,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,WAAW,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;CACjD,CAAC;AAEF,uDAAuD;AACvD,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC,WAAW;SACb,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;SAC5C,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAmB,EAAE,IAAI,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,6DAA6D;AAC7D,SAAS,aAAa,CAAC,IAAY,EAAE,UAAmB;IACtD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,aAAa,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QACnC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE;YACvC,IAAI,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,CAAa,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,UAAkB,EAAE,KAAa,EAAE,GAAQ;IAC3D,qDAAqD;IACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IACvE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACzC,WAAW,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,qBAAqB,UAAU,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,UAAkB,EAAE,KAAa,EAAE,GAAQ;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAElD,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1D,MAAM,UAAU,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAExC,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,mDAAmD;IACnD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,IAAI,CACT,UAAU;YACR,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,CAAC;YACvC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CACtC,CAAC;QAEF,KAAK,MAAM,OAAO,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAC9C,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAEnF,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,aAAa,CAAC,UAAkB;IACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,CAAC;IACnD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1B,aAAa,CAAC,UAAU,CAAC,CAAC;AAC5B,CAAC;AAED,wEAAwE;AACxE,SAAS,QAAQ,CAAC,IAAc;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IAEvC,yBAAyB;IACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAY,CAAC,CAAC;QACjC,CAAC;QACD,4BAA4B;QAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YACpE,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrD,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAS;gBACrC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAK,MAAc,CAAC,IAAI,EAAE,CAAC;oBAC1C,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,MAAM,EAAE,EAAE,MAAa,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAElC,8CAA8C;IAC9C,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO;IAE5C,wBAAwB;IACxB,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,KAAK,EAAE,CAAC;gBACR,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpB,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,0BAA0B;QAC1B,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI;YAAE,SAAS;QAC/E,iBAAiB;QACjB,IAAI,IAAI;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACvB,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,aAAa,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,eAAe;IAC7B,sCAAsC;IACtC,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAED,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,oDAAoD;IACpD,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE;QAC7C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,MAAc,CAAC,MAAM,GAAG;YACvB,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACjF,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,kBAAkB,CAAC;YACtC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC;YAChC,QAAQ,EAAE,GAAG,EAAE;gBACb,MAAM,MAAM,GAA4B,EAAE,CAAC;gBAC3C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE;oBAAE,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBAC1D,OAAO,MAAM,CAAC;YAChB,CAAC;SACF,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,EAAE;QACV,QAAQ,EAAE,CAAC;QACX,WAAW,EAAE,CAAC;QACd,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QAC3D,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAC3B,YAAY,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NodeData, Ref } from '@treenity/core/core';
|
|
2
|
+
export type BindCtx = {
|
|
3
|
+
getNode: (path: string) => NodeData | undefined;
|
|
4
|
+
getChildren: (path: string) => NodeData[];
|
|
5
|
+
};
|
|
6
|
+
export declare function evaluateRef(ref: Ref, ctx: BindCtx): unknown;
|
|
7
|
+
/** Check if first pipe in $map is a collection pipe (needs children subscription) */
|
|
8
|
+
export declare function isCollectionRef(ref: Ref): boolean;
|
|
9
|
+
/** Check if $map contains `once` pipe — disables reactive subscription */
|
|
10
|
+
export declare function hasOnce(ref: Ref): boolean;
|
|
11
|
+
/** Extract all external #/path refs from a $map expression (for subscriptions) */
|
|
12
|
+
export declare function extractArgPaths(ref: Ref): string[];
|
|
13
|
+
//# sourceMappingURL=eval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/bind/eval.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAIzD,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAC;IAChD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;CAC3C,CAAC;AA6BF,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAmC3D;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAKjD;AAED,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAIzC;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE,CAclD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// $ref + $map evaluator
|
|
2
|
+
// Resolves source from $ref, applies $map pipeline
|
|
3
|
+
// #field (self) and #/path.field (external) args resolved from context
|
|
4
|
+
import { isRefArg, parseMapExpr } from './parse';
|
|
5
|
+
import { getPipe } from './pipes';
|
|
6
|
+
// Collection pipe names — when first step is one of these, resolve source as children
|
|
7
|
+
const COLLECTION_PIPES = new Set(['last', 'first', 'count', 'avg', 'max', 'min', 'sum', 'map']);
|
|
8
|
+
// Parsed expression cache
|
|
9
|
+
const exprCache = new Map();
|
|
10
|
+
function getCachedExpr(map) {
|
|
11
|
+
let expr = exprCache.get(map);
|
|
12
|
+
if (!expr) {
|
|
13
|
+
expr = parseMapExpr(map);
|
|
14
|
+
exprCache.set(map, expr);
|
|
15
|
+
}
|
|
16
|
+
return expr;
|
|
17
|
+
}
|
|
18
|
+
/** Resolve a pipe argument — ref args looked up from context, scalars pass through */
|
|
19
|
+
function resolveArg(arg, ctx, refPath) {
|
|
20
|
+
if (!isRefArg(arg))
|
|
21
|
+
return arg;
|
|
22
|
+
const path = arg.$ref === '.' ? refPath : arg.$ref;
|
|
23
|
+
let val = ctx.getNode(path);
|
|
24
|
+
for (const f of arg.fields) {
|
|
25
|
+
if (val == null || typeof val !== 'object')
|
|
26
|
+
return undefined;
|
|
27
|
+
val = val[f];
|
|
28
|
+
}
|
|
29
|
+
return val;
|
|
30
|
+
}
|
|
31
|
+
export function evaluateRef(ref, ctx) {
|
|
32
|
+
// Plain ref without $map — resolve to node
|
|
33
|
+
if (!ref.$map) {
|
|
34
|
+
return ctx.getNode(ref.$ref);
|
|
35
|
+
}
|
|
36
|
+
const expr = getCachedExpr(ref.$map);
|
|
37
|
+
const firstStep = expr.steps[0];
|
|
38
|
+
// Determine source: children (if first pipe is collection) or single node
|
|
39
|
+
let value;
|
|
40
|
+
if (firstStep?.type === 'pipe' && COLLECTION_PIPES.has(firstStep.name)) {
|
|
41
|
+
value = ctx.getChildren(ref.$ref);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
value = ctx.getNode(ref.$ref);
|
|
45
|
+
}
|
|
46
|
+
// Apply pipeline left-to-right
|
|
47
|
+
for (const step of expr.steps) {
|
|
48
|
+
if (value === undefined || value === null)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (step.type === 'field') {
|
|
51
|
+
value = value[step.name];
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const fn = getPipe(step.name);
|
|
55
|
+
if (!fn) {
|
|
56
|
+
console.warn(`[bind] unknown pipe: ${step.name}`);
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const resolved = step.args.map(a => resolveArg(a, ctx, ref.$ref));
|
|
60
|
+
value = fn(value, ...resolved);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
/** Check if first pipe in $map is a collection pipe (needs children subscription) */
|
|
66
|
+
export function isCollectionRef(ref) {
|
|
67
|
+
if (!ref.$map)
|
|
68
|
+
return false;
|
|
69
|
+
const expr = getCachedExpr(ref.$map);
|
|
70
|
+
const first = expr.steps[0];
|
|
71
|
+
return first?.type === 'pipe' && COLLECTION_PIPES.has(first.name);
|
|
72
|
+
}
|
|
73
|
+
/** Check if $map contains `once` pipe — disables reactive subscription */
|
|
74
|
+
export function hasOnce(ref) {
|
|
75
|
+
if (!ref.$map)
|
|
76
|
+
return false;
|
|
77
|
+
const expr = getCachedExpr(ref.$map);
|
|
78
|
+
return expr.steps.some(s => s.type === 'pipe' && s.name === 'once');
|
|
79
|
+
}
|
|
80
|
+
/** Extract all external #/path refs from a $map expression (for subscriptions) */
|
|
81
|
+
export function extractArgPaths(ref) {
|
|
82
|
+
if (!ref.$map)
|
|
83
|
+
return [];
|
|
84
|
+
const expr = getCachedExpr(ref.$map);
|
|
85
|
+
const paths = [];
|
|
86
|
+
for (const step of expr.steps) {
|
|
87
|
+
if (step.type === 'pipe') {
|
|
88
|
+
for (const arg of step.args) {
|
|
89
|
+
if (isRefArg(arg) && arg.$ref !== '.') {
|
|
90
|
+
paths.push(arg.$ref);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return paths;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=eval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval.js","sourceRoot":"","sources":["../../src/bind/eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type NodeData } from '@treenity/core/core';
|
|
2
|
+
/** Reactive access to computed binding values for a node */
|
|
3
|
+
export declare function useComputed(path: string): Record<string, unknown>;
|
|
4
|
+
/** Node with computed bindings merged — raw + computed overlay */
|
|
5
|
+
export declare function useResolvedNode(path: string): [NodeData | undefined, (next: NodeData) => Promise<void>];
|
|
6
|
+
/** Evaluate a $ref+$map expression reactively — no node needed */
|
|
7
|
+
export declare function useEvalRef(path: string, map: string): unknown;
|
|
8
|
+
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/bind/hook.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAS3D,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUjE;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,QAAQ,GAAG,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAkDvG;AAOD,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CA0B7D"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// React hooks for computed bindings
|
|
2
|
+
import * as cache from '#cache';
|
|
3
|
+
import { set, usePath } from '#hooks';
|
|
4
|
+
import { isRef } from '@treenity/core/core';
|
|
5
|
+
import { useCallback, useMemo, useSyncExternalStore } from 'react';
|
|
6
|
+
import { useSnapshot } from 'valtio';
|
|
7
|
+
import { proxy } from 'valtio/vanilla';
|
|
8
|
+
import { getComputed, getComputedProxy, subscribeComputed } from './computed';
|
|
9
|
+
import { evaluateRef, extractArgPaths, isCollectionRef } from './eval';
|
|
10
|
+
const EMPTY_PROXY = proxy({});
|
|
11
|
+
/** Reactive access to computed binding values for a node */
|
|
12
|
+
export function useComputed(path) {
|
|
13
|
+
// Structural: detect proxy creation (first computed value for this path)
|
|
14
|
+
useSyncExternalStore(useCallback((cb) => subscribeComputed(path, cb), [path]), useCallback(() => getComputed(path), [path]));
|
|
15
|
+
// Field-level: re-render only when accessed computed fields change
|
|
16
|
+
const p = getComputedProxy(path);
|
|
17
|
+
return useSnapshot(p ?? EMPTY_PROXY);
|
|
18
|
+
}
|
|
19
|
+
/** Node with computed bindings merged — raw + computed overlay */
|
|
20
|
+
export function useResolvedNode(path) {
|
|
21
|
+
const node = usePath(path);
|
|
22
|
+
const computed = useComputed(path);
|
|
23
|
+
if (!node)
|
|
24
|
+
return [undefined, set];
|
|
25
|
+
// Check if node has any $ref+$map bindings that need resolving
|
|
26
|
+
const hasComputed = Object.keys(computed).length > 0;
|
|
27
|
+
const hasBindings = Object.values(node).some(v => isRef(v) && v.$map);
|
|
28
|
+
if (!hasComputed && !hasBindings)
|
|
29
|
+
return [node, set];
|
|
30
|
+
const merged = { ...node };
|
|
31
|
+
// Apply computed values
|
|
32
|
+
for (const [key, value] of Object.entries(computed)) {
|
|
33
|
+
// Support dotted keys for sub-component fields (e.g. "mesh.width")
|
|
34
|
+
if (key.includes('.')) {
|
|
35
|
+
const [comp, field] = key.split('.');
|
|
36
|
+
if (merged[comp] && typeof merged[comp] === 'object') {
|
|
37
|
+
merged[comp] = { ...merged[comp], [field]: value };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
merged[key] = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Strip unresolved $ref+$map bindings — computed not ready yet, use 0 default
|
|
45
|
+
// Without this, raw ref objects leak to consumers (e.g. Three.js rotation={[0, {$ref:...}, 0]} → NaN)
|
|
46
|
+
for (const key of Object.keys(merged)) {
|
|
47
|
+
if (key.startsWith('$'))
|
|
48
|
+
continue;
|
|
49
|
+
const v = merged[key];
|
|
50
|
+
if (isRef(v) && v.$map) {
|
|
51
|
+
merged[key] = 0;
|
|
52
|
+
}
|
|
53
|
+
// Sub-component fields
|
|
54
|
+
if (v && typeof v === 'object' && !isRef(v) && '$type' in v) {
|
|
55
|
+
let changed = false;
|
|
56
|
+
const comp = { ...v };
|
|
57
|
+
for (const sk of Object.keys(comp)) {
|
|
58
|
+
if (sk.startsWith('$'))
|
|
59
|
+
continue;
|
|
60
|
+
if (isRef(comp[sk]) && comp[sk].$map) {
|
|
61
|
+
comp[sk] = 0;
|
|
62
|
+
changed = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (changed)
|
|
66
|
+
merged[key] = comp;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [merged, set];
|
|
70
|
+
}
|
|
71
|
+
const evalCtx = {
|
|
72
|
+
getNode: (p) => cache.get(p),
|
|
73
|
+
getChildren: (p) => cache.getChildren(p),
|
|
74
|
+
};
|
|
75
|
+
/** Evaluate a $ref+$map expression reactively — no node needed */
|
|
76
|
+
export function useEvalRef(path, map) {
|
|
77
|
+
const ref = useMemo(() => ({ $ref: path, $map: map }), [path, map]);
|
|
78
|
+
// Subscribe to all relevant paths: main source + @/path args
|
|
79
|
+
const subscribe = useCallback((cb) => {
|
|
80
|
+
const unsubs = [];
|
|
81
|
+
unsubs.push(isCollectionRef(ref)
|
|
82
|
+
? cache.subscribeChildren(path, cb)
|
|
83
|
+
: cache.subscribePath(path, cb));
|
|
84
|
+
for (const argPath of extractArgPaths(ref)) {
|
|
85
|
+
unsubs.push(cache.subscribePath(argPath, cb));
|
|
86
|
+
}
|
|
87
|
+
return () => unsubs.forEach(u => u());
|
|
88
|
+
}, [ref, path]);
|
|
89
|
+
const getSnapshot = useCallback(() => {
|
|
90
|
+
try {
|
|
91
|
+
return evaluateRef(ref, evalCtx);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
}, [ref]);
|
|
97
|
+
return useSyncExternalStore(subscribe, getSnapshot);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/bind/hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type RefArg = {
|
|
2
|
+
$ref: string;
|
|
3
|
+
fields: string[];
|
|
4
|
+
};
|
|
5
|
+
export type PipeArg = number | string | RefArg;
|
|
6
|
+
export type MapExpr = {
|
|
7
|
+
steps: PipeStep[];
|
|
8
|
+
};
|
|
9
|
+
export type PipeStep = {
|
|
10
|
+
type: 'pipe';
|
|
11
|
+
name: string;
|
|
12
|
+
args: PipeArg[];
|
|
13
|
+
} | {
|
|
14
|
+
type: 'field';
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function isRefArg(arg: PipeArg): arg is RefArg;
|
|
18
|
+
export declare function parseMapExpr(expr: string): MapExpr;
|
|
19
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/bind/parse.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AACxD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE,CAAC;AAE5C,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAEpD;AA0ED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASlD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// $map expression parser
|
|
2
|
+
// Syntax: selector.field | pipe1(args) | pipe2(args)
|
|
3
|
+
// Source path lives in $ref, not here — parser handles $map content only
|
|
4
|
+
//
|
|
5
|
+
// Access modes:
|
|
6
|
+
// .field = drill into current pipe value
|
|
7
|
+
// #field = lookup from source node ($ref path) — like URI fragment
|
|
8
|
+
// #/path.field = lookup from external node — absolute path after #
|
|
9
|
+
export function isRefArg(arg) {
|
|
10
|
+
return typeof arg === 'object' && arg !== null && '$ref' in arg;
|
|
11
|
+
}
|
|
12
|
+
const PIPE_RE = /^([a-zA-Z_]\w*)\(([^)]*)\)(.*)$/;
|
|
13
|
+
function parseArg(s) {
|
|
14
|
+
const t = s.trim();
|
|
15
|
+
// # = node ref: #field (self), #/path.field (external)
|
|
16
|
+
if (t.startsWith('#')) {
|
|
17
|
+
const rest = t.slice(1);
|
|
18
|
+
if (rest.startsWith('/')) {
|
|
19
|
+
// External: #/path.field
|
|
20
|
+
const dotIdx = rest.indexOf('.');
|
|
21
|
+
if (dotIdx === -1)
|
|
22
|
+
return { $ref: rest, fields: [] };
|
|
23
|
+
return { $ref: rest.slice(0, dotIdx), fields: rest.slice(dotIdx + 1).split('.') };
|
|
24
|
+
}
|
|
25
|
+
// Self: #field or #comp.field
|
|
26
|
+
return { $ref: '.', fields: rest.length ? rest.split('.') : [] };
|
|
27
|
+
}
|
|
28
|
+
const n = Number(t);
|
|
29
|
+
return Number.isFinite(n) ? n : t;
|
|
30
|
+
}
|
|
31
|
+
function parseSegment(raw) {
|
|
32
|
+
const s = raw.trim();
|
|
33
|
+
if (!s)
|
|
34
|
+
return [];
|
|
35
|
+
// #field — self-ref field access (like URI fragment)
|
|
36
|
+
if (s.startsWith('#') && !s.startsWith('#/')) {
|
|
37
|
+
const rest = s.slice(1);
|
|
38
|
+
return rest.split('.').map(name => ({ type: 'field', name }));
|
|
39
|
+
}
|
|
40
|
+
// Pure field chain: .foo.bar — drill into pipe value
|
|
41
|
+
if (s.startsWith('.')) {
|
|
42
|
+
return parseFieldChain(s);
|
|
43
|
+
}
|
|
44
|
+
// pipe(args) optionally followed by .field chain
|
|
45
|
+
const m = PIPE_RE.exec(s);
|
|
46
|
+
if (m) {
|
|
47
|
+
const steps = [{
|
|
48
|
+
type: 'pipe',
|
|
49
|
+
name: m[1],
|
|
50
|
+
args: m[2] ? m[2].split(',').map(parseArg) : [],
|
|
51
|
+
}];
|
|
52
|
+
if (m[3])
|
|
53
|
+
steps.push(...parseFieldChain(m[3]));
|
|
54
|
+
return steps;
|
|
55
|
+
}
|
|
56
|
+
// Bare name (round, abs): pipe with no args, optionally followed by .field
|
|
57
|
+
const bare = /^([a-zA-Z_]\w*)(.*)$/.exec(s);
|
|
58
|
+
if (bare) {
|
|
59
|
+
const steps = [{ type: 'pipe', name: bare[1], args: [] }];
|
|
60
|
+
if (bare[2])
|
|
61
|
+
steps.push(...parseFieldChain(bare[2]));
|
|
62
|
+
return steps;
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
function parseFieldChain(s) {
|
|
67
|
+
const steps = [];
|
|
68
|
+
let rest = s;
|
|
69
|
+
while (rest) {
|
|
70
|
+
const m = /^\.([a-zA-Z_$]\w*)(.*)$/.exec(rest);
|
|
71
|
+
if (!m)
|
|
72
|
+
break;
|
|
73
|
+
steps.push({ type: 'field', name: m[1] });
|
|
74
|
+
rest = m[2];
|
|
75
|
+
}
|
|
76
|
+
return steps;
|
|
77
|
+
}
|
|
78
|
+
export function parseMapExpr(expr) {
|
|
79
|
+
const parts = expr.split('|').map(s => s.trim());
|
|
80
|
+
const steps = [];
|
|
81
|
+
for (const part of parts) {
|
|
82
|
+
steps.push(...parseSegment(part));
|
|
83
|
+
}
|
|
84
|
+
return { steps };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/bind/parse.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,qDAAqD;AACrD,yEAAyE;AACzE,EAAE;AACF,gBAAgB;AAChB,mDAAmD;AACnD,6EAA6E;AAC7E,uEAAuE;AAWvE,MAAM,UAAU,QAAQ,CAAC,GAAY;IACnC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC;AAClE,CAAC;AAED,MAAM,OAAO,GAAG,iCAAiC,CAAC;AAElD,SAAS,QAAQ,CAAC,CAAS;IACzB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAEnB,uDAAuD;IACvD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,yBAAyB;YACzB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,MAAM,KAAK,CAAC,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YACrD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACpF,CAAC;QACD,8BAA8B;QAC9B,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACnE,CAAC;IAED,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACrB,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,qDAAqD;IACrD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,qDAAqD;IACrD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,iDAAiD;IACjD,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,KAAK,GAAe,CAAC;gBACzB,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBACV,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;aAChD,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2EAA2E;IAC3E,MAAM,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5C,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,KAAK,GAAe,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,eAAe,CAAC,CAAS;IAChC,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,CAAC;YAAE,MAAM;QACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipes.d.ts","sourceRoot":"","sources":["../../src/bind/pipes.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAIrE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExD"}
|