clapton 0.0.17 → 0.0.18

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.
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;