sigmx 0.1.1 → 0.2.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 +10 -10
- package/dist/kernel/compile.d.ts +8 -9
- package/dist/kernel/compile.js +102 -67
- package/dist/kernel/compile.js.map +2 -2
- package/dist/kernel/contracts.d.ts +11 -5
- package/dist/kernel/index.d.ts +2 -2
- package/dist/kernel/index.js +5 -6
- package/dist/kernel/index.js.map +2 -2
- package/dist/kernel/precompile.d.ts +8 -10
- package/dist/kernel/precompile.js +25 -75
- package/dist/kernel/precompile.js.map +2 -2
- package/dist/kernel/precompiled.d.ts +7 -4
- package/dist/kernel/precompiled.js +5 -5
- package/dist/kernel/precompiled.js.map +2 -2
- package/dist/kernel/reactive.d.ts +8 -2
- package/dist/kernel/reactive.js +91 -62
- package/dist/kernel/reactive.js.map +3 -3
- package/dist/kernel/runtime.js +78 -68
- package/dist/kernel/runtime.js.map +3 -3
- package/dist/kernel/scan.d.ts +1 -1
- package/dist/kernel/scan.js +3 -3
- package/dist/kernel/scan.js.map +2 -2
- package/dist/kernel/state.d.ts +4 -3
- package/dist/kernel/state.js +91 -80
- package/dist/kernel/state.js.map +2 -2
- package/dist/kernel/strict-csp.d.ts +0 -5
- package/dist/kernel/strict-csp.js +2 -2
- package/dist/kernel/strict-csp.js.map +2 -2
- package/dist/lib/casing.d.ts +4 -1
- package/dist/lib/casing.js +8 -1
- package/dist/lib/casing.js.map +2 -2
- package/dist/lib/objects.d.ts +5 -3
- package/dist/lib/objects.js +10 -5
- package/dist/lib/objects.js.map +2 -2
- package/dist/lib/schedule.d.ts +3 -3
- package/dist/lib/schedule.js +12 -10
- package/dist/lib/schedule.js.map +2 -2
- package/dist/lib/sse.d.ts +10 -0
- package/dist/lib/sse.js +32 -29
- package/dist/lib/sse.js.map +2 -2
- package/dist/plugins/def.d.ts +5 -0
- package/dist/plugins/def.js +22 -0
- package/dist/plugins/def.js.map +7 -0
- package/dist/plugins/directives/attribute-sync.js +8 -12
- package/dist/plugins/directives/attribute-sync.js.map +2 -2
- package/dist/plugins/directives/boost.d.ts +1 -1
- package/dist/plugins/directives/boost.js +34 -31
- package/dist/plugins/directives/boost.js.map +2 -2
- package/dist/plugins/directives/busy-flag.js +13 -16
- package/dist/plugins/directives/busy-flag.js.map +2 -2
- package/dist/plugins/directives/class-toggle.js +17 -16
- package/dist/plugins/directives/class-toggle.js.map +2 -2
- package/dist/plugins/directives/cloak.js +2 -7
- package/dist/plugins/directives/cloak.js.map +2 -2
- package/dist/plugins/directives/collapse.js +36 -37
- package/dist/plugins/directives/collapse.js.map +2 -2
- package/dist/plugins/directives/declare.js +5 -8
- package/dist/plugins/directives/declare.js.map +2 -2
- package/dist/plugins/directives/derive.js +9 -18
- package/dist/plugins/directives/derive.js.map +2 -2
- package/dist/plugins/directives/element-ref.js +8 -8
- package/dist/plugins/directives/element-ref.js.map +2 -2
- package/dist/plugins/directives/event-listener.js +18 -26
- package/dist/plugins/directives/event-listener.js.map +2 -2
- package/dist/plugins/directives/frame-loop.js +9 -14
- package/dist/plugins/directives/frame-loop.js.map +2 -2
- package/dist/plugins/directives/html.js +6 -7
- package/dist/plugins/directives/html.js.map +2 -2
- package/dist/plugins/directives/inline-style.js +17 -20
- package/dist/plugins/directives/inline-style.js.map +2 -2
- package/dist/plugins/directives/mask.js +19 -23
- package/dist/plugins/directives/mask.js.map +2 -2
- package/dist/plugins/directives/media-query.d.ts +4 -1
- package/dist/plugins/directives/media-query.js +13 -13
- package/dist/plugins/directives/media-query.js.map +2 -2
- package/dist/plugins/directives/on-mount.js +4 -12
- package/dist/plugins/directives/on-mount.js.map +2 -2
- package/dist/plugins/directives/patch-listener.js +24 -19
- package/dist/plugins/directives/patch-listener.js.map +2 -2
- package/dist/plugins/directives/remove-me.js +7 -8
- package/dist/plugins/directives/remove-me.js.map +2 -2
- package/dist/plugins/directives/scroll-to.d.ts +4 -1
- package/dist/plugins/directives/scroll-to.js +8 -14
- package/dist/plugins/directives/scroll-to.js.map +2 -2
- package/dist/plugins/directives/size-watch.js +7 -12
- package/dist/plugins/directives/size-watch.js.map +2 -2
- package/dist/plugins/directives/state-dump.js +6 -10
- package/dist/plugins/directives/state-dump.js.map +2 -2
- package/dist/plugins/directives/storage-sync.js +13 -9
- package/dist/plugins/directives/storage-sync.js.map +2 -2
- package/dist/plugins/directives/teleport.js +8 -14
- package/dist/plugins/directives/teleport.js.map +2 -2
- package/dist/plugins/directives/text-content.js +6 -7
- package/dist/plugins/directives/text-content.js.map +2 -2
- package/dist/plugins/directives/timer.js +7 -13
- package/dist/plugins/directives/timer.js.map +2 -2
- package/dist/plugins/directives/transition.d.ts +1 -2
- package/dist/plugins/directives/transition.js +32 -34
- package/dist/plugins/directives/transition.js.map +2 -2
- package/dist/plugins/directives/tween.d.ts +2 -2
- package/dist/plugins/directives/tween.js +34 -50
- package/dist/plugins/directives/tween.js.map +2 -2
- package/dist/plugins/directives/two-way-bind.d.ts +1 -1
- package/dist/plugins/directives/two-way-bind.js +70 -97
- package/dist/plugins/directives/two-way-bind.js.map +2 -2
- package/dist/plugins/directives/url-params.js +35 -59
- package/dist/plugins/directives/url-params.js.map +3 -3
- package/dist/plugins/directives/url-replace.js +6 -7
- package/dist/plugins/directives/url-replace.js.map +2 -2
- package/dist/plugins/directives/validity.js +6 -9
- package/dist/plugins/directives/validity.js.map +2 -2
- package/dist/plugins/directives/viewport.js +18 -26
- package/dist/plugins/directives/viewport.js.map +2 -2
- package/dist/plugins/directives/visibility.js +9 -14
- package/dist/plugins/directives/visibility.js.map +2 -2
- package/dist/plugins/directives/watch.js +2 -8
- package/dist/plugins/directives/watch.js.map +2 -2
- package/dist/plugins/functions/bulk-set.js +7 -6
- package/dist/plugins/functions/bulk-set.js.map +2 -2
- package/dist/plugins/functions/bulk-toggle.js +7 -6
- package/dist/plugins/functions/bulk-toggle.js.map +2 -2
- package/dist/plugins/functions/confirm.js +2 -2
- package/dist/plugins/functions/confirm.js.map +2 -2
- package/dist/plugins/functions/copy-text.js +5 -5
- package/dist/plugins/functions/copy-text.js.map +2 -2
- package/dist/plugins/functions/dispatch.js +5 -5
- package/dist/plugins/functions/dispatch.js.map +2 -2
- package/dist/plugins/functions/locale-format.d.ts +4 -1
- package/dist/plugins/functions/locale-format.js +9 -16
- package/dist/plugins/functions/locale-format.js.map +2 -2
- package/dist/plugins/functions/range-map.js +6 -6
- package/dist/plugins/functions/range-map.js.map +2 -2
- package/dist/plugins/functions/request.d.ts +7 -3
- package/dist/plugins/functions/request.js +77 -86
- package/dist/plugins/functions/request.js.map +2 -2
- package/dist/plugins/functions/untracked-read.js +3 -2
- package/dist/plugins/functions/untracked-read.js.map +2 -2
- package/dist/plugins/functions/websocket.d.ts +3 -3
- package/dist/plugins/functions/websocket.js +13 -24
- package/dist/plugins/functions/websocket.js.map +2 -2
- package/dist/plugins/index.d.ts +0 -2
- package/dist/plugins/index.js +0 -4
- package/dist/plugins/index.js.map +2 -2
- package/dist/plugins/server-events/apply-elements.d.ts +1 -1
- package/dist/plugins/server-events/apply-elements.js +41 -43
- package/dist/plugins/server-events/apply-elements.js.map +2 -2
- package/dist/plugins/server-events/apply-state.js +9 -12
- package/dist/plugins/server-events/apply-state.js.map +2 -2
- package/dist/plugins/server-events/morph.js +46 -66
- package/dist/plugins/server-events/morph.js.map +3 -3
- package/dist/presets/all.js +0 -4
- package/dist/presets/all.js.map +2 -2
- package/dist/server.d.ts +10 -4
- package/dist/server.js +42 -14
- package/dist/server.js.map +2 -2
- package/dist/sigmx.standalone.js +1 -1
- package/dist/vite.js +17 -7
- package/dist/vite.js.map +2 -2
- package/package.json +4 -2
- package/dist/plugins/directives/transition-name.d.ts +0 -1
- package/dist/plugins/directives/transition-name.js +0 -11
- package/dist/plugins/directives/transition-name.js.map +0 -7
- package/dist/plugins/directives/trap.d.ts +0 -5
- package/dist/plugins/directives/trap.js +0 -54
- package/dist/plugins/directives/trap.js.map +0 -7
package/dist/kernel/runtime.js
CHANGED
|
@@ -1,66 +1,59 @@
|
|
|
1
1
|
import { recase } from "../lib/casing.js";
|
|
2
2
|
import { functionCompiler } from "./compile.js";
|
|
3
|
-
import {
|
|
3
|
+
import { rootEffect } from "./reactive.js";
|
|
4
4
|
import { createStore } from "./state.js";
|
|
5
5
|
const isEl = (n) => n.nodeType === 1;
|
|
6
|
-
const tree = (n) => isEl(n) ? [n
|
|
7
|
-
const parsed = /* @__PURE__ */ new Map();
|
|
6
|
+
const tree = (n) => n.querySelectorAll ? [...isEl(n) ? [n] : [], ...n.querySelectorAll("*")] : [];
|
|
8
7
|
const parseAttr = (raw) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
8
|
+
const [head, ...modParts] = raw.split("__");
|
|
9
|
+
const [, plugin, key] = /^([^:]*)(?::(.*))?$/.exec(head);
|
|
10
|
+
return {
|
|
11
|
+
plugin,
|
|
12
|
+
key,
|
|
13
|
+
mods: new Map(
|
|
14
|
+
modParts.map((m) => {
|
|
15
|
+
const [name, ...args] = m.split(".");
|
|
16
|
+
return [name, args];
|
|
17
|
+
})
|
|
18
|
+
)
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const cut = (list, s) => {
|
|
22
|
+
for (const p of list) if (s.startsWith(p)) return s.slice(p.length);
|
|
22
23
|
};
|
|
23
|
-
const fail = (message, info) => Object.assign(new Error(message), { info });
|
|
24
24
|
const createRuntime = (options) => {
|
|
25
25
|
const prefixes = [].concat(options.prefix ?? "data-");
|
|
26
26
|
const eventPrefixes = [].concat(options.eventPrefix ?? "sigmx-");
|
|
27
27
|
const store = options.store ?? createStore();
|
|
28
|
-
const compiler = options.compile ?? functionCompiler;
|
|
29
28
|
const { expressions } = options;
|
|
30
29
|
const onError = options.onError ?? ((e, info) => console.error(e, info));
|
|
31
30
|
const attributes = /* @__PURE__ */ Object.create(null);
|
|
32
|
-
const actions = /* @__PURE__ */ Object.create(null);
|
|
33
|
-
const handlers = /* @__PURE__ */ Object.create(null);
|
|
34
31
|
const runtime = {
|
|
35
32
|
prefixes,
|
|
36
33
|
attr: (name) => prefixes[0] + name,
|
|
37
34
|
store,
|
|
38
|
-
compiler,
|
|
35
|
+
compiler: options.compile ?? functionCompiler,
|
|
39
36
|
emit: (type, detail) => document.dispatchEvent(new CustomEvent(`sigmx-${type}`, { detail })),
|
|
40
37
|
call: (name, ctx, args) => {
|
|
41
|
-
const a = actions[name];
|
|
38
|
+
const a = runtime.actions[name];
|
|
42
39
|
if (!a) throw ctx.error(`unknown action @${name}`);
|
|
43
40
|
return a.call(ctx, ...args);
|
|
44
41
|
},
|
|
45
42
|
eventPrefixes,
|
|
46
43
|
handle: (event, data) => {
|
|
47
|
-
const
|
|
48
|
-
const h = handlers[p ? event.slice(p.length) : event];
|
|
44
|
+
const h = runtime.handlers[cut(eventPrefixes, event) ?? event];
|
|
49
45
|
h?.handle(runtime, data);
|
|
50
46
|
return !!h;
|
|
51
47
|
},
|
|
52
48
|
attributes,
|
|
53
|
-
actions,
|
|
54
|
-
handlers
|
|
49
|
+
actions: /* @__PURE__ */ Object.create(null),
|
|
50
|
+
handlers: /* @__PURE__ */ Object.create(null)
|
|
55
51
|
};
|
|
56
52
|
const mounted = /* @__PURE__ */ new Map();
|
|
57
53
|
const roots = /* @__PURE__ */ new Set();
|
|
58
|
-
const ignoreSelf = prefixes.map((p) => `[${p}ignore__self]`).join();
|
|
59
54
|
const ignoreAny = prefixes.map((p) => `[${p}ignore]`).join();
|
|
60
|
-
const ignored = (el) =>
|
|
61
|
-
|
|
62
|
-
for (const p of prefixes) if (attr.startsWith(p)) return attr.slice(p.length);
|
|
63
|
-
};
|
|
55
|
+
const ignored = (el) => !!el.closest(ignoreAny);
|
|
56
|
+
let destroyed = false;
|
|
64
57
|
const unmount = (els) => {
|
|
65
58
|
for (const el of els) {
|
|
66
59
|
const m = mounted.get(el);
|
|
@@ -72,29 +65,30 @@ const createRuntime = (options) => {
|
|
|
72
65
|
m?.get(attr)?.();
|
|
73
66
|
m?.delete(attr);
|
|
74
67
|
};
|
|
75
|
-
const actionsFor = (el, evt, error, cleanup, report) => {
|
|
76
|
-
const ctx = { el, evt, store, runtime, error, cleanup };
|
|
77
|
-
return new Proxy(
|
|
78
|
-
{},
|
|
79
|
-
{
|
|
80
|
-
get: (_, name) => (...args) => {
|
|
81
|
-
const r = runtime.call(name, ctx, args);
|
|
82
|
-
if (r instanceof Promise) r.catch(report);
|
|
83
|
-
return r;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
);
|
|
87
|
-
};
|
|
88
68
|
const mount = (el, attr, raw, value, only) => {
|
|
89
69
|
const { plugin: name, key, mods } = parseAttr(raw);
|
|
90
70
|
const plugin = attributes[name];
|
|
91
71
|
if (!plugin || only && !only.has(name)) return;
|
|
92
72
|
unmountAttr(el, attr);
|
|
93
73
|
const disposers = [];
|
|
74
|
+
const cleanup = (f) => {
|
|
75
|
+
disposers.push(f);
|
|
76
|
+
return () => {
|
|
77
|
+
const i = disposers.indexOf(f);
|
|
78
|
+
if (i >= 0) disposers.splice(i, 1);
|
|
79
|
+
};
|
|
80
|
+
};
|
|
94
81
|
const info = { plugin: name, el, attr };
|
|
95
|
-
const error = (message, extra) =>
|
|
82
|
+
const error = (message, extra) => Object.assign(new Error(`${prefixes[0]}${name}: ${message}`), { info: { ...info, ...extra } });
|
|
96
83
|
const report = (e) => onError(e, info);
|
|
97
84
|
let fn;
|
|
85
|
+
const watched = /* @__PURE__ */ new WeakSet();
|
|
86
|
+
const watch = (r) => {
|
|
87
|
+
if (r instanceof Promise && !watched.has(r)) {
|
|
88
|
+
watched.add(r);
|
|
89
|
+
r.catch(report);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
98
92
|
const ctx = {
|
|
99
93
|
el,
|
|
100
94
|
plugin: name,
|
|
@@ -104,10 +98,27 @@ const createRuntime = (options) => {
|
|
|
104
98
|
mods,
|
|
105
99
|
cased: (style = "camel") => recase(key ?? "", mods.get("case")?.[0] || style),
|
|
106
100
|
evaluate: (evt, ...args) => {
|
|
107
|
-
|
|
108
|
-
|
|
101
|
+
if (plugin.literal && !mods.has("dynamic")) return value;
|
|
102
|
+
fn ??= expressions(value, ["el", "evt", ...plugin.args ?? []]);
|
|
103
|
+
const actx = { el, evt, store, runtime, error, cleanup, report };
|
|
104
|
+
const actions = new Proxy(
|
|
105
|
+
{},
|
|
106
|
+
{
|
|
107
|
+
get: (_, name2) => (...args2) => {
|
|
108
|
+
const r2 = runtime.call(name2, actx, args2);
|
|
109
|
+
watch(r2);
|
|
110
|
+
return r2;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
const r = fn(store, actions, el, evt, ...args);
|
|
115
|
+
watch(r);
|
|
116
|
+
return r;
|
|
117
|
+
},
|
|
118
|
+
// Root-owned: an attribute mounted from inside another effect must outlive that effect's re-runs.
|
|
119
|
+
effect: (f) => {
|
|
120
|
+
cleanup(rootEffect(f, report));
|
|
109
121
|
},
|
|
110
|
-
effect: (f) => disposers.push(effect(f, report)),
|
|
111
122
|
listen: (target, type, f, opts) => {
|
|
112
123
|
const h = (e) => {
|
|
113
124
|
try {
|
|
@@ -117,10 +128,11 @@ const createRuntime = (options) => {
|
|
|
117
128
|
}
|
|
118
129
|
};
|
|
119
130
|
target.addEventListener(type, h, opts);
|
|
120
|
-
|
|
131
|
+
cleanup(() => target.removeEventListener(type, h, opts));
|
|
121
132
|
},
|
|
122
|
-
cleanup
|
|
133
|
+
cleanup,
|
|
123
134
|
error,
|
|
135
|
+
report,
|
|
124
136
|
store,
|
|
125
137
|
runtime
|
|
126
138
|
};
|
|
@@ -133,12 +145,16 @@ const createRuntime = (options) => {
|
|
|
133
145
|
for (const d of disposers.splice(0)) d();
|
|
134
146
|
});
|
|
135
147
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
148
|
+
for (const [k, v] of [
|
|
149
|
+
["key", key],
|
|
150
|
+
["value", value]
|
|
151
|
+
]) {
|
|
152
|
+
const rule = plugin[k];
|
|
153
|
+
if (rule && rule === "required" === !v) throw error(`${rule === "required" ? "needs a" : "takes no"} ${k}`);
|
|
154
|
+
}
|
|
140
155
|
const r = plugin.mount(ctx);
|
|
141
|
-
if (typeof r === "function")
|
|
156
|
+
if (typeof r === "function") cleanup(r);
|
|
157
|
+
else watch(r);
|
|
142
158
|
} catch (e) {
|
|
143
159
|
report(e);
|
|
144
160
|
}
|
|
@@ -147,7 +163,7 @@ const createRuntime = (options) => {
|
|
|
147
163
|
for (const el of els) {
|
|
148
164
|
if (ignored(el)) continue;
|
|
149
165
|
for (const { name, value } of [...el.attributes]) {
|
|
150
|
-
const raw =
|
|
166
|
+
const raw = cut(prefixes, name);
|
|
151
167
|
if (raw && !mounted.get(el)?.has(name)) mount(el, name, raw, value, only);
|
|
152
168
|
}
|
|
153
169
|
}
|
|
@@ -155,10 +171,10 @@ const createRuntime = (options) => {
|
|
|
155
171
|
const observer = new MutationObserver((records) => {
|
|
156
172
|
for (const { type, target, attributeName, addedNodes, removedNodes } of records) {
|
|
157
173
|
if (type === "childList") {
|
|
158
|
-
for (const n of removedNodes) unmount(tree(n));
|
|
174
|
+
for (const n of removedNodes) if (!n.isConnected) unmount(tree(n));
|
|
159
175
|
for (const n of addedNodes) mountEls(tree(n));
|
|
160
176
|
} else if (attributeName && isEl(target) && !ignored(target)) {
|
|
161
|
-
const raw =
|
|
177
|
+
const raw = cut(prefixes, attributeName);
|
|
162
178
|
if (!raw) continue;
|
|
163
179
|
const value = target.getAttribute(attributeName);
|
|
164
180
|
if (value === null) unmountAttr(target, attributeName);
|
|
@@ -166,26 +182,19 @@ const createRuntime = (options) => {
|
|
|
166
182
|
}
|
|
167
183
|
}
|
|
168
184
|
});
|
|
169
|
-
let ready = false;
|
|
170
185
|
const apply = (root = document.documentElement, observe = true, only) => {
|
|
186
|
+
if (destroyed) return;
|
|
171
187
|
mountEls(tree(root), only);
|
|
172
188
|
if (observe && !roots.has(root)) {
|
|
173
189
|
observer.observe(root, { subtree: true, childList: true, attributes: true });
|
|
174
190
|
roots.add(root);
|
|
175
191
|
}
|
|
176
|
-
if (!ready && roots.has(document.documentElement)) {
|
|
177
|
-
ready = true;
|
|
178
|
-
runtime.emit("ready");
|
|
179
|
-
}
|
|
180
192
|
};
|
|
181
193
|
const use = (...plugins) => {
|
|
182
194
|
const added = /* @__PURE__ */ new Set();
|
|
183
195
|
for (const p of plugins) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
added.add(p.name);
|
|
187
|
-
} else if (p.type === "action") actions[p.name] = p;
|
|
188
|
-
else handlers[p.name] = p;
|
|
196
|
+
runtime[`${p.type}s`][p.name] = p;
|
|
197
|
+
if (p.type === "attribute") added.add(p.name);
|
|
189
198
|
}
|
|
190
199
|
if (added.size) for (const r of roots) apply(r, false, added);
|
|
191
200
|
};
|
|
@@ -200,6 +209,7 @@ const createRuntime = (options) => {
|
|
|
200
209
|
apply: (root, observe) => apply(root, observe),
|
|
201
210
|
use,
|
|
202
211
|
destroy: () => {
|
|
212
|
+
destroyed = true;
|
|
203
213
|
observer.disconnect();
|
|
204
214
|
stopPatches();
|
|
205
215
|
unmount([...mounted.keys()]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/runtime.ts"],
|
|
4
|
-
"sourcesContent": ["import { type CaseStyle, recase } from '../lib/casing.js';\nimport { functionCompiler } from './compile.js';\nimport type {\n ActionCtx,\n AttributePlugin,\n Ctx,\n El,\n Evaluator,\n Mods,\n Plugin,\n Runtime,\n RuntimeOptions,\n Sigmx,\n} from './contracts.js';\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAyB,cAAc;AACvC,SAAS,wBAAwB;AAajC,SAAS,
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["import { type CaseStyle, recase } from '../lib/casing.js';\nimport { functionCompiler } from './compile.js';\nimport type {\n ActionCtx,\n AttributePlugin,\n Ctx,\n El,\n Evaluator,\n Mods,\n Plugin,\n Runtime,\n RuntimeOptions,\n Sigmx,\n} from './contracts.js';\nimport { rootEffect } from './reactive.js';\nimport { createStore } from './state.js';\n\nconst isEl = (n: Node): n is El => n.nodeType === 1;\n/** An element (or shadow root) followed by every element under it; nothing for text and comment nodes. */\nconst tree = (n: Node): El[] =>\n (n as ParentNode).querySelectorAll ? [...(isEl(n) ? [n] : []), ...(n as ParentNode).querySelectorAll<El>('*')] : [];\n\ntype Parsed = { plugin: string; key: string | undefined; mods: Mods };\n\n/** 'on:click__debounce.300ms__prevent' \u2192 { plugin: 'on', key: 'click', mods: {debounce: ['300ms'], prevent: []} } */\nexport const parseAttr = (raw: string): Parsed => {\n const [head, ...modParts] = raw.split('__');\n const [, plugin, key] = /^([^:]*)(?::(.*))?$/.exec(head) as string[];\n return {\n plugin,\n key,\n mods: new Map(\n modParts.map((m) => {\n const [name, ...args] = m.split('.');\n return [name, args];\n }),\n ),\n };\n};\n\n/** The rest of `s` after the first prefix in `list` that it starts with; undefined when none matches. */\nconst cut = (list: readonly string[], s: string): string | undefined => {\n for (const p of list) if (s.startsWith(p)) return s.slice(p.length);\n};\n\n/** Low-level constructor: you supply the expression pipeline. `createSigmx` wraps it with the runtime compiler. */\nexport const createRuntime = (options: RuntimeOptions): Sigmx => {\n const prefixes = ([] as string[]).concat(options.prefix ?? 'data-');\n const eventPrefixes = ([] as string[]).concat(options.eventPrefix ?? 'sigmx-');\n const store = options.store ?? createStore();\n const { expressions } = options;\n const onError = options.onError ?? ((e, info) => console.error(e, info));\n const attributes: Record<string, AttributePlugin> = Object.create(null);\n\n const runtime: Runtime = {\n prefixes,\n attr: (name) => prefixes[0] + name,\n store,\n compiler: options.compile ?? functionCompiler,\n emit: (type, detail) => document.dispatchEvent(new CustomEvent(`sigmx-${type}`, { detail })),\n call: (name, ctx, args) => {\n const a = runtime.actions[name];\n if (!a) throw ctx.error(`unknown action @${name}`);\n return a.call(ctx, ...args);\n },\n eventPrefixes,\n handle: (event, data) => {\n const h = runtime.handlers[cut(eventPrefixes, event) ?? event];\n h?.handle(runtime, data);\n return !!h;\n },\n attributes,\n actions: Object.create(null),\n handlers: Object.create(null),\n };\n\n // element \u2192 attribute name \u2192 dispose\n const mounted = new Map<El, Map<string, () => void>>();\n const roots = new Set<El | ShadowRoot>();\n const ignoreAny = prefixes.map((p) => `[${p}ignore]`).join();\n const ignored = (el: El) => !!el.closest(ignoreAny);\n let destroyed = false;\n\n const unmount = (els: Iterable<El>): void => {\n for (const el of els) {\n const m = mounted.get(el);\n if (m && mounted.delete(el)) for (const d of m.values()) d();\n }\n };\n\n const unmountAttr = (el: El, attr: string): void => {\n const m = mounted.get(el);\n m?.get(attr)?.();\n m?.delete(attr);\n };\n\n const mount = (el: El, attr: string, raw: string, value: string, only?: Set<string>): void => {\n const { plugin: name, key, mods } = parseAttr(raw);\n const plugin = attributes[name];\n if (!plugin || (only && !only.has(name))) return;\n unmountAttr(el, attr);\n\n const disposers: (() => void)[] = [];\n const cleanup = (f: () => void) => {\n disposers.push(f);\n return () => {\n const i = disposers.indexOf(f);\n if (i >= 0) disposers.splice(i, 1);\n };\n };\n const info = { plugin: name, el, attr };\n const error: Ctx['error'] = (message, extra) =>\n Object.assign(new Error(`${prefixes[0]}${name}: ${message}`), { info: { ...info, ...extra } });\n const report = (e: unknown) => onError(e, info);\n let fn: Evaluator | undefined;\n const watched = new WeakSet<Promise<unknown>>(); // promises already routed to onError\n const watch = (r: unknown) => {\n if (r instanceof Promise && !watched.has(r)) {\n watched.add(r);\n r.catch(report);\n }\n };\n const ctx: Ctx = {\n el,\n plugin: name,\n attr,\n key,\n value,\n mods,\n cased: (style = 'camel') => recase(key ?? '', (mods.get('case')?.[0] as CaseStyle) || style),\n evaluate: (evt, ...args) => {\n if (plugin.literal && !mods.has('dynamic')) return value;\n fn ??= expressions(value, ['el', 'evt', ...(plugin.args ?? [])]);\n const actx: ActionCtx = { el, evt, store, runtime, error, cleanup, report };\n const actions = new Proxy(\n {},\n {\n get:\n (_, name: string) =>\n (...args: any[]) => {\n const r = runtime.call(name, actx, args);\n watch(r); // async actions (requests) reject long after the expression returned\n return r;\n },\n },\n );\n const r = fn(store, actions, el, evt, ...args);\n watch(r); // an expression's own rejected promise is reported too, once\n return r;\n },\n // Root-owned: an attribute mounted from inside another effect must outlive that effect's re-runs.\n effect: (f) => {\n cleanup(rootEffect(f, report));\n },\n listen: (target, type, f, opts) => {\n const h = (e: Event) => {\n try {\n f(e);\n } catch (err) {\n report(err);\n }\n };\n target.addEventListener(type, h, opts);\n cleanup(() => target.removeEventListener(type, h, opts));\n },\n cleanup,\n error,\n report,\n store,\n runtime,\n };\n\n let m = mounted.get(el);\n if (!m) {\n m = new Map();\n mounted.set(el, m);\n }\n m.set(attr, () => {\n for (const d of disposers.splice(0)) d();\n });\n\n try {\n // Contract checks: a keyed directive without a key would otherwise write to the path ''.\n for (const [k, v] of [\n ['key', key],\n ['value', value],\n ] as const) {\n const rule = plugin[k];\n if (rule && (rule === 'required') === !v) throw error(`${rule === 'required' ? 'needs a' : 'takes no'} ${k}`);\n }\n const r: unknown = plugin.mount(ctx);\n if (typeof r === 'function') cleanup(r as () => void);\n else watch(r); // an async mount that rejects is reported, not lost\n } catch (e) {\n report(e);\n }\n };\n\n const mountEls = (els: Iterable<El>, only?: Set<string>): void => {\n for (const el of els) {\n if (ignored(el)) continue;\n for (const { name, value } of [...el.attributes]) {\n const raw = cut(prefixes, name);\n // Observers can report a subtree more than once (nested insertions); a mounted attribute stays as it is.\n if (raw && !mounted.get(el)?.has(name)) mount(el, name, raw, value, only);\n }\n }\n };\n\n const observer = new MutationObserver((records) => {\n for (const { type, target, attributeName, addedNodes, removedNodes } of records) {\n if (type === 'childList') {\n // A node that is still connected was moved (teleport, morph), not removed: it keeps its state.\n for (const n of removedNodes) if (!n.isConnected) unmount(tree(n));\n for (const n of addedNodes) mountEls(tree(n));\n } else if (attributeName && isEl(target) && !ignored(target)) {\n const raw = cut(prefixes, attributeName);\n if (!raw) continue;\n const value = target.getAttribute(attributeName);\n if (value === null) unmountAttr(target, attributeName);\n else mount(target, attributeName, raw, value);\n }\n }\n });\n\n const apply = (root: El | ShadowRoot = document.documentElement, observe = true, only?: Set<string>) => {\n if (destroyed) return;\n mountEls(tree(root), only);\n if (observe && !roots.has(root)) {\n observer.observe(root, { subtree: true, childList: true, attributes: true });\n roots.add(root);\n }\n };\n\n const use = (...plugins: Plugin[]): void => {\n const added = new Set<string>();\n for (const p of plugins) {\n (runtime as any)[`${p.type}s`][p.name] = p;\n if (p.type === 'attribute') added.add(p.name);\n }\n if (added.size) for (const r of roots) apply(r, false, added);\n };\n\n const stopPatches = store.onPatch((patch) => runtime.emit('signal-patch', patch));\n use(...(options.plugins ?? []));\n\n const sigmx: Sigmx = {\n runtime,\n store,\n get $() {\n return store.$;\n },\n apply: (root, observe) => apply(root, observe),\n use,\n destroy: () => {\n destroyed = true;\n observer.disconnect();\n stopPatches();\n unmount([...mounted.keys()]);\n roots.clear();\n },\n };\n\n if (options.autoStart ?? true) {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => sigmx.apply(), { once: true });\n } else {\n sigmx.apply();\n }\n }\n return sigmx;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["name", "args", "r"]
|
|
7
7
|
}
|
package/dist/kernel/scan.d.ts
CHANGED
package/dist/kernel/scan.js
CHANGED
|
@@ -11,7 +11,7 @@ const builtinPlugins = () => Object.entries(builtins).filter(([, v]) => v && typ
|
|
|
11
11
|
name: p.name,
|
|
12
12
|
type: p.type,
|
|
13
13
|
from: "sigmx/plugins",
|
|
14
|
-
|
|
14
|
+
literal: p.literal,
|
|
15
15
|
args: p.args
|
|
16
16
|
};
|
|
17
17
|
});
|
|
@@ -25,14 +25,14 @@ const customPluginMeta = (exportName, source, from) => {
|
|
|
25
25
|
const body = m[2];
|
|
26
26
|
const name = /\bname\s*:\s*['"`]([^'"`]+)['"`]/.exec(body)?.[1];
|
|
27
27
|
if (!name) return;
|
|
28
|
-
const
|
|
28
|
+
const literal = /\bliteral\s*:\s*true/.test(body);
|
|
29
29
|
const args = /\bargs\s*:\s*\[([^\]]*)\]/.exec(body)?.[1];
|
|
30
30
|
return {
|
|
31
31
|
export: exportName,
|
|
32
32
|
name,
|
|
33
33
|
type: m[1],
|
|
34
34
|
from,
|
|
35
|
-
|
|
35
|
+
literal: literal || void 0,
|
|
36
36
|
args: args?.split(",").map((s) => s.trim().replace(/^['"`]|['"`]$/g, "")).filter(Boolean)
|
|
37
37
|
};
|
|
38
38
|
};
|
package/dist/kernel/scan.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/kernel/scan.ts"],
|
|
4
|
-
"sourcesContent": ["// Node only; never bundled for the browser.\nimport * as builtins from '../plugins/index.js';\nimport type { Plugin } from './contracts.js';\n\nexport type PluginMeta = {\n export: string;\n name: string;\n type: Plugin['type'];\n from: string;\n
|
|
5
|
-
"mappings": "AACA,YAAY,cAAc;AAY1B,MAAM,UAAU,CAAC,WAAW,YAAY,WAAW,aAAa,cAAc,aAAa,OAAO;AAE3F,MAAM,UAAoC;AAAA,EAC/C,GAAG,OAAO,YAAY,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,YAAY,CAAC,CAAC,CAAC;AAAA,EAC9E,OAAO,CAAC,WAAW,YAAY,iBAAiB,YAAY;AAC9D;AAEO,MAAM,iBAAiB,MAC5B,OAAO,QAAQ,QAAQ,EACpB,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,KAAK,OAAO,MAAM,YAAY,UAAW,CAAY,EACvE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM;AACjB,QAAM,IAAI;AACV,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM,EAAE;AAAA,IACR,MAAM,EAAE;AAAA,IACR,MAAM;AAAA,IACN,SAAU,EAAU;AAAA,IACpB,MAAO,EAAU;AAAA,EACnB;AACF,CAAC;AAME,MAAM,mBAAmB,CAAC,YAAoB,QAAgB,SAAyC;AAC5G,QAAM,KAAK,IAAI;AAAA,IACb,sBAAsB,UAAU;AAAA,IAChC;AAAA,EACF;AACA,QAAM,IAAI,GAAG,KAAK,MAAM;AACxB,MAAI,CAAC,EAAG;AACR,QAAM,OAAO,EAAE,CAAC;AAChB,QAAM,OAAO,mCAAmC,KAAK,IAAI,IAAI,CAAC;AAC9D,MAAI,CAAC,KAAM;AACX,QAAM,UAAU
|
|
4
|
+
"sourcesContent": ["// Node only; never bundled for the browser.\nimport * as builtins from '../plugins/index.js';\nimport type { Plugin } from './contracts.js';\n\nexport type PluginMeta = {\n export: string;\n name: string;\n type: Plugin['type'];\n from: string;\n literal?: boolean;\n args?: string[];\n};\n\nconst NETWORK = ['httpGet', 'httpPost', 'httpPut', 'httpPatch', 'httpDelete', 'websocket', 'boost'];\n\nexport const implied: Record<string, string[]> = {\n ...Object.fromEntries(NETWORK.map((n) => [n, ['applyElements', 'applyState']])),\n boost: ['httpGet', 'httpPost', 'applyElements', 'applyState'],\n};\n\nexport const builtinPlugins = (): PluginMeta[] =>\n Object.entries(builtins)\n .filter(([, v]) => v && typeof v === 'object' && 'type' in (v as object))\n .map(([key, v]) => {\n const p = v as Plugin;\n return {\n export: key,\n name: p.name,\n type: p.type,\n from: 'sigmx/plugins',\n literal: (p as any).literal,\n args: (p as any).args,\n };\n });\n\n/**\n * Read a custom plugin's metadata from its source without executing it: finds\n * `attribute({ name: 'x', ... })`, `action({...})` or `handler({...})` near `export const <exportName>`.\n */\nexport const customPluginMeta = (exportName: string, source: string, from: string): PluginMeta | undefined => {\n const re = new RegExp(\n `export\\\\s+const\\\\s+${exportName}\\\\s*(?::[^=]+)?=\\\\s*(attribute|action|handler)\\\\s*\\\\(\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*\\\\)`,\n 'm',\n );\n const m = re.exec(source);\n if (!m) return;\n const body = m[2];\n const name = /\\bname\\s*:\\s*['\"`]([^'\"`]+)['\"`]/.exec(body)?.[1];\n if (!name) return;\n const literal = /\\bliteral\\s*:\\s*true/.test(body);\n const args = /\\bargs\\s*:\\s*\\[([^\\]]*)\\]/.exec(body)?.[1];\n return {\n export: exportName,\n name,\n type: m[1] as Plugin['type'],\n from,\n literal: literal || undefined,\n args: args\n ?.split(',')\n .map((s) => s.trim().replace(/^['\"`]|['\"`]$/g, ''))\n .filter(Boolean),\n };\n};\n\nconst esc = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** True if `source` refers to the plugin: `data-<name>` for directives, `@name(` for functions, the name as a string for handlers. */\nexport const mentions = (source: string, p: PluginMeta, prefixes: string[]): boolean => {\n const n = esc(p.name);\n if (p.type === 'attribute')\n return prefixes.some((pre) => new RegExp(`(^|[\\\\s\"'\\`<])${esc(pre)}${n}(?=[\\\\s=:_>\"'\\`/]|$)`, 'm').test(source));\n if (p.type === 'action') return new RegExp(`@${n}\\\\s*\\\\(`).test(source);\n return new RegExp(`['\"\\`](?:[\\\\w-]+-)?${n}['\"\\`]`).test(source);\n};\n\nexport type Selection = {\n plugins: PluginMeta[];\n reasons: Record<string, string>;\n unused: string[];\n};\n\n/**\n * Decide which plugins to ship. `sources` are file contents; `custom` are extra plugins (from\n * `customPluginMeta`); `always` are export names that ship regardless.\n */\nexport const selectPlugins = (\n sources: string[],\n {\n prefixes = ['data-'],\n always = [],\n custom = [],\n }: { prefixes?: string[]; always?: string[]; custom?: PluginMeta[] } = {},\n): Selection => {\n const known = [...builtinPlugins(), ...custom];\n const byExport = new Map(known.map((p) => [p.export, p]));\n const reasons: Record<string, string> = {};\n const add = (exp: string, why: string) => {\n if (!byExport.has(exp) || reasons[exp]) return;\n reasons[exp] = why;\n for (const dep of implied[exp] ?? []) add(dep, exp);\n };\n for (const exp of always) add(exp, 'always');\n const text = sources.join('\\n');\n for (const p of known)\n if (!reasons[p.export] && (p.type !== 'handler' || custom.includes(p)) && mentions(text, p, prefixes))\n add(p.export, 'used');\n const plugins = known.filter((p) => reasons[p.export]);\n return { plugins, reasons, unused: known.filter((p) => !reasons[p.export]).map((p) => p.export) };\n};\n\nexport const generatePluginsModule = (sel: Selection): string => {\n const groups = new Map<string, string[]>();\n for (const p of sel.plugins) groups.set(p.from, [...(groups.get(p.from) ?? []), p.export]);\n const imports = [...groups]\n .map(([from, names]) => `import { ${names.join(', ')} } from ${JSON.stringify(from)}`)\n .join('\\n');\n return `${imports}\\nexport const plugins = [${sel.plugins.map((p) => p.export).join(', ')}]\\nexport const report = ${JSON.stringify({ reasons: sel.reasons, unused: sel.unused }, null, 2)}\\n`;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/kernel/state.d.ts
CHANGED
|
@@ -14,7 +14,10 @@ export interface Store {
|
|
|
14
14
|
remove(path: string): void;
|
|
15
15
|
has(path: string): boolean;
|
|
16
16
|
define(path: string, node: Signal<any>): void;
|
|
17
|
-
paths
|
|
17
|
+
/** Leaf paths, filtered; `computed: false` leaves out computed signals. */
|
|
18
|
+
paths(filter?: Filter, options?: {
|
|
19
|
+
computed?: boolean;
|
|
20
|
+
}): string[];
|
|
18
21
|
snapshot(filter?: Filter, options?: {
|
|
19
22
|
at?: string;
|
|
20
23
|
computed?: boolean;
|
|
@@ -22,7 +25,5 @@ export interface Store {
|
|
|
22
25
|
/** Called after each settled batch with the nested object of changed paths (null = removed). */
|
|
23
26
|
onPatch(fn: (patch: Patch) => void): () => void;
|
|
24
27
|
readonly $: any;
|
|
25
|
-
/** Identifier scope for compiled expressions: resolves `$count`, `$user`, and `$`. */
|
|
26
|
-
readonly scope: object;
|
|
27
28
|
}
|
|
28
29
|
export declare const createStore: () => Store;
|