@daz4126/helium 0.23.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 +18 -58
- package/helium.js +20 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,11 +18,10 @@ It's really simple to use - just sprinkle the magic @attributes into your HTML a
|
|
|
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
|
|
@@ -705,34 +702,16 @@ Object containing all elements marked with `@ref` (prefixed with `$`):
|
|
|
705
702
|
<button @click="console.log($username.value)">Log Username</button>
|
|
706
703
|
```
|
|
707
704
|
|
|
708
|
-
##
|
|
705
|
+
## Functions
|
|
709
706
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
### Setting Default Values
|
|
713
|
-
|
|
714
|
-
The following will set the count variable to an initial value of 29 and the name variable to "Helium":
|
|
715
|
-
|
|
716
|
-
```javascript
|
|
717
|
-
helium({
|
|
718
|
-
count: 29,
|
|
719
|
-
name: "Helium"
|
|
720
|
-
})
|
|
721
|
-
```
|
|
722
|
-
|
|
723
|
-
These variables will be available in all Helium expressions:
|
|
724
|
-
|
|
725
|
-
```html
|
|
726
|
-
<p @text="count"></p> <!-- Shows: 29 -->
|
|
727
|
-
<p @text="name"></p> <!-- Shows: Helium -->
|
|
728
|
-
```
|
|
707
|
+
Functions can be imported using `@import` or defined using the `@data` attribute.
|
|
729
708
|
|
|
730
709
|
### Adding Functions
|
|
731
710
|
|
|
732
711
|
You can add functions that can be called from event handlers and other expressions:
|
|
733
712
|
|
|
734
|
-
```
|
|
735
|
-
|
|
713
|
+
```html
|
|
714
|
+
@data= "{
|
|
736
715
|
appendTo(element) {
|
|
737
716
|
const li = document.createElement("li")
|
|
738
717
|
li.textContent = "New Item"
|
|
@@ -745,7 +724,7 @@ helium({
|
|
|
745
724
|
currency: 'USD'
|
|
746
725
|
}).format(amount)
|
|
747
726
|
}
|
|
748
|
-
}
|
|
727
|
+
}"
|
|
749
728
|
```
|
|
750
729
|
|
|
751
730
|
Using these functions:
|
|
@@ -765,12 +744,12 @@ Using these functions:
|
|
|
765
744
|
|
|
766
745
|
❌ **This won't work as expected:**
|
|
767
746
|
|
|
768
|
-
```
|
|
769
|
-
|
|
747
|
+
```html
|
|
748
|
+
@data = "{
|
|
770
749
|
increment(n = 1) {
|
|
771
750
|
count += n // 'count' is not defined in this scope
|
|
772
751
|
}
|
|
773
|
-
}
|
|
752
|
+
}"
|
|
774
753
|
```
|
|
775
754
|
|
|
776
755
|
```html
|
|
@@ -780,12 +759,12 @@ helium({
|
|
|
780
759
|
✅ **Instead, pass variables as arguments:**
|
|
781
760
|
|
|
782
761
|
**Option 1: Pass specific variables**
|
|
783
|
-
```
|
|
784
|
-
|
|
762
|
+
```html
|
|
763
|
+
@data = "{
|
|
785
764
|
increment(currentCount, n = 1) {
|
|
786
765
|
return currentCount + n
|
|
787
766
|
}
|
|
788
|
-
}
|
|
767
|
+
}"
|
|
789
768
|
```
|
|
790
769
|
|
|
791
770
|
```html
|
|
@@ -796,8 +775,8 @@ helium({
|
|
|
796
775
|
|
|
797
776
|
This is the recommended approach when you need to update variables:
|
|
798
777
|
|
|
799
|
-
```
|
|
800
|
-
|
|
778
|
+
```html
|
|
779
|
+
@data = "{
|
|
801
780
|
increment(data, n = 1) {
|
|
802
781
|
data.count += n // Will trigger reactivity
|
|
803
782
|
},
|
|
@@ -807,7 +786,7 @@ helium({
|
|
|
807
786
|
data.name = ''
|
|
808
787
|
data.items = []
|
|
809
788
|
}
|
|
810
|
-
}
|
|
789
|
+
}"
|
|
811
790
|
```
|
|
812
791
|
|
|
813
792
|
```html
|
|
@@ -829,7 +808,6 @@ If you include [Idiomorph](https://github.com/bigskysoftware/idiomorph), Helium
|
|
|
829
808
|
<script src="https://unpkg.com/idiomorph@0.3.0/dist/idiomorph.min.js"></script>
|
|
830
809
|
<script type="module">
|
|
831
810
|
import helium from 'https://cdn.jsdelivr.net/gh/daz-codes/helium/helium.js';
|
|
832
|
-
helium();
|
|
833
811
|
</script>
|
|
834
812
|
```
|
|
835
813
|
|
|
@@ -891,24 +869,6 @@ Helium automatically integrates with Turbo Drive:
|
|
|
891
869
|
|
|
892
870
|
No additional configuration needed - just use Helium with Turbo normally.
|
|
893
871
|
|
|
894
|
-
### Manual Cleanup
|
|
895
|
-
|
|
896
|
-
If you need to manually clean up Helium (for example, when unmounting a section of your page):
|
|
897
|
-
|
|
898
|
-
```javascript
|
|
899
|
-
window.heliumTeardown()
|
|
900
|
-
```
|
|
901
|
-
|
|
902
|
-
This will:
|
|
903
|
-
- Disconnect the MutationObserver
|
|
904
|
-
- Remove all event listeners
|
|
905
|
-
- Clear all internal state
|
|
906
|
-
|
|
907
|
-
To reinitialize after teardown:
|
|
908
|
-
```javascript
|
|
909
|
-
helium()
|
|
910
|
-
```
|
|
911
|
-
|
|
912
872
|
## Security Considerations
|
|
913
873
|
|
|
914
874
|
### XSS Prevention
|
package/helium.js
CHANGED
|
@@ -34,7 +34,7 @@ window.helium = function() {
|
|
|
34
34
|
|
|
35
35
|
const update = (data,targets,actions,template) => {
|
|
36
36
|
const newTargets = [];
|
|
37
|
-
targets
|
|
37
|
+
targets.forEach((target,i) => {
|
|
38
38
|
const element = target instanceof Node ? target : (HELIUM.refs.get(target.trim()) || $(target.trim()));
|
|
39
39
|
if(element){
|
|
40
40
|
const content = template ? template(data) : data;
|
|
@@ -46,7 +46,7 @@ window.helium = function() {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const ajax = (url,method,options={},params={}) => {
|
|
49
|
-
if(options.loading
|
|
49
|
+
if(options.loading) options.target = update(options.loading,options.target,options.action) || options.target;
|
|
50
50
|
const fd = params instanceof FormData, token = document.querySelector('meta[name="csrf-token"]')?.content;
|
|
51
51
|
const path = new URL(url, window.location.href);
|
|
52
52
|
const sameOrigin = path.origin === window.location.origin;
|
|
@@ -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
|
}
|
|
@@ -278,9 +289,9 @@ function processElements(element) {
|
|
|
278
289
|
if (!mods.includes("outside") || !el.contains(e.target)) {
|
|
279
290
|
if (isHttpMethod) {
|
|
280
291
|
const getAttr = name => el.getAttribute(`data-he-${name}`) || el.getAttribute(`@${name}`);
|
|
281
|
-
const pairs = getAttr('target')
|
|
282
|
-
const target = pairs
|
|
283
|
-
const action = pairs
|
|
292
|
+
const pairs = (getAttr('target') || "").split(",").map(p => p.split(":").map(s => s.trim()));
|
|
293
|
+
const target = pairs.map(([target]) => target);
|
|
294
|
+
const action = pairs.map(([, action]) => action);
|
|
284
295
|
const options = {
|
|
285
296
|
...(getAttr("options") && parseEx(getAttr("options") || "{}")),
|
|
286
297
|
...(target && { target }),
|