@daz4126/helium 0.12.0 → 0.13.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/helium.js +39 -13
- package/package.json +1 -1
package/helium.js
CHANGED
|
@@ -3,9 +3,10 @@ const getEvent = el => ({form:"submit",input:"input",textarea:"input",select:"ch
|
|
|
3
3
|
const debounce=(f,d)=>{let t;return(...a)=>(clearTimeout(t),t=setTimeout(f,d,...a))}
|
|
4
4
|
|
|
5
5
|
export default function helium(data = {}) {
|
|
6
|
+
let initFn;
|
|
6
7
|
const he = (n,...a) => a.map(b => `|@${b}|data-he-${b}|`).join``.includes(`|${n.split('.')[0]}|`);
|
|
7
8
|
const root = document.querySelector("[\\@helium]") || document.querySelector("[data-helium]") || document.body;
|
|
8
|
-
const [bindings, refs, listeners] = [new Map(), new Map(), new WeakMap()];
|
|
9
|
+
const [bindings, refs, listeners, processed] = [new Map(), new Map(), new WeakMap(), new WeakSet()];
|
|
9
10
|
const $ = s => document.querySelector(s);
|
|
10
11
|
const html = s => Object.assign(document.createElement("template"),{innerHTML:s.trim()}).content.firstChild
|
|
11
12
|
|
|
@@ -27,9 +28,16 @@ const ajax = (u,m,o={},p={}) => {
|
|
|
27
28
|
...(!fd&&m!=="GET"&&{"Content-Type":"application/json"}),
|
|
28
29
|
...(t&&{"X-CSRF-Token":t})
|
|
29
30
|
},body:m==="GET"?null:(fd?p:JSON.stringify(p)),credentials:"same-origin"})
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
.then(r => {
|
|
32
|
+
const type = r.headers.get("content-type") || "";
|
|
33
|
+
return (type.includes("turbo-stream") ? r.text().then(d => ({ t: true, d })) :
|
|
34
|
+
type.includes("json") ? r.json() :
|
|
35
|
+
r.text());
|
|
36
|
+
}).then(d =>
|
|
37
|
+
d.t && "Turbo"
|
|
38
|
+
? Turbo.renderStreamMessage(d.d)
|
|
39
|
+
: update(d, o.target, o.loading ? "replace" : o.action, o.template)
|
|
40
|
+
).catch(e => console.error("AJAX:", e.message));
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
const get = (u,t) => ajax(u,"GET",t);
|
|
@@ -46,7 +54,12 @@ const ajax = (u,m,o={},p={}) => {
|
|
|
46
54
|
function applyBinding(b,e={},elCtx=b.el){
|
|
47
55
|
const {el,prop,fn}=b;
|
|
48
56
|
const r=fn($,state,e,elCtx,html,...Object.values(data),...[...refs.values()]);
|
|
49
|
-
if(prop==="innerHTML"){
|
|
57
|
+
if(prop==="innerHTML"){
|
|
58
|
+
isUpdatingDOM=1;
|
|
59
|
+
const content = el.innerHTML=Array.isArray(r)?r.join``:r
|
|
60
|
+
typeof Idiomorph === "object" ? Idiomorph.morph(el, content,{morphStyle:'innerHTML'}) : el.innerHTML = content;
|
|
61
|
+
isUpdatingDOM=0
|
|
62
|
+
}
|
|
50
63
|
else if(prop==="class"&&r&&typeof r==="object")for(const[k,v]of Object.entries(r))k.split(/\s+/).forEach(c=>el.classList.toggle(c,v));
|
|
51
64
|
else if(prop==="style"&&r&&typeof r==="object")el.style=Object.entries(r).filter(([,v])=>v).map(([k,v])=>`${k}:${v}`).join(";")
|
|
52
65
|
else if(prop in el){if(el.type==="radio")el.checked=el.value===r;else el[prop]=prop==="textContent"?r:parseEx(r)}
|
|
@@ -60,10 +73,19 @@ function applyBinding(b,e={},elCtx=b.el){
|
|
|
60
73
|
} catch {return () => expr}
|
|
61
74
|
};
|
|
62
75
|
|
|
63
|
-
const trackDependencies = fn => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
76
|
+
const trackDependencies = (fn, el) => {
|
|
77
|
+
const accessed = new Set();
|
|
78
|
+
const trackProxy = new Proxy(data, {
|
|
79
|
+
get(target, prop) {
|
|
80
|
+
if (typeof prop == 'string') accessed.add(prop);
|
|
81
|
+
const val = target[prop];
|
|
82
|
+
return typeof val == "object" && val != null ? new Proxy(val, this) : val;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
try { fn.call(null, $, trackProxy, refs); } catch {}
|
|
87
|
+
return [...accessed];
|
|
88
|
+
};
|
|
67
89
|
|
|
68
90
|
const cleanup = el => {
|
|
69
91
|
[el,...el.querySelectorAll('*')].forEach(e => {
|
|
@@ -75,8 +97,8 @@ const trackDependencies = fn => {
|
|
|
75
97
|
function processElements(element) {
|
|
76
98
|
const newBindings = [];
|
|
77
99
|
if (element.nodeType == 1) {
|
|
78
|
-
if (
|
|
79
|
-
|
|
100
|
+
if (processed.has(element)) return newBindings;
|
|
101
|
+
processed.add(element);
|
|
80
102
|
}
|
|
81
103
|
|
|
82
104
|
const heElements=[element,...element.querySelectorAll("*")].filter(e=>[...e.attributes].some(a=>/^(@|:|data-he)/.test(a.name)))
|
|
@@ -98,6 +120,9 @@ const trackDependencies = fn => {
|
|
|
98
120
|
};
|
|
99
121
|
|
|
100
122
|
heElements.forEach(el => {
|
|
123
|
+
if (processed.has(el)) return;
|
|
124
|
+
processed.add(el);
|
|
125
|
+
|
|
101
126
|
const execFn = v => compile(v, true)($, state, {}, el, html,get,post, put,patch,del, ...Object.values(data), ...[...refs.values()]);
|
|
102
127
|
const inputType = el.type?.toLowerCase();
|
|
103
128
|
const isCheckbox = inputType == "checkbox", isRadio = inputType == "radio", isSelect = el.tagName == "SELECT";
|
|
@@ -131,7 +156,7 @@ const trackDependencies = fn => {
|
|
|
131
156
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, {el, prop: name.slice(1), fn}));
|
|
132
157
|
}
|
|
133
158
|
if (he(name,"init")) {
|
|
134
|
-
|
|
159
|
+
initFn = compile(value,true);
|
|
135
160
|
} else if (name.startsWith("@") || name.startsWith("data-he")) {
|
|
136
161
|
const fullName = name.startsWith("@") ? name.slice(1) : name.slice(8);
|
|
137
162
|
const [eventName, ...mods] = fullName.split(".");
|
|
@@ -189,9 +214,10 @@ const trackDependencies = fn => {
|
|
|
189
214
|
if(isUpdatingDOM)return;
|
|
190
215
|
for(const m of ms){
|
|
191
216
|
m.removedNodes.forEach(n=>n.nodeType===1&&cleanup(n));
|
|
192
|
-
m.addedNodes.forEach(n=>n.nodeType===1&&!
|
|
217
|
+
m.addedNodes.forEach(n=>n.nodeType===1&&!processed.has(n)&&processElements(n).forEach(applyBinding));
|
|
193
218
|
}
|
|
194
219
|
}).observe(root,{childList:1,subtree:1});
|
|
195
220
|
processElements(root);
|
|
196
221
|
for (const [key, items] of bindings.entries()) items.forEach(applyBinding);
|
|
222
|
+
if(initFn) initFn($, state, {}, {}, html,get,post, put,patch,del, ...Object.values(data), ...[...refs.values()])
|
|
197
223
|
}
|