clapton 0.0.5 → 0.0.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ced6ec2a5091225623d714847395bbbe1a5aa58d8b655b8fd9ba427a3cad253a
4
- data.tar.gz: 15d4b56faaa648195800818fae39753ebbf66b18551042397217f9913ffbdb7a
3
+ metadata.gz: 01e0976bdfdb23e447884dec93ee2f25ceb2d5e0312ca4a54aeed3ba603a69c2
4
+ data.tar.gz: e950680f7a0928e186eb14ae04d1479e741e55670ec16ee97a6cc4b799edeb0e
5
5
  SHA512:
6
- metadata.gz: 94e5dd398e4264ef1a8a4429fb34dbb9bfc80abf3e162712cf6fea236f0991209bbfc04e19a550590e0af739ccef393e1325bc19a0c1daa04b697d12b77436cd
7
- data.tar.gz: faea93854fc326fa2933df5a191cc079296c751153a88cd5d93432db8cb4d0671d5c8a18a0b13534437f760996dfe1a2200162e3c3ce618389ef7a8c28075992
6
+ metadata.gz: d3ed3bd257263eb9875acb301c798d18bed14700cbed7352b8ac55187e320f8a49a555a6fbbd90e3db6980c9b4572ed62371a7d3f16af7b60a858a1ab02102de
7
+ data.tar.gz: d89a048e4c2df53e1fb35c01063c6f59e3eef7f3737907b8523c8c919ad2eb84fc7cce63f138455ecf6d29650df12a387d64e7e348fedfffdc47760cf6b14393
data/README.md CHANGED
@@ -137,6 +137,12 @@ mount Clapton::Engine => "/clapton"
137
137
 
138
138
  ![TODO APP DEMO](./docs/todo-app-demo.gif)
139
139
 
140
+ ### Component rendering
141
+
142
+ ```html
143
+ <%= clapton_component_tag([:TaskListComponent, { tasks: @tasks.map { |task| { id: task.id, title: task.title, due: task.due, done: task.done } }]) %>
144
+ ```
145
+
140
146
  ### Generate Component and State
141
147
 
142
148
  ```bash
@@ -17,5 +17,15 @@ module Clapton
17
17
  end
18
18
  tag.div(id: "clapton", data: { clapton: datas })
19
19
  end
20
+
21
+ def clapton_component_tag(component)
22
+ state_class = component[0].to_s.gsub("Component", "State")
23
+ if Object.const_defined?(state_class)
24
+ data = { component: component[0].to_s, state: Object.const_get(state_class).new(component[1]).to_h }
25
+ else
26
+ data = { component: component[0].to_s, state: {} }
27
+ end
28
+ tag.div(class: "clapton-component", data: { clapton: data })
29
+ end
20
30
  end
21
31
  end
@@ -1393,15 +1393,19 @@ const initializeInputs$1 = () => {
1393
1393
 
1394
1394
  const initializeComponents = () => {
1395
1395
  const components = document.querySelector("#clapton")?.getAttribute("data-clapton") || "[]";
1396
- JSON.parse(components).forEach(createAndAppendComponent);
1396
+ JSON.parse(components).forEach((component) => createAndAppendComponent(component, document.querySelector("#clapton")));
1397
+ document.querySelectorAll(".clapton-component").forEach((element) => {
1398
+ const component = JSON.parse(element.getAttribute("data-clapton") || "{}");
1399
+ createAndAppendComponent(component, element);
1400
+ });
1397
1401
  };
1398
- const createAndAppendComponent = (component) => {
1402
+ const createAndAppendComponent = (component, element) => {
1399
1403
  const componentDom = document.createElement('div');
1400
1404
  const instance = new window[component.component](component.state);
1401
1405
  componentDom.innerHTML = instance.render;
1402
1406
  const firstChild = componentDom.firstChild;
1403
1407
  if (firstChild) {
1404
- document.querySelector("#clapton")?.appendChild(firstChild);
1408
+ element.appendChild(firstChild);
1405
1409
  }
1406
1410
  };
1407
1411
  document.addEventListener("DOMContentLoaded", () => {
@@ -43,42 +43,53 @@ var Clapton = (function (exports) {
43
43
  .replace(/'/g, "&#039;");
44
44
  };
45
45
 
46
- class Box {
46
+ class BlockQuote {
47
47
  constructor(attributes = {}) {
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>`;
53
+ }
51
54
  add(child) {
52
55
  this.children.push(child);
53
56
  return this;
54
57
  }
55
- get render() {
56
- return `<div ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</div>`;
57
- }
58
58
  }
59
59
 
60
- class Component {
61
- constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) {
62
- this._state = state;
63
- this.id = id;
64
- this._errors = errors;
65
- this._root = new Box({ data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } });
60
+ class Box {
61
+ constructor(attributes = {}) {
62
+ this.children = [];
63
+ this.attributes = attributes;
64
+ }
65
+ add(child) {
66
+ this.children.push(child);
67
+ return this;
66
68
  }
67
69
  get render() {
68
- return this._root.render;
70
+ return `<div ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</div>`;
69
71
  }
70
72
  }
71
73
 
72
- class Text {
73
- constructor(value) {
74
- this.value = value;
74
+ class Button {
75
+ constructor(attributes = {}) {
76
+ this.attributes = attributes;
77
+ this.children = [];
78
+ }
79
+ add(child) {
80
+ this.children.push(child);
81
+ return this;
75
82
  }
76
83
  get render() {
77
- return this.value;
84
+ return `<button ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</button>`;
85
+ }
86
+ add_action(event, klass, fn, options = {}) {
87
+ this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
88
+ return this;
78
89
  }
79
90
  }
80
91
 
81
- class TextField {
92
+ class Checkbox {
82
93
  constructor(state, attribute, attributes = {}) {
83
94
  this.state = state;
84
95
  this.attributes = attributes;
@@ -86,7 +97,7 @@ var Clapton = (function (exports) {
86
97
  this.attributes["data-attribute"] = attribute;
87
98
  }
88
99
  get render() {
89
- return `<input type='text' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
100
+ return `<input type='checkbox' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
90
101
  }
91
102
  add_action(event, klass, fn, options = {}) {
92
103
  this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
@@ -94,36 +105,18 @@ var Clapton = (function (exports) {
94
105
  }
95
106
  }
96
107
 
97
- class Link {
108
+ class Code {
98
109
  constructor(attributes = {}) {
99
110
  this.children = [];
100
111
  this.attributes = attributes;
101
112
  }
102
113
  get render() {
103
- return `<a ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</a>`;
104
- }
105
- add(child) {
106
- this.children.push(child);
107
- return this;
108
- }
109
- }
110
-
111
- class Button {
112
- constructor(attributes = {}) {
113
- this.attributes = attributes;
114
- this.children = [];
114
+ return `<code ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</code>`;
115
115
  }
116
116
  add(child) {
117
117
  this.children.push(child);
118
118
  return this;
119
119
  }
120
- get render() {
121
- return `<button ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</button>`;
122
- }
123
- add_action(event, klass, fn, options = {}) {
124
- this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
125
- return this;
126
- }
127
120
  }
128
121
 
129
122
  class DateTimeField {
@@ -168,11 +161,262 @@ var Clapton = (function (exports) {
168
161
  }
169
162
  }
170
163
 
164
+ class Element {
165
+ constructor(type, attributes = {}) {
166
+ this.children = [];
167
+ this.type = type;
168
+ this.attributes = attributes;
169
+ }
170
+ get render() {
171
+ return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</${this.type}>`;
172
+ }
173
+ add(child) {
174
+ this.children.push(child);
175
+ return this;
176
+ }
177
+ }
178
+
179
+ class Emphasis {
180
+ constructor(attributes = {}) {
181
+ this.children = [];
182
+ this.attributes = attributes;
183
+ }
184
+ get render() {
185
+ return `<em ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</em>`;
186
+ }
187
+ add(child) {
188
+ this.children.push(child);
189
+ return this;
190
+ }
191
+ }
192
+
193
+ class Form {
194
+ constructor(attributes = {}) {
195
+ this.children = [];
196
+ this.attributes = attributes;
197
+ }
198
+ get render() {
199
+ return `<form ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</form>`;
200
+ }
201
+ add(child) {
202
+ this.children.push(child);
203
+ return this;
204
+ }
205
+ }
206
+
207
+ class Heading {
208
+ constructor(level, attributes = {}) {
209
+ this.children = [];
210
+ this.level = level;
211
+ this.attributes = attributes;
212
+ }
213
+ get render() {
214
+ return `<h${this.level} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</h${this.level}>`;
215
+ }
216
+ add(child) {
217
+ this.children.push(child);
218
+ return this;
219
+ }
220
+ }
221
+
222
+ class Image {
223
+ constructor(src, alt, attributes = {}) {
224
+ this.children = [];
225
+ this.attributes = attributes;
226
+ this.src = src;
227
+ this.alt = alt;
228
+ }
229
+ get render() {
230
+ return `<img src='${this.src}' alt='${this.alt}' ${htmlAttributes(this.attributes)}/>`;
231
+ }
232
+ }
233
+
234
+ class Link {
235
+ constructor(href, attributes = {}) {
236
+ this.children = [];
237
+ this.attributes = attributes;
238
+ this.href = href;
239
+ }
240
+ get render() {
241
+ return `<a href='${this.href}' ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</a>`;
242
+ }
243
+ add(child) {
244
+ this.children.push(child);
245
+ return this;
246
+ }
247
+ }
248
+
249
+ class ListItem {
250
+ constructor(attributes = {}) {
251
+ this.children = [];
252
+ this.attributes = attributes;
253
+ }
254
+ add(child) {
255
+ this.children.push(child);
256
+ return this;
257
+ }
258
+ get render() {
259
+ return `<li ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</li>`;
260
+ }
261
+ }
262
+
263
+ class List {
264
+ constructor(attributes = {}) {
265
+ this.children = [];
266
+ this.attributes = attributes;
267
+ }
268
+ add(child) {
269
+ this.children.push(child);
270
+ return this;
271
+ }
272
+ get render() {
273
+ return `<ul ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</ul>`;
274
+ }
275
+ }
276
+
277
+ class OrderedList {
278
+ constructor(attributes = {}) {
279
+ this.children = [];
280
+ this.attributes = attributes;
281
+ }
282
+ add(child) {
283
+ this.children.push(child);
284
+ return this;
285
+ }
286
+ get render() {
287
+ return `<ol ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</ol>`;
288
+ }
289
+ }
290
+
291
+ class Paragraph {
292
+ constructor(attributes = {}) {
293
+ this.children = [];
294
+ this.attributes = attributes;
295
+ }
296
+ get render() {
297
+ return `<p ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</p>`;
298
+ }
299
+ add(child) {
300
+ this.children.push(child);
301
+ return this;
302
+ }
303
+ }
304
+
305
+ class Quote {
306
+ constructor(attributes = {}) {
307
+ this.children = [];
308
+ this.attributes = attributes;
309
+ }
310
+ get render() {
311
+ return `<q ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</q>`;
312
+ }
313
+ add(child) {
314
+ this.children.push(child);
315
+ return this;
316
+ }
317
+ }
318
+
319
+ class RadioButton {
320
+ constructor(state, attribute, attributes = {}) {
321
+ this.state = state;
322
+ this.attributes = attributes;
323
+ this.attribute = attribute;
324
+ this.attributes["data-attribute"] = attribute;
325
+ }
326
+ get render() {
327
+ return `<input type='radio' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
328
+ }
329
+ add_action(event, klass, fn, options = {}) {
330
+ this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
331
+ return this;
332
+ }
333
+ }
334
+
335
+ class Select {
336
+ constructor(options = [], state, attribute, attributes = {}) {
337
+ this.children = [];
338
+ this.options = options;
339
+ this.state = state;
340
+ this.attribute = attribute;
341
+ this.attributes = attributes;
342
+ }
343
+ get render() {
344
+ 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>`;
345
+ }
346
+ }
347
+
348
+ class Span {
349
+ constructor(attributes = {}) {
350
+ this.children = [];
351
+ this.attributes = attributes;
352
+ }
353
+ get render() {
354
+ return `<span ${htmlAttributes(this.attributes)}>${this.children.map(child => child.render).join("")}</span>`;
355
+ }
356
+ add(child) {
357
+ this.children.push(child);
358
+ return this;
359
+ }
360
+ }
361
+
362
+ class Component {
363
+ constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) {
364
+ this._state = state;
365
+ this.id = id;
366
+ this._errors = errors;
367
+ this._root = new Box({ data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } });
368
+ }
369
+ get render() {
370
+ return this._root.render;
371
+ }
372
+ }
373
+
374
+ class TextField {
375
+ constructor(state, attribute, attributes = {}) {
376
+ this.state = state;
377
+ this.attributes = attributes;
378
+ this.attribute = attribute;
379
+ this.attributes["data-attribute"] = attribute;
380
+ }
381
+ get render() {
382
+ return `<input type='text' ${htmlAttributes(this.attributes)} value='${this.state[this.attribute] || ""}'/>`;
383
+ }
384
+ add_action(event, klass, fn, options = {}) {
385
+ this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`;
386
+ return this;
387
+ }
388
+ }
389
+
390
+ class Text {
391
+ constructor(value) {
392
+ this.value = value;
393
+ }
394
+ get render() {
395
+ return this.value;
396
+ }
397
+ }
398
+
399
+ exports.BlockQuote = BlockQuote;
171
400
  exports.Box = Box;
172
401
  exports.Button = Button;
402
+ exports.Checkbox = Checkbox;
403
+ exports.Code = Code;
173
404
  exports.Component = Component;
174
405
  exports.DateTimeField = DateTimeField;
406
+ exports.Element = Element;
407
+ exports.Emphasis = Emphasis;
408
+ exports.Form = Form;
409
+ exports.Heading = Heading;
410
+ exports.Image = Image;
175
411
  exports.Link = Link;
412
+ exports.List = List;
413
+ exports.ListItem = ListItem;
414
+ exports.OrderedList = OrderedList;
415
+ exports.Paragraph = Paragraph;
416
+ exports.Quote = Quote;
417
+ exports.RadioButton = RadioButton;
418
+ exports.Select = Select;
419
+ exports.Span = Span;
176
420
  exports.Text = Text;
177
421
  exports.TextField = TextField;
178
422
 
@@ -17,16 +17,20 @@ interface ComponentInstance {
17
17
 
18
18
  const initializeComponents = () => {
19
19
  const components = document.querySelector("#clapton")?.getAttribute("data-clapton") || "[]";
20
- JSON.parse(components).forEach(createAndAppendComponent);
20
+ JSON.parse(components).forEach((component: ComponentDefinition) => createAndAppendComponent(component, document.querySelector("#clapton")!));
21
+ document.querySelectorAll(".clapton-component").forEach((element) => {
22
+ const component = JSON.parse(element.getAttribute("data-clapton") || "{}");
23
+ createAndAppendComponent(component, element as HTMLElement);
24
+ });
21
25
  };
22
26
 
23
- const createAndAppendComponent = (component: ComponentDefinition) => {
27
+ const createAndAppendComponent = (component: ComponentDefinition, element: HTMLElement) => {
24
28
  const componentDom = document.createElement('div');
25
29
  const instance = new (window[component.component as any] as any)(component.state);
26
30
  componentDom.innerHTML = instance.render;
27
31
  const firstChild = componentDom.firstChild as HTMLElement;
28
32
  if (firstChild) {
29
- document.querySelector("#clapton")?.appendChild(firstChild);
33
+ element.appendChild(firstChild);
30
34
  }
31
35
  };
32
36
 
@@ -1,3 +1,3 @@
1
1
  module Clapton
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.7'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clapton
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moeki Kawakami