diff --git a/README.md b/README.md index 76fc0fe..733886d 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,12 @@ To use a Clapton component in your view: # app/components/task_list_component.rb class TaskListComponent < Clapton::Component def render - box = c.box + box = c(:box) @state.tasks.each do |task| box.add(TaskItemComponent.new(id: task[:id], title: task[:title], due: task[:due], done: task[:done])) end - btn = c.button - btn.add(c.text("Add Task")) + btn = c(:button) + btn.add(c(:text, "Add Task")) btn.add_action(:click, :TaskListState, :add_task) box.add(btn) end @@ -51,15 +51,15 @@ end # app/components/task_item_component.rb class TaskItemComponent < Clapton::Component def render - box = c.box - btn = c.button - btn.add(c.text(@state.done ? "✅" : "🟩")) + box = c(:box) + btn = c(:button) + btn.add(c(:text, @state.done ? "✅" : "🟩")) btn.add_action(:click, :TaskListState, :toggle_done) - tf = c.input(@state, :title) + tf = c(:input, @state, :title) tf.add_action(:input, :TaskListState, :update_title) - dt = c.datetime(@state, :due) + dt = c(:datetime, @state, :due) dt.add_action(:input, :TaskListState, :update_due) box.add(btn).add(tf).add(dt) @@ -171,7 +171,7 @@ The `render` event is a special event that is triggered when the component is re class TaskListComponent < Clapton::Component def render # ... - box = c.box + box = c(:box) box.add_action(:render, :TaskListState, :add_empty_task, debounce: 500) end end @@ -256,31 +256,31 @@ text = Clapton::Text.new("Hello")` ### Preset Component Methods ```javascript -c.bq(...props) -c.box(...props) -c.b(...props) -c.button(...props) -c.check(...props) -c.code(...props) -c.datetime(...props) -c.el(...props) -c.embed(...props) -c.em(...props) -c.form(...props) -c.h(...props) -c.img(...props) -c.a(...props) -c.li(...props) -c.ul(...props) -c.ol(...props) -c.p(...props) -c.q(...props) -c.radio(...props) -c.select(...props) -c.span(...props) -c.textarea(...props) -c.input(...props) -c.text(...props) +c(:bq, ...props) +c(:box, ...props) +c(:b, ...props) +c(:button, ...props) +c(:check, ...props) +c(:code, ...props) +c(:datetime, ...props) +c(:el, ...props) +c(:embed, ...props) +c(:em, ...props) +c(:form, ...props) +c(:h, ...props) +c(:img, ...props) +c(:a, ...props) +c(:li, ...props) +c(:ul, ...props) +c(:ol, ...props) +c(:p, ...props) +c(:q, ...props) +c(:radio, ...props) +c(:select, ...props) +c(:span, ...props) +c(:textarea, ...props) +c(:input, ...props) +c(:text, ...props) ``` ### Streaming diff --git a/app/helpers/clapton/clapton_helper.rb b/app/helpers/clapton/clapton_helper.rb index da117e1..a9af95d 100644 --- a/app/helpers/clapton/clapton_helper.rb +++ b/app/helpers/clapton/clapton_helper.rb @@ -9,6 +9,7 @@ def clapton_javascript_tag "imports": { "client": "/clapton/client.js", "components": "/clapton/components.js", + "c": "/clapton/c.js", #{ all_components.map do |component| "\"#{File.basename(component, ".rb").camelize}\": \"/clapton/#{File.basename(component, ".rb").camelize}.js\"" end.join(",\n") } diff --git a/lib/clapton/engine.rb b/lib/clapton/engine.rb index 0065b42..2b9641b 100644 --- a/lib/clapton/engine.rb +++ b/lib/clapton/engine.rb @@ -24,6 +24,7 @@ class Engine < ::Rails::Engine FileUtils.mkdir_p(Rails.root.join("public", "clapton")) unless Rails.root.join("public", "clapton").exist? File.write(Rails.root.join("public", "clapton", "components.js"), File.read(File.join(__dir__, "javascripts", "dist", "components.js"))) File.write(Rails.root.join("public", "clapton", "client.js"), File.read(File.join(__dir__, "javascripts", "dist", "client.js"))) + File.write(Rails.root.join("public", "clapton", "c.js"), File.read(File.join(__dir__, "javascripts", "dist", "c.js"))) compile_components @@ -44,6 +45,8 @@ def compile_components js = "" js += "import { Clapton } from 'components';" js += "\n" + js += "import { c } from 'c';" + js += "\n" code.scan(/(\w+)Component\.new/).each do |match| js += "import { #{match[0]}Component } from '#{match[0]}Component';" js += "\n" diff --git a/lib/clapton/javascripts/dist/c b/lib/clapton/javascripts/dist/c new file mode 100644 index 0000000..04ae484 --- /dev/null +++ b/lib/clapton/javascripts/dist/c @@ -0,0 +1,559 @@ +var c = (function (exports) { + 'use strict'; + + const htmlAttributes = (params) => { + const customDataAttributes = params.data || {}; + const others = Object.keys(params).filter(key => key !== "data"); + const flattenDataAttributes = (data, prefix = "data") => { + return Object.keys(data).reduce((acc, key) => { + const value = data[key]; + if (typeof value === "object" && value !== null) { + acc.push(...flattenDataAttributes(value, `${prefix}-${key}`)); + } + else { + acc.push(`${prefix}-${key}='${escapeHtml(value)}'`); + } + return acc; + }, []); + }; + return [ + others.map(key => { + if (key === "disabled") { + if (params[key] === false) { + return ""; + } + else { + return `${key}`; + } + } + return `${key}='${escapeHtml(params[key])}'`; + }).join(" "), + flattenDataAttributes(customDataAttributes).join(" ") + ].filter(Boolean).join(" "); + }; + const escapeHtml = (unsafe) => { + if (typeof unsafe !== "string") { + return ""; + } + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + }; + + class BlockQuote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
${this.children.map(child => child.renderWrapper).join("")}
`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Box { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
${this.children.map(child => child.renderWrapper).join("")}
`; + } + add_action(eventType, stateName, fnName, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${eventType}->${stateName}#${fnName}@${options.debounce || 0}`; + return this; + } + } + + class Button { + constructor(attributes = {}) { + this.attributes = attributes; + this.children = []; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Bold { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Checkbox { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Code { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class DateTimeField { + constructor(state, attribute, attributes = {}) { + this.attributes = {}; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + const value = this.state[this.attribute] ? this.datetime_local_value(this.state[this.attribute]) : ""; + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + datetime_local_value(value) { + if (!value) { + return ""; + } + const date = new Date(value); + date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); + let month = date.getMonth() + 1; + let day = date.getDate(); + let hours = date.getHours(); + let minutes = date.getMinutes(); + if (month < 10) { + month = `0${month}`; + } + if (day < 10) { + day = `0${day}`; + } + if (hours < 10) { + hours = `0${hours}`; + } + if (minutes < 10) { + minutes = `0${minutes}`; + } + return `${date.getFullYear()}-${month}-${day}T${hours}:${minutes}`; + } + } + + class Element { + constructor(type, attributes = {}) { + this.children = []; + this.type = type; + this.attributes = attributes; + } + get renderWrapper() { + return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Embed { + constructor(html) { + this.html = html; + } + get renderWrapper() { + return this.html; + } + } + + class Emphasis { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Form { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
${this.children.map(child => child.renderWrapper).join("")}
`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Heading { + constructor(level, attributes = {}) { + this.children = []; + this.level = level; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Image { + constructor(src, alt, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.src = src; + this.alt = alt; + } + get renderWrapper() { + return `${this.alt}`; + } + } + + class Link { + constructor(href, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.href = href; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class ListItem { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
  • ${this.children.map(child => child.renderWrapper).join("")}
  • `; + } + } + + class List { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + } + + class OrderedList { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
      ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + } + + class Paragraph { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `

    ${this.children.map(child => child.renderWrapper).join("")}

    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Quote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class RadioButton { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Select { + constructor(options = [], state, attribute, attributes = {}) { + this.children = []; + this.options = options; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + } + get renderWrapper() { + return ``; + } + } + + class Span { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Component { + constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { + this._state = state; + this.id = id; + this._errors = errors; + } + get render() { + return new Box({}); + } + get renderWrapper() { + const root = this.render; + if (root.attributes) { + root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + else { + root.attributes = { data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + return root.renderWrapper; + } + } + + class TextField { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Text { + constructor(value) { + this.value = value; + } + get renderWrapper() { + return this.value; + } + } + + class TextArea { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + const Clapton = { + Box, Component, Text, TextField, Button, DateTimeField, BlockQuote, Checkbox, Code, Element, Emphasis, Form, Heading, Image, Link, List, ListItem, OrderedList, Paragraph, Quote, RadioButton, Select, Span, Embed, Bold, TextArea + }; + + const bq = (...props) => { + return new Clapton.BlockQuote(...props); + }; + const box = (...props) => { + return new Clapton.Box(...props); + }; + const b = (...props) => { + return new Clapton.Bold(...props); + }; + const button = (...props) => { + return new Clapton.Button(...props); + }; + const check = (...props) => { + return new Clapton.Checkbox(props[0], props[1], props[2]); + }; + const code = (...props) => { + return new Clapton.Code(...props); + }; + const datetime = (...props) => { + return new Clapton.DateTimeField(props[0], props[1], props[2]); + }; + const el = (...props) => { + return new Clapton.Element(props[0], props[1]); + }; + const embed = (...props) => { + return new Clapton.Embed(props[0]); + }; + const em = (...props) => { + return new Clapton.Emphasis(...props); + }; + const form = (...props) => { + return new Clapton.Form(...props); + }; + const h = (...props) => { + return new Clapton.Heading(props[0], props[1]); + }; + const img = (...props) => { + return new Clapton.Image(props[0], props[1], props[2]); + }; + const a = (...props) => { + return new Clapton.Link(props[0], props[1]); + }; + const li = (...props) => { + return new Clapton.ListItem(...props); + }; + const ul = (...props) => { + return new Clapton.List(...props); + }; + const ol = (...props) => { + return new Clapton.OrderedList(...props); + }; + const p = (...props) => { + return new Clapton.Paragraph(...props); + }; + const q = (...props) => { + return new Clapton.Quote(...props); + }; + const radio = (...props) => { + return new Clapton.RadioButton(props[0], props[1], props[2]); + }; + const select = (...props) => { + return new Clapton.Select(props[0], props[1], props[2]); + }; + const span = (...props) => { + return new Clapton.Span(...props); + }; + const textarea = (...props) => { + return new Clapton.TextArea(props[0], props[1], props[2]); + }; + const input = (...props) => { + return new Clapton.TextField(props[0], props[1], props[2]); + }; + const text = (...props) => { + return new Clapton.Text(props[0]); + }; + + exports.a = a; + exports.b = b; + exports.box = box; + exports.bq = bq; + exports.button = button; + exports.check = check; + exports.code = code; + exports.datetime = datetime; + exports.el = el; + exports.em = em; + exports.embed = embed; + exports.form = form; + exports.h = h; + exports.img = img; + exports.input = input; + exports.li = li; + exports.ol = ol; + exports.p = p; + exports.q = q; + exports.radio = radio; + exports.select = select; + exports.span = span; + exports.text = text; + exports.textarea = textarea; + exports.ul = ul; + + return exports; + +})({}); diff --git a/lib/clapton/javascripts/dist/c-base.js b/lib/clapton/javascripts/dist/c-base.js new file mode 100644 index 0000000..022de7d --- /dev/null +++ b/lib/clapton/javascripts/dist/c-base.js @@ -0,0 +1,589 @@ +var c = (function () { + 'use strict'; + + const htmlAttributes = (params) => { + const customDataAttributes = params.data || {}; + const others = Object.keys(params).filter(key => key !== "data"); + const flattenDataAttributes = (data, prefix = "data") => { + return Object.keys(data).reduce((acc, key) => { + const value = data[key]; + if (typeof value === "object" && value !== null) { + acc.push(...flattenDataAttributes(value, `${prefix}-${key}`)); + } + else { + acc.push(`${prefix}-${key}='${escapeHtml(value)}'`); + } + return acc; + }, []); + }; + return [ + others.map(key => { + if (key === "disabled") { + if (params[key] === false) { + return ""; + } + else { + return `${key}`; + } + } + return `${key}='${escapeHtml(params[key])}'`; + }).join(" "), + flattenDataAttributes(customDataAttributes).join(" ") + ].filter(Boolean).join(" "); + }; + const escapeHtml = (unsafe) => { + if (typeof unsafe !== "string") { + return ""; + } + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + }; + + class BlockQuote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Box { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add_action(eventType, stateName, fnName, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${eventType}->${stateName}#${fnName}@${options.debounce || 0}`; + return this; + } + } + + class Button { + constructor(attributes = {}) { + this.attributes = attributes; + this.children = []; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Bold { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Checkbox { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Code { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class DateTimeField { + constructor(state, attribute, attributes = {}) { + this.attributes = {}; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + const value = this.state[this.attribute] ? this.datetime_local_value(this.state[this.attribute]) : ""; + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + datetime_local_value(value) { + if (!value) { + return ""; + } + const date = new Date(value); + date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); + let month = date.getMonth() + 1; + let day = date.getDate(); + let hours = date.getHours(); + let minutes = date.getMinutes(); + if (month < 10) { + month = `0${month}`; + } + if (day < 10) { + day = `0${day}`; + } + if (hours < 10) { + hours = `0${hours}`; + } + if (minutes < 10) { + minutes = `0${minutes}`; + } + return `${date.getFullYear()}-${month}-${day}T${hours}:${minutes}`; + } + } + + class Element { + constructor(type, attributes = {}) { + this.children = []; + this.type = type; + this.attributes = attributes; + } + get renderWrapper() { + return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Embed { + constructor(html) { + this.html = html; + } + get renderWrapper() { + return this.html; + } + } + + class Emphasis { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Form { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Heading { + constructor(level, attributes = {}) { + this.children = []; + this.level = level; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Image { + constructor(src, alt, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.src = src; + this.alt = alt; + } + get renderWrapper() { + return `${this.alt}`; + } + } + + class Link { + constructor(href, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.href = href; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class ListItem { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
  • ${this.children.map(child => child.renderWrapper).join("")}
  • `; + } + } + + class List { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + } + + class OrderedList { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
      ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + } + + class Paragraph { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `

    ${this.children.map(child => child.renderWrapper).join("")}

    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Quote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class RadioButton { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Select { + constructor(options = [], state, attribute, attributes = {}) { + this.children = []; + this.options = options; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + } + get renderWrapper() { + return ``; + } + } + + class Span { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Component { + constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { + this._state = state; + this.id = id; + this._errors = errors; + } + get render() { + return new Box({}); + } + get renderWrapper() { + const root = this.render; + if (root.attributes) { + root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + else { + root.attributes = { data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + return root.renderWrapper; + } + } + + class TextField { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Text { + constructor(value) { + this.value = value; + } + get renderWrapper() { + return this.value; + } + } + + class TextArea { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + const Clapton = { + Box, Component, Text, TextField, Button, DateTimeField, BlockQuote, Checkbox, Code, Element, Emphasis, Form, Heading, Image, Link, List, ListItem, OrderedList, Paragraph, Quote, RadioButton, Select, Span, Embed, Bold, TextArea + }; + + const bq = (...props) => { + return new Clapton.BlockQuote(...props); + }; + const box = (...props) => { + return new Clapton.Box(...props); + }; + const b = (...props) => { + return new Clapton.Bold(...props); + }; + const button = (...props) => { + return new Clapton.Button(...props); + }; + const check = (...props) => { + return new Clapton.Checkbox(props[0], props[1], props[2]); + }; + const code = (...props) => { + return new Clapton.Code(...props); + }; + const datetime = (...props) => { + return new Clapton.DateTimeField(props[0], props[1], props[2]); + }; + const el = (...props) => { + return new Clapton.Element(props[0], props[1]); + }; + const embed = (...props) => { + return new Clapton.Embed(props[0]); + }; + const em = (...props) => { + return new Clapton.Emphasis(...props); + }; + const form = (...props) => { + return new Clapton.Form(...props); + }; + const h = (...props) => { + return new Clapton.Heading(props[0], props[1]); + }; + const img = (...props) => { + return new Clapton.Image(props[0], props[1], props[2]); + }; + const a = (...props) => { + return new Clapton.Link(props[0], props[1]); + }; + const li = (...props) => { + return new Clapton.ListItem(...props); + }; + const ul = (...props) => { + return new Clapton.List(...props); + }; + const ol = (...props) => { + return new Clapton.OrderedList(...props); + }; + const p = (...props) => { + return new Clapton.Paragraph(...props); + }; + const q = (...props) => { + return new Clapton.Quote(...props); + }; + const radio = (...props) => { + return new Clapton.RadioButton(props[0], props[1], props[2]); + }; + const select = (...props) => { + return new Clapton.Select(props[0], props[1], props[2]); + }; + const span = (...props) => { + return new Clapton.Span(...props); + }; + const textarea = (...props) => { + return new Clapton.TextArea(props[0], props[1], props[2]); + }; + const input = (...props) => { + return new Clapton.TextField(props[0], props[1], props[2]); + }; + const text = (...props) => { + return new Clapton.Text(props[0]); + }; + const c = (name, ...props) => { + switch (name) { + case "bq": + return bq(...props); + case "box": + return box(...props); + case "b": + return b(...props); + case "button": + return button(...props); + case "check": + return check(...props); + case "code": + return code(...props); + case "datetime": + return datetime(...props); + case "el": + return el(...props); + case "embed": + return embed(...props); + case "em": + return em(...props); + case "form": + return form(...props); + case "h": + return h(...props); + case "img": + return img(...props); + case "a": + return a(...props); + case "li": + return li(...props); + case "ul": + return ul(...props); + case "ol": + return ol(...props); + case "p": + return p(...props); + case "q": + return q(...props); + case "radio": + return radio(...props); + case "select": + return select(...props); + case "span": + return span(...props); + case "textarea": + return textarea(...props); + case "input": + return input(...props); + case "text": + return text(...props); + default: + return new Clapton.Component(...props); + } + }; + + return c; + +})(); diff --git a/lib/clapton/javascripts/dist/c-for-test.js b/lib/clapton/javascripts/dist/c-for-test.js new file mode 100644 index 0000000..022de7d --- /dev/null +++ b/lib/clapton/javascripts/dist/c-for-test.js @@ -0,0 +1,589 @@ +var c = (function () { + 'use strict'; + + const htmlAttributes = (params) => { + const customDataAttributes = params.data || {}; + const others = Object.keys(params).filter(key => key !== "data"); + const flattenDataAttributes = (data, prefix = "data") => { + return Object.keys(data).reduce((acc, key) => { + const value = data[key]; + if (typeof value === "object" && value !== null) { + acc.push(...flattenDataAttributes(value, `${prefix}-${key}`)); + } + else { + acc.push(`${prefix}-${key}='${escapeHtml(value)}'`); + } + return acc; + }, []); + }; + return [ + others.map(key => { + if (key === "disabled") { + if (params[key] === false) { + return ""; + } + else { + return `${key}`; + } + } + return `${key}='${escapeHtml(params[key])}'`; + }).join(" "), + flattenDataAttributes(customDataAttributes).join(" ") + ].filter(Boolean).join(" "); + }; + const escapeHtml = (unsafe) => { + if (typeof unsafe !== "string") { + return ""; + } + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + }; + + class BlockQuote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Box { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add_action(eventType, stateName, fnName, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${eventType}->${stateName}#${fnName}@${options.debounce || 0}`; + return this; + } + } + + class Button { + constructor(attributes = {}) { + this.attributes = attributes; + this.children = []; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Bold { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Checkbox { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Code { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class DateTimeField { + constructor(state, attribute, attributes = {}) { + this.attributes = {}; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + const value = this.state[this.attribute] ? this.datetime_local_value(this.state[this.attribute]) : ""; + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + datetime_local_value(value) { + if (!value) { + return ""; + } + const date = new Date(value); + date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); + let month = date.getMonth() + 1; + let day = date.getDate(); + let hours = date.getHours(); + let minutes = date.getMinutes(); + if (month < 10) { + month = `0${month}`; + } + if (day < 10) { + day = `0${day}`; + } + if (hours < 10) { + hours = `0${hours}`; + } + if (minutes < 10) { + minutes = `0${minutes}`; + } + return `${date.getFullYear()}-${month}-${day}T${hours}:${minutes}`; + } + } + + class Element { + constructor(type, attributes = {}) { + this.children = []; + this.type = type; + this.attributes = attributes; + } + get renderWrapper() { + return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Embed { + constructor(html) { + this.html = html; + } + get renderWrapper() { + return this.html; + } + } + + class Emphasis { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Form { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Heading { + constructor(level, attributes = {}) { + this.children = []; + this.level = level; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Image { + constructor(src, alt, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.src = src; + this.alt = alt; + } + get renderWrapper() { + return `${this.alt}`; + } + } + + class Link { + constructor(href, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.href = href; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class ListItem { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
  • ${this.children.map(child => child.renderWrapper).join("")}
  • `; + } + } + + class List { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + } + + class OrderedList { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
      ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + } + + class Paragraph { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `

    ${this.children.map(child => child.renderWrapper).join("")}

    `; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Quote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class RadioButton { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Select { + constructor(options = [], state, attribute, attributes = {}) { + this.children = []; + this.options = options; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + } + get renderWrapper() { + return ``; + } + } + + class Span { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } + } + + class Component { + constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { + this._state = state; + this.id = id; + this._errors = errors; + } + get render() { + return new Box({}); + } + get renderWrapper() { + const root = this.render; + if (root.attributes) { + root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + else { + root.attributes = { data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + return root.renderWrapper; + } + } + + class TextField { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + class Text { + constructor(value) { + this.value = value; + } + get renderWrapper() { + return this.value; + } + } + + class TextArea { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + } + + const Clapton = { + Box, Component, Text, TextField, Button, DateTimeField, BlockQuote, Checkbox, Code, Element, Emphasis, Form, Heading, Image, Link, List, ListItem, OrderedList, Paragraph, Quote, RadioButton, Select, Span, Embed, Bold, TextArea + }; + + const bq = (...props) => { + return new Clapton.BlockQuote(...props); + }; + const box = (...props) => { + return new Clapton.Box(...props); + }; + const b = (...props) => { + return new Clapton.Bold(...props); + }; + const button = (...props) => { + return new Clapton.Button(...props); + }; + const check = (...props) => { + return new Clapton.Checkbox(props[0], props[1], props[2]); + }; + const code = (...props) => { + return new Clapton.Code(...props); + }; + const datetime = (...props) => { + return new Clapton.DateTimeField(props[0], props[1], props[2]); + }; + const el = (...props) => { + return new Clapton.Element(props[0], props[1]); + }; + const embed = (...props) => { + return new Clapton.Embed(props[0]); + }; + const em = (...props) => { + return new Clapton.Emphasis(...props); + }; + const form = (...props) => { + return new Clapton.Form(...props); + }; + const h = (...props) => { + return new Clapton.Heading(props[0], props[1]); + }; + const img = (...props) => { + return new Clapton.Image(props[0], props[1], props[2]); + }; + const a = (...props) => { + return new Clapton.Link(props[0], props[1]); + }; + const li = (...props) => { + return new Clapton.ListItem(...props); + }; + const ul = (...props) => { + return new Clapton.List(...props); + }; + const ol = (...props) => { + return new Clapton.OrderedList(...props); + }; + const p = (...props) => { + return new Clapton.Paragraph(...props); + }; + const q = (...props) => { + return new Clapton.Quote(...props); + }; + const radio = (...props) => { + return new Clapton.RadioButton(props[0], props[1], props[2]); + }; + const select = (...props) => { + return new Clapton.Select(props[0], props[1], props[2]); + }; + const span = (...props) => { + return new Clapton.Span(...props); + }; + const textarea = (...props) => { + return new Clapton.TextArea(props[0], props[1], props[2]); + }; + const input = (...props) => { + return new Clapton.TextField(props[0], props[1], props[2]); + }; + const text = (...props) => { + return new Clapton.Text(props[0]); + }; + const c = (name, ...props) => { + switch (name) { + case "bq": + return bq(...props); + case "box": + return box(...props); + case "b": + return b(...props); + case "button": + return button(...props); + case "check": + return check(...props); + case "code": + return code(...props); + case "datetime": + return datetime(...props); + case "el": + return el(...props); + case "embed": + return embed(...props); + case "em": + return em(...props); + case "form": + return form(...props); + case "h": + return h(...props); + case "img": + return img(...props); + case "a": + return a(...props); + case "li": + return li(...props); + case "ul": + return ul(...props); + case "ol": + return ol(...props); + case "p": + return p(...props); + case "q": + return q(...props); + case "radio": + return radio(...props); + case "select": + return select(...props); + case "span": + return span(...props); + case "textarea": + return textarea(...props); + case "input": + return input(...props); + case "text": + return text(...props); + default: + return new Clapton.Component(...props); + } + }; + + return c; + +})(); diff --git a/lib/clapton/javascripts/dist/c.js b/lib/clapton/javascripts/dist/c.js new file mode 100644 index 0000000..f8586cc --- /dev/null +++ b/lib/clapton/javascripts/dist/c.js @@ -0,0 +1,584 @@ +const htmlAttributes = (params) => { + const customDataAttributes = params.data || {}; + const others = Object.keys(params).filter(key => key !== "data"); + const flattenDataAttributes = (data, prefix = "data") => { + return Object.keys(data).reduce((acc, key) => { + const value = data[key]; + if (typeof value === "object" && value !== null) { + acc.push(...flattenDataAttributes(value, `${prefix}-${key}`)); + } + else { + acc.push(`${prefix}-${key}='${escapeHtml(value)}'`); + } + return acc; + }, []); + }; + return [ + others.map(key => { + if (key === "disabled") { + if (params[key] === false) { + return ""; + } + else { + return `${key}`; + } + } + return `${key}='${escapeHtml(params[key])}'`; + }).join(" "), + flattenDataAttributes(customDataAttributes).join(" ") + ].filter(Boolean).join(" "); +}; +const escapeHtml = (unsafe) => { + if (typeof unsafe !== "string") { + return ""; + } + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +}; + +class BlockQuote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Box { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add_action(eventType, stateName, fnName, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${eventType}->${stateName}#${fnName}@${options.debounce || 0}`; + return this; + } +} + +class Button { + constructor(attributes = {}) { + this.attributes = attributes; + this.children = []; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } +} + +class Bold { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Checkbox { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } +} + +class Code { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class DateTimeField { + constructor(state, attribute, attributes = {}) { + this.attributes = {}; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + const value = this.state[this.attribute] ? this.datetime_local_value(this.state[this.attribute]) : ""; + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } + datetime_local_value(value) { + if (!value) { + return ""; + } + const date = new Date(value); + date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); + let month = date.getMonth() + 1; + let day = date.getDate(); + let hours = date.getHours(); + let minutes = date.getMinutes(); + if (month < 10) { + month = `0${month}`; + } + if (day < 10) { + day = `0${day}`; + } + if (hours < 10) { + hours = `0${hours}`; + } + if (minutes < 10) { + minutes = `0${minutes}`; + } + return `${date.getFullYear()}-${month}-${day}T${hours}:${minutes}`; + } +} + +class Element { + constructor(type, attributes = {}) { + this.children = []; + this.type = type; + this.attributes = attributes; + } + get renderWrapper() { + return `<${this.type} ${htmlAttributes(this.attributes)}>${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Embed { + constructor(html) { + this.html = html; + } + get renderWrapper() { + return this.html; + } +} + +class Emphasis { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Form { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `
    ${this.children.map(child => child.renderWrapper).join("")}
    `; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Heading { + constructor(level, attributes = {}) { + this.children = []; + this.level = level; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Image { + constructor(src, alt, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.src = src; + this.alt = alt; + } + get renderWrapper() { + return `${this.alt}`; + } +} + +class Link { + constructor(href, attributes = {}) { + this.children = []; + this.attributes = attributes; + this.href = href; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class ListItem { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
  • ${this.children.map(child => child.renderWrapper).join("")}
  • `; + } +} + +class List { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return ``; + } +} + +class OrderedList { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + add(child) { + this.children.push(child); + return this; + } + get renderWrapper() { + return `
      ${this.children.map(child => child.renderWrapper).join("")}
    `; + } +} + +class Paragraph { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `

    ${this.children.map(child => child.renderWrapper).join("")}

    `; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Quote { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class RadioButton { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } +} + +class Select { + constructor(options = [], state, attribute, attributes = {}) { + this.children = []; + this.options = options; + this.state = state; + this.attribute = attribute; + this.attributes = attributes; + } + get renderWrapper() { + return ``; + } +} + +class Span { + constructor(attributes = {}) { + this.children = []; + this.attributes = attributes; + } + get renderWrapper() { + return `${this.children.map(child => child.renderWrapper).join("")}`; + } + add(child) { + this.children.push(child); + return this; + } +} + +class Component { + constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { + this._state = state; + this.id = id; + this._errors = errors; + } + get render() { + return new Box({}); + } + get renderWrapper() { + const root = this.render; + if (root.attributes) { + root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + else { + root.attributes = { data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + return root.renderWrapper; + } +} + +class TextField { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } +} + +class Text { + constructor(value) { + this.value = value; + } + get renderWrapper() { + return this.value; + } +} + +class TextArea { + constructor(state, attribute, attributes = {}) { + this.state = state; + this.attributes = attributes; + this.attribute = attribute; + this.attributes["data-attribute"] = attribute; + } + get renderWrapper() { + return ``; + } + add_action(event, klass, fn, options = {}) { + this.attributes["data-action"] = `${this.attributes["data-action"] || ""} ${event}->${klass}#${fn}@${options.debounce || 0}`; + return this; + } +} + +const Clapton = { + Box, Component, Text, TextField, Button, DateTimeField, BlockQuote, Checkbox, Code, Element, Emphasis, Form, Heading, Image, Link, List, ListItem, OrderedList, Paragraph, Quote, RadioButton, Select, Span, Embed, Bold, TextArea +}; + +const bq = (...props) => { + return new Clapton.BlockQuote(...props); +}; +const box = (...props) => { + return new Clapton.Box(...props); +}; +const b = (...props) => { + return new Clapton.Bold(...props); +}; +const button = (...props) => { + return new Clapton.Button(...props); +}; +const check = (...props) => { + return new Clapton.Checkbox(props[0], props[1], props[2]); +}; +const code = (...props) => { + return new Clapton.Code(...props); +}; +const datetime = (...props) => { + return new Clapton.DateTimeField(props[0], props[1], props[2]); +}; +const el = (...props) => { + return new Clapton.Element(props[0], props[1]); +}; +const embed = (...props) => { + return new Clapton.Embed(props[0]); +}; +const em = (...props) => { + return new Clapton.Emphasis(...props); +}; +const form = (...props) => { + return new Clapton.Form(...props); +}; +const h = (...props) => { + return new Clapton.Heading(props[0], props[1]); +}; +const img = (...props) => { + return new Clapton.Image(props[0], props[1], props[2]); +}; +const a = (...props) => { + return new Clapton.Link(props[0], props[1]); +}; +const li = (...props) => { + return new Clapton.ListItem(...props); +}; +const ul = (...props) => { + return new Clapton.List(...props); +}; +const ol = (...props) => { + return new Clapton.OrderedList(...props); +}; +const p = (...props) => { + return new Clapton.Paragraph(...props); +}; +const q = (...props) => { + return new Clapton.Quote(...props); +}; +const radio = (...props) => { + return new Clapton.RadioButton(props[0], props[1], props[2]); +}; +const select = (...props) => { + return new Clapton.Select(props[0], props[1], props[2]); +}; +const span = (...props) => { + return new Clapton.Span(...props); +}; +const textarea = (...props) => { + return new Clapton.TextArea(props[0], props[1], props[2]); +}; +const input = (...props) => { + return new Clapton.TextField(props[0], props[1], props[2]); +}; +const text = (...props) => { + return new Clapton.Text(props[0]); +}; +const c = (name, ...props) => { + switch (name) { + case "bq": + return bq(...props); + case "box": + return box(...props); + case "b": + return b(...props); + case "button": + return button(...props); + case "check": + return check(...props); + case "code": + return code(...props); + case "datetime": + return datetime(...props); + case "el": + return el(...props); + case "embed": + return embed(...props); + case "em": + return em(...props); + case "form": + return form(...props); + case "h": + return h(...props); + case "img": + return img(...props); + case "a": + return a(...props); + case "li": + return li(...props); + case "ul": + return ul(...props); + case "ol": + return ol(...props); + case "p": + return p(...props); + case "q": + return q(...props); + case "radio": + return radio(...props); + case "select": + return select(...props); + case "span": + return span(...props); + case "textarea": + return textarea(...props); + case "input": + return input(...props); + case "text": + return text(...props); + default: + return new Clapton.Component(...props); + } +}; + +export { c }; diff --git a/lib/clapton/javascripts/dist/components-for-test.js b/lib/clapton/javascripts/dist/components-for-test.js index 2a4d0a7..e0f99d6 100644 --- a/lib/clapton/javascripts/dist/components-for-test.js +++ b/lib/clapton/javascripts/dist/components-for-test.js @@ -386,6 +386,27 @@ var Clapton = (function (exports) { } } + class Component { + constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { + this._state = state; + this.id = id; + this._errors = errors; + } + get render() { + return new Box({}); + } + get renderWrapper() { + const root = this.render; + if (root.attributes) { + root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + else { + root.attributes = { data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; + } + return root.renderWrapper; + } + } + class TextField { constructor(state, attribute, attributes = {}) { this.state = state; @@ -427,110 +448,6 @@ var Clapton = (function (exports) { } } - const Clapton = { - Box, Component, Text, TextField, Button, DateTimeField, BlockQuote, Checkbox, Code, Element, Emphasis, Form, Heading, Image, Link, List, ListItem, OrderedList, Paragraph, Quote, RadioButton, Select, Span, Embed, Bold, TextArea - }; - - class Presets { - bq(...props) { - return new Clapton.BlockQuote(...props); - } - box(...props) { - return new Clapton.Box(...props); - } - b(...props) { - return new Clapton.Bold(...props); - } - button(...props) { - return new Clapton.Button(...props); - } - check(...props) { - return new Clapton.Checkbox(props[0], props[1], props[2]); - } - code(...props) { - return new Clapton.Code(...props); - } - datetime(...props) { - return new Clapton.DateTimeField(props[0], props[1], props[2]); - } - el(...props) { - return new Clapton.Element(props[0], props[1]); - } - embed(...props) { - return new Clapton.Embed(props[0]); - } - em(...props) { - return new Clapton.Emphasis(...props); - } - form(...props) { - return new Clapton.Form(...props); - } - h(...props) { - return new Clapton.Heading(props[0], props[1]); - } - img(...props) { - return new Clapton.Image(props[0], props[1], props[2]); - } - a(...props) { - return new Clapton.Link(props[0], props[1]); - } - li(...props) { - return new Clapton.ListItem(...props); - } - ul(...props) { - return new Clapton.List(...props); - } - ol(...props) { - return new Clapton.OrderedList(...props); - } - p(...props) { - return new Clapton.Paragraph(...props); - } - q(...props) { - return new Clapton.Quote(...props); - } - radio(...props) { - return new Clapton.RadioButton(props[0], props[1], props[2]); - } - select(...props) { - return new Clapton.Select(props[0], props[1], props[2]); - } - span(...props) { - return new Clapton.Span(...props); - } - textarea(...props) { - return new Clapton.TextArea(props[0], props[1], props[2]); - } - input(...props) { - return new Clapton.TextField(props[0], props[1], props[2]); - } - text(...props) { - return new Clapton.Text(props[0]); - } - } - - class Component { - constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { - this._state = state; - this.id = id; - this._errors = errors; - this._c = new Presets(); - } - get render() { - return new Box({}); - } - get renderWrapper() { - const root = this.render; - if (root.attributes) { - root.attributes = { ...root.attributes, data: { ...root.attributes.data, component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; - } - else { - root.attributes = { data: { component: this.constructor.name, state: JSON.stringify(this._state), id: this.id, errors: this._errors } }; - } - return root.renderWrapper; - } - } - exports.BlockQuote = BlockQuote; exports.Bold = Bold; exports.Box = Box; diff --git a/lib/clapton/javascripts/dist/components.js b/lib/clapton/javascripts/dist/components.js index 90d8ad1..4cfc7fe 100644 --- a/lib/clapton/javascripts/dist/components.js +++ b/lib/clapton/javascripts/dist/components.js @@ -383,90 +383,11 @@ class Span { } } -class Presets { - bq(...props) { - return new Clapton.BlockQuote(...props); - } - box(...props) { - return new Clapton.Box(...props); - } - b(...props) { - return new Clapton.Bold(...props); - } - button(...props) { - return new Clapton.Button(...props); - } - check(...props) { - return new Clapton.Checkbox(props[0], props[1], props[2]); - } - code(...props) { - return new Clapton.Code(...props); - } - datetime(...props) { - return new Clapton.DateTimeField(props[0], props[1], props[2]); - } - el(...props) { - return new Clapton.Element(props[0], props[1]); - } - embed(...props) { - return new Clapton.Embed(props[0]); - } - em(...props) { - return new Clapton.Emphasis(...props); - } - form(...props) { - return new Clapton.Form(...props); - } - h(...props) { - return new Clapton.Heading(props[0], props[1]); - } - img(...props) { - return new Clapton.Image(props[0], props[1], props[2]); - } - a(...props) { - return new Clapton.Link(props[0], props[1]); - } - li(...props) { - return new Clapton.ListItem(...props); - } - ul(...props) { - return new Clapton.List(...props); - } - ol(...props) { - return new Clapton.OrderedList(...props); - } - p(...props) { - return new Clapton.Paragraph(...props); - } - q(...props) { - return new Clapton.Quote(...props); - } - radio(...props) { - return new Clapton.RadioButton(props[0], props[1], props[2]); - } - select(...props) { - return new Clapton.Select(props[0], props[1], props[2]); - } - span(...props) { - return new Clapton.Span(...props); - } - textarea(...props) { - return new Clapton.TextArea(props[0], props[1], props[2]); - } - input(...props) { - return new Clapton.TextField(props[0], props[1], props[2]); - } - text(...props) { - return new Clapton.Text(props[0]); - } -} - class Component { constructor(state = {}, id = Math.random().toString(36).substring(2, 10), errors = []) { this._state = state; this.id = id; this._errors = errors; - this._c = new Presets(); } get render() { return new Box({}); diff --git a/lib/clapton/javascripts/rollup.config.mjs b/lib/clapton/javascripts/rollup.config.mjs index 28efe15..dbdd498 100644 --- a/lib/clapton/javascripts/rollup.config.mjs +++ b/lib/clapton/javascripts/rollup.config.mjs @@ -34,6 +34,37 @@ export default [ }) ] }, + { + input: 'src/c.ts', + output: { + file: 'dist/c.js', + format: 'esm' + }, + plugins: [ + resolve(), + commonjs(), + typescript({ + tsconfig: './tsconfig.json', + sourceMap: false + }) + ] + }, + { + input: 'src/c-for-test.ts', + output: { + file: 'dist/c-for-test.js', + format: 'iife', + name: 'c' + }, + plugins: [ + resolve(), + commonjs(), + typescript({ + tsconfig: './tsconfig.json', + sourceMap: false + }) + ] + }, { input: 'src/client.ts', output: { diff --git a/lib/clapton/javascripts/src/c-for-test.ts b/lib/clapton/javascripts/src/c-for-test.ts new file mode 100644 index 0000000..ea4496d --- /dev/null +++ b/lib/clapton/javascripts/src/c-for-test.ts @@ -0,0 +1,160 @@ +import { Clapton } from "components" + +const bq = (...props: any[]) => { + return new Clapton.BlockQuote(...props) +} + +const box = (...props: any[]) => { + return new Clapton.Box(...props) +} + +const b = (...props: any[]) => { + return new Clapton.Bold(...props) +} + +const button = (...props: any[]) => { + return new Clapton.Button(...props) +} + +const check = (...props: any[]) => { + return new Clapton.Checkbox(props[0], props[1], props[2]) +} + +const code = (...props: any[]) => { + return new Clapton.Code(...props) +} + +const datetime = (...props: any[]) => { + return new Clapton.DateTimeField(props[0], props[1], props[2]) +} + +const el = (...props: any[]) => { + return new Clapton.Element(props[0], props[1]) +} + +const embed = (...props: any[]) => { + return new Clapton.Embed(props[0]) +} + +const em = (...props: any[]) => { + return new Clapton.Emphasis(...props) +} + +const form = (...props: any[]) => { + return new Clapton.Form(...props) +} + +const h = (...props: any[]) => { + return new Clapton.Heading(props[0], props[1]) +} + +const img = (...props: any[]) => { + return new Clapton.Image(props[0], props[1], props[2]) +} + +const a = (...props: any[]) => { + return new Clapton.Link(props[0], props[1]) +} + +const li = (...props: any[]) => { + return new Clapton.ListItem(...props) +} + +const ul = (...props: any[]) => { + return new Clapton.List(...props) +} + +const ol = (...props: any[]) => { + return new Clapton.OrderedList(...props) +} + +const p = (...props: any[]) => { + return new Clapton.Paragraph(...props) +} + +const q = (...props: any[]) => { + return new Clapton.Quote(...props) +} + +const radio = (...props: any[]) => { + return new Clapton.RadioButton(props[0], props[1], props[2]) +} + +const select = (...props: any[]) => { + return new Clapton.Select(props[0], props[1], props[2]) +} + +const span = (...props: any[]) => { + return new Clapton.Span(...props) +} + +const textarea = (...props: any[]) => { + return new Clapton.TextArea(props[0], props[1], props[2]) +} + +const input = (...props: any[]) => { + return new Clapton.TextField(props[0], props[1], props[2]) +} + +const text = (...props: any[]) => { + return new Clapton.Text(props[0]) +} + +const c = (name: string, ...props: any[]) => { + switch (name) { + case "bq": + return bq(...props) + case "box": + return box(...props) + case "b": + return b(...props) + case "button": + return button(...props) + case "check": + return check(...props) + case "code": + return code(...props) + case "datetime": + return datetime(...props) + case "el": + return el(...props) + case "embed": + return embed(...props) + case "em": + return em(...props) + case "form": + return form(...props) + case "h": + return h(...props) + case "img": + return img(...props) + case "a": + return a(...props) + case "li": + return li(...props) + case "ul": + return ul(...props) + case "ol": + return ol(...props) + case "p": + return p(...props) + case "q": + return q(...props) + case "radio": + return radio(...props) + case "select": + return select(...props) + case "span": + return span(...props) + case "textarea": + return textarea(...props) + case "input": + return input(...props) + case "text": + return text(...props) + default: + return new Clapton.Component(...props) + } +} + +export default c diff --git a/lib/clapton/javascripts/src/c.ts b/lib/clapton/javascripts/src/c.ts new file mode 100644 index 0000000..63b879b --- /dev/null +++ b/lib/clapton/javascripts/src/c.ts @@ -0,0 +1,160 @@ +import { Clapton } from "components" + +const bq = (...props: any[]) => { + return new Clapton.BlockQuote(...props) +} + +const box = (...props: any[]) => { + return new Clapton.Box(...props) +} + +const b = (...props: any[]) => { + return new Clapton.Bold(...props) +} + +const button = (...props: any[]) => { + return new Clapton.Button(...props) +} + +const check = (...props: any[]) => { + return new Clapton.Checkbox(props[0], props[1], props[2]) +} + +const code = (...props: any[]) => { + return new Clapton.Code(...props) +} + +const datetime = (...props: any[]) => { + return new Clapton.DateTimeField(props[0], props[1], props[2]) +} + +const el = (...props: any[]) => { + return new Clapton.Element(props[0], props[1]) +} + +const embed = (...props: any[]) => { + return new Clapton.Embed(props[0]) +} + +const em = (...props: any[]) => { + return new Clapton.Emphasis(...props) +} + +const form = (...props: any[]) => { + return new Clapton.Form(...props) +} + +const h = (...props: any[]) => { + return new Clapton.Heading(props[0], props[1]) +} + +const img = (...props: any[]) => { + return new Clapton.Image(props[0], props[1], props[2]) +} + +const a = (...props: any[]) => { + return new Clapton.Link(props[0], props[1]) +} + +const li = (...props: any[]) => { + return new Clapton.ListItem(...props) +} + +const ul = (...props: any[]) => { + return new Clapton.List(...props) +} + +const ol = (...props: any[]) => { + return new Clapton.OrderedList(...props) +} + +const p = (...props: any[]) => { + return new Clapton.Paragraph(...props) +} + +const q = (...props: any[]) => { + return new Clapton.Quote(...props) +} + +const radio = (...props: any[]) => { + return new Clapton.RadioButton(props[0], props[1], props[2]) +} + +const select = (...props: any[]) => { + return new Clapton.Select(props[0], props[1], props[2]) +} + +const span = (...props: any[]) => { + return new Clapton.Span(...props) +} + +const textarea = (...props: any[]) => { + return new Clapton.TextArea(props[0], props[1], props[2]) +} + +const input = (...props: any[]) => { + return new Clapton.TextField(props[0], props[1], props[2]) +} + +const text = (...props: any[]) => { + return new Clapton.Text(props[0]) +} + +const c = (name: string, ...props: any[]) => { + switch (name) { + case "bq": + return bq(...props) + case "box": + return box(...props) + case "b": + return b(...props) + case "button": + return button(...props) + case "check": + return check(...props) + case "code": + return code(...props) + case "datetime": + return datetime(...props) + case "el": + return el(...props) + case "embed": + return embed(...props) + case "em": + return em(...props) + case "form": + return form(...props) + case "h": + return h(...props) + case "img": + return img(...props) + case "a": + return a(...props) + case "li": + return li(...props) + case "ul": + return ul(...props) + case "ol": + return ol(...props) + case "p": + return p(...props) + case "q": + return q(...props) + case "radio": + return radio(...props) + case "select": + return select(...props) + case "span": + return span(...props) + case "textarea": + return textarea(...props) + case "input": + return input(...props) + case "text": + return text(...props) + default: + return new Clapton.Component(...props) + } +} + +export { c } diff --git a/lib/clapton/javascripts/src/components/component.ts b/lib/clapton/javascripts/src/components/component.ts index 32852b8..56cfc20 100644 --- a/lib/clapton/javascripts/src/components/component.ts +++ b/lib/clapton/javascripts/src/components/component.ts @@ -1,17 +1,14 @@ import { Box } from "./box"; -import { Presets } from "./presets"; export class Component { id: string; _state: any; _errors: any[]; - _c: Presets; constructor(state: any = {}, id: string = Math.random().toString(36).substring(2, 10), errors: any[] = []) { this._state = state; this.id = id; this._errors = errors; - this._c = new Presets() } get render(): any { diff --git a/lib/clapton/javascripts/src/components/presets.ts b/lib/clapton/javascripts/src/components/presets.ts deleted file mode 100644 index e2655bf..0000000 --- a/lib/clapton/javascripts/src/components/presets.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { Clapton } from "components"; - -export class Presets { - bq(...props: any[]) { - return new Clapton.BlockQuote(...props) - } - - box(...props: any[]) { - return new Clapton.Box(...props) - } - - b(...props: any[]) { - return new Clapton.Bold(...props) - } - - button(...props: any[]) { - return new Clapton.Button(...props) - } - - check(...props: any[]) { - return new Clapton.Checkbox(props[0], props[1], props[2]) - } - - code(...props: any[]) { - return new Clapton.Code(...props) - } - - datetime(...props: any[]) { - return new Clapton.DateTimeField(props[0], props[1], props[2]) - } - - el(...props: any[]) { - return new Clapton.Element(props[0], props[1]) - } - - embed(...props: any[]) { - return new Clapton.Embed(props[0]) - } - - em(...props: any[]) { - return new Clapton.Emphasis(...props) - } - - form(...props: any[]) { - return new Clapton.Form(...props) - } - - h(...props: any[]) { - return new Clapton.Heading(props[0], props[1]) - } - - img(...props: any[]) { - return new Clapton.Image(props[0], props[1], props[2]) - } - - a(...props: any[]) { - return new Clapton.Link(props[0], props[1]) - } - - li(...props: any[]) { - return new Clapton.ListItem(...props) - } - - ul(...props: any[]) { - return new Clapton.List(...props) - } - - ol(...props: any[]) { - return new Clapton.OrderedList(...props) - } - - - p(...props: any[]) { - return new Clapton.Paragraph(...props) - } - - q(...props: any[]) { - return new Clapton.Quote(...props) - } - - radio(...props: any[]) { - return new Clapton.RadioButton(props[0], props[1], props[2]) - } - - select(...props: any[]) { - return new Clapton.Select(props[0], props[1], props[2]) - } - - - span(...props: any[]) { - return new Clapton.Span(...props) - } - - textarea(...props: any[]) { - return new Clapton.TextArea(props[0], props[1], props[2]) - } - - input(...props: any[]) { - return new Clapton.TextField(props[0], props[1], props[2]) - } - - text(...props: any[]) { - return new Clapton.Text(props[0]) - } -} diff --git a/lib/clapton/test_helper/base.rb b/lib/clapton/test_helper/base.rb index d5f2713..d94e2ec 100644 --- a/lib/clapton/test_helper/base.rb +++ b/lib/clapton/test_helper/base.rb @@ -5,10 +5,9 @@ module Base def render_component(component, params) js = File.read(File.join(__dir__, "..", "javascripts", "dist", "components-for-test.js")) + js += File.read(File.join(__dir__, "..", "javascripts", "dist", "c-for-test.js")) Dir.glob(Rails.root.join("app", "components", "**", "*.rb")).each do |file| code = File.read(file) - code = code.gsub(/([^a-zA-Z0-9])c\.(\w+?)\(/, '\1@c.\2(') - code = code.gsub(/([^a-zA-Z0-9])c\.(\w+?)(\.|$)/, '\1@c.\2()\3') js += Ruby2JS.convert(code, preset: true) js += "\n" end diff --git a/test/dummy/app/components/chat_component.rb b/test/dummy/app/components/chat_component.rb index f730847..81e3b75 100644 --- a/test/dummy/app/components/chat_component.rb +++ b/test/dummy/app/components/chat_component.rb @@ -1,6 +1,6 @@ class ChatComponent < Clapton::Component def render - box = c.box + box = c(:box) @state[:messages].each do |message| box.add(MessageComponent.new(role: message[:role], content: message[:content])) end diff --git a/test/dummy/app/components/home_component.rb b/test/dummy/app/components/home_component.rb index 1078f89..5ea2dff 100644 --- a/test/dummy/app/components/home_component.rb +++ b/test/dummy/app/components/home_component.rb @@ -1,7 +1,7 @@ class HomeComponent < Clapton::Component def render - box = c.box - box.add(c.text(@state.message)) + box = c(:box) + box.add(c(:text, @state.message)) box end end diff --git a/test/dummy/app/components/message_component.rb b/test/dummy/app/components/message_component.rb index 48a9829..5ad115f 100644 --- a/test/dummy/app/components/message_component.rb +++ b/test/dummy/app/components/message_component.rb @@ -1,7 +1,7 @@ class MessageComponent < Clapton::Component def render - box = c.box - box.add(c.text("#{@state[:role]}: #{@state[:content]}")) + box = c(:box) + box.add(c(:text, "#{@state[:role]}: #{@state[:content]}")) box end end diff --git a/test/dummy/app/components/sample_component.rb b/test/dummy/app/components/sample_component.rb index 8d6700f..2927882 100644 --- a/test/dummy/app/components/sample_component.rb +++ b/test/dummy/app/components/sample_component.rb @@ -1,65 +1,65 @@ class SampleComponent < Clapton::Component def render - box = c.box({ class: "sample-component" }) + box = c(:box, { class: "sample-component" }) text = Clapton::Text.new(@state.message) box .add(Clapton::BlockQuote.new.add(text)) - .add(c.bq.add(text)) + .add(c(:bq).add(text)) .add(Clapton::Box.new.add(text)) - .add(c.box.add(text)) + .add(c(:box).add(text)) .add(Clapton::Button.new.add(text)) - .add(c.button.add(text)) + .add(c(:button).add(text)) .add(Clapton::Checkbox.new(@state, :boolean, {})) - .add(c.check(@state, :boolean, {})) + .add(c(:check, @state, :boolean, {})) .add(Clapton::Code.new(text)) - .add(c.code.add(text)) + .add(c(:code).add(text)) .add(Clapton::DateTimeField.new(@state, :datetime, {})) - .add(c.datetime(@state, :datetime, {})) + .add(c(:datetime, @state, :datetime, {})) .add(Clapton::Element.new("p").add(text)) - .add(c.el("p").add(text)) + .add(c(:el, "p").add(text)) .add(Clapton::Embed.new("

    Text

    ")) - .add(c.embed("

    Text

    ")) + .add(c(:embed, "

    Text

    ")) .add(Clapton::Emphasis.new(text)) - .add(c.em.add(text)) + .add(c(:em).add(text)) .add(Clapton::Form.new.add(text)) - .add(c.form.add(text)) + .add(c(:form).add(text)) .add(Clapton::Heading.new(1, text)) - .add(c.h(1, text)) + .add(c(:h, 1, text)) .add(Clapton::Image.new("https://example.com/image.png", "Image")) - .add(c.img("https://example.com/image.png", "Image")) + .add(c(:img, "https://example.com/image.png", "Image")) .add(Clapton::Link.new("https://example.com").add(text)) - .add(c.a("https://example.com").add(text)) + .add(c(:a, "https://example.com").add(text)) .add(Clapton::List.new.add( Clapton::ListItem.new.add(text), Clapton::ListItem.new.add(text), )) - .add(c.ul.add( - c.li.add(text), - c.li.add(text), + .add(c(:ul).add( + c(:li).add(text), + c(:li).add(text), )) .add(Clapton::OrderedList.new.add( Clapton::ListItem.new.add(text), Clapton::ListItem.new.add(text), )) - .add(c.ol.add( - c.li.add(text), - c.li.add(text), + .add(c(:ol).add( + c(:li).add(text), + c(:li).add(text), )) .add(Clapton::Paragraph.new(text)) - .add(c.p.add(text)) + .add(c(:p).add(text)) .add(Clapton::Quote.new(text)) - .add(c.q.add(text)) + .add(c(:q).add(text)) .add(Clapton::RadioButton.new(@state, :boolean, {})) - .add(c.radio(@state, :boolean, {})) + .add(c(:radio, @state, :boolean, {})) .add(Clapton::Select.new([], :HomeState, :boolean)) - .add(c.select([], :HomeState, :boolean)) + .add(c(:select, [], :HomeState, :boolean)) .add(Clapton::Span.new.add(text)) - .add(c.span.add(text)) + .add(c(:span).add(text)) .add(Clapton::TextArea.new(@state, :message, {})) - .add(c.textarea(@state, :message, {})) + .add(c(:textarea, @state, :message, {})) .add(Clapton::TextField.new(@state, :message, {})) - .add(c.input(@state, :message, {})) + .add(c(:input, @state, :message, {})) .add(Clapton::Text.new("Hello World")) - .add(c.text("Hello World")) + .add(c(:text, "Hello World")) end end diff --git a/test/dummy/app/components/task_item_component.rb b/test/dummy/app/components/task_item_component.rb index 2c4a689..5787801 100644 --- a/test/dummy/app/components/task_item_component.rb +++ b/test/dummy/app/components/task_item_component.rb @@ -1,14 +1,14 @@ class TaskItemComponent < Clapton::Component def render - box = c.box - btn = c.button({ "data-testid": "task-done-#{@state.id}" }) - btn.add(c.text(@state.done ? "✅" : "🟩")) + box = c(:box) + btn = c(:button, { "data-testid": "task-done-#{@state.id}" }) + btn.add(c(:text, @state.done ? "✅" : "🟩")) btn.add_action(:click, :TaskListState, :toggle_done) - tf = c.input(@state, :title, { "data-testid": "task-title-#{@state.id}" }) + tf = c(:input, @state, :title, { "data-testid": "task-title-#{@state.id}" }) tf.add_action(:input, :TaskListState, :update_title) - dt = c.datetime(@state, :due, { "data-testid": "task-due-#{@state.id}" }) + dt = c(:datetime, @state, :due, { "data-testid": "task-due-#{@state.id}" }) dt.add_action(:input, :TaskListState, :update_due) box.add(btn).add(tf).add(dt) diff --git a/test/dummy/app/components/task_list_component.rb b/test/dummy/app/components/task_list_component.rb index b0d4fda..0ae792d 100644 --- a/test/dummy/app/components/task_list_component.rb +++ b/test/dummy/app/components/task_list_component.rb @@ -1,11 +1,11 @@ class TaskListComponent < Clapton::Component def render - box = c.box + box = c(:box) @state.tasks.each do |task| box.add(TaskItemComponent.new(id: task[:id], title: task[:title], due: task[:due], done: task[:done])) end - add_button = Clapton::Button.new - add_button.add(Clapton::Text.new("Add Task")) + add_button = c(:button) + add_button.add(c(:text, "Add Task")) add_button.add_action(:click, :TaskListState, :add_task) box.add(add_button) box.add_action(:render, :TaskListState, :add_empty_task, debounce: 600) diff --git a/test/dummy/app/components/user_item_component.rb b/test/dummy/app/components/user_item_component.rb index f8ebaba..41b7ba0 100644 --- a/test/dummy/app/components/user_item_component.rb +++ b/test/dummy/app/components/user_item_component.rb @@ -1,10 +1,10 @@ class UserItemComponent < Clapton::Component def render - box = c.box - link = c.link({ href: "/users/#{state[:id]}" }) - link.add(c.text(state[:name])) + box = c(:box) + link = c(:link, { href: "/users/#{state[:id]}" }) + link.add(c(:text, state[:name])) form = UserFormComponent.new({ id: state[:id], name: state[:name], count: state[:count] }) - text = c.text(state[:count].to_s) + text = c(:text, state[:count].to_s) box.add(link).add(form).add(text) end end diff --git a/test/dummy/app/components/user_list_component.rb b/test/dummy/app/components/user_list_component.rb index 6335f5a..0858eee 100644 --- a/test/dummy/app/components/user_list_component.rb +++ b/test/dummy/app/components/user_list_component.rb @@ -1,6 +1,6 @@ class UserListComponent < Clapton::Component def render - box = c.box + box = c(:box) state[:users].each do |user| box.add(UserItemComponent.new(id: user[:id], name: user[:name], count: user[:count])) end diff --git a/test/dummy/app/components/user_prompt_component.rb b/test/dummy/app/components/user_prompt_component.rb index cffef66..9f8c098 100644 --- a/test/dummy/app/components/user_prompt_component.rb +++ b/test/dummy/app/components/user_prompt_component.rb @@ -1,9 +1,9 @@ class UserPromptComponent < Clapton::Component def render - box = c.box - text_field = c.input(@state, :content) - button = c.button({ disabled: @state.content.empty? }) - button.add(c.text("Send")) + box = c(:box) + text_field = c(:input, @state, :content) + button = c(:button, { disabled: @state.content.empty? }) + button.add(c(:text, "Send")) button.add_action(:click, :ChatState, :send) box.add(text_field).add(button) box