clapton 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -7
  3. data/lib/clapton/javascripts/dist/client.js +12 -4
  4. data/lib/clapton/javascripts/dist/components-for-test.js +49 -45
  5. data/lib/clapton/javascripts/dist/components.js +49 -45
  6. data/lib/clapton/javascripts/src/channel/clapton-channel.js +1 -1
  7. data/lib/clapton/javascripts/src/client.ts +9 -2
  8. data/lib/clapton/javascripts/src/components/block-quote.spec.ts +6 -6
  9. data/lib/clapton/javascripts/src/components/block-quote.ts +2 -2
  10. data/lib/clapton/javascripts/src/components/bold.spec.ts +3 -3
  11. data/lib/clapton/javascripts/src/components/bold.ts +2 -2
  12. data/lib/clapton/javascripts/src/components/box.spec.ts +6 -6
  13. data/lib/clapton/javascripts/src/components/box.ts +2 -2
  14. data/lib/clapton/javascripts/src/components/button.spec.ts +5 -5
  15. data/lib/clapton/javascripts/src/components/button.ts +2 -2
  16. data/lib/clapton/javascripts/src/components/checkbox.spec.ts +3 -3
  17. data/lib/clapton/javascripts/src/components/checkbox.ts +1 -1
  18. data/lib/clapton/javascripts/src/components/code.spec.ts +6 -6
  19. data/lib/clapton/javascripts/src/components/code.ts +2 -2
  20. data/lib/clapton/javascripts/src/components/component.ts +8 -4
  21. data/lib/clapton/javascripts/src/components/datetime-field.spec.ts +3 -3
  22. data/lib/clapton/javascripts/src/components/datetime-field.ts +1 -1
  23. data/lib/clapton/javascripts/src/components/element.spec.ts +6 -6
  24. data/lib/clapton/javascripts/src/components/element.ts +2 -2
  25. data/lib/clapton/javascripts/src/components/embed.spec.ts +1 -1
  26. data/lib/clapton/javascripts/src/components/embed.ts +1 -1
  27. data/lib/clapton/javascripts/src/components/emphasis.spec.ts +6 -6
  28. data/lib/clapton/javascripts/src/components/emphasis.ts +2 -2
  29. data/lib/clapton/javascripts/src/components/form.spec.ts +6 -6
  30. data/lib/clapton/javascripts/src/components/form.ts +2 -2
  31. data/lib/clapton/javascripts/src/components/heading.spec.ts +6 -6
  32. data/lib/clapton/javascripts/src/components/heading.ts +2 -2
  33. data/lib/clapton/javascripts/src/components/image.spec.ts +2 -2
  34. data/lib/clapton/javascripts/src/components/image.ts +1 -1
  35. data/lib/clapton/javascripts/src/components/link.spec.ts +6 -6
  36. data/lib/clapton/javascripts/src/components/link.ts +2 -2
  37. data/lib/clapton/javascripts/src/components/list-item.spec.ts +6 -6
  38. data/lib/clapton/javascripts/src/components/list-item.ts +2 -2
  39. data/lib/clapton/javascripts/src/components/list.spec.ts +6 -6
  40. data/lib/clapton/javascripts/src/components/list.ts +2 -2
  41. data/lib/clapton/javascripts/src/components/ordered-list.spec.ts +6 -6
  42. data/lib/clapton/javascripts/src/components/ordered-list.ts +2 -2
  43. data/lib/clapton/javascripts/src/components/paragraph.spec.ts +6 -6
  44. data/lib/clapton/javascripts/src/components/paragraph.ts +2 -2
  45. data/lib/clapton/javascripts/src/components/presets.ts +1 -1
  46. data/lib/clapton/javascripts/src/components/quote.spec.ts +6 -6
  47. data/lib/clapton/javascripts/src/components/quote.ts +2 -2
  48. data/lib/clapton/javascripts/src/components/radio-button.spec.ts +3 -3
  49. data/lib/clapton/javascripts/src/components/radio-button.ts +1 -1
  50. data/lib/clapton/javascripts/src/components/select.spec.ts +6 -6
  51. data/lib/clapton/javascripts/src/components/select.ts +2 -2
  52. data/lib/clapton/javascripts/src/components/span.spec.ts +6 -6
  53. data/lib/clapton/javascripts/src/components/span.ts +2 -2
  54. data/lib/clapton/javascripts/src/components/text-area.spec.ts +3 -3
  55. data/lib/clapton/javascripts/src/components/text-area.ts +1 -1
  56. data/lib/clapton/javascripts/src/components/text-field.spec.ts +3 -3
  57. data/lib/clapton/javascripts/src/components/text-field.ts +1 -1
  58. data/lib/clapton/javascripts/src/components/text.spec.ts +2 -2
  59. data/lib/clapton/javascripts/src/components/text.ts +1 -1
  60. data/lib/clapton/javascripts/src/dom/update-component.ts +1 -1
  61. data/lib/clapton/test_helper/base.rb +1 -1
  62. data/lib/clapton/version.rb +1 -1
  63. data/lib/rails/generators/clapton_generator.rb +2 -0
  64. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f88a3c4f18d2b7b88414e36366129851c5edf38ce1fdefb0ff17b81a34ff1f1
4
- data.tar.gz: 7fa52de397a29a416b48cdc1a50d291618546ba38e0adf014b2907c57eff6982
3
+ metadata.gz: 75a7ef3678828970fe19e84f474a8480a2b3aef73bb7cad48d771952560dc26f
4
+ data.tar.gz: d183141896d4742b8481d03db28e1d38d1b0ba3d447c8a0c4444d46fa06cec72
5
5
  SHA512:
6
- metadata.gz: 55b858f91dc9bef90d79e8ea714ece958e85af9dacb2e6d99a1f3e79e146f2c612c8536d615b21b8fe6d87b3a31f7acfb07f5f9d0c3650f91b3bc0eb57d3b7d6
7
- data.tar.gz: 9c2f938f18a19c296bc3d2c2ea513ca8f1f964266c377d00e28c8a51676fbf4dae33c9ef42d5b2a97ba15159e2496bbf4480e54ccd605c030446c19a2835c6c3
6
+ metadata.gz: d22f7c4bd63092f2f1e701f91d8e86d19bd7a7b1f2ea0fe2bc42709d94b84737e34eaacad59b3c58485407932c372b9535cf2649905f81c8a8e2f17b8bfcba3c
7
+ data.tar.gz: ea1047109748b7b047c96823727fc3d681d74463d04ca97bb28bac3b354c1b4d3474a9ab001fb03be1029f769cf6fa0ccc69536b24131f75481ae673bd2b08b9
data/README.md CHANGED
@@ -34,14 +34,14 @@ To use a Clapton component in your view:
34
34
  # app/components/task_list_component.rb
35
35
  class TaskListComponent < Clapton::Component
36
36
  def render
37
+ box = c.box
37
38
  @state.tasks.each do |task|
38
- @root.add(TaskItemComponent.new(id: task[:id], title: task[:title], due: task[:due], done: task[:done]))
39
+ box.add(TaskItemComponent.new(id: task[:id], title: task[:title], due: task[:due], done: task[:done]))
39
40
  end
40
41
  btn = c.button
41
42
  btn.add(c.text("Add Task"))
42
43
  btn.add_action(:click, :TaskListState, :add_task)
43
- @root.add(btn)
44
- @root.render
44
+ box.add(btn)
45
45
  end
46
46
  end
47
47
 
@@ -51,6 +51,7 @@ end
51
51
  # app/components/task_item_component.rb
52
52
  class TaskItemComponent < Clapton::Component
53
53
  def render
54
+ box = c.box
54
55
  btn = c.button
55
56
  btn.add(c.text(@state.done ? "✅" : "🟩"))
56
57
  btn.add_action(:click, :TaskListState, :toggle_done)
@@ -61,8 +62,7 @@ class TaskItemComponent < Clapton::Component
61
62
  dt = c.datetime(@state, :due)
62
63
  dt.add_action(:input, :TaskListState, :update_due)
63
64
 
64
- @root.add(btn).add(tf).add(dt)
65
- @root.render
65
+ box.add(btn).add(tf).add(dt)
66
66
  end
67
67
  end
68
68
 
@@ -171,8 +171,8 @@ The `render` event is a special event that is triggered when the component is re
171
171
  class TaskListComponent < Clapton::Component
172
172
  def render
173
173
  # ...
174
- @root.add_action(:render, :TaskListState, :add_empty_task, debounce: 500)
175
- @root.render
174
+ box = c.box
175
+ box.add_action(:render, :TaskListState, :add_empty_task, debounce: 500)
176
176
  end
177
177
  end
178
178
  ```
@@ -1291,7 +1291,7 @@ const updateComponent = async (component, state, property, target) => {
1291
1291
  const module = await import(`${componentName}`);
1292
1292
  const ComponentClass = module[componentName];
1293
1293
  const instance = new ComponentClass(state, component.dataset.id);
1294
- morphdom(component, instance.render);
1294
+ morphdom(component, instance.renderWrapper);
1295
1295
  };
1296
1296
 
1297
1297
  const initializeInputs = () => {
@@ -1324,7 +1324,7 @@ const claptonChannel = consumer.subscriptions.create("Clapton::ClaptonChannel",
1324
1324
  const component = document.querySelector(`[data-id="${data.component.id}"]`);
1325
1325
  const module = await import(`${data.component.name}`);
1326
1326
  const instance = new module[data.component.name](data.state, data.component.id, errors);
1327
- morphdom(component, instance.render, {
1327
+ morphdom(component, instance.renderWrapper, {
1328
1328
  onBeforeElUpdated: (_fromEl, toEl) => {
1329
1329
  toEl.setAttribute("data-set-event-handler", "true");
1330
1330
  return true;
@@ -1424,13 +1424,21 @@ const initializeComponents = async () => {
1424
1424
  }
1425
1425
  };
1426
1426
  const createAndAppendComponent = async (component, element) => {
1427
+ if (!element) {
1428
+ return;
1429
+ }
1427
1430
  const componentDom = document.createElement('div');
1428
1431
  const module = await import(`${component.component}`);
1429
1432
  const instance = new module[component.component](component.state);
1430
- componentDom.innerHTML = instance.render;
1433
+ componentDom.innerHTML = instance.renderWrapper;
1431
1434
  const firstChild = componentDom.firstChild;
1432
1435
  if (firstChild) {
1433
- element.appendChild(firstChild);
1436
+ if (element.children.length > 0) {
1437
+ element.appendChild(firstChild);
1438
+ }
1439
+ else {
1440
+ element.outerHTML = firstChild.outerHTML;
1441
+ }
1434
1442
  }
1435
1443
  };
1436
1444
  document.addEventListener("DOMContentLoaded", async () => {
@@ -48,8 +48,8 @@ var Clapton = (function (exports) {
48
48
  this.children = [];
49
49
  this.attributes = attributes;
50
50
  }
51
- get render() {
52
- return `<blockquote ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</blockquote>`;
51
+ get renderWrapper() {
52
+ return `<blockquote ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</blockquote>`;
53
53
  }
54
54
  add(child) {
55
55
  this.children.push(child);
@@ -66,8 +66,8 @@ var Clapton = (function (exports) {
66
66
  this.children.push(child);
67
67
  return this;
68
68
  }
69
- get render() {
70
- return `<div ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</div>`;
69
+ get renderWrapper() {
70
+ return `<div ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</div>`;
71
71
  }
72
72
  add_action(eventType, stateName, fnName, options = {}) {
73
73
  this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${eventType}->${stateName}#${fnName}@${options.debounce || 0}`;
@@ -80,8 +80,8 @@ var Clapton = (function (exports) {
80
80
  this.children = [];
81
81
  this.attributes = attributes;
82
82
  }
83
- get render() {
84
- return `<strong ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</strong>`;
83
+ get renderWrapper() {
84
+ return `<strong ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</strong>`;
85
85
  }
86
86
  add(child) {
87
87
  this.children.push(child);
@@ -98,8 +98,8 @@ var Clapton = (function (exports) {
98
98
  this.children.push(child);
99
99
  return this;
100
100
  }
101
- get render() {
102
- return `<button ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</button>`;
101
+ get renderWrapper() {
102
+ return `<button ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</button>`;
103
103
  }
104
104
  add_action(event, klass, fn, options = {}) {
105
105
  this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
@@ -114,7 +114,7 @@ var Clapton = (function (exports) {
114
114
  this.attribute = attribute;
115
115
  this.attributes["data-attribute"] = attribute;
116
116
  }
117
- get render() {
117
+ get renderWrapper() {
118
118
  return `<input type='checkbox' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
119
119
  }
120
120
  add_action(event, klass, fn, options = {}) {
@@ -128,8 +128,8 @@ var Clapton = (function (exports) {
128
128
  this.children = [];
129
129
  this.attributes = attributes;
130
130
  }
131
- get render() {
132
- return `<code ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</code>`;
131
+ get renderWrapper() {
132
+ return `<code ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</code>`;
133
133
  }
134
134
  add(child) {
135
135
  this.children.push(child);
@@ -145,7 +145,7 @@ var Clapton = (function (exports) {
145
145
  this.attributes = attributes;
146
146
  this.attributes["data-attribute"] = attribute;
147
147
  }
148
- get render() {
148
+ get renderWrapper() {
149
149
  const value = this.state[this.attribute] ? this.datetime_local_value(this.state[this.attribute]) : "";
150
150
  return `<input type='datetime-local' ${htmlAttributes(this.attributes)} value='${value}'/>`;
151
151
  }
@@ -185,8 +185,8 @@ var Clapton = (function (exports) {
185
185
  this.type = type;
186
186
  this.attributes = attributes;
187
187
  }
188
- get render() {
189
- return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</${this.type}>`;
188
+ get renderWrapper() {
189
+ return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</${this.type}>`;
190
190
  }
191
191
  add(child) {
192
192
  this.children.push(child);
@@ -198,7 +198,7 @@ var Clapton = (function (exports) {
198
198
  constructor(html) {
199
199
  this.html = html;
200
200
  }
201
- get render() {
201
+ get renderWrapper() {
202
202
  return this.html;
203
203
  }
204
204
  }
@@ -208,8 +208,8 @@ var Clapton = (function (exports) {
208
208
  this.children = [];
209
209
  this.attributes = attributes;
210
210
  }
211
- get render() {
212
- return `<em ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</em>`;
211
+ get renderWrapper() {
212
+ return `<em ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</em>`;
213
213
  }
214
214
  add(child) {
215
215
  this.children.push(child);
@@ -222,8 +222,8 @@ var Clapton = (function (exports) {
222
222
  this.children = [];
223
223
  this.attributes = attributes;
224
224
  }
225
- get render() {
226
- return `<form ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</form>`;
225
+ get renderWrapper() {
226
+ return `<form ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</form>`;
227
227
  }
228
228
  add(child) {
229
229
  this.children.push(child);
@@ -237,8 +237,8 @@ var Clapton = (function (exports) {
237
237
  this.level = level;
238
238
  this.attributes = attributes;
239
239
  }
240
- get render() {
241
- return `<h${this.level} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</h${this.level}>`;
240
+ get renderWrapper() {
241
+ return `<h${this.level} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</h${this.level}>`;
242
242
  }
243
243
  add(child) {
244
244
  this.children.push(child);
@@ -253,7 +253,7 @@ var Clapton = (function (exports) {
253
253
  this.src = src;
254
254
  this.alt = alt;
255
255
  }
256
- get render() {
256
+ get renderWrapper() {
257
257
  return `<img src='${this.src}' alt='${this.alt}' ${htmlAttributes(this.attributes)}/>`;
258
258
  }
259
259
  }
@@ -264,8 +264,8 @@ var Clapton = (function (exports) {
264
264
  this.attributes = attributes;
265
265
  this.href = href;
266
266
  }
267
- get render() {
268
- return `<a href='${this.href}' ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</a>`;
267
+ get renderWrapper() {
268
+ return `<a href='${this.href}' ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</a>`;
269
269
  }
270
270
  add(child) {
271
271
  this.children.push(child);
@@ -282,8 +282,8 @@ var Clapton = (function (exports) {
282
282
  this.children.push(child);
283
283
  return this;
284
284
  }
285
- get render() {
286
- return `<li ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</li>`;
285
+ get renderWrapper() {
286
+ return `<li ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</li>`;
287
287
  }
288
288
  }
289
289
 
@@ -296,8 +296,8 @@ var Clapton = (function (exports) {
296
296
  this.children.push(child);
297
297
  return this;
298
298
  }
299
- get render() {
300
- return `<ul ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</ul>`;
299
+ get renderWrapper() {
300
+ return `<ul ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</ul>`;
301
301
  }
302
302
  }
303
303
 
@@ -310,8 +310,8 @@ var Clapton = (function (exports) {
310
310
  this.children.push(child);
311
311
  return this;
312
312
  }
313
- get render() {
314
- return `<ol ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</ol>`;
313
+ get renderWrapper() {
314
+ return `<ol ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</ol>`;
315
315
  }
316
316
  }
317
317
 
@@ -320,8 +320,8 @@ var Clapton = (function (exports) {
320
320
  this.children = [];
321
321
  this.attributes = attributes;
322
322
  }
323
- get render() {
324
- return `<p ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</p>`;
323
+ get renderWrapper() {
324
+ return `<p ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</p>`;
325
325
  }
326
326
  add(child) {
327
327
  this.children.push(child);
@@ -334,8 +334,8 @@ var Clapton = (function (exports) {
334
334
  this.children = [];
335
335
  this.attributes = attributes;
336
336
  }
337
- get render() {
338
- return `<q ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</q>`;
337
+ get renderWrapper() {
338
+ return `<q ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</q>`;
339
339
  }
340
340
  add(child) {
341
341
  this.children.push(child);
@@ -350,7 +350,7 @@ var Clapton = (function (exports) {
350
350
  this.attribute = attribute;
351
351
  this.attributes["data-attribute"] = attribute;
352
352
  }
353
- get render() {
353
+ get renderWrapper() {
354
354
  return `<input type='radio' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
355
355
  }
356
356
  add_action(event, klass, fn, options = {}) {
@@ -367,8 +367,8 @@ var Clapton = (function (exports) {
367
367
  this.attribute = attribute;
368
368
  this.attributes = attributes;
369
369
  }
370
- get render() {
371
- return `<select ${htmlAttributes(this.attributes)}>${this.options.map(option => `<option value='${option.value}'${option.value === this.state[this.attribute] ? " selected" : ""}>${option.text}</option>`).join("")}${this.children.map(child => child.render).join("")}</select>`;
370
+ get renderWrapper() {
371
+ return `<select ${htmlAttributes(this.attributes)}>${this.options.map(option => `<option value='${option.value}'${option.value === this.state[this.attribute] ? " selected" : ""}>${option.text}</option>`).join("")}${this.children.map(child => child.renderWrapper).join("")}</select>`;
372
372
  }
373
373
  }
374
374
 
@@ -377,8 +377,8 @@ var Clapton = (function (exports) {
377
377
  this.children = [];
378
378
  this.attributes = attributes;
379
379
  }
380
- get render() {
381
- return `<span ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</span>`;
380
+ get renderWrapper() {
381
+ return `<span ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</span>`;
382
382
  }
383
383
  add(child) {
384
384
  this.children.push(child);
@@ -393,7 +393,7 @@ var Clapton = (function (exports) {
393
393
  this.attribute = attribute;
394
394
  this.attributes["data-attribute"] = attribute;
395
395
  }
396
- get render() {
396
+ get renderWrapper() {
397
397
  return `<input type='text' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
398
398
  }
399
399
  add_action(event, klass, fn, options = {}) {
@@ -406,7 +406,7 @@ var Clapton = (function (exports) {
406
406
  constructor(value) {
407
407
  this.value = value;
408
408
  }
409
- get render() {
409
+ get renderWrapper() {
410
410
  return this.value;
411
411
  }
412
412
  }
@@ -418,7 +418,7 @@ var Clapton = (function (exports) {
418
418
  this.attribute = attribute;
419
419
  this.attributes["data-attribute"] = attribute;
420
420
  }
421
- get render() {
421
+ get renderWrapper() {
422
422
  return `<textarea ${htmlAttributes(this.attributes)}>${this.state[this.attribute] || ""}</textarea>`;
423
423
  }
424
424
  add_action(event, klass, fn, options = {}) {
@@ -469,7 +469,7 @@ var Clapton = (function (exports) {
469
469
  return new Clapton.Heading(props[0], props[1]);
470
470
  }
471
471
  img(...props) {
472
- return new Clapton.Image(props[0], props[1]);
472
+ return new Clapton.Image(props[0], props[1], props[2]);
473
473
  }
474
474
  a(...props) {
475
475
  return new Clapton.Link(props[0], props[1]);
@@ -514,11 +514,15 @@ var Clapton = (function (exports) {
514
514
  this._state = state;
515
515
  this.id = id;
516
516
  this._errors = errors;
517
- this._root = new Box({ data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } });
518
517
  this._c = new Presets();
519
518
  }
520
519
  get render() {
521
- return this._root.render;
520
+ return new Box({});
521
+ }
522
+ get renderWrapper() {
523
+ const root = this.render;
524
+ root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } };
525
+ return root.renderWrapper;
522
526
  }
523
527
  }
524
528
 
@@ -45,8 +45,8 @@ class BlockQuote {
45
45
  this.children = [];
46
46
  this.attributes = attributes;
47
47
  }
48
- get render() {
49
- return `<blockquote ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</blockquote>`;
48
+ get renderWrapper() {
49
+ return `<blockquote ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</blockquote>`;
50
50
  }
51
51
  add(child) {
52
52
  this.children.push(child);
@@ -63,8 +63,8 @@ class Box {
63
63
  this.children.push(child);
64
64
  return this;
65
65
  }
66
- get render() {
67
- return `<div ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</div>`;
66
+ get renderWrapper() {
67
+ return `<div ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</div>`;
68
68
  }
69
69
  add_action(eventType, stateName, fnName, options = {}) {
70
70
  this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${eventType}->${stateName}#${fnName}@${options.debounce || 0}`;
@@ -81,8 +81,8 @@ class Button {
81
81
  this.children.push(child);
82
82
  return this;
83
83
  }
84
- get render() {
85
- return `<button ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</button>`;
84
+ get renderWrapper() {
85
+ return `<button ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</button>`;
86
86
  }
87
87
  add_action(event, klass, fn, options = {}) {
88
88
  this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
@@ -95,8 +95,8 @@ class Bold {
95
95
  this.children = [];
96
96
  this.attributes = attributes;
97
97
  }
98
- get render() {
99
- return `<strong ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</strong>`;
98
+ get renderWrapper() {
99
+ return `<strong ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</strong>`;
100
100
  }
101
101
  add(child) {
102
102
  this.children.push(child);
@@ -111,7 +111,7 @@ class Checkbox {
111
111
  this.attribute = attribute;
112
112
  this.attributes["data-attribute"] = attribute;
113
113
  }
114
- get render() {
114
+ get renderWrapper() {
115
115
  return `<input type='checkbox' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
116
116
  }
117
117
  add_action(event, klass, fn, options = {}) {
@@ -125,8 +125,8 @@ class Code {
125
125
  this.children = [];
126
126
  this.attributes = attributes;
127
127
  }
128
- get render() {
129
- return `<code ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</code>`;
128
+ get renderWrapper() {
129
+ return `<code ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</code>`;
130
130
  }
131
131
  add(child) {
132
132
  this.children.push(child);
@@ -142,7 +142,7 @@ class DateTimeField {
142
142
  this.attributes = attributes;
143
143
  this.attributes["data-attribute"] = attribute;
144
144
  }
145
- get render() {
145
+ get renderWrapper() {
146
146
  const value = this.state[this.attribute] ? this.datetime_local_value(this.state[this.attribute]) : "";
147
147
  return `<input type='datetime-local' ${htmlAttributes(this.attributes)} value='${value}'/>`;
148
148
  }
@@ -182,8 +182,8 @@ class Element {
182
182
  this.type = type;
183
183
  this.attributes = attributes;
184
184
  }
185
- get render() {
186
- return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</${this.type}>`;
185
+ get renderWrapper() {
186
+ return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</${this.type}>`;
187
187
  }
188
188
  add(child) {
189
189
  this.children.push(child);
@@ -195,7 +195,7 @@ class Embed {
195
195
  constructor(html) {
196
196
  this.html = html;
197
197
  }
198
- get render() {
198
+ get renderWrapper() {
199
199
  return this.html;
200
200
  }
201
201
  }
@@ -205,8 +205,8 @@ class Emphasis {
205
205
  this.children = [];
206
206
  this.attributes = attributes;
207
207
  }
208
- get render() {
209
- return `<em ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</em>`;
208
+ get renderWrapper() {
209
+ return `<em ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</em>`;
210
210
  }
211
211
  add(child) {
212
212
  this.children.push(child);
@@ -219,8 +219,8 @@ class Form {
219
219
  this.children = [];
220
220
  this.attributes = attributes;
221
221
  }
222
- get render() {
223
- return `<form ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</form>`;
222
+ get renderWrapper() {
223
+ return `<form ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</form>`;
224
224
  }
225
225
  add(child) {
226
226
  this.children.push(child);
@@ -234,8 +234,8 @@ class Heading {
234
234
  this.level = level;
235
235
  this.attributes = attributes;
236
236
  }
237
- get render() {
238
- return `<h${this.level} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</h${this.level}>`;
237
+ get renderWrapper() {
238
+ return `<h${this.level} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</h${this.level}>`;
239
239
  }
240
240
  add(child) {
241
241
  this.children.push(child);
@@ -250,7 +250,7 @@ class Image {
250
250
  this.src = src;
251
251
  this.alt = alt;
252
252
  }
253
- get render() {
253
+ get renderWrapper() {
254
254
  return `<img src='${this.src}' alt='${this.alt}' ${htmlAttributes(this.attributes)}/>`;
255
255
  }
256
256
  }
@@ -261,8 +261,8 @@ class Link {
261
261
  this.attributes = attributes;
262
262
  this.href = href;
263
263
  }
264
- get render() {
265
- return `<a href='${this.href}' ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</a>`;
264
+ get renderWrapper() {
265
+ return `<a href='${this.href}' ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</a>`;
266
266
  }
267
267
  add(child) {
268
268
  this.children.push(child);
@@ -279,8 +279,8 @@ class ListItem {
279
279
  this.children.push(child);
280
280
  return this;
281
281
  }
282
- get render() {
283
- return `<li ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</li>`;
282
+ get renderWrapper() {
283
+ return `<li ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</li>`;
284
284
  }
285
285
  }
286
286
 
@@ -293,8 +293,8 @@ class List {
293
293
  this.children.push(child);
294
294
  return this;
295
295
  }
296
- get render() {
297
- return `<ul ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</ul>`;
296
+ get renderWrapper() {
297
+ return `<ul ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</ul>`;
298
298
  }
299
299
  }
300
300
 
@@ -307,8 +307,8 @@ class OrderedList {
307
307
  this.children.push(child);
308
308
  return this;
309
309
  }
310
- get render() {
311
- return `<ol ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</ol>`;
310
+ get renderWrapper() {
311
+ return `<ol ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</ol>`;
312
312
  }
313
313
  }
314
314
 
@@ -317,8 +317,8 @@ class Paragraph {
317
317
  this.children = [];
318
318
  this.attributes = attributes;
319
319
  }
320
- get render() {
321
- return `<p ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</p>`;
320
+ get renderWrapper() {
321
+ return `<p ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</p>`;
322
322
  }
323
323
  add(child) {
324
324
  this.children.push(child);
@@ -331,8 +331,8 @@ class Quote {
331
331
  this.children = [];
332
332
  this.attributes = attributes;
333
333
  }
334
- get render() {
335
- return `<q ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</q>`;
334
+ get renderWrapper() {
335
+ return `<q ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</q>`;
336
336
  }
337
337
  add(child) {
338
338
  this.children.push(child);
@@ -347,7 +347,7 @@ class RadioButton {
347
347
  this.attribute = attribute;
348
348
  this.attributes["data-attribute"] = attribute;
349
349
  }
350
- get render() {
350
+ get renderWrapper() {
351
351
  return `<input type='radio' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
352
352
  }
353
353
  add_action(event, klass, fn, options = {}) {
@@ -364,8 +364,8 @@ class Select {
364
364
  this.attribute = attribute;
365
365
  this.attributes = attributes;
366
366
  }
367
- get render() {
368
- return `<select ${htmlAttributes(this.attributes)}>${this.options.map(option => `<option value='${option.value}'${option.value === this.state[this.attribute] ? " selected" : ""}>${option.text}</option>`).join("")}${this.children.map(child => child.render).join("")}</select>`;
367
+ get renderWrapper() {
368
+ return `<select ${htmlAttributes(this.attributes)}>${this.options.map(option => `<option value='${option.value}'${option.value === this.state[this.attribute] ? " selected" : ""}>${option.text}</option>`).join("")}${this.children.map(child => child.renderWrapper).join("")}</select>`;
369
369
  }
370
370
  }
371
371
 
@@ -374,8 +374,8 @@ class Span {
374
374
  this.children = [];
375
375
  this.attributes = attributes;
376
376
  }
377
- get render() {
378
- return `<span ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</span>`;
377
+ get renderWrapper() {
378
+ return `<span ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}</span>`;
379
379
  }
380
380
  add(child) {
381
381
  this.children.push(child);
@@ -421,7 +421,7 @@ class Presets {
421
421
  return new Clapton.Heading(props[0], props[1]);
422
422
  }
423
423
  img(...props) {
424
- return new Clapton.Image(props[0], props[1]);
424
+ return new Clapton.Image(props[0], props[1], props[2]);
425
425
  }
426
426
  a(...props) {
427
427
  return new Clapton.Link(props[0], props[1]);
@@ -466,11 +466,15 @@ class Component {
466
466
  this._state = state;
467
467
  this.id = id;
468
468
  this._errors = errors;
469
- this._root = new Box({ data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } });
470
469
  this._c = new Presets();
471
470
  }
472
471
  get render() {
473
- return this._root.render;
472
+ return new Box({});
473
+ }
474
+ get renderWrapper() {
475
+ const root = this.render;
476
+ root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } };
477
+ return root.renderWrapper;
474
478
  }
475
479
  }
476
480
 
@@ -481,7 +485,7 @@ class TextField {
481
485
  this.attribute = attribute;
482
486
  this.attributes["data-attribute"] = attribute;
483
487
  }
484
- get render() {
488
+ get renderWrapper() {
485
489
  return `<input type='text' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
486
490
  }
487
491
  add_action(event, klass, fn, options = {}) {
@@ -494,7 +498,7 @@ class Text {
494
498
  constructor(value) {
495
499
  this.value = value;
496
500
  }
497
- get render() {
501
+ get renderWrapper() {
498
502
  return this.value;
499
503
  }
500
504
  }
@@ -506,7 +510,7 @@ class TextArea {
506
510
  this.attribute = attribute;
507
511
  this.attributes["data-attribute"] = attribute;
508
512
  }
509
- get render() {
513
+ get renderWrapper() {
510
514
  return `<textarea ${htmlAttributes(this.attributes)}>${this.state[this.attribute] || ""}</textarea>`;
511
515
  }
512
516
  add_action(event, klass, fn, options = {}) {
@@ -16,7 +16,7 @@ export const claptonChannel = consumer.subscriptions.create("Clapton::ClaptonCha
16
16
  const component = document.querySelector(`[data-id="${data.component.id}"]`)
17
17
  const module = await import(`${data.component.name}`);
18
18
  const instance = new module[data.component.name](data.state, data.component.id, errors);
19
- morphdom(component, instance.render, {
19
+ morphdom(component, instance.renderWrapper, {
20
20
  onBeforeElUpdated: (_fromEl, toEl) => {
21
21
  toEl.setAttribute("data-set-event-handler", "true");
22
22
  return true;