resonantjs 1.0.2 → 1.0.3

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.
@@ -4,6 +4,11 @@
4
4
  <title>Resonant.js Task Manager Demo</title>
5
5
  <script src="../resonant.js"></script>
6
6
  </head>
7
+ <style>
8
+ .done {
9
+ text-decoration: line-through;
10
+ }
11
+ </style>
7
12
  <body>
8
13
  <h1>Resonant.js Task Manager Demo</h1>
9
14
 
@@ -11,6 +16,9 @@
11
16
  <div>
12
17
  <h2>Add New Task</h2>
13
18
  <input type="text" placeholder="Task Name" res="taskName" />
19
+ <p>
20
+ Name: <span res="taskName"></span>
21
+ </p>
14
22
  <button onclick="addTask()">Add Task</button>
15
23
  </div>
16
24
 
@@ -43,6 +51,13 @@
43
51
  console.log(`Action taken: ${action} for ${task.name}`);
44
52
  });
45
53
 
54
+ function remove(task) {
55
+ const index = tasks.indexOf(task);
56
+ tasks.splice(index, 1);
57
+
58
+ //You could use as well, still trying to figure out if I want to leave this or not
59
+ }
60
+
46
61
  // Add a function to add a new task
47
62
  function addTask() {
48
63
  const newTask = { name: taskName, done: false };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "resonantjs",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
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
@@ -76,6 +76,7 @@ class Resonant {
76
76
  this._triggerCallbacks(variableName, action, item, property, oldValue);
77
77
  this.updateElement(variableName);
78
78
  this.updateConditionalsFor(variableName);
79
+ this.updateStylesFor(variableName);
79
80
  }, 0);
80
81
  }
81
82
  }
@@ -93,6 +94,7 @@ class Resonant {
93
94
  this._assignValueToData(variableName, newValue);
94
95
  this.updateElement(variableName);
95
96
  this.updateConditionalsFor(variableName);
97
+ this.updateStylesFor(variableName);
96
98
  if (!Array.isArray(newValue) && typeof newValue !== 'object') {
97
99
  this._queueUpdate(variableName, 'modified', this.data[variableName]);
98
100
  }
@@ -110,6 +112,7 @@ class Resonant {
110
112
  element.value = value;
111
113
  element.oninput = () => {
112
114
  this.data[variableName] = element.value;
115
+ this._queueUpdate(variableName, 'modified', this.data[variableName]);
113
116
  };
114
117
  element.setAttribute('data-resonant-bound', 'true');
115
118
  }
@@ -138,6 +141,16 @@ class Resonant {
138
141
  subEl.innerHTML = value[key];
139
142
  }
140
143
  subEl.setAttribute('data-resonant-bound', 'true');
144
+ } else {
145
+ if (subEl.tagName === 'INPUT' || subEl.tagName === 'TEXTAREA') {
146
+ if (subEl.type === 'checkbox') {
147
+ subEl.checked = value[key];
148
+ } else {
149
+ subEl.value = value[key];
150
+ }
151
+ } else {
152
+ subEl.innerHTML = value[key];
153
+ }
141
154
  }
142
155
  }
143
156
  });
@@ -147,6 +160,7 @@ class Resonant {
147
160
  });
148
161
 
149
162
  this.updateConditionalsFor(variableName);
163
+ this.updateStylesFor(variableName);
150
164
  }
151
165
 
152
166
  updateConditionalsFor(variableName) {
@@ -165,6 +179,23 @@ class Resonant {
165
179
  });
166
180
  }
167
181
 
182
+ updateStylesFor(variableName) {
183
+ const styleElements = document.querySelectorAll(`[res-style*="${variableName}"]`);
184
+ styleElements.forEach(styleElement => {
185
+ const styleCondition = styleElement.getAttribute('res-style');
186
+ try {
187
+ const styleClass = eval(styleCondition);
188
+ if (styleClass) {
189
+ styleElement.classList.add(styleClass);
190
+ } else {
191
+ styleElement.classList.remove(styleClass);
192
+ }
193
+ } catch (e) {
194
+ console.error(`Error evaluating style for ${variableName}: ${styleCondition}`, e);
195
+ }
196
+ });
197
+ }
198
+
168
199
  _renderArray(variableName, el) {
169
200
  let template = el.cloneNode(true);
170
201
  el.innerHTML = '';
@@ -200,18 +231,26 @@ class Resonant {
200
231
  subEl.innerHTML = instance[key];
201
232
  }
202
233
  subEl.setAttribute('data-resonant-bound', 'true');
234
+ } else {
235
+ if (subEl.tagName === 'INPUT' || subEl.tagName === 'TEXTAREA') {
236
+ if (subEl.type === 'checkbox') {
237
+ subEl.checked = instance[key];
238
+ } else {
239
+ subEl.value = instance[key];
240
+ }
241
+ } else {
242
+ subEl.innerHTML = instance[key];
243
+ }
203
244
  }
204
245
  }
205
246
  }
206
247
 
207
- // Handle res-onclick
208
248
  const onclickElements = clonedEl.querySelectorAll('[res-onclick], [res-onclick-remove]');
209
249
  onclickElements.forEach(onclickEl => {
210
250
  const functionName = onclickEl.getAttribute('res-onclick');
211
251
  const removeKey = onclickEl.getAttribute('res-onclick-remove');
212
252
 
213
253
  if (functionName) {
214
- // Remove any existing event listeners to prevent duplicates
215
254
  onclickEl.onclick = null;
216
255
 
217
256
  onclickEl.onclick = () => {
@@ -0,0 +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)}}