@daz4126/helium 0.18.0 → 0.20.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.
Files changed (2) hide show
  1. package/helium.js +37 -41
  2. package/package.json +1 -1
package/helium.js CHANGED
@@ -34,11 +34,11 @@ window.helium = function() {
34
34
 
35
35
  const update = (data,target,action,template) => {
36
36
  const element = target instanceof Node ? target : (HELIUM.refs.get(target) || $(target));
37
- if(element){
38
- const content = html(template ? template(data) : data);
39
- action ? element[action=="replace"?"replaceWith":action](content) : element.innerHTML = content;
40
- return content
41
- } else state[target] = data
37
+ if(element){
38
+ const content = html(template ? template(data) : data);
39
+ action ? element[action=="replace"?"replaceWith":action](content) : element.innerHTML = content;
40
+ return content
41
+ } else state[target] = data
42
42
  }
43
43
 
44
44
  const ajax = (u,m,o={},p={}) => {
@@ -117,32 +117,39 @@ function applyBinding(b,e={},elCtx=b.el){
117
117
  .map(([k,v])=>`${k}:${v}`).join(";");
118
118
 
119
119
  if (prop in el) {
120
- if(el.type==="radio") el.checked = el.value===r;
120
+ if (el.type === "radio" && prop != "checked") el.checked = el.value===r;
121
121
  else el[prop] = prop==="textContent"?r:parseEx(r);
122
122
  return;
123
123
  }
124
124
 
125
125
  el.setAttribute(prop, parseEx(r));
126
126
  }
127
-
127
+
128
128
  const compile = (expr, withReturn = false) => {
129
- // Auto-detect if this should be a statement block
130
- const hasStatements = /[;\r\n]/.test(expr);
131
- const useReturn = withReturn && (!hasStatements || expr.trim().startsWith('{') && expr.trim().endsWith('}'));
132
- const key = `${useReturn}:${expr}`;
129
+ const key = `${withReturn}:${expr}`;
133
130
  if (HELIUM.fnCache.has(key)) return HELIUM.fnCache.get(key);
134
131
  try {
135
132
  const fn = new Function(
136
133
  "$","$data","$event","$el","$html","$get","$post","$put","$patch","$delete",
137
134
  ...Object.keys(state), ...[...HELIUM.refs.keys()],
138
- useReturn
135
+ withReturn
139
136
  ? `with($data){return(${expr.trim()})}`
140
137
  : `with($data){${expr.trim()}}`
141
138
  );
142
139
  HELIUM.fnCache.set(key, fn);
143
140
  return fn;
144
141
  } catch {
145
- return () => expr;
142
+ try {
143
+ const fn = new Function(
144
+ "$","$data","$event","$el","$html","$get","$post","$put","$patch","$delete",
145
+ ...Object.keys(state), ...[...HELIUM.refs.keys()],
146
+ `with($data){${expr.trim()}}`
147
+ );
148
+ HELIUM.fnCache.set(key, fn);
149
+ return fn;
150
+ } catch {
151
+ return () => expr;
152
+ }
146
153
  }
147
154
  };
148
155
 
@@ -218,15 +225,14 @@ function processElements(element) {
218
225
  }
219
226
  else if (name.startsWith(":") || name.startsWith("data-he-attr:")) {
220
227
  const fn = compile(value, true);
221
- deferredBindings.push(() => trackDependencies(fn, el).forEach(dep => addBinding(dep, {el, prop: name.slice(name.startsWith(":") ? 1 : 13), fn})));
228
+ deferredBindings.push({el, prop: name.slice(name.startsWith(":") ? 1 : 13), fn});
222
229
  }
223
230
  else if (he(name, "ref")) {
224
231
  HELIUM.refs.set("$" + value, el);
225
232
  }
226
233
  else if (he(name, "text", "html")) {
227
234
  const fn = compile(value, true);
228
- const b = {el, prop: he(name, "text") ? "textContent" : "innerHTML", fn};
229
- deferredBindings.push(() => trackDependencies(fn, el).forEach(dep => addBinding(dep, b)));
235
+ deferredBindings.push({el, prop: he(name, "text") ? "textContent" : "innerHTML", fn});
230
236
  }
231
237
  else if (he(name, "bind")) {
232
238
  const event = (isCheckbox || isRadio || isSelect) ? "change" : "input";
@@ -242,20 +248,17 @@ function processElements(element) {
242
248
  }
243
249
  else if (he(name, "hidden", "visible")) {
244
250
  const fn = compile(`${he(name, "hidden") ? "!" : ""}!(${value})`, true);
245
- deferredBindings.push(() => trackDependencies(fn, el).forEach(dep => addBinding(dep, {el, prop: "hidden", fn})));
251
+ deferredBindings.push({el, prop: "hidden", fn});
246
252
  }
247
253
  else if (he(name, "calculate")) {
248
254
  const calc = name.split(":")[1];
249
255
  const fn = compile(value, true);
250
- deferredBindings.push(() => trackDependencies(fn, el, true).forEach(key => addBinding(key, {el, calc, prop: null, fn})));
256
+ deferredBindings.push({el, calc, prop: null, fn});
251
257
  }
252
258
  else if (he(name, "effect")) {
253
259
  const keys = name.split(":").slice(1);
254
260
  const fn = compile(value, true);
255
- deferredBindings.push(() => {
256
- const tracked = keys.includes("*") ? [ALL] : trackDependencies(fn, el, true).concat(keys);
257
- tracked.forEach(key => addBinding(key, {el, prop: null, fn}));
258
- })
261
+ deferredBindings.push({el, prop: null, fn, keys});
259
262
  }
260
263
  else if (he(name, "init")) {
261
264
  initFn = compile(value, true);
@@ -291,7 +294,11 @@ function processElements(element) {
291
294
  ...(getAttr("template") && { template: execFn(getAttr("template")),}),
292
295
  ...(getAttr("loading") && { loading: execFn(getAttr("loading"))}),
293
296
  };
294
- let paramsAttr = getAttr('params') || '{}';
297
+ let paramsAttr = getAttr("params");
298
+ if (!paramsAttr && el.hasAttribute("name")) {
299
+ const keys = el.getAttribute("name").match(/\w+/g).map(key => `${key}:`).join``;
300
+ paramsAttr = keys + (isCheckbox ? "checked" : "value");
301
+ } else paramsAttr ||= "{}";
295
302
  if (!paramsAttr.trim().startsWith("{") && paramsAttr.includes(":")) {
296
303
  const props = paramsAttr.split(":").map(s => s.trim());
297
304
  paramsAttr = props.reduceRight((acc, key, i) => `{ ${key}: ${i == 1 ? `'${el[acc]}'` : acc} }`);
@@ -311,13 +318,13 @@ function processElements(element) {
311
318
  }
312
319
  }
313
320
  });
314
- deferredBindings.forEach(fn => fn());
321
+ deferredBindings.forEach(b => {
322
+ const tracked = b.keys?.includes("*") ? [ALL] : trackDependencies(b.fn, b.el, true).concat(b.keys);
323
+ tracked.forEach(key => addBinding(key, b));
324
+ })
315
325
  return newBindings;
316
326
  }
317
327
 
318
- // Disconnect old observer if it exists
319
- if (HELIUM.observer) HELIUM.observer.disconnect();
320
-
321
328
  // Create new observer
322
329
  HELIUM.observer = new MutationObserver(ms => {
323
330
  for (const m of ms) {
@@ -334,22 +341,11 @@ function processElements(element) {
334
341
 
335
342
  window.heliumTeardown = function() {
336
343
  if (HELIUM?.observer) HELIUM.observer.disconnect();
337
- HELIUM?.bindings?.clear();
338
- HELIUM?.refs?.clear();
339
- HELIUM?.parentKeys?.clear();
340
- HELIUM?.fnCache?.clear();
341
344
  HELIUM = null;
342
345
  }
343
346
 
344
347
  // Initialize on load
345
- document.addEventListener("DOMContentLoaded", () => helium());
346
-
348
+ document.addEventListener("DOMContentLoaded",_ => helium());
347
349
  // Turbo integration
348
- document.addEventListener("turbo:before-render", () => {
349
- if (HELIUM?.observer) HELIUM.observer.disconnect();
350
- window.heliumTeardown();
351
- });
352
-
353
- document.addEventListener("turbo:render", () => {
354
- helium();
355
- });
350
+ document.addEventListener("turbo:before-render",_ => window.heliumTeardown());
351
+ document.addEventListener("turbo:render",_ => helium());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daz4126/helium",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "main": "helium.js",
5
5
  "type": "module",
6
6
  "scripts": {