resonantjs 1.0.3 → 1.0.4

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.
@@ -16,9 +16,6 @@
16
16
  <div>
17
17
  <h2>Add New Task</h2>
18
18
  <input type="text" placeholder="Task Name" res="taskName" />
19
- <p>
20
- Name: <span res="taskName"></span>
21
- </p>
22
19
  <button onclick="addTask()">Add Task</button>
23
20
  </div>
24
21
 
@@ -26,10 +23,10 @@
26
23
  <div>
27
24
  <h2>Task List</h2>
28
25
  <ul res="tasks">
29
- <li>
26
+ <li res-style="tasks.done ? 'done' : ''">
30
27
  <input type="checkbox" res-prop="done" />
31
28
  <span res-prop="name"></span>
32
- <button res-onclick-remove="name">Remove</button>
29
+ <button res-onclick="remove">Remove</button>
33
30
  </li>
34
31
  </ul>
35
32
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "resonantjs",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "A lightweight JavaScript framework that enables reactive data-binding for building dynamic and responsive web applications. It simplifies creating interactive UIs by automatically updating the DOM when your data changes.",
5
5
  "main": "resonant.js",
6
6
  "repository": {
package/resonant.js CHANGED
@@ -69,6 +69,7 @@ class Resonant {
69
69
  }
70
70
 
71
71
  _queueUpdate(variableName, action, item, property, oldValue) {
72
+
72
73
  if (!this.pendingUpdates.has(variableName)) {
73
74
  this.pendingUpdates.add(variableName);
74
75
  setTimeout(() => {
@@ -106,10 +107,12 @@ class Resonant {
106
107
  const elements = document.querySelectorAll(`[res="${variableName}"]`);
107
108
  const value = this.data[variableName];
108
109
 
110
+
111
+
109
112
  elements.forEach(element => {
110
113
  if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
114
+ element.value = value;
111
115
  if (!element.hasAttribute('data-resonant-bound')) {
112
- element.value = value;
113
116
  element.oninput = () => {
114
117
  this.data[variableName] = element.value;
115
118
  this._queueUpdate(variableName, 'modified', this.data[variableName]);
@@ -181,14 +184,40 @@ class Resonant {
181
184
 
182
185
  updateStylesFor(variableName) {
183
186
  const styleElements = document.querySelectorAll(`[res-style*="${variableName}"]`);
187
+
184
188
  styleElements.forEach(styleElement => {
185
- const styleCondition = styleElement.getAttribute('res-style');
189
+ let styleCondition = styleElement.getAttribute('res-style');
186
190
  try {
187
- const styleClass = eval(styleCondition);
188
- if (styleClass) {
189
- styleElement.classList.add(styleClass);
191
+ let parent = styleElement;
192
+ let index = null;
193
+ while (parent && !index) {
194
+ index = parent.getAttribute('res-index');
195
+ parent = parent.parentElement;
196
+ }
197
+
198
+ if (index !== null) {
199
+ const item = this.data[variableName][index];
200
+ styleCondition = styleCondition.replace(new RegExp(`\\b${variableName}\\b`, 'g'), 'item');
201
+ const styleClass = new Function('item', `return ${styleCondition}`)(item);
202
+
203
+ if (styleClass) {
204
+ styleElement.classList.add(styleClass);
205
+ } else {
206
+ var elementHasStyle = styleElement.classList.contains(styleClass);
207
+ if (elementHasStyle) {
208
+ styleElement.classList.remove(styleClass);
209
+ }
210
+ }
190
211
  } else {
191
- styleElement.classList.remove(styleClass);
212
+ const styleClass = eval(styleCondition);
213
+ if (styleClass) {
214
+ styleElement.classList.add(styleClass);
215
+ } else {
216
+ var elementHasStyle = styleElement.classList.contains(styleClass);
217
+ if (elementHasStyle) {
218
+ styleElement.classList.remove(styleClass);
219
+ }
220
+ }
192
221
  }
193
222
  } catch (e) {
194
223
  console.error(`Error evaluating style for ${variableName}: ${styleCondition}`, e);
package/resonant.min.js CHANGED
@@ -1 +1 @@
1
- class Resonant{constructor(){this.data={},this.callbacks={},this.pendingUpdates=new Set}add(e,t){this._assignValueToData(e,t),this._defineProperty(e),this.updateElement(e)}addAll(e){Object.entries(e).forEach(([e,t])=>{this.add(e,t)})}_assignValueToData(e,t){Array.isArray(t)?this.data[e]=this._createArray(e,t):this.data[e]="object"==typeof t?this._createObject(e,t):t}_createObject(r,e){return e[Symbol("isProxy")]=!0,new Proxy(e,{set:(e,t,a)=>{var s;return e[t]!==a&&(s=e[t],e[t]=a,this._queueUpdate(r,"modified",e,t,s)),!0}})}_createArray(i,e){const n=this;return new Proxy(e,{get(e,t){return"object"!=typeof e[t]||e[t][Symbol("isProxy")]||(e[t]=n._createObject(i+`[${t}]`,e[t])),e[t]},set(e,t,a){var s,r;return e[t]!==a&&(s=e.hasOwnProperty(t)?"modified":"added",r=e[t],e[t]=a,n._queueUpdate(i,s,e[t],t,r)),!0},deleteProperty(e,t){var a=e[t];return e.splice(t,1),n._queueUpdate(i,"removed",a,t),!0}})}_queueUpdate(e,t,a,s,r){this.pendingUpdates.has(e)||(this.pendingUpdates.add(e),setTimeout(()=>{this.pendingUpdates.delete(e),this._triggerCallbacks(e,t,a,s,r),this.updateElement(e),this.updateConditionalsFor(e),this.updateStylesFor(e)},0))}_triggerCallbacks(t,a,s,r,i){this.callbacks[t]&&this.callbacks[t].forEach(e=>e(this.data[t],s,a,r,i))}_defineProperty(t){Object.defineProperty(window,t,{get:()=>this.data[t],set:e=>{this._assignValueToData(t,e),this.updateElement(t),this.updateConditionalsFor(t),this.updateStylesFor(t),Array.isArray(e)||"object"==typeof e||this._queueUpdate(t,"modified",this.data[t])}})}updateElement(a){var e=document.querySelectorAll(`[res="${a}"]`);const s=this.data[a];e.forEach(e=>{"INPUT"===e.tagName||"TEXTAREA"===e.tagName?e.hasAttribute("data-resonant-bound")||(e.value=s,e.oninput=()=>{this.data[a]=e.value,this._queueUpdate(a,"modified",this.data[a])},e.setAttribute("data-resonant-bound","true")):Array.isArray(s)?(e.querySelectorAll(`[res="${a}"][res-rendered=true]`).forEach(e=>e.remove()),this._renderArray(a,e)):"object"==typeof s?e.querySelectorAll("[res-prop]").forEach(e=>{const t=e.getAttribute("res-prop");t&&t in s&&(e.hasAttribute("data-resonant-bound")?"INPUT"===e.tagName||"TEXTAREA"===e.tagName?"checkbox"===e.type?e.checked=s[t]:e.value=s[t]:e.innerHTML=s[t]:("INPUT"===e.tagName||"TEXTAREA"===e.tagName?"checkbox"===e.type?(e.checked=s[t],e.onchange=()=>{this.data[a][t]=e.checked}):(e.value=s[t],e.oninput=()=>{this.data[a][t]=e.value}):e.innerHTML=s[t],e.setAttribute("data-resonant-bound","true")))}):e.innerHTML=s}),this.updateConditionalsFor(a),this.updateStylesFor(a)}updateConditionalsFor(variableName){const conditionalElements=document.querySelectorAll(`[res-conditional*="${variableName}"]`);conditionalElements.forEach(conditionalElement=>{const condition=conditionalElement.getAttribute("res-conditional");try{eval(condition)?conditionalElement.style.display="":conditionalElement.style.display="none"}catch(e){}})}updateStylesFor(variableName){const styleElements=document.querySelectorAll(`[res-style*="${variableName}"]`);styleElements.forEach(styleElement=>{const styleCondition=styleElement.getAttribute("res-style");try{const styleClass=eval(styleCondition);styleClass?styleElement.classList.add(styleClass):styleElement.classList.remove(styleClass)}catch(e){}})}_renderArray(r,i){let n=i.cloneNode(!0);i.innerHTML="",window[r+"_template"]?n=window[r+"_template"]:window[r+"_template"]=n,this.data[r].forEach((s,e)=>{var t=n.cloneNode(!0);t.setAttribute("res-index",e);for(let e in s){const a=t.querySelector(`[res-prop="${e}"]`);a&&(a.hasAttribute("data-resonant-bound")?"INPUT"===a.tagName||"TEXTAREA"===a.tagName?"checkbox"===a.type?a.checked=s[e]:a.value=s[e]:a.innerHTML=s[e]:("INPUT"===a.tagName||"TEXTAREA"===a.tagName?"checkbox"===a.type?(a.checked=s[e],a.onchange=()=>{s[e]=a.checked,this._queueUpdate(r,"modified",s,e,s[e])}):(a.value=s[e],a.oninput=()=>{s[e]=a.value,this._queueUpdate(r,"modified",s,e,s[e])}):a.innerHTML=s[e],a.setAttribute("data-resonant-bound","true")))}t.querySelectorAll("[res-onclick], [res-onclick-remove]").forEach(e=>{const t=e.getAttribute("res-onclick"),a=e.getAttribute("res-onclick-remove");t&&(e.onclick=null,e.onclick=()=>{new Function("item",`return ${t}(item)`)(s)}),a&&(e.onclick=null,e.onclick=()=>{var e=this.data[r].findIndex(e=>e[a]===s[a]);-1!==e&&this.data[r].splice(e,1)})}),t.setAttribute("res-rendered",!0),i.appendChild(t)})}addCallback(e,t){this.callbacks[e]||(this.callbacks[e]=[]),this.callbacks[e].push(t)}}
1
+ class Resonant{constructor(){this.data={},this.callbacks={},this.pendingUpdates=new Set}add(e,t){this._assignValueToData(e,t),this._defineProperty(e),this.updateElement(e)}addAll(e){Object.entries(e).forEach(([e,t])=>{this.add(e,t)})}_assignValueToData(e,t){Array.isArray(t)?this.data[e]=this._createArray(e,t):this.data[e]="object"==typeof t?this._createObject(e,t):t}_createObject(n,e){return e[Symbol("isProxy")]=!0,new Proxy(e,{set:(e,t,a)=>{var s;return e[t]!==a&&(s=e[t],e[t]=a,this._queueUpdate(n,"modified",e,t,s)),!0}})}_createArray(l,e){const i=this;return new Proxy(e,{get(e,t){return"object"!=typeof e[t]||e[t][Symbol("isProxy")]||(e[t]=i._createObject(l+`[${t}]`,e[t])),e[t]},set(e,t,a){var s,n;return e[t]!==a&&(s=e.hasOwnProperty(t)?"modified":"added",n=e[t],e[t]=a,i._queueUpdate(l,s,e[t],t,n)),!0},deleteProperty(e,t){var a=e[t];return e.splice(t,1),i._queueUpdate(l,"removed",a,t),!0}})}_queueUpdate(e,t,a,s,n){this.pendingUpdates.has(e)||(this.pendingUpdates.add(e),setTimeout(()=>{this.pendingUpdates.delete(e),this._triggerCallbacks(e,t,a,s,n),this.updateElement(e),this.updateConditionalsFor(e),this.updateStylesFor(e)},0))}_triggerCallbacks(t,a,s,n,l){this.callbacks[t]&&this.callbacks[t].forEach(e=>e(this.data[t],s,a,n,l))}_defineProperty(t){Object.defineProperty(window,t,{get:()=>this.data[t],set:e=>{this._assignValueToData(t,e),this.updateElement(t),this.updateConditionalsFor(t),this.updateStylesFor(t),Array.isArray(e)||"object"==typeof e||this._queueUpdate(t,"modified",this.data[t])}})}updateElement(a){var e=document.querySelectorAll(`[res="${a}"]`);const s=this.data[a];e.forEach(e=>{"INPUT"===e.tagName||"TEXTAREA"===e.tagName?(e.value=s,e.hasAttribute("data-resonant-bound")||(e.oninput=()=>{this.data[a]=e.value,this._queueUpdate(a,"modified",this.data[a])},e.setAttribute("data-resonant-bound","true"))):Array.isArray(s)?(e.querySelectorAll(`[res="${a}"][res-rendered=true]`).forEach(e=>e.remove()),this._renderArray(a,e)):"object"==typeof s?e.querySelectorAll("[res-prop]").forEach(e=>{const t=e.getAttribute("res-prop");t&&t in s&&(e.hasAttribute("data-resonant-bound")?"INPUT"===e.tagName||"TEXTAREA"===e.tagName?"checkbox"===e.type?e.checked=s[t]:e.value=s[t]:e.innerHTML=s[t]:("INPUT"===e.tagName||"TEXTAREA"===e.tagName?"checkbox"===e.type?(e.checked=s[t],e.onchange=()=>{this.data[a][t]=e.checked}):(e.value=s[t],e.oninput=()=>{this.data[a][t]=e.value}):e.innerHTML=s[t],e.setAttribute("data-resonant-bound","true")))}):e.innerHTML=s}),this.updateConditionalsFor(a),this.updateStylesFor(a)}updateConditionalsFor(variableName){const conditionalElements=document.querySelectorAll(`[res-conditional*="${variableName}"]`);conditionalElements.forEach(conditionalElement=>{const condition=conditionalElement.getAttribute("res-conditional");try{eval(condition)?conditionalElement.style.display="":conditionalElement.style.display="none"}catch(e){}})}updateStylesFor(variableName){const styleElements=document.querySelectorAll(`[res-style*="${variableName}"]`);styleElements.forEach(styleElement=>{let styleCondition=styleElement.getAttribute("res-style");try{let parent=styleElement,index=null;for(;parent&&!index;)index=parent.getAttribute("res-index"),parent=parent.parentElement;if(null!==index){const item=this.data[variableName][index],styleClass=(styleCondition=styleCondition.replace(new RegExp(`\\b${variableName}\\b`,"g"),"item"),new Function("item","return "+styleCondition)(item));var elementHasStyle;styleClass?styleElement.classList.add(styleClass):(elementHasStyle=styleElement.classList.contains(styleClass),elementHasStyle&&styleElement.classList.remove(styleClass))}else{const styleClass=eval(styleCondition);var elementHasStyle;styleClass?styleElement.classList.add(styleClass):(elementHasStyle=styleElement.classList.contains(styleClass),elementHasStyle&&styleElement.classList.remove(styleClass))}}catch(e){}})}_renderArray(n,l){let i=l.cloneNode(!0);l.innerHTML="",window[n+"_template"]?i=window[n+"_template"]:window[n+"_template"]=i,this.data[n].forEach((s,e)=>{var t=i.cloneNode(!0);t.setAttribute("res-index",e);for(let e in s){const a=t.querySelector(`[res-prop="${e}"]`);a&&(a.hasAttribute("data-resonant-bound")?"INPUT"===a.tagName||"TEXTAREA"===a.tagName?"checkbox"===a.type?a.checked=s[e]:a.value=s[e]:a.innerHTML=s[e]:("INPUT"===a.tagName||"TEXTAREA"===a.tagName?"checkbox"===a.type?(a.checked=s[e],a.onchange=()=>{s[e]=a.checked,this._queueUpdate(n,"modified",s,e,s[e])}):(a.value=s[e],a.oninput=()=>{s[e]=a.value,this._queueUpdate(n,"modified",s,e,s[e])}):a.innerHTML=s[e],a.setAttribute("data-resonant-bound","true")))}t.querySelectorAll("[res-onclick], [res-onclick-remove]").forEach(e=>{const t=e.getAttribute("res-onclick"),a=e.getAttribute("res-onclick-remove");t&&(e.onclick=null,e.onclick=()=>{new Function("item",`return ${t}(item)`)(s)}),a&&(e.onclick=null,e.onclick=()=>{var e=this.data[n].findIndex(e=>e[a]===s[a]);-1!==e&&this.data[n].splice(e,1)})}),t.setAttribute("res-rendered",!0),l.appendChild(t)})}addCallback(e,t){this.callbacks[e]||(this.callbacks[e]=[]),this.callbacks[e].push(t)}}