clapton 0.0.16 → 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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -8
  3. data/lib/clapton/engine.rb +1 -1
  4. data/lib/clapton/javascripts/dist/client.js +12 -4
  5. data/lib/clapton/javascripts/dist/components-for-test.js +49 -45
  6. data/lib/clapton/javascripts/dist/components.js +49 -45
  7. data/lib/clapton/javascripts/src/channel/clapton-channel.js +1 -1
  8. data/lib/clapton/javascripts/src/client.ts +9 -2
  9. data/lib/clapton/javascripts/src/components/block-quote.spec.ts +6 -6
  10. data/lib/clapton/javascripts/src/components/block-quote.ts +2 -2
  11. data/lib/clapton/javascripts/src/components/bold.spec.ts +3 -3
  12. data/lib/clapton/javascripts/src/components/bold.ts +2 -2
  13. data/lib/clapton/javascripts/src/components/box.spec.ts +6 -6
  14. data/lib/clapton/javascripts/src/components/box.ts +2 -2
  15. data/lib/clapton/javascripts/src/components/button.spec.ts +5 -5
  16. data/lib/clapton/javascripts/src/components/button.ts +2 -2
  17. data/lib/clapton/javascripts/src/components/checkbox.spec.ts +3 -3
  18. data/lib/clapton/javascripts/src/components/checkbox.ts +1 -1
  19. data/lib/clapton/javascripts/src/components/code.spec.ts +6 -6
  20. data/lib/clapton/javascripts/src/components/code.ts +2 -2
  21. data/lib/clapton/javascripts/src/components/component.ts +8 -4
  22. data/lib/clapton/javascripts/src/components/datetime-field.spec.ts +3 -3
  23. data/lib/clapton/javascripts/src/components/datetime-field.ts +1 -1
  24. data/lib/clapton/javascripts/src/components/element.spec.ts +6 -6
  25. data/lib/clapton/javascripts/src/components/element.ts +2 -2
  26. data/lib/clapton/javascripts/src/components/embed.spec.ts +1 -1
  27. data/lib/clapton/javascripts/src/components/embed.ts +1 -1
  28. data/lib/clapton/javascripts/src/components/emphasis.spec.ts +6 -6
  29. data/lib/clapton/javascripts/src/components/emphasis.ts +2 -2
  30. data/lib/clapton/javascripts/src/components/form.spec.ts +6 -6
  31. data/lib/clapton/javascripts/src/components/form.ts +2 -2
  32. data/lib/clapton/javascripts/src/components/heading.spec.ts +6 -6
  33. data/lib/clapton/javascripts/src/components/heading.ts +2 -2
  34. data/lib/clapton/javascripts/src/components/image.spec.ts +2 -2
  35. data/lib/clapton/javascripts/src/components/image.ts +1 -1
  36. data/lib/clapton/javascripts/src/components/link.spec.ts +6 -6
  37. data/lib/clapton/javascripts/src/components/link.ts +2 -2
  38. data/lib/clapton/javascripts/src/components/list-item.spec.ts +6 -6
  39. data/lib/clapton/javascripts/src/components/list-item.ts +2 -2
  40. data/lib/clapton/javascripts/src/components/list.spec.ts +6 -6
  41. data/lib/clapton/javascripts/src/components/list.ts +2 -2
  42. data/lib/clapton/javascripts/src/components/ordered-list.spec.ts +6 -6
  43. data/lib/clapton/javascripts/src/components/ordered-list.ts +2 -2
  44. data/lib/clapton/javascripts/src/components/paragraph.spec.ts +6 -6
  45. data/lib/clapton/javascripts/src/components/paragraph.ts +2 -2
  46. data/lib/clapton/javascripts/src/components/presets.ts +1 -1
  47. data/lib/clapton/javascripts/src/components/quote.spec.ts +6 -6
  48. data/lib/clapton/javascripts/src/components/quote.ts +2 -2
  49. data/lib/clapton/javascripts/src/components/radio-button.spec.ts +3 -3
  50. data/lib/clapton/javascripts/src/components/radio-button.ts +1 -1
  51. data/lib/clapton/javascripts/src/components/select.spec.ts +6 -6
  52. data/lib/clapton/javascripts/src/components/select.ts +2 -2
  53. data/lib/clapton/javascripts/src/components/span.spec.ts +6 -6
  54. data/lib/clapton/javascripts/src/components/span.ts +2 -2
  55. data/lib/clapton/javascripts/src/components/text-area.spec.ts +3 -3
  56. data/lib/clapton/javascripts/src/components/text-area.ts +1 -1
  57. data/lib/clapton/javascripts/src/components/text-field.spec.ts +3 -3
  58. data/lib/clapton/javascripts/src/components/text-field.ts +1 -1
  59. data/lib/clapton/javascripts/src/components/text.spec.ts +2 -2
  60. data/lib/clapton/javascripts/src/components/text.ts +1 -1
  61. data/lib/clapton/javascripts/src/dom/update-component.ts +1 -1
  62. data/lib/clapton/test_helper/base.rb +2 -2
  63. data/lib/clapton/version.rb +2 -1
  64. data/lib/rails/generators/clapton_generator.rb +2 -0
  65. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f420efd6abefefc796433bad77369a93a3686057519240abf5a9e118758ade2
4
- data.tar.gz: f34d535b066e305f893bd291e464d2dfd231df8fbf837b04668fcbaa0a0b4b84
3
+ metadata.gz: 75a7ef3678828970fe19e84f474a8480a2b3aef73bb7cad48d771952560dc26f
4
+ data.tar.gz: d183141896d4742b8481d03db28e1d38d1b0ba3d447c8a0c4444d46fa06cec72
5
5
  SHA512:
6
- metadata.gz: '08125a3863fc85cae262381041e72fdacdfc1fe8dd4f677cd4f5f55e658b713b3c8fa6238289c2b0fc1b5e4cc1bbb4e9ead48179eee8af6cde67b26fe5293e30'
7
- data.tar.gz: 6e9a70c6be7c02f4642d44ce4f766ea8a72460962e8a0437f71bafbdaad11df2f0cfbe6fd4c10953a63ab0d324c5720286a17edc5dc66a59ca4637c5ef239258
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
  ```
@@ -183,7 +183,7 @@ end
183
183
  block_quote = Clapton::BlockQuote.new
184
184
  block_quote.add(Clapton::Text.new("Hello"))
185
185
 
186
- box = **Clapton**::Box.new
186
+ box = Clapton::Box.new
187
187
  box.add(Clapton::Text.new("Hello"))
188
188
 
189
189
  button = Clapton::Button.new
@@ -49,7 +49,7 @@ module Clapton
49
49
  js += "\n"
50
50
  end
51
51
  code = code.gsub(/([^a-zA-Z0-9])c\.(\w+?)\(/, '\1@c.\2(')
52
- code = code.gsub(/([^a-zA-Z0-9])c\.(\w+?)\./, '\1@c.\2().')
52
+ code = code.gsub(/([^a-zA-Z0-9])c\.(\w+?)(\.|$)/, '\1@c.\2()\3')
53
53
  js += Ruby2JS.convert(code, preset: true)
54
54
  js += "\n"
55
55
  js += "export { #{File.basename(file, ".rb").camelize} };"
@@ -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