@daz4126/helium 0.3.1 → 0.5.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 (3) hide show
  1. package/README.md +53 -5
  2. package/helium.js +76 -21
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -145,7 +145,7 @@ It's possible to dynamically update the attributes of elements. To do this, just
145
145
  In the following example, the `<div>` element has a dynamic class attribute that will be 'normal' if the count is less than 10, but 'danger' if the count is 10 or more:
146
146
 
147
147
  ```html
148
- <div :class="count < 10 ? 'active' : 'danger'>
148
+ <div :class="count < 10 ? 'normal' : 'danger'>
149
149
  The count is <b @text=count></b>
150
150
  </div>
151
151
  ```
@@ -154,9 +154,30 @@ In the following example, the `<div>` element has a dynamic class attribute that
154
154
 
155
155
  `$` is an alias for `document.querySelector`
156
156
 
157
- `$el` is an alias for the element
158
157
 
159
- `$event` is an alias for the event object of an event handler
158
+ ```html
159
+ <div @click="$('#header').classList.add('active')">Activate Header!</div>
160
+ ```
161
+
162
+ `$el` is an alias for the element:
163
+
164
+ ```html
165
+ <div @click="$el.remove()">Click to remove me!</div>
166
+ ```
167
+
168
+ `$event` is an alias for the event object of an event handler:
169
+
170
+
171
+ ```html
172
+ <div @click="console.log($event.timeStamp)">Log the timestamp</div>
173
+ ```
174
+
175
+ `@data` gives you access to the data object that contains all the Helium variables:
176
+
177
+
178
+ ```html
179
+ <div @click="console.log($data)">Log the data</div>
180
+ ```
160
181
 
161
182
  ## Default Variables and Functions
162
183
 
@@ -178,7 +199,6 @@ helium({
178
199
  element.append(li)
179
200
  }
180
201
  })
181
-
182
202
  ```
183
203
 
184
204
  This function can then be called from an event handler, such as `@click`:
@@ -188,4 +208,32 @@ This function can then be called from an event handler, such as `@click`:
188
208
  <button @click="appendTo($list)>Append item to list</button>
189
209
  ```
190
210
 
191
- Note that Magic attributes and Helium variables are not available inside these functions and changing the value of a reactive variable will not trigger an update. They are best used for side effects (such as DOM manipulation) and to return data.
211
+ Note that magic attributes and Helium variables are not available inside these functions. However, you can pass them as arguments and they will then be available in the function. If you pass Helium variables then they will be passed as values and updating them inside the function will *not* trigger a reactive update. A solution is to pass the magic `$data` attribute as an argument, then updating the properties of this inside the function *will* trigger a reactive update.
212
+
213
+ So instead of this:
214
+
215
+ ```html
216
+ <button @click="increment(count)">Increment Count</button>
217
+ ```
218
+
219
+ ```javascript
220
+ helium({
221
+ increment(count,n = 1){
222
+ count += n
223
+ }
224
+ })
225
+ ```
226
+
227
+ You should do this instead:
228
+
229
+ ```html
230
+ <button @click="increment($data)">Increment Count</button>
231
+ ```
232
+
233
+ ```javascript
234
+ helium({
235
+ increment(data,n = 1){
236
+ data.count += n
237
+ }
238
+ })
239
+ ```
package/helium.js CHANGED
@@ -5,6 +5,11 @@ export default function helium(data = {}) {
5
5
  document.body;
6
6
  const [bindings, refs] = [new Map(), new Map()];
7
7
  const $ = (selector) => document.querySelector(selector);
8
+ const html = (string) => {
9
+ const temp = document.createElement("template");
10
+ temp.innerHTML = string;
11
+ return temp.content.firstChild;
12
+ };
8
13
  const state = new Proxy(data, {
9
14
  get(target, prop) {
10
15
  return target[prop];
@@ -33,12 +38,13 @@ export default function helium(data = {}) {
33
38
  try {
34
39
  return new Function(
35
40
  "$",
36
- "$state",
41
+ "$data",
37
42
  "$event",
38
43
  "$el",
44
+ "$html",
39
45
  ...Object.keys(data),
40
46
  ...[...refs.keys()],
41
- `with($state) { ${withReturn ? "return" : ""} (${expr.trim()}) }`,
47
+ `with($data) { ${withReturn ? "return" : ""} (${expr.trim()}) }`,
42
48
  );
43
49
  } catch (err) {
44
50
  return () => expr;
@@ -65,8 +71,6 @@ export default function helium(data = {}) {
65
71
  heliumElements.forEach((el) => {
66
72
  for (const { name, value } of el.attributes) {
67
73
  if (
68
- name == "@react" ||
69
- name == "data-he-react" ||
70
74
  name == "@text" ||
71
75
  name == "data-he-text" ||
72
76
  name == "@bind" ||
@@ -75,10 +79,7 @@ export default function helium(data = {}) {
75
79
  try {
76
80
  new Function(`let ${value} = 1`);
77
81
  state[value] ||=
78
- name == "@react" ||
79
- name == "data-he-react" ||
80
- name == "@text" ||
81
- name == "data-he-text"
82
+ name == "@text" || name == "data-he-text"
82
83
  ? el.textContent
83
84
  : el.value;
84
85
  } catch (e) {}
@@ -95,17 +96,13 @@ export default function helium(data = {}) {
95
96
  state,
96
97
  {},
97
98
  el,
99
+ html,
98
100
  ...Object.values(data),
99
101
  ...[...refs.values()],
100
102
  ),
101
103
  );
102
104
  if (name == "@ref" || name == "data-he-ref") refs.set("$" + value, el);
103
- if (
104
- name == "@react" ||
105
- name == "data-he-react" ||
106
- name == "@text" ||
107
- name == "data-he-text"
108
- )
105
+ if (name == "@text" || name == "data-he-text")
109
106
  Object.keys(state)
110
107
  .filter((key) => value.includes(key))
111
108
  .forEach((val) =>
@@ -174,6 +171,7 @@ export default function helium(data = {}) {
174
171
  state,
175
172
  undefined,
176
173
  el,
174
+ html,
177
175
  ...Object.values(data),
178
176
  ...[...refs.values()],
179
177
  );
@@ -181,21 +179,68 @@ export default function helium(data = {}) {
181
179
  const [eventName, ...modifiers] = name
182
180
  .slice(name.startsWith("@") ? 1 : 10)
183
181
  .split(".");
184
- const receiver = modifiers.includes("outside") ? document : el;
185
- receiver.addEventListener(eventName, function _handler(e) {
182
+ const receiver =
183
+ modifiers.includes("outside") || modifiers.includes("document")
184
+ ? document
185
+ : el;
186
+ const debounce = (fn, delay) => {
187
+ let timeout;
188
+ return function (...args) {
189
+ clearTimeout(timeout);
190
+ timeout = setTimeout(() => fn.apply(this, args), delay);
191
+ };
192
+ };
193
+
194
+ let debounceDelay = 0;
195
+ const debounceModifier = modifiers.find((m) =>
196
+ m.startsWith("debounce"),
197
+ );
198
+ if (debounceModifier) {
199
+ const time = debounceModifier.split(":")[1];
200
+ if (time && !isNaN(time)) debounceDelay = Number(time);
201
+ else debounceDelay = 300;
202
+ }
203
+
204
+ function _handler(e) {
186
205
  if (modifiers.includes("prevent")) e.preventDefault();
187
- if (!modifiers.includes("outside") || !el.contains(e.target))
206
+ const keyModifiers = {
207
+ shift: "shiftKey",
208
+ ctrl: "ctrlKey",
209
+ alt: "altKey",
210
+ meta: "metaKey",
211
+ };
212
+ for (const [mod, prop] of Object.entries(keyModifiers)) {
213
+ if (modifiers.includes(mod) && !e[prop]) return;
214
+ }
215
+ if (["keydown", "keyup", "keypress"].includes(eventName)) {
216
+ const last = modifiers[modifiers.length - 1];
217
+ if (last) {
218
+ let keyName = e.key;
219
+ if (keyName === " ") keyName = "Space";
220
+ else if (keyName === "Escape") keyName = "Esc";
221
+ if (keyName.toLowerCase() !== last.toLowerCase()) return;
222
+ }
223
+ }
224
+
225
+ if (!modifiers.includes("outside") || !el.contains(e.target)) {
188
226
  compileExpression(value, false)(
189
227
  $,
190
228
  state,
191
229
  e,
192
230
  el,
231
+ html,
193
232
  ...Object.values(data),
194
233
  ...[...refs.values()],
195
234
  );
235
+ }
196
236
  if (modifiers.includes("once"))
197
- el.removeEventListener(eventName, _handler);
198
- });
237
+ el.removeEventListener(eventName, debouncedHandler);
238
+ }
239
+
240
+ const debouncedHandler =
241
+ debounceDelay > 0 ? debounce(_handler, debounceDelay) : _handler;
242
+
243
+ receiver.addEventListener(eventName, debouncedHandler);
199
244
  }
200
245
  }
201
246
  });
@@ -207,8 +252,18 @@ export default function helium(data = {}) {
207
252
  }
208
253
  });
209
254
  observer.observe(element, { childList: true, subtree: true });
210
- for (const [key, items] of bindings.entries())
211
- items.forEach((binding) => applyBinding(binding));
255
+ for (const [key, items] of bindings.entries()) items.forEach(applyBinding);
212
256
  }
213
257
  processElements(root);
214
258
  }
259
+
260
+ helium({
261
+ appendTo: (el) =>
262
+ el.append(
263
+ html(`<p :class="count > 3 && 'danger'" @click=$el.remove()>OG!!</p>`),
264
+ ),
265
+ open: false,
266
+ placeholder: "test placehodler",
267
+ count: 0,
268
+ name: "",
269
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daz4126/helium",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "main": "helium.js",
5
5
  "type": "module",
6
6
  "keywords": [