@daz4126/helium 0.3.1 → 0.4.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 +56 -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
@@ -33,12 +33,12 @@ export default function helium(data = {}) {
33
33
  try {
34
34
  return new Function(
35
35
  "$",
36
- "$state",
36
+ "$data",
37
37
  "$event",
38
38
  "$el",
39
39
  ...Object.keys(data),
40
40
  ...[...refs.keys()],
41
- `with($state) { ${withReturn ? "return" : ""} (${expr.trim()}) }`,
41
+ `with($data) { ${withReturn ? "return" : ""} (${expr.trim()}) }`,
42
42
  );
43
43
  } catch (err) {
44
44
  return () => expr;
@@ -65,8 +65,6 @@ export default function helium(data = {}) {
65
65
  heliumElements.forEach((el) => {
66
66
  for (const { name, value } of el.attributes) {
67
67
  if (
68
- name == "@react" ||
69
- name == "data-he-react" ||
70
68
  name == "@text" ||
71
69
  name == "data-he-text" ||
72
70
  name == "@bind" ||
@@ -75,10 +73,7 @@ export default function helium(data = {}) {
75
73
  try {
76
74
  new Function(`let ${value} = 1`);
77
75
  state[value] ||=
78
- name == "@react" ||
79
- name == "data-he-react" ||
80
- name == "@text" ||
81
- name == "data-he-text"
76
+ name == "@text" || name == "data-he-text"
82
77
  ? el.textContent
83
78
  : el.value;
84
79
  } catch (e) {}
@@ -100,12 +95,7 @@ export default function helium(data = {}) {
100
95
  ),
101
96
  );
102
97
  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
- )
98
+ if (name == "@text" || name == "data-he-text")
109
99
  Object.keys(state)
110
100
  .filter((key) => value.includes(key))
111
101
  .forEach((val) =>
@@ -181,10 +171,50 @@ export default function helium(data = {}) {
181
171
  const [eventName, ...modifiers] = name
182
172
  .slice(name.startsWith("@") ? 1 : 10)
183
173
  .split(".");
184
- const receiver = modifiers.includes("outside") ? document : el;
185
- receiver.addEventListener(eventName, function _handler(e) {
174
+ const receiver =
175
+ modifiers.includes("outside") || modifiers.includes("document")
176
+ ? document
177
+ : el;
178
+ const debounce = (fn, delay) => {
179
+ let timeout;
180
+ return function (...args) {
181
+ clearTimeout(timeout);
182
+ timeout = setTimeout(() => fn.apply(this, args), delay);
183
+ };
184
+ };
185
+
186
+ let debounceDelay = 0;
187
+ const debounceModifier = modifiers.find((m) =>
188
+ m.startsWith("debounce"),
189
+ );
190
+ if (debounceModifier) {
191
+ const time = debounceModifier.split(":")[1];
192
+ if (time && !isNaN(time)) debounceDelay = Number(time);
193
+ else debounceDelay = 300;
194
+ }
195
+
196
+ function _handler(e) {
186
197
  if (modifiers.includes("prevent")) e.preventDefault();
187
- if (!modifiers.includes("outside") || !el.contains(e.target))
198
+ const keyModifiers = {
199
+ shift: "shiftKey",
200
+ ctrl: "ctrlKey",
201
+ alt: "altKey",
202
+ meta: "metaKey",
203
+ };
204
+ for (const [mod, prop] of Object.entries(keyModifiers)) {
205
+ if (modifiers.includes(mod) && !e[prop]) return;
206
+ }
207
+ if (["keydown", "keyup", "keypress"].includes(eventName)) {
208
+ const last = modifiers[modifiers.length - 1];
209
+ if (last) {
210
+ let keyName = e.key;
211
+ if (keyName === " ") keyName = "Space";
212
+ else if (keyName === "Escape") keyName = "Esc";
213
+ if (keyName.toLowerCase() !== last.toLowerCase()) return;
214
+ }
215
+ }
216
+
217
+ if (!modifiers.includes("outside") || !el.contains(e.target)) {
188
218
  compileExpression(value, false)(
189
219
  $,
190
220
  state,
@@ -193,9 +223,15 @@ export default function helium(data = {}) {
193
223
  ...Object.values(data),
194
224
  ...[...refs.values()],
195
225
  );
226
+ }
196
227
  if (modifiers.includes("once"))
197
- el.removeEventListener(eventName, _handler);
198
- });
228
+ el.removeEventListener(eventName, debouncedHandler);
229
+ }
230
+
231
+ const debouncedHandler =
232
+ debounceDelay > 0 ? debounce(_handler, debounceDelay) : _handler;
233
+
234
+ receiver.addEventListener(eventName, debouncedHandler);
199
235
  }
200
236
  }
201
237
  });
@@ -207,8 +243,7 @@ export default function helium(data = {}) {
207
243
  }
208
244
  });
209
245
  observer.observe(element, { childList: true, subtree: true });
210
- for (const [key, items] of bindings.entries())
211
- items.forEach((binding) => applyBinding(binding));
246
+ for (const [key, items] of bindings.entries()) items.forEach(applyBinding);
212
247
  }
213
248
  processElements(root);
214
249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daz4126/helium",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "main": "helium.js",
5
5
  "type": "module",
6
6
  "keywords": [