@daz4126/helium 0.10.1 → 0.10.2
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 +23 -24
- package/package.json +1 -1
package/helium.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default function helium(data = {}) {
|
|
2
|
-
const he = (
|
|
2
|
+
const he = (name,...args) => args.map(b => `|@${b}|data-he-${b}|`).join``.includes(`|${name}|`)
|
|
3
3
|
const root = document.querySelector("[\\@helium]") || document.querySelector("[data-helium]") || document.body;
|
|
4
4
|
const [bindings, refs, listeners] = [new Map(), new Map(), new WeakMap()];
|
|
5
5
|
const $ = (s) => document.querySelector(s);
|
|
@@ -20,7 +20,7 @@ export default function helium(data = {}) {
|
|
|
20
20
|
fetch(url, {
|
|
21
21
|
method,
|
|
22
22
|
headers,
|
|
23
|
-
body: method
|
|
23
|
+
body: method == "GET" ? null : JSON.stringify(opts),
|
|
24
24
|
credentials: "same-origin"
|
|
25
25
|
})
|
|
26
26
|
.then(r => r.headers.get("content-type")?.includes("application/json") ? r.json() : r.text())
|
|
@@ -34,7 +34,7 @@ export default function helium(data = {}) {
|
|
|
34
34
|
const handler = {
|
|
35
35
|
get(target, prop, receiver) {
|
|
36
36
|
const val = Reflect.get(target, prop, receiver);
|
|
37
|
-
return typeof val
|
|
37
|
+
return typeof val == "object" && val != null ? new Proxy(val, handler) : val;
|
|
38
38
|
},
|
|
39
39
|
set(target, prop, val) {
|
|
40
40
|
const result = Reflect.set(target, prop, val);
|
|
@@ -51,7 +51,7 @@ export default function helium(data = {}) {
|
|
|
51
51
|
const result = fn($, state, event, elCtx, html, get, post, put, patch, del, ...Object.values(data), ...[...refs.values()]);
|
|
52
52
|
if (prop == "innerHTML") {
|
|
53
53
|
isUpdatingDOM = true;
|
|
54
|
-
el.innerHTML = result;
|
|
54
|
+
el.innerHTML = Array.isArray(result) ? result.join`` : result;
|
|
55
55
|
isUpdatingDOM = false;
|
|
56
56
|
} else if(prop == "class" && typeof result == "object"){
|
|
57
57
|
Object.entries(result).forEach(([k, v]) => el.classList.toggle(k, v));
|
|
@@ -79,9 +79,9 @@ const trackDependencies = (fn, el) => {
|
|
|
79
79
|
const accessed = new Set();
|
|
80
80
|
const trackProxy = new Proxy(data, {
|
|
81
81
|
get(target, prop) {
|
|
82
|
-
if (typeof prop
|
|
82
|
+
if (typeof prop == 'string') accessed.add(prop);
|
|
83
83
|
const val = target[prop];
|
|
84
|
-
return typeof val
|
|
84
|
+
return typeof val == "object" && val != null ? new Proxy(val, this) : val;
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
87
|
|
|
@@ -99,7 +99,7 @@ const trackDependencies = (fn, el) => {
|
|
|
99
99
|
|
|
100
100
|
function processElements(element) {
|
|
101
101
|
const newBindings = [];
|
|
102
|
-
if (element.nodeType
|
|
102
|
+
if (element.nodeType == 1) {
|
|
103
103
|
if (element.hasAttribute?.("data-he-p")) return newBindings;
|
|
104
104
|
element.setAttribute("data-he-p", "");
|
|
105
105
|
}
|
|
@@ -112,10 +112,11 @@ const trackDependencies = (fn, el) => {
|
|
|
112
112
|
// Seed default state values
|
|
113
113
|
heElements.forEach(el => {
|
|
114
114
|
for (const { name, value } of el.attributes || []) {
|
|
115
|
-
if (he("text","html","bind")
|
|
115
|
+
if (he(name,"text","html","bind")) {
|
|
116
116
|
try {
|
|
117
117
|
new Function(`let ${value}=1`);
|
|
118
|
-
|
|
118
|
+
const val = he(name,"bind") ? el.type == "checkbox" ? el.checked : el.value : el.textContent;
|
|
119
|
+
state[value] ||= Number.isNaN(Number(val)) ? val : Number(val);
|
|
119
120
|
} catch (e) {}
|
|
120
121
|
}
|
|
121
122
|
}
|
|
@@ -131,19 +132,18 @@ const trackDependencies = (fn, el) => {
|
|
|
131
132
|
const execFn = v => compile(v, true)($, state, {}, el, html, get, post, put, patch, del, ...Object.values(data), ...[...refs.values()]);
|
|
132
133
|
for (const { name, value } of el.attributes || []) {
|
|
133
134
|
if (["@data","data-he"].includes(name)) Object.assign(state, execFn(value));
|
|
134
|
-
if (he("ref")
|
|
135
|
-
|
|
136
|
-
if (he("text","html").includes(name)) {
|
|
135
|
+
if (he(name,"ref")) refs.set("$" + value, el);
|
|
136
|
+
if (he(name,"text","html")) {
|
|
137
137
|
const fn = compile(value, true);
|
|
138
|
-
const b = { el, prop: he("text")
|
|
138
|
+
const b = { el, prop: he(name,"text") ? "textContent" : "innerHTML", fn };
|
|
139
139
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, b));
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
if (he("bind")
|
|
142
|
+
if (he(name,"bind")) {
|
|
143
143
|
const inputType = el.type?.toLowerCase();
|
|
144
|
-
const isCheckbox = inputType
|
|
145
|
-
const isRadio = inputType
|
|
146
|
-
const event = (isCheckbox || isRadio || el.tagName
|
|
144
|
+
const isCheckbox = inputType == "checkbox";
|
|
145
|
+
const isRadio = inputType == "radio";
|
|
146
|
+
const event = (isCheckbox || isRadio || el.tagName == "SELECT") ? "change" : "input";
|
|
147
147
|
const prop = isCheckbox ? "checked" : "value";
|
|
148
148
|
|
|
149
149
|
const inputHandler = e => state[value] = isCheckbox ? e.target.checked : e.target.value;
|
|
@@ -158,8 +158,8 @@ const trackDependencies = (fn, el) => {
|
|
|
158
158
|
else el.value = state[value] ?? "";
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
if (he("hidden","visible")
|
|
162
|
-
const fn = compile(`${he("hidden")
|
|
161
|
+
if (he(name,"hidden","visible")) {
|
|
162
|
+
const fn = compile(`${he(name,"hidden") ? "!" : ""}!(${value})`, true);
|
|
163
163
|
const b = { el, prop: "hidden", fn };
|
|
164
164
|
|
|
165
165
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, b));
|
|
@@ -171,12 +171,11 @@ const trackDependencies = (fn, el) => {
|
|
|
171
171
|
trackDependencies(fn, el).forEach(dep => addBinding(dep, b));
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
if (he("init")
|
|
174
|
+
if (he(name,"init")) {
|
|
175
175
|
compile(value, false)($, state, undefined, el, html, get, post, put, patch, del, ...Object.values(data), ...[...refs.values()]);
|
|
176
176
|
} else if (name.startsWith("@") || name.startsWith("data-he-on")) {
|
|
177
177
|
const [eventName, ...mods] = name.slice(name.startsWith("@") ? 1 : 10).split(".");
|
|
178
178
|
const receiver = mods.includes("outside") || mods.includes("document") ? document : el;
|
|
179
|
-
|
|
180
179
|
let debounceDelay = 0;
|
|
181
180
|
const debounceMod = mods.find(m => m.startsWith("debounce"));
|
|
182
181
|
if (debounceMod) {
|
|
@@ -193,7 +192,7 @@ const trackDependencies = (fn, el) => {
|
|
|
193
192
|
if (["keydown","keyup","keypress"].includes(eventName)) {
|
|
194
193
|
const last = mods[mods.length - 1];
|
|
195
194
|
if (last) {
|
|
196
|
-
let keyName = e.key
|
|
195
|
+
let keyName = e.key == " " ? "Space" : e.key == "Escape" ? "Esc" : e.key;
|
|
197
196
|
if (keyName.toLowerCase() !== last.toLowerCase()) return;
|
|
198
197
|
}
|
|
199
198
|
}
|
|
@@ -226,10 +225,10 @@ const trackDependencies = (fn, el) => {
|
|
|
226
225
|
if (isUpdatingDOM) return;
|
|
227
226
|
for (const m of mutations) {
|
|
228
227
|
for (const node of m.removedNodes) {
|
|
229
|
-
if (node.nodeType
|
|
228
|
+
if (node.nodeType == 1) cleanup(node);
|
|
230
229
|
}
|
|
231
230
|
for (const node of m.addedNodes) {
|
|
232
|
-
if (node.nodeType
|
|
231
|
+
if (node.nodeType == 1 && !node.hasAttribute("data-he-p")) {
|
|
233
232
|
processElements(node).forEach(applyBinding);
|
|
234
233
|
}
|
|
235
234
|
}
|