@daz4126/helium 0.22.0 → 0.24.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.
- package/README.md +34 -67
- package/helium.js +16 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,17 +12,16 @@ Here's a simple example of a button that counts the number of times it has been
|
|
|
12
12
|
|
|
13
13
|
It's really simple to use - just sprinkle the magic @attributes into your HTML and watch it come alive!
|
|
14
14
|
|
|
15
|
-
[See more examples here](https://codepen.io/daz4126/pen/
|
|
15
|
+
[See more examples here](https://codepen.io/daz4126/pen/ogxGMX)
|
|
16
16
|
|
|
17
17
|
## Why Helium?
|
|
18
18
|
|
|
19
19
|
Helium is designed for developers who want:
|
|
20
20
|
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
25
|
-
- **Progressive enhancement** - Add interactivity gradually where you need it
|
|
21
|
+
- **Lightweight** - Just over 3KB minified and gzipped
|
|
22
|
+
- **Powerful** - Declarative JavaScript in your HTML
|
|
23
|
+
- **Zero build step** Works directly in the browser with no compiling
|
|
24
|
+
- **Easy to learn** If you know HTML and basic JavaScript, you're ready
|
|
26
25
|
|
|
27
26
|
## Installation
|
|
28
27
|
|
|
@@ -33,7 +32,6 @@ Just import from the CDN in a script tag directly in your HTML page:
|
|
|
33
32
|
```html
|
|
34
33
|
<script type="module">
|
|
35
34
|
import helium from 'https://cdn.jsdelivr.net/gh/daz-codes/helium/helium.js';
|
|
36
|
-
helium();
|
|
37
35
|
</script>
|
|
38
36
|
```
|
|
39
37
|
|
|
@@ -47,7 +45,6 @@ Then include it in your JavaScript file and call the helium() function:
|
|
|
47
45
|
|
|
48
46
|
```javascript
|
|
49
47
|
import helium from "@daz4126/helium"
|
|
50
|
-
helium()
|
|
51
48
|
```
|
|
52
49
|
|
|
53
50
|
### Automatic Initialization
|
|
@@ -367,6 +364,8 @@ You can add modifiers by appending them with a dot (`.`) after the event name:
|
|
|
367
364
|
|
|
368
365
|
Helium includes built-in support for making HTTP requests directly from event handlers. This makes it easy to load data, submit forms, and update parts of your page without writing fetch code.
|
|
369
366
|
|
|
367
|
+
[See some examples here](https://codepen.io/daz4126/pen/dPMVGdX)
|
|
368
|
+
|
|
370
369
|
### Available HTTP Methods
|
|
371
370
|
|
|
372
371
|
- `@get` - GET request
|
|
@@ -463,6 +462,17 @@ Specifies the request parameters. Can be:
|
|
|
463
462
|
```
|
|
464
463
|
|
|
465
464
|
**Shorthand Syntax:**
|
|
465
|
+
|
|
466
|
+
You can write the params in shorthand using `:` separated string of attributes:
|
|
467
|
+
|
|
468
|
+
```html
|
|
469
|
+
<!-- Creates { user: { name: [value] } } -->
|
|
470
|
+
<button @post="/api/save" @params="user:name:value" name="value">
|
|
471
|
+
Save
|
|
472
|
+
</button>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Magic Parmas Syntax:**
|
|
466
476
|
If the element has a `name` attribute, Helium automatically extracts its value:
|
|
467
477
|
|
|
468
478
|
```html
|
|
@@ -478,14 +488,6 @@ For checkboxes:
|
|
|
478
488
|
<button @post="/api/consent" name="agreed">Submit</button>
|
|
479
489
|
```
|
|
480
490
|
|
|
481
|
-
**Nested Object Syntax:**
|
|
482
|
-
```html
|
|
483
|
-
<!-- Creates { user: { name: [value] } } -->
|
|
484
|
-
<button @post="/api/save" @params="user:name:value" name="value">
|
|
485
|
-
Save
|
|
486
|
-
</button>
|
|
487
|
-
```
|
|
488
|
-
|
|
489
491
|
**FormData Example:**
|
|
490
492
|
```html
|
|
491
493
|
<form @post="/api/upload">
|
|
@@ -690,6 +692,8 @@ HTTP request functions that can be called programmatically:
|
|
|
690
692
|
</button>
|
|
691
693
|
```
|
|
692
694
|
|
|
695
|
+
The arguments are `url`,`params` (not for `$get`) and `options`. `options` is an object that can include the properties `loading`,`target`, `template`
|
|
696
|
+
|
|
693
697
|
### $refs
|
|
694
698
|
Object containing all elements marked with `@ref` (prefixed with `$`):
|
|
695
699
|
|
|
@@ -698,34 +702,16 @@ Object containing all elements marked with `@ref` (prefixed with `$`):
|
|
|
698
702
|
<button @click="console.log($username.value)">Log Username</button>
|
|
699
703
|
```
|
|
700
704
|
|
|
701
|
-
##
|
|
702
|
-
|
|
703
|
-
The helium function accepts a single JavaScript object as an argument. This can include default variable values and functions that can then be called inside the JavaScript expressions.
|
|
704
|
-
|
|
705
|
-
### Setting Default Values
|
|
706
|
-
|
|
707
|
-
The following will set the count variable to an initial value of 29 and the name variable to "Helium":
|
|
708
|
-
|
|
709
|
-
```javascript
|
|
710
|
-
helium({
|
|
711
|
-
count: 29,
|
|
712
|
-
name: "Helium"
|
|
713
|
-
})
|
|
714
|
-
```
|
|
705
|
+
## Functions
|
|
715
706
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
```html
|
|
719
|
-
<p @text="count"></p> <!-- Shows: 29 -->
|
|
720
|
-
<p @text="name"></p> <!-- Shows: Helium -->
|
|
721
|
-
```
|
|
707
|
+
Functions can be imported using `@import` or defined using the `@data` attribute.
|
|
722
708
|
|
|
723
709
|
### Adding Functions
|
|
724
710
|
|
|
725
711
|
You can add functions that can be called from event handlers and other expressions:
|
|
726
712
|
|
|
727
|
-
```
|
|
728
|
-
|
|
713
|
+
```html
|
|
714
|
+
@data= "{
|
|
729
715
|
appendTo(element) {
|
|
730
716
|
const li = document.createElement("li")
|
|
731
717
|
li.textContent = "New Item"
|
|
@@ -738,7 +724,7 @@ helium({
|
|
|
738
724
|
currency: 'USD'
|
|
739
725
|
}).format(amount)
|
|
740
726
|
}
|
|
741
|
-
}
|
|
727
|
+
}"
|
|
742
728
|
```
|
|
743
729
|
|
|
744
730
|
Using these functions:
|
|
@@ -758,12 +744,12 @@ Using these functions:
|
|
|
758
744
|
|
|
759
745
|
❌ **This won't work as expected:**
|
|
760
746
|
|
|
761
|
-
```
|
|
762
|
-
|
|
747
|
+
```html
|
|
748
|
+
@data = "{
|
|
763
749
|
increment(n = 1) {
|
|
764
750
|
count += n // 'count' is not defined in this scope
|
|
765
751
|
}
|
|
766
|
-
}
|
|
752
|
+
}"
|
|
767
753
|
```
|
|
768
754
|
|
|
769
755
|
```html
|
|
@@ -773,12 +759,12 @@ helium({
|
|
|
773
759
|
✅ **Instead, pass variables as arguments:**
|
|
774
760
|
|
|
775
761
|
**Option 1: Pass specific variables**
|
|
776
|
-
```
|
|
777
|
-
|
|
762
|
+
```html
|
|
763
|
+
@data = "{
|
|
778
764
|
increment(currentCount, n = 1) {
|
|
779
765
|
return currentCount + n
|
|
780
766
|
}
|
|
781
|
-
}
|
|
767
|
+
}"
|
|
782
768
|
```
|
|
783
769
|
|
|
784
770
|
```html
|
|
@@ -789,8 +775,8 @@ helium({
|
|
|
789
775
|
|
|
790
776
|
This is the recommended approach when you need to update variables:
|
|
791
777
|
|
|
792
|
-
```
|
|
793
|
-
|
|
778
|
+
```html
|
|
779
|
+
@data = "{
|
|
794
780
|
increment(data, n = 1) {
|
|
795
781
|
data.count += n // Will trigger reactivity
|
|
796
782
|
},
|
|
@@ -800,7 +786,7 @@ helium({
|
|
|
800
786
|
data.name = ''
|
|
801
787
|
data.items = []
|
|
802
788
|
}
|
|
803
|
-
}
|
|
789
|
+
}"
|
|
804
790
|
```
|
|
805
791
|
|
|
806
792
|
```html
|
|
@@ -822,7 +808,6 @@ If you include [Idiomorph](https://github.com/bigskysoftware/idiomorph), Helium
|
|
|
822
808
|
<script src="https://unpkg.com/idiomorph@0.3.0/dist/idiomorph.min.js"></script>
|
|
823
809
|
<script type="module">
|
|
824
810
|
import helium from 'https://cdn.jsdelivr.net/gh/daz-codes/helium/helium.js';
|
|
825
|
-
helium();
|
|
826
811
|
</script>
|
|
827
812
|
```
|
|
828
813
|
|
|
@@ -884,24 +869,6 @@ Helium automatically integrates with Turbo Drive:
|
|
|
884
869
|
|
|
885
870
|
No additional configuration needed - just use Helium with Turbo normally.
|
|
886
871
|
|
|
887
|
-
### Manual Cleanup
|
|
888
|
-
|
|
889
|
-
If you need to manually clean up Helium (for example, when unmounting a section of your page):
|
|
890
|
-
|
|
891
|
-
```javascript
|
|
892
|
-
window.heliumTeardown()
|
|
893
|
-
```
|
|
894
|
-
|
|
895
|
-
This will:
|
|
896
|
-
- Disconnect the MutationObserver
|
|
897
|
-
- Remove all event listeners
|
|
898
|
-
- Clear all internal state
|
|
899
|
-
|
|
900
|
-
To reinitialize after teardown:
|
|
901
|
-
```javascript
|
|
902
|
-
helium()
|
|
903
|
-
```
|
|
904
|
-
|
|
905
872
|
## Security Considerations
|
|
906
873
|
|
|
907
874
|
### XSS Prevention
|
package/helium.js
CHANGED
|
@@ -57,7 +57,7 @@ fetch(url, {
|
|
|
57
57
|
...(!fd && method !== "GET" && {"Content-Type":"application/json"}),
|
|
58
58
|
...(sameOrigin && token ? {"X-CSRF-Token": token} : {})
|
|
59
59
|
},
|
|
60
|
-
body: method === "GET" ? null : (fd ? params : JSON.stringify(
|
|
60
|
+
body: method === "GET" ? null : (fd ? params : JSON.stringify(params)),
|
|
61
61
|
credentials: sameOrigin ? "same-origin" : "omit"
|
|
62
62
|
})
|
|
63
63
|
.then(res => {
|
|
@@ -180,7 +180,7 @@ const trackDependencies = (fn, el, excludeChanged = false) => {
|
|
|
180
180
|
});
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
-
function processElements(element) {
|
|
183
|
+
async function processElements(element) {
|
|
184
184
|
const newBindings = [];
|
|
185
185
|
const deferredBindings = [];
|
|
186
186
|
|
|
@@ -191,6 +191,20 @@ function processElements(element) {
|
|
|
191
191
|
HELIUM.bindings.set(val, b.calc ? [b,...(HELIUM.bindings.get(val) || [])] : [...(HELIUM.bindings.get(val) || []), b]);
|
|
192
192
|
b.calc ? newBindings.unshift(b) : newBindings.push(b);
|
|
193
193
|
};
|
|
194
|
+
|
|
195
|
+
heElements.forEach(async el => {
|
|
196
|
+
const importAttr = el.getAttribute("@import") || el.getAttribute("data-he-import");
|
|
197
|
+
if (importAttr) {
|
|
198
|
+
importAttr.split(",").map(m => m.trim()).forEach(async moduleName => {
|
|
199
|
+
try {
|
|
200
|
+
const module = await import(`helium_modules/${moduleName}.js`);
|
|
201
|
+
Object.keys(module).forEach(key => state[key] = module[key]);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(`Failed to import module: ${moduleName}`, error.message);
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
})
|
|
194
208
|
|
|
195
209
|
heElements.forEach(el => {
|
|
196
210
|
HELIUM.processed.add(el);
|
|
@@ -249,9 +263,6 @@ function processElements(element) {
|
|
|
249
263
|
else if (he(name, "effect")) {
|
|
250
264
|
deferredBindings.push({el, prop: null, fn: compile(value, true), keys: name.split(":").slice(1)});
|
|
251
265
|
}
|
|
252
|
-
else if (he(name, "import")) {
|
|
253
|
-
value.split(",").map(s => s.trim()).forEach(v => state[v] = window[v]);
|
|
254
|
-
}
|
|
255
266
|
else if (he(name, "init")) {
|
|
256
267
|
initFn = compile(value, true);
|
|
257
268
|
}
|