@daz4126/helium 0.11.0 → 0.11.1
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 +26 -35
- package/package.json +1 -1
package/helium.js
CHANGED
|
@@ -7,9 +7,10 @@ export default function helium(data = {}) {
|
|
|
7
7
|
const root = document.querySelector("[\\@helium]") || document.querySelector("[data-helium]") || document.body;
|
|
8
8
|
const [bindings, refs, listeners] = [new Map(), new Map(), new WeakMap()];
|
|
9
9
|
const $ = s => document.querySelector(s);
|
|
10
|
-
const html = s =>
|
|
10
|
+
const html = s => Object.assign(document.createElement("template"),{innerHTML:s.trim()}).content.firstChild
|
|
11
11
|
|
|
12
12
|
const ajax=(u,m,o={},p={})=>{
|
|
13
|
+
console.log("ajax: ", u,m,o.target,p)
|
|
13
14
|
const fd=p instanceof FormData,t=document.querySelector('meta[name="csrf-token"]')?.content;
|
|
14
15
|
fetch(u,{method:m,headers:{
|
|
15
16
|
Accept:"text/vnd.turbo-stream.html,application/json,text/html",
|
|
@@ -23,8 +24,13 @@ const ajax=(u,m,o={},p={})=>{
|
|
|
23
24
|
const c=o.template?o.template(d):d;
|
|
24
25
|
o.action?o.target[o.action=="replace"?"replaceWith":o.action](html(c)):o.target.innerHTML=c;
|
|
25
26
|
}
|
|
26
|
-
}).catch(e=>
|
|
27
|
+
}).catch(e=>{
|
|
28
|
+
console.error("AJAX:",e.message);
|
|
29
|
+
})
|
|
27
30
|
}
|
|
31
|
+
|
|
32
|
+
const get = (u,t) => ajax(u,"GET",t);
|
|
33
|
+
const [post, put, patch, del] = ["POST","PUT","PATCH","DELETE"].map(m => (u, d, t) => ajax(u, m, t, d));
|
|
28
34
|
|
|
29
35
|
const handler = {
|
|
30
36
|
get: (t, p, r) => {const v = Reflect.get(t, p, r); return typeof v == "object" && v != null ? new Proxy(v, handler) : v},
|
|
@@ -46,13 +52,13 @@ function applyBinding(b,e={},elCtx=b.el){
|
|
|
46
52
|
|
|
47
53
|
const compile = (expr, withReturn = false) => {
|
|
48
54
|
try {
|
|
49
|
-
return new Function("$", "$data", "$event", "$el", "$html",
|
|
55
|
+
return new Function("$", "$data", "$event", "$el", "$html","$get", "$post", "$put","$patch","$delete",...Object.keys(data), ...[...refs.keys()],
|
|
50
56
|
`with($data){${withReturn ? "return" : ""}(${expr.trim()})}`);
|
|
51
57
|
} catch {return () => expr}
|
|
52
58
|
};
|
|
53
59
|
|
|
54
60
|
const trackDependencies=fn=>{
|
|
55
|
-
const s=new Set(),p=new Proxy(
|
|
61
|
+
const s=new Set(),p=new Proxy(state,{get:(t,k)=>{if(typeof k=="string")s.add(k);const v=t[k];return v&&typeof v=="object"?new Proxy(v,this):v}});
|
|
56
62
|
try{fn($,p,refs)}catch{};return[...s]
|
|
57
63
|
}
|
|
58
64
|
|
|
@@ -89,47 +95,40 @@ const trackDependencies=fn=>{
|
|
|
89
95
|
};
|
|
90
96
|
|
|
91
97
|
heElements.forEach(el => {
|
|
92
|
-
const execFn = v => compile(v, true)($, state, {}, el, html, ...Object.values(data), ...[...refs.values()]);
|
|
98
|
+
const execFn = v => compile(v, true)($, state, {}, el, html,get,post, put,patch,del, ...Object.values(data), ...[...refs.values()]);
|
|
93
99
|
const inputType = el.type?.toLowerCase();
|
|
94
100
|
const isCheckbox = inputType == "checkbox", isRadio = inputType == "radio", isSelect = el.tagName == "SELECT";
|
|
95
101
|
|
|
96
102
|
for (const {name, value} of el.attributes || []) {
|
|
97
103
|
if (["@data","data-he"].includes(name)) Object.assign(state, execFn(value));
|
|
98
|
-
if (he(name,"ref")) refs.set("$" + value, el);
|
|
99
|
-
|
|
104
|
+
if (he(name,"ref")) refs.set("$" + value, el);
|
|
100
105
|
if (he(name,"text","html")) {
|
|
101
106
|
const fn = compile(value, true);
|
|
102
107
|
const b = {el, prop: he(name,"text") ? "textContent" : "innerHTML", fn};
|
|
103
108
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, b));
|
|
104
109
|
}
|
|
105
|
-
|
|
106
110
|
if (he(name,"bind")) {
|
|
107
111
|
const event = (isCheckbox || isRadio || isSelect) ? "change" : "input";
|
|
108
112
|
const prop = isCheckbox ? "checked" : "value";
|
|
109
|
-
const inputHandler = e => state[value] = isCheckbox ? e.target.checked : e.target.value;
|
|
110
|
-
|
|
113
|
+
const inputHandler = e => state[value] = isCheckbox ? e.target.checked : e.target.value;
|
|
111
114
|
el.addEventListener(event, inputHandler);
|
|
112
115
|
if (!listeners.has(el)) listeners.set(el, []);
|
|
113
116
|
listeners.get(el).push({receiver: el, event, handler: inputHandler});
|
|
114
|
-
addBinding(value, {el, prop, fn: compile(value, true)});
|
|
115
|
-
|
|
117
|
+
addBinding(value, {el, prop, fn: compile(value, true)});
|
|
116
118
|
if (isCheckbox) el.checked = !!state[value];
|
|
117
119
|
else if (isRadio) el.checked = el.value == state[value];
|
|
118
120
|
else el.value = state[value] ?? "";
|
|
119
121
|
}
|
|
120
|
-
|
|
121
122
|
if (he(name,"hidden","visible")) {
|
|
122
123
|
const fn = compile(`${he(name,"hidden") ? "!" : ""}!(${value})`, true);
|
|
123
124
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, {el, prop: "hidden", fn}));
|
|
124
125
|
}
|
|
125
|
-
|
|
126
126
|
if (name.startsWith(":")) {
|
|
127
127
|
const fn = compile(value, true);
|
|
128
128
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, {el, prop: name.slice(1), fn}));
|
|
129
129
|
}
|
|
130
|
-
|
|
131
130
|
if (he(name,"init")) {
|
|
132
|
-
|
|
131
|
+
execFn(value);
|
|
133
132
|
} else if (name.startsWith("@") || name.startsWith("data-he")) {
|
|
134
133
|
const fullName = name.startsWith("@") ? name.slice(1) : name.slice(8);
|
|
135
134
|
const [eventName, ...mods] = fullName.split(".");
|
|
@@ -138,40 +137,35 @@ const trackDependencies=fn=>{
|
|
|
138
137
|
const receiver = mods.includes("outside") || mods.includes("document") ? document : el;
|
|
139
138
|
const debounceMod = mods.find(m => m.startsWith("debounce"));
|
|
140
139
|
const debounceDelay = debounceMod ? (t => t && !isNaN(t) ? Number(t) : 300)(debounceMod.split(":")[1]) : 0;
|
|
141
|
-
|
|
142
140
|
const _handler = e => {
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
const exFn = v => compile(v, true)($, state, e, el, html,get,post,put,patch,del, ...Object.values(data), ...[...refs.values()])
|
|
142
|
+
if (mods.includes("prevent")) e.preventDefault();
|
|
145
143
|
const keyMods = {shift: "shiftKey", ctrl: "ctrlKey", alt: "altKey", meta: "metaKey"};
|
|
146
|
-
for (const [mod, prop] of Object.entries(keyMods)) if (mods.includes(mod) && !e[prop]) return;
|
|
147
|
-
|
|
144
|
+
for (const [mod, prop] of Object.entries(keyMods)) if (mods.includes(mod) && !e[prop]) return;
|
|
148
145
|
if (["keydown","keyup","keypress"].includes(event)) {
|
|
149
146
|
const last = mods[mods.length - 1];
|
|
150
147
|
if (last && !["prevent","once","outside","document"].includes(last)) {
|
|
151
148
|
const keyName = e.key == " " ? "Space" : e.key == "Escape" ? "Esc" : e.key;
|
|
152
149
|
if (keyName.toLowerCase() !== last.toLowerCase()) return;
|
|
153
150
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (!mods.includes("outside") || !el.contains(e.target)) {
|
|
151
|
+
}
|
|
152
|
+
if (!mods.includes("outside") || !el.contains(e.target)) {
|
|
157
153
|
if (isHttpMethod) {
|
|
158
|
-
const options =
|
|
159
|
-
let paramsAttr = el.getAttribute('data-he-params') || el.getAttribute('params') || '{}';
|
|
160
|
-
|
|
154
|
+
const options = exFn(el.getAttribute('data-he-options') || el.getAttribute('options') || '{}');
|
|
155
|
+
let paramsAttr = el.getAttribute('data-he-params') || el.getAttribute('params') || '{}';
|
|
161
156
|
if (!paramsAttr.trim().startsWith("{") && paramsAttr.includes(":")) {
|
|
162
157
|
const props = paramsAttr.split(":").map(s => s.trim());
|
|
163
158
|
paramsAttr = props.reduceRight((acc, key, i) => `{ ${key}: ${i == 1 ? `'${el[acc]}'` : acc} }`);
|
|
164
159
|
}
|
|
165
|
-
const params =
|
|
160
|
+
const params = exFn(paramsAttr);
|
|
161
|
+
console.log("params: ",params)
|
|
166
162
|
ajax(value, eventName.toUpperCase(), options, params);
|
|
167
163
|
} else {
|
|
168
|
-
|
|
164
|
+
exFn(value);
|
|
169
165
|
}
|
|
170
|
-
}
|
|
171
|
-
|
|
166
|
+
}
|
|
172
167
|
if (mods.includes("once")) receiver.removeEventListener(event, handler);
|
|
173
168
|
};
|
|
174
|
-
|
|
175
169
|
const handler = debounceDelay > 0 ? debounce(_handler, debounceDelay) : _handler;
|
|
176
170
|
receiver.addEventListener(event, handler);
|
|
177
171
|
if (!listeners.has(el)) listeners.set(el, []);
|
|
@@ -179,10 +173,8 @@ const trackDependencies=fn=>{
|
|
|
179
173
|
}
|
|
180
174
|
}
|
|
181
175
|
});
|
|
182
|
-
|
|
183
176
|
return newBindings;
|
|
184
177
|
}
|
|
185
|
-
|
|
186
178
|
new MutationObserver(ms=>{
|
|
187
179
|
if(isUpdatingDOM)return;
|
|
188
180
|
for(const m of ms){
|
|
@@ -190,7 +182,6 @@ const trackDependencies=fn=>{
|
|
|
190
182
|
m.addedNodes.forEach(n=>n.nodeType==1&&!n.hasAttribute("data-he-p")&&processElements(n).forEach(applyBinding));
|
|
191
183
|
}
|
|
192
184
|
}).observe(root,{childList:1,subtree:1});
|
|
193
|
-
|
|
194
185
|
processElements(root);
|
|
195
186
|
for (const [key, items] of bindings.entries()) items.forEach(applyBinding);
|
|
196
187
|
}
|