matestack-ui-core 0.7.6 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +8 -0
- data/README.md +695 -121
- data/app/concepts/matestack/ui/core/abbr/abbr.haml +3 -3
- data/app/concepts/matestack/ui/core/abbr/abbr.rb +1 -8
- data/app/concepts/matestack/ui/core/action/action.haml +1 -1
- data/app/concepts/matestack/ui/core/action/action.rb +23 -19
- data/app/concepts/matestack/ui/core/actionview/dynamic.haml +4 -4
- data/app/concepts/matestack/ui/core/address/address.haml +3 -3
- data/app/concepts/matestack/ui/core/address/address.rb +1 -1
- data/app/concepts/matestack/ui/core/app/app.haml +2 -3
- data/app/concepts/matestack/ui/core/app/app.js +4 -1
- data/app/concepts/matestack/ui/core/app/app.rb +32 -56
- data/app/concepts/matestack/ui/core/app/store.js +27 -1
- data/app/concepts/matestack/ui/core/area/area.haml +1 -1
- data/app/concepts/matestack/ui/core/area/area.rb +2 -14
- data/app/concepts/matestack/ui/core/article/article.haml +3 -3
- data/app/concepts/matestack/ui/core/article/article.rb +1 -1
- data/app/concepts/matestack/ui/core/aside/aside.haml +1 -1
- data/app/concepts/matestack/ui/core/aside/aside.rb +0 -1
- data/app/concepts/matestack/ui/core/async/async.haml +6 -2
- data/app/concepts/matestack/ui/core/async/async.js +43 -31
- data/app/concepts/matestack/ui/core/async/async.rb +29 -4
- data/app/concepts/matestack/ui/core/async/children_wrapper.haml +2 -0
- data/app/concepts/matestack/ui/core/b/b.haml +3 -3
- data/app/concepts/matestack/ui/core/b/b.rb +1 -1
- data/app/concepts/matestack/ui/core/bdi/bdi.haml +3 -3
- data/app/concepts/matestack/ui/core/bdi/bdi.rb +1 -0
- data/app/concepts/matestack/ui/core/bdo/bdo.haml +3 -3
- data/app/concepts/matestack/ui/core/bdo/bdo.rb +2 -7
- data/app/concepts/matestack/ui/core/blockquote/blockquote.haml +3 -3
- data/app/concepts/matestack/ui/core/blockquote/blockquote.rb +2 -7
- data/app/concepts/matestack/ui/core/br/br.haml +4 -4
- data/app/concepts/matestack/ui/core/br/br.rb +1 -1
- data/app/concepts/matestack/ui/core/button/button.haml +3 -3
- data/app/concepts/matestack/ui/core/button/button.rb +3 -7
- data/app/concepts/matestack/ui/core/cable/cable.haml +4 -0
- data/app/concepts/matestack/ui/core/cable/cable.js +100 -0
- data/app/concepts/matestack/ui/core/cable/cable.rb +28 -0
- data/app/concepts/matestack/ui/core/cable/children_wrapper.haml +2 -0
- data/app/concepts/matestack/ui/core/caption/caption.haml +3 -3
- data/app/concepts/matestack/ui/core/caption/caption.rb +1 -1
- data/app/concepts/matestack/ui/core/cite/cite.haml +3 -3
- data/app/concepts/matestack/ui/core/cite/cite.rb +1 -1
- data/app/concepts/matestack/ui/core/code/code.haml +3 -3
- data/app/concepts/matestack/ui/core/code/code.rb +1 -1
- data/app/concepts/matestack/ui/core/collection/content/content.js +2 -2
- data/app/concepts/matestack/ui/core/collection/content/content.rb +4 -6
- data/app/concepts/matestack/ui/core/collection/content/next/next.haml +1 -1
- data/app/concepts/matestack/ui/core/collection/content/page/link/link.haml +1 -1
- data/app/concepts/matestack/ui/core/collection/content/page/link/link.rb +5 -3
- data/app/concepts/matestack/ui/core/collection/content/previous/previous.haml +1 -1
- data/app/concepts/matestack/ui/core/collection/filter/filter.rb +4 -5
- data/app/concepts/matestack/ui/core/collection/filter/input/input.rb +11 -8
- data/app/concepts/matestack/ui/core/collection/filter/reset/reset.haml +1 -1
- data/app/concepts/matestack/ui/core/collection/filter/select/select.haml +10 -0
- data/app/concepts/matestack/ui/core/collection/filter/select/select.rb +30 -0
- data/app/concepts/matestack/ui/core/collection/filter/submit/submit.haml +1 -1
- data/app/concepts/matestack/ui/core/collection/helper.rb +14 -6
- data/app/concepts/matestack/ui/core/collection/order/order.js +1 -1
- data/app/concepts/matestack/ui/core/collection/order/order.rb +4 -5
- data/app/concepts/matestack/ui/core/collection/order/toggle/indicator/indicator.rb +9 -5
- data/app/concepts/matestack/ui/core/collection/order/toggle/toggle.haml +1 -1
- data/app/concepts/matestack/ui/core/collection/order/toggle/toggle.rb +0 -1
- data/app/concepts/matestack/ui/core/component/base.rb +430 -0
- data/app/concepts/matestack/ui/core/component/children.haml +2 -2
- data/app/concepts/matestack/ui/core/component/component.js +9 -46
- data/app/concepts/matestack/ui/core/component/dynamic.haml +1 -1
- data/app/concepts/matestack/ui/core/component/dynamic.rb +25 -247
- data/app/concepts/matestack/ui/core/component/static.rb +3 -12
- data/app/concepts/matestack/ui/core/data/data.haml +3 -3
- data/app/concepts/matestack/ui/core/data/data.rb +2 -5
- data/app/concepts/matestack/ui/core/datalist/datalist.haml +2 -2
- data/app/concepts/matestack/ui/core/datalist/datalist.rb +1 -2
- data/app/concepts/matestack/ui/core/dd/dd.haml +3 -3
- data/app/concepts/matestack/ui/core/dd/dd.rb +1 -1
- data/app/concepts/matestack/ui/core/del/del.haml +3 -3
- data/app/concepts/matestack/ui/core/del/del.rb +2 -0
- data/app/concepts/matestack/ui/core/details/details.haml +1 -1
- data/app/concepts/matestack/ui/core/details/details.rb +1 -1
- data/app/concepts/matestack/ui/core/dfn/dfn.haml +3 -3
- data/app/concepts/matestack/ui/core/dfn/dfn.rb +1 -1
- data/app/concepts/matestack/ui/core/dialog/dialog.haml +3 -3
- data/app/concepts/matestack/ui/core/dialog/dialog.rb +2 -5
- data/app/concepts/matestack/ui/core/div/div.haml +1 -1
- data/app/concepts/matestack/ui/core/div/div.rb +0 -1
- data/app/concepts/matestack/ui/core/dl/dl.haml +3 -3
- data/app/concepts/matestack/ui/core/dl/dl.rb +2 -2
- data/app/concepts/matestack/ui/core/dt/dt.haml +3 -3
- data/app/concepts/matestack/ui/core/dt/dt.rb +1 -1
- data/app/concepts/matestack/ui/core/em/em.haml +3 -3
- data/app/concepts/matestack/ui/core/em/em.rb +1 -1
- data/app/concepts/matestack/ui/core/fieldset/fieldset.haml +4 -4
- data/app/concepts/matestack/ui/core/fieldset/fieldset.rb +3 -6
- data/app/concepts/matestack/ui/core/figure/figure.haml +1 -1
- data/app/concepts/matestack/ui/core/figure/figure.rb +0 -1
- data/app/concepts/matestack/ui/core/footer/footer.haml +1 -1
- data/app/concepts/matestack/ui/core/footer/footer.rb +0 -1
- data/app/concepts/matestack/ui/core/form/checkbox/checkbox.rb +79 -0
- data/app/concepts/matestack/ui/core/form/form.haml +1 -1
- data/app/concepts/matestack/ui/core/form/form.js +25 -20
- data/app/concepts/matestack/ui/core/form/form.rb +35 -24
- data/app/concepts/matestack/ui/core/form/has_errors.rb +54 -0
- data/app/concepts/matestack/ui/core/form/has_input_html_attributes.rb +13 -0
- data/app/concepts/matestack/ui/core/form/input/input.rb +32 -52
- data/app/concepts/matestack/ui/core/form/radio/radio.rb +71 -0
- data/app/concepts/matestack/ui/core/form/select/select.haml +9 -80
- data/app/concepts/matestack/ui/core/form/select/select.rb +41 -56
- data/app/concepts/matestack/ui/core/form/submit/submit.haml +1 -1
- data/app/concepts/matestack/ui/core/form/submit/submit.rb +5 -2
- data/app/concepts/matestack/ui/core/form/textarea/textarea.rb +28 -0
- data/app/concepts/matestack/ui/core/form/utils.rb +47 -0
- data/app/concepts/matestack/ui/core/header/header.haml +1 -1
- data/app/concepts/matestack/ui/core/header/header.rb +0 -1
- data/app/concepts/matestack/ui/core/heading/heading.haml +4 -49
- data/app/concepts/matestack/ui/core/heading/heading.rb +1 -1
- data/app/concepts/matestack/ui/core/hr/hr.haml +1 -1
- data/app/concepts/matestack/ui/core/hr/hr.rb +0 -1
- data/app/concepts/matestack/ui/core/icon/icon.haml +3 -3
- data/app/concepts/matestack/ui/core/icon/icon.rb +1 -1
- data/app/concepts/matestack/ui/core/iframe/iframe.haml +3 -3
- data/app/concepts/matestack/ui/core/iframe/iframe.rb +3 -10
- data/app/concepts/matestack/ui/core/img/img.haml +1 -1
- data/app/concepts/matestack/ui/core/img/img.rb +8 -8
- data/app/concepts/matestack/ui/core/input/input.haml +1 -2
- data/app/concepts/matestack/ui/core/input/input.rb +4 -4
- data/app/concepts/matestack/ui/core/ins/ins.haml +3 -3
- data/app/concepts/matestack/ui/core/ins/ins.rb +2 -6
- data/app/concepts/matestack/ui/core/isolated/children_wrapper.haml +2 -0
- data/app/concepts/matestack/ui/core/isolated/isolated.haml +10 -0
- data/app/concepts/matestack/ui/core/isolated/isolated.js +108 -0
- data/app/concepts/matestack/ui/core/isolated/isolated.rb +59 -0
- data/app/concepts/matestack/ui/core/js/core.js +6 -4
- data/app/concepts/matestack/ui/core/kbd/kbd.haml +3 -3
- data/app/concepts/matestack/ui/core/kbd/kbd.rb +1 -0
- data/app/concepts/matestack/ui/core/label/label.haml +3 -3
- data/app/concepts/matestack/ui/core/label/label.rb +2 -6
- data/app/concepts/matestack/ui/core/legend/legend.haml +3 -3
- data/app/concepts/matestack/ui/core/legend/legend.rb +1 -1
- data/app/concepts/matestack/ui/core/li/li.haml +3 -3
- data/app/concepts/matestack/ui/core/li/li.rb +2 -1
- data/app/concepts/matestack/ui/core/link/link.haml +3 -3
- data/app/concepts/matestack/ui/core/link/link.rb +10 -14
- data/app/concepts/matestack/ui/core/main/main.haml +1 -1
- data/app/concepts/matestack/ui/core/main/main.rb +0 -1
- data/app/concepts/matestack/ui/core/map/map.haml +1 -1
- data/app/concepts/matestack/ui/core/map/map.rb +1 -7
- data/app/concepts/matestack/ui/core/mark/mark.haml +3 -3
- data/app/concepts/matestack/ui/core/mark/mark.rb +1 -0
- data/app/concepts/matestack/ui/core/meter/meter.haml +1 -1
- data/app/concepts/matestack/ui/core/meter/meter.rb +1 -10
- data/app/concepts/matestack/ui/core/nav/nav.haml +1 -1
- data/app/concepts/matestack/ui/core/nav/nav.rb +0 -1
- data/app/concepts/matestack/ui/core/noscript/noscript.haml +3 -3
- data/app/concepts/matestack/ui/core/noscript/noscript.rb +1 -1
- data/app/concepts/matestack/ui/core/object/object.haml +1 -1
- data/app/concepts/matestack/ui/core/object/object.rb +1 -11
- data/app/concepts/matestack/ui/core/ol/ol.haml +1 -1
- data/app/concepts/matestack/ui/core/ol/ol.rb +1 -1
- data/app/concepts/matestack/ui/core/onclick/onclick.haml +1 -1
- data/app/concepts/matestack/ui/core/onclick/onclick.rb +1 -0
- data/app/concepts/matestack/ui/core/optgroup/optgroup.haml +1 -1
- data/app/concepts/matestack/ui/core/optgroup/optgroup.rb +1 -6
- data/app/concepts/matestack/ui/core/option/option.haml +3 -3
- data/app/concepts/matestack/ui/core/option/option.rb +2 -8
- data/app/concepts/matestack/ui/core/output/output.haml +3 -3
- data/app/concepts/matestack/ui/core/output/output.rb +2 -7
- data/app/concepts/matestack/ui/core/page/{content.js → content/content.js} +8 -2
- data/app/concepts/matestack/ui/core/page/content/content.rb +28 -0
- data/app/concepts/matestack/ui/core/page/page.haml +3 -9
- data/app/concepts/matestack/ui/core/page/page.rb +15 -179
- data/app/concepts/matestack/ui/core/paragraph/paragraph.haml +3 -3
- data/app/concepts/matestack/ui/core/paragraph/paragraph.rb +1 -1
- data/app/concepts/matestack/ui/core/param/param.haml +1 -1
- data/app/concepts/matestack/ui/core/param/param.rb +1 -6
- data/app/concepts/matestack/ui/core/partial/partial.rb +0 -1
- data/app/concepts/matestack/ui/core/picture/picture.haml +1 -1
- data/app/concepts/matestack/ui/core/pre/pre.haml +3 -3
- data/app/concepts/matestack/ui/core/pre/pre.rb +1 -1
- data/app/concepts/matestack/ui/core/progress/progress.haml +1 -1
- data/app/concepts/matestack/ui/core/progress/progress.rb +1 -10
- data/app/concepts/matestack/ui/core/q/q.haml +3 -3
- data/app/concepts/matestack/ui/core/q/q.rb +2 -7
- data/app/concepts/matestack/ui/core/rp/rp.haml +3 -3
- data/app/concepts/matestack/ui/core/rp/rp.rb +1 -1
- data/app/concepts/matestack/ui/core/rt/rt.haml +3 -3
- data/app/concepts/matestack/ui/core/rt/rt.rb +1 -1
- data/app/concepts/matestack/ui/core/ruby/ruby.haml +3 -3
- data/app/concepts/matestack/ui/core/ruby/ruby.rb +1 -1
- data/app/concepts/matestack/ui/core/s/s.haml +3 -3
- data/app/concepts/matestack/ui/core/s/s.rb +1 -1
- data/app/concepts/matestack/ui/core/samp/samp.haml +3 -3
- data/app/concepts/matestack/ui/core/samp/samp.rb +1 -0
- data/app/concepts/matestack/ui/core/section/section.haml +1 -1
- data/app/concepts/matestack/ui/core/section/section.rb +0 -1
- data/app/concepts/matestack/ui/core/slot/slot.rb +1 -2
- data/app/concepts/matestack/ui/core/small/small.haml +3 -3
- data/app/concepts/matestack/ui/core/small/small.rb +1 -1
- data/app/concepts/matestack/ui/core/span/span.haml +3 -3
- data/app/concepts/matestack/ui/core/span/span.rb +1 -1
- data/app/concepts/matestack/ui/core/strong/strong.haml +3 -3
- data/app/concepts/matestack/ui/core/strong/strong.rb +1 -1
- data/app/concepts/matestack/ui/core/sub/sub.haml +3 -3
- data/app/concepts/matestack/ui/core/sub/sub.rb +1 -1
- data/app/concepts/matestack/ui/core/summary/summary.haml +3 -3
- data/app/concepts/matestack/ui/core/summary/summary.rb +1 -1
- data/app/concepts/matestack/ui/core/sup/sup.haml +3 -3
- data/app/concepts/matestack/ui/core/sup/sup.rb +1 -1
- data/app/concepts/matestack/ui/core/table/table.haml +1 -1
- data/app/concepts/matestack/ui/core/table/table.rb +0 -1
- data/app/concepts/matestack/ui/core/tbody/tbody.haml +1 -1
- data/app/concepts/matestack/ui/core/tbody/tbody.rb +0 -1
- data/app/concepts/matestack/ui/core/td/td.haml +3 -3
- data/app/concepts/matestack/ui/core/td/td.rb +2 -1
- data/app/concepts/matestack/ui/core/template/template.haml +1 -1
- data/app/concepts/matestack/ui/core/textarea/textarea.haml +5 -0
- data/app/concepts/matestack/ui/core/textarea/textarea.rb +10 -0
- data/app/concepts/matestack/ui/core/tfoot/tfoot.haml +1 -1
- data/app/concepts/matestack/ui/core/tfoot/tfoot.rb +0 -1
- data/app/concepts/matestack/ui/core/th/th.haml +3 -3
- data/app/concepts/matestack/ui/core/th/th.rb +2 -1
- data/app/concepts/matestack/ui/core/thead/thead.haml +1 -1
- data/app/concepts/matestack/ui/core/thead/thead.rb +0 -1
- data/app/concepts/matestack/ui/core/time/time.haml +1 -1
- data/app/concepts/matestack/ui/core/time/time.rb +1 -7
- data/app/concepts/matestack/ui/core/toggle/toggle.haml +2 -0
- data/app/concepts/matestack/ui/core/toggle/toggle.js +71 -0
- data/app/concepts/matestack/ui/core/toggle/toggle.rb +13 -0
- data/app/concepts/matestack/ui/core/tr/tr.haml +1 -1
- data/app/concepts/matestack/ui/core/tr/tr.rb +0 -1
- data/app/concepts/matestack/ui/core/transition/transition.haml +3 -3
- data/app/concepts/matestack/ui/core/transition/transition.js +1 -0
- data/app/concepts/matestack/ui/core/transition/transition.rb +14 -7
- data/app/concepts/matestack/ui/core/u/u.haml +3 -3
- data/app/concepts/matestack/ui/core/u/u.rb +1 -1
- data/app/concepts/matestack/ui/core/ul/ul.haml +1 -1
- data/app/concepts/matestack/ui/core/ul/ul.rb +0 -1
- data/app/concepts/matestack/ui/core/unescaped/unescaped.rb +3 -1
- data/app/concepts/matestack/ui/core/var/var.haml +3 -3
- data/app/concepts/matestack/ui/core/var/var.rb +1 -0
- data/app/concepts/matestack/ui/core/video/video.haml +2 -2
- data/app/concepts/matestack/ui/core/video/video.rb +4 -14
- data/app/concepts/matestack/ui/core/view/view.haml +1 -0
- data/app/concepts/matestack/ui/core/view/view.rb +30 -0
- data/app/concepts/matestack/ui/core/wbr/wbr.haml +5 -1
- data/app/concepts/matestack/ui/core/wbr/wbr.rb +1 -0
- data/app/concepts/matestack/ui/core/youtube/youtube.haml +1 -1
- data/app/concepts/matestack/ui/core/youtube/youtube.rb +18 -16
- data/app/helpers/matestack/ui/core/application_helper.rb +94 -21
- data/app/lib/matestack/ui/component.rb +1 -0
- data/app/lib/matestack/ui/core/has_view_context.rb +6 -4
- data/app/lib/matestack/ui/core/html_attributes.rb +43 -0
- data/app/lib/matestack/ui/core/properties.rb +161 -0
- data/app/lib/matestack/ui/core/rendering/default_renderer_class_determiner.rb +33 -0
- data/app/lib/matestack/ui/core/rendering/main_renderer.rb +203 -0
- data/app/lib/matestack/ui/isolated_component.rb +1 -0
- data/app/lib/matestack/ui/vue_js_component.rb +1 -0
- data/lib/matestack/ui/core.rb +4 -2
- data/lib/matestack/ui/core/cell.rb +0 -2
- data/lib/matestack/ui/core/component/registry.rb +47 -0
- data/lib/matestack/ui/core/components.rb +269 -0
- data/lib/matestack/ui/core/dsl.rb +6 -0
- data/lib/matestack/ui/core/engine.rb +16 -0
- data/lib/matestack/ui/core/version.rb +1 -1
- data/vendor/assets/javascripts/dist/matestack-ui-core.js +467 -142
- data/vendor/assets/javascripts/dist/matestack-ui-core.js.map +1 -1
- data/vendor/assets/javascripts/dist/matestack-ui-core.min.js +1 -1
- data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.br +0 -0
- data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.gz +0 -0
- data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.map +1 -1
- data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.map.br +0 -0
- data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.map.gz +0 -0
- metadata +50 -63
- data/MIT-LICENSE +0 -20
- data/app/concepts/matestack/ui/core/absolute/absolute.haml +0 -3
- data/app/concepts/matestack/ui/core/absolute/absolute.rb +0 -17
- data/app/concepts/matestack/ui/core/collection/filter/input/input.haml +0 -2
- data/app/concepts/matestack/ui/core/component/response.haml +0 -2
- data/app/concepts/matestack/ui/core/component/response_dynamic.haml +0 -7
- data/app/concepts/matestack/ui/core/component/response_dynamic_without_rerender.haml +0 -3
- data/app/concepts/matestack/ui/core/component/static.haml +0 -1
- data/app/concepts/matestack/ui/core/form/inline/inline.haml +0 -6
- data/app/concepts/matestack/ui/core/form/inline/inline.rb +0 -9
- data/app/concepts/matestack/ui/core/form/input/input.haml +0 -46
- data/app/concepts/matestack/ui/core/html/html.haml +0 -3
- data/app/concepts/matestack/ui/core/html/html.js +0 -10
- data/app/concepts/matestack/ui/core/html/html.rb +0 -17
- data/app/concepts/matestack/ui/core/isolate/isolate.haml +0 -2
- data/app/concepts/matestack/ui/core/isolate/isolate.rb +0 -11
- data/app/concepts/matestack/ui/core/page/content.haml +0 -7
- data/app/concepts/matestack/ui/core/page/content.rb +0 -5
- data/app/concepts/matestack/ui/core/pg/pg.haml +0 -5
- data/app/concepts/matestack/ui/core/pg/pg.rb +0 -5
- data/app/lib/matestack/ui/core/app_node.rb +0 -53
- data/app/lib/matestack/ui/core/component_node.rb +0 -87
- data/app/lib/matestack/ui/core/page_node.rb +0 -100
- data/app/lib/matestack/ui/core/render.rb +0 -89
- data/app/lib/matestack/ui/core/to_cell.rb +0 -129
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9912bb90f1207c60c0e31895fabbe090e93bca8c63fe85a4c075b92386ed1a32
|
4
|
+
data.tar.gz: 768a1f1071275163d1a3870fb4d8401960b757fc803f3ab82b8bf17a3b4a22c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d79c8aa967c5f223ff69b211eaa36d715bb0615a4eec5c303ea62b5f13e53fa7b4945778cf143ba9098c42f9608bc1da1d89f43f3689cb3239bf7cc79903b316
|
7
|
+
data.tar.gz: 8cff6d3684d75949299bce178f7c3114dbef3333fe794ef821df0422be2100f4f4c383e2f0c06348b03928518cd834729d4b9096b885c6f415615b2221a44f28
|
data/LICENSE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Copyright (c) Matestack GmbH
|
2
|
+
|
3
|
+
matestack-ui-core is an Open Source project licensed under the terms of
|
4
|
+
the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
|
5
|
+
for license text.
|
6
|
+
|
7
|
+
Matestack will provide a commercial-friendly license allowing private forks
|
8
|
+
and modifications of matestack-ui-core. Please request at jonas@matestack.io
|
data/README.md
CHANGED
@@ -1,240 +1,814 @@
|
|
1
|
-
![](https://github.com/matestack/matestack-ui-core/workflows/specs/badge.svg)
|
2
|
-
[![
|
1
|
+
[![Specs](https://github.com/matestack/matestack-ui-core/workflows/specs/badge.svg)](https://github.com/matestack/matestack-ui-core/actions)
|
2
|
+
[![Discord](https://img.shields.io/discord/771413294136426496.svg)](https://discord.com/invite/c6tQxFG)
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/matestack-ui-core.svg)](https://badge.fury.io/rb/matestack-ui-core)
|
4
|
-
[![Docs](https://img.shields.io/badge/docs-matestack-blue.svg)](https://
|
4
|
+
[![Docs](https://img.shields.io/badge/docs-matestack-blue.svg)](https://docs.matestack.io)
|
5
|
+
[![Twitter Follow](https://img.shields.io/twitter/follow/matestack.svg?style=social)](https://twitter.com/matestack)
|
5
6
|
|
6
7
|
![matestack logo](./logo.png)
|
7
8
|
|
8
|
-
# matestack
|
9
|
+
# matestack-ui-core | UI in pure Ruby
|
9
10
|
|
10
|
-
|
11
|
+
Boost your productivity & easily create component based web UIs in pure Ruby.
|
12
|
+
Reactivity included if desired.
|
11
13
|
|
12
|
-
|
14
|
+
`matestack-ui-core` enables you to craft maintainable web UIs in pure Ruby, skipping ERB and HTML. UI code becomes a native and fun part of your Rails app. Thanks to reactive core components, reactivity can be optionally added on top without writing JavaScript, just using a simple Ruby DSL.
|
15
|
+
|
16
|
+
You end up writing 50% less code while increasing productivity, maintainability and developer happiness. Work with pure Ruby. If necessary, extend with pure JavaScript. No Opal involved.
|
17
|
+
|
18
|
+
The main goals are:
|
13
19
|
|
14
|
-
- Reduction of complexity of modern web development, moving front and backend closer together
|
15
20
|
- More maintainable UI code, using a component-based structure written in Ruby
|
16
|
-
- Increased development speed and happiness, offering prebuilt UI-Components for
|
21
|
+
- Increased development speed and happiness, offering prebuilt UI-Components for typical requirements
|
17
22
|
- Modern, dynamic UI feeling without the need to implement a separate JavaScript Application
|
18
23
|
|
19
|
-
matestack can progressively replace the classic Rails-View-Layer. You are able to use
|
24
|
+
`matestack-ui-core` can progressively replace the classic Rails-View-Layer. You are able to use
|
20
25
|
it alongside your classic views and incrementally turn your Rails-App into a
|
21
26
|
dynamic Web-App.
|
22
27
|
|
23
|
-
|
28
|
+
## Documentation/Installation
|
29
|
+
|
30
|
+
Documentation can be found [here](https://docs.matestack.io)
|
31
|
+
|
32
|
+
## Changelog
|
33
|
+
|
34
|
+
Changelog can be found [here](./CHANGELOG.md)
|
35
|
+
|
36
|
+
## Community
|
37
|
+
|
38
|
+
As a low-barrier feedback channel for our early users, we have set up a Discord server that can be found [here](https://discord.com/invite/c6tQxFG). You are very welcome to ask questions and send us feedback there!
|
39
|
+
|
40
|
+
## Contribution
|
41
|
+
|
42
|
+
We are happy to accept contributors of any kind! In order to make it as easy and fun as possible to contribute to `matestack-ui-core`, we would like to onboard contributors personally! Best way to become a contributor: Ping us on Discord! We will schedule a video call with you and show you, how and what to work on :)
|
43
|
+
|
44
|
+
Here are some good first issues for first time contributors: [good first issues](https://github.com/matestack/matestack-ui-core/issues?q=is%3Aopen+is%3Aissue+label%3A"good+first+issue")
|
24
45
|
|
25
|
-
|
46
|
+
## Features
|
26
47
|
|
27
|
-
|
28
|
-
* core refactoring, increased core maintainability and code quality
|
29
|
-
* better integration in existing rails apps
|
30
|
-
* improved documentation
|
31
|
-
* improved dynamic core components (especially form components)
|
48
|
+
On our [landingpage](https://www.matestack.io), we're presenting the following features alongside some live demos!
|
32
49
|
|
50
|
+
### 1. Create UI components in pure Ruby
|
33
51
|
|
34
|
-
|
52
|
+
Craft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.
|
35
53
|
|
36
|
-
|
54
|
+
#### Implement UI components in pure Ruby
|
37
55
|
|
38
|
-
|
56
|
+
Create Ruby classes within your Rails project and call matestack's core components through a Ruby DSL in order to craft your UIs.
|
57
|
+
The Ruby method \"div\" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. \"title\") or require them (e.g. \"body\").
|
58
|
+
|
59
|
+
`app/matestack/components/card.rb`
|
39
60
|
|
40
|
-
#### Define your UI in a Ruby Class
|
41
61
|
```ruby
|
42
|
-
class Pages::MyPage < Matestack::Ui::Page
|
43
62
|
|
44
|
-
|
45
|
-
|
46
|
-
|
63
|
+
class Components::Card < Matestack::Ui::Component
|
64
|
+
|
65
|
+
requires :body
|
66
|
+
optional :title
|
67
|
+
optional :image
|
47
68
|
|
48
69
|
def response
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
70
|
+
div class: "card shadow-sm border-0 bg-light" do
|
71
|
+
img path: image, class: "w-100" if image.present?
|
72
|
+
div class: "card-body" do
|
73
|
+
heading size: 5, text: title if title.present?
|
74
|
+
paragraph class: "card-text", text: body
|
54
75
|
end
|
55
|
-
|
76
|
+
end
|
56
77
|
end
|
57
78
|
|
79
|
+
end
|
80
|
+
|
81
|
+
```
|
82
|
+
|
83
|
+
#### Use your Ruby UI components on your existing Rails views
|
84
|
+
|
85
|
+
Register your Ruby UI component classes with your desired DSL method and use the \"matestack_component\" helper in order to render your component within existing ERB views or Rails controllers.
|
86
|
+
The Ruby method \"card\" for example calls your \"Card\" class, enabling you to create a reuseable card components, abstracting UI complexity in your ow components.
|
87
|
+
|
88
|
+
`app/views/your_view.html.erb`
|
89
|
+
|
90
|
+
```erb
|
91
|
+
|
92
|
+
<!-- some other erb markup -->
|
93
|
+
<%= matestack_component :card, title: "hello", body: "world" %>
|
94
|
+
<!-- some other erb markup -->
|
95
|
+
|
96
|
+
```
|
97
|
+
|
98
|
+
`app/matestack/components/registry.rb`
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
module Components::Registry
|
102
|
+
|
103
|
+
Matestack::Ui::Core::Component::Registry.register_components(
|
104
|
+
card: Components::Card,
|
105
|
+
#...
|
106
|
+
)
|
107
|
+
|
58
108
|
end
|
59
109
|
```
|
60
|
-
|
110
|
+
|
111
|
+
|
112
|
+
#### Use Ruby methods as partials
|
113
|
+
|
114
|
+
Split your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation.
|
115
|
+
Using this approach helps you to create a clean, readable and maintainable codebase.
|
116
|
+
|
117
|
+
`app/matestack/components/card.rb`
|
61
118
|
|
62
119
|
```ruby
|
63
|
-
|
120
|
+
|
121
|
+
class Components::Card < Matestack::Ui::Component
|
122
|
+
|
123
|
+
requires :body
|
124
|
+
optional :title
|
125
|
+
optional :image
|
126
|
+
optional :footer
|
64
127
|
|
65
128
|
def response
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
129
|
+
div class: "card shadow-sm border-0 bg-light" do
|
130
|
+
img path: image, class: "w-100" if image.present?
|
131
|
+
card_content
|
132
|
+
card_footer if footer.present?
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def card_content
|
137
|
+
div class: "card-body" do
|
138
|
+
heading size: 5, text: title if title.present?
|
139
|
+
paragraph class: "card-text", text: body
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def card_footer
|
144
|
+
div class: "card-footer text-muted" do
|
145
|
+
plain footer
|
146
|
+
end
|
85
147
|
end
|
86
148
|
|
87
149
|
end
|
150
|
+
|
151
|
+
```
|
152
|
+
|
153
|
+
`app/views/your_view.html.erb`
|
154
|
+
|
155
|
+
```erb
|
156
|
+
<!-- some other erb markup -->
|
157
|
+
<%= matestack_component :card, title: "hello", body: "world", footer: "foo" %>
|
158
|
+
<!-- some other erb markup -->
|
88
159
|
```
|
89
160
|
|
161
|
+
|
162
|
+
#### Use class inheritance
|
163
|
+
|
164
|
+
Because it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation.
|
165
|
+
Class inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.
|
166
|
+
|
167
|
+
`app/matestack/components/blue_card.rb`
|
168
|
+
|
90
169
|
```ruby
|
91
|
-
|
170
|
+
|
171
|
+
class Components::BlueCard < Components::Card
|
92
172
|
|
93
173
|
def response
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
174
|
+
div class: "card shadow-sm border-0 bg-primary text-white" do
|
175
|
+
img path: image, class: "w-100" if image.present?
|
176
|
+
card_content #defined in parent class
|
177
|
+
card_footer if footer.present? #defined in parent class
|
178
|
+
end
|
99
179
|
end
|
100
180
|
|
101
181
|
end
|
182
|
+
|
102
183
|
```
|
184
|
+
|
185
|
+
`app/matestack/components/registry.rb`
|
186
|
+
|
103
187
|
```ruby
|
104
|
-
|
188
|
+
module Components::Registry
|
189
|
+
|
190
|
+
Matestack::Ui::Core::Component::Registry.register_components(
|
191
|
+
blue_card: Components::BlueCard,
|
192
|
+
#...
|
193
|
+
)
|
194
|
+
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
198
|
+
`app/views/your_view.html.erb`
|
199
|
+
|
200
|
+
```erb
|
201
|
+
<!-- some other erb markup -->
|
202
|
+
<%= matestack_component :blue_card, title: "hello", body: "world" %>
|
203
|
+
<!-- some other erb markup -->
|
204
|
+
```
|
205
|
+
|
206
|
+
#### Use components within components
|
207
|
+
|
208
|
+
Just like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components.
|
209
|
+
You decide when using a Ruby method partial should be replaced by another self contained UI component!
|
210
|
+
|
211
|
+
`app/matestack/components/card.rb`
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
|
215
|
+
class Components::Card < Matestack::Ui::Component
|
216
|
+
|
217
|
+
requires :body
|
218
|
+
optional :title
|
219
|
+
optional :image
|
105
220
|
|
106
221
|
def response
|
107
|
-
|
108
|
-
|
109
|
-
|
222
|
+
div class: "card shadow-sm border-0 bg-light" do
|
223
|
+
img path: image, class: "w-100" if image.present?
|
224
|
+
# calling the CardBody component rather than using Ruby method partials
|
225
|
+
card_body title: title, body: body
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
```
|
232
|
+
`app/matestack/components/card_body.rb`
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
|
236
|
+
class Components::CardBody < Matestack::Ui::Component
|
237
|
+
|
238
|
+
requires :body
|
239
|
+
optional :title
|
240
|
+
|
241
|
+
def response
|
242
|
+
# Just an example. Would make more sense, if this component had
|
243
|
+
# a more complex structure
|
244
|
+
div class: "card-body" do
|
245
|
+
heading size: 5, text: title if title.present?
|
246
|
+
paragraph class: "card-text", text: body
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
```
|
253
|
+
|
254
|
+
|
255
|
+
`app/matestack/components/registry.rb`
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
module Components::Registry
|
259
|
+
|
260
|
+
Matestack::Ui::Core::Component::Registry.register_components(
|
261
|
+
card: Components::Card,
|
262
|
+
card_body: Components::CardBody,
|
263
|
+
#...
|
264
|
+
)
|
265
|
+
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
#### Yield components into components
|
270
|
+
|
271
|
+
Sometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components!
|
272
|
+
Using this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.
|
273
|
+
|
274
|
+
|
275
|
+
`app/matestack/components/card.rb`
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
|
279
|
+
class Components::Card < Matestack::Ui::Component
|
280
|
+
|
281
|
+
requires :body
|
282
|
+
optional :title
|
283
|
+
optional :image
|
284
|
+
|
285
|
+
def response
|
286
|
+
div class: "card shadow-sm border-0 bg-light" do
|
287
|
+
img path: image, class: "w-100" if image.present?
|
288
|
+
card_body do
|
289
|
+
# yielding a block into the card_body component
|
290
|
+
heading size: 5, text: title if title.present?
|
291
|
+
paragraph class: "card-text", text: body
|
110
292
|
end
|
111
|
-
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
```
|
299
|
+
|
300
|
+
`app/matestack/components/card_body.rb`
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
|
304
|
+
class Components::CardBody < Matestack::Ui::Component
|
305
|
+
|
306
|
+
def response
|
307
|
+
# Just an example. Would make more sense, if this component had
|
308
|
+
# a more complex structure
|
309
|
+
div class: "card-body" do
|
310
|
+
yield_components
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
```
|
317
|
+
|
318
|
+
#### Use named slots for advanced content injection
|
319
|
+
|
320
|
+
If you need to inject multiple blocks into your UI component, you can use \"slots\"!
|
321
|
+
Slots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!
|
322
|
+
|
323
|
+
`app/matestack/components/card.rb`
|
324
|
+
|
325
|
+
```ruby
|
326
|
+
|
327
|
+
class Components::Card < Matestack::Ui::Component
|
328
|
+
|
329
|
+
requires :body
|
330
|
+
optional :title
|
331
|
+
optional :image
|
332
|
+
|
333
|
+
def response
|
334
|
+
div class: "card shadow-sm border-0 bg-light" do
|
335
|
+
img path: image, class: "w-100" if image.present?
|
336
|
+
card_body slots: { heading: heading_slot, body: body_slot }
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def heading_slot
|
341
|
+
slot do
|
342
|
+
heading size: 5, text: title if title.present?
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def body_slot
|
347
|
+
slot do
|
348
|
+
paragraph class: "card-text", text: body
|
349
|
+
end
|
112
350
|
end
|
113
351
|
|
114
352
|
end
|
353
|
+
|
115
354
|
```
|
116
|
-
|
355
|
+
`app/matestack/components/card_body.rb`
|
356
|
+
|
117
357
|
```ruby
|
118
|
-
|
358
|
+
|
359
|
+
class Components::CardBody < Matestack::Ui::Component
|
360
|
+
|
361
|
+
requires :slots
|
119
362
|
|
120
363
|
def response
|
121
|
-
|
122
|
-
|
123
|
-
|
364
|
+
# Just an example. Would make more sense, if this component had
|
365
|
+
# a more complex structure
|
366
|
+
div class: "card-body" do
|
367
|
+
div class: "heading-section" do
|
368
|
+
slot slots[:heading]
|
124
369
|
end
|
125
|
-
|
126
|
-
|
127
|
-
div id: "my-div" do
|
128
|
-
plain DateTime.now
|
129
|
-
end
|
370
|
+
div class: "body-section" do
|
371
|
+
slot slots[:body]
|
130
372
|
end
|
131
|
-
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
```
|
379
|
+
|
380
|
+
|
381
|
+
### 2. Use reactive UI components in pure Ruby
|
382
|
+
|
383
|
+
What about going even one step further and implement REACTIVE UIs in pure Ruby? Matestack's reactive core components can be used with a simple Ruby DSL enabling you to create reactive UIs without touching JavaScript!
|
384
|
+
|
385
|
+
#### Toggle parts of the UI based on events
|
386
|
+
|
387
|
+
Matestack offers an event hub. Reactive components can emit and receive events through this event hub. \"onclick\" and \"toggle\" calling two of these reactive core components.
|
388
|
+
\"onclick\" emits an event which causes the body of the \"toggle\" component to be visible for 5 seconds in this example.
|
389
|
+
|
390
|
+
`app/matestack/components/some_component.rb`
|
391
|
+
|
392
|
+
```ruby
|
393
|
+
|
394
|
+
class Components::SomeComponent < Matestack::Ui::Component
|
395
|
+
|
396
|
+
def response
|
397
|
+
onclick emit: "some_event" do
|
398
|
+
button text: "click me"
|
399
|
+
end
|
400
|
+
toggle show_on: "some_event", hide_after: 5000 do
|
401
|
+
plain "Oh yes! You clicked me!"
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
406
|
+
|
407
|
+
```
|
408
|
+
|
409
|
+
#### Call controller actions without JavaScript
|
410
|
+
|
411
|
+
Core components offer basic dynamic behaviour and let you easily call controller actions and react to server responses on the client side without full page reload.
|
412
|
+
The \"action\" component is configured to emit an event after successfully performed an HTTP request against a Rails controller action, which is receive by the \"toggle\" component, displaying the success message.
|
413
|
+
|
414
|
+
`app/matestack/components/some_component.rb`
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
|
418
|
+
class Components::SomeComponent < Matestack::Ui::Component
|
419
|
+
|
420
|
+
def response
|
421
|
+
action my_action_config do
|
422
|
+
button text: "click me"
|
423
|
+
end
|
424
|
+
toggle show_on: "some_event", hide_after: 5000 do
|
425
|
+
plain "Success!"
|
426
|
+
end
|
132
427
|
end
|
133
428
|
|
134
429
|
def my_action_config
|
135
430
|
{
|
431
|
+
path: some_rails_route_path,
|
136
432
|
method: :post,
|
137
|
-
path: :some_rails_routing_path,
|
138
433
|
success: {
|
139
|
-
emit: "
|
434
|
+
emit: "some_event"
|
140
435
|
}
|
141
436
|
}
|
142
437
|
end
|
143
438
|
|
144
439
|
end
|
440
|
+
|
145
441
|
```
|
146
|
-
|
442
|
+
|
443
|
+
|
444
|
+
### Dynamically handle form input without JavaScript
|
445
|
+
|
446
|
+
Create dynamic forms for ActiveRecord Models (or plain objects) and display server side responses, like validation errors or success messages, without relying on a full page reload.
|
447
|
+
Events emitted by the \"form\" component can be used to toggle parts of the UI.
|
448
|
+
|
449
|
+
`app/matestack/components/some_component.rb`
|
450
|
+
|
147
451
|
```ruby
|
148
|
-
|
452
|
+
|
453
|
+
class Components::SomeComponent < Matestack::Ui::Component
|
149
454
|
|
150
455
|
def prepare
|
151
|
-
@
|
456
|
+
@new_active_record_instance = MyActiveRecordModel.new
|
152
457
|
end
|
153
458
|
|
154
459
|
def response
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
button text: "Submit me!"
|
160
|
-
end
|
460
|
+
form my_form_config do
|
461
|
+
form_input key: :some_attribute, type: :text
|
462
|
+
form_submit do
|
463
|
+
button text: "click me"
|
161
464
|
end
|
162
|
-
|
163
|
-
|
465
|
+
end
|
466
|
+
toggle show_on: "submitted", hide_after: 5000 do
|
467
|
+
span class: "message success" do
|
468
|
+
plain "created successfully"
|
164
469
|
end
|
165
|
-
|
470
|
+
end
|
471
|
+
toggle show_on: "failed", hide_after: 5000 do
|
472
|
+
span class: "message failure" do
|
473
|
+
plain "data was not saved, please check form"
|
474
|
+
end
|
475
|
+
end
|
166
476
|
end
|
167
477
|
|
168
478
|
def my_form_config
|
169
479
|
{
|
170
|
-
for: @
|
480
|
+
for: @new_active_record_instance,
|
481
|
+
path: some_rails_route_path,
|
171
482
|
method: :post,
|
172
|
-
path: :some_action_path,
|
173
483
|
success: {
|
174
|
-
|
175
|
-
path: :my_second_page_path,
|
176
|
-
}
|
484
|
+
emit: "submitted"
|
177
485
|
},
|
178
486
|
failure: {
|
179
|
-
emit: "
|
487
|
+
emit: "failed"
|
180
488
|
}
|
181
489
|
}
|
182
490
|
end
|
183
491
|
|
184
492
|
end
|
493
|
+
|
185
494
|
```
|
186
|
-
|
495
|
+
|
496
|
+
#### Implement asynchronous, event-based UI rerendering in pure Ruby
|
497
|
+
|
498
|
+
Using matestack's built-in event system, you can rerender parts of the UI on client side events, such as form or action submissions. Even server side events pushed via ActionCable may be received!
|
499
|
+
The \"async\" component requests a new version of its body at the server via an HTTP GET request after receiving the configured event. After successfu server response, the DOM of the \"async\" component gets updated. Everything else stays untouched.
|
500
|
+
|
501
|
+
`app/matestack/components/some_component.rb`
|
502
|
+
|
187
503
|
```ruby
|
188
|
-
class Pages::MyPage < Matestack::Ui::Page
|
189
504
|
|
190
|
-
|
191
|
-
@comments = Comment.last(5)
|
192
|
-
end
|
505
|
+
class Components::SomeComponent < Matestack::Ui::Component
|
193
506
|
|
194
507
|
def response
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
508
|
+
form my_form_config do
|
509
|
+
#...
|
510
|
+
end
|
511
|
+
#...
|
512
|
+
async rerender_on: "submitted", id: "my-model-list" do
|
513
|
+
ul do
|
514
|
+
MyActiveRecordModel.last(5).each do |model|
|
515
|
+
li text: model.some_attribute
|
203
516
|
end
|
204
517
|
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
def my_form_config
|
522
|
+
{
|
523
|
+
#...
|
524
|
+
success: {
|
525
|
+
emit: "submitted"
|
526
|
+
},
|
527
|
+
failure: {
|
528
|
+
emit: "failed"
|
529
|
+
}
|
205
530
|
}
|
206
531
|
end
|
207
532
|
|
208
533
|
end
|
534
|
+
|
209
535
|
```
|
210
|
-
|
536
|
+
|
537
|
+
#### Manipulate parts of the UI via ActionCable
|
538
|
+
|
539
|
+
\"async\" rerenders its whole body - but what about just appending the element to the list after successful form submission?
|
540
|
+
The \"cable\" component can be configured to receive events and data pushed via ActionCable from the server side and just append/prepend new chunks of HTM (ideally rendered through a component) to the current \"cable\" component body. Updating and deleting is also supported!
|
541
|
+
|
542
|
+
`app/matestack/components/some_component.rb`
|
211
543
|
|
212
544
|
```ruby
|
545
|
+
|
546
|
+
class Components::SomeComponent < Matestack::Ui::Component
|
547
|
+
|
548
|
+
def response
|
549
|
+
form my_form_config do
|
550
|
+
#...
|
551
|
+
end
|
552
|
+
#...
|
553
|
+
ul do
|
554
|
+
cable prepend_on: "new_element_created", id: "mocked-instance-list" do
|
555
|
+
MyActiveRecordModel.last(5).each do |model|
|
556
|
+
li text: model
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
end
|
563
|
+
|
564
|
+
```
|
565
|
+
|
566
|
+
`app/controllers/some_controller.rb`
|
567
|
+
|
568
|
+
```ruby
|
569
|
+
# within your controller action handling the form input
|
213
570
|
ActionCable.server.broadcast("matestack_ui_core", {
|
214
|
-
|
571
|
+
event: "new_element_created",
|
572
|
+
data: matestack_component(:li, text: params[:some_attribute])
|
215
573
|
})
|
574
|
+
|
216
575
|
```
|
217
576
|
|
218
|
-
|
577
|
+
#### Easily extend with Vue.js
|
219
578
|
|
220
|
-
|
579
|
+
Matestack's dynamic parts are built on Vue.js. If you want to implement custom dynamic behaviour, you can simply create your own Vue components and use them along matestacks core components.
|
580
|
+
It's even possible to interact with matestack's core components using the built-in event bus.
|
221
581
|
|
222
|
-
|
582
|
+
`app/matestack/components/some_component.rb`
|
223
583
|
|
224
|
-
|
584
|
+
```ruby
|
585
|
+
|
586
|
+
class Components::SomeComponent < Matestack::Ui::Component
|
225
587
|
|
226
|
-
|
588
|
+
def response
|
589
|
+
my_vue_js_component
|
590
|
+
toggle show_on: "some_event", hide_after: "3000" do
|
591
|
+
span class: "message success" do
|
592
|
+
plain "event triggered from custom vuejs component"
|
593
|
+
end
|
594
|
+
end
|
595
|
+
end
|
227
596
|
|
228
|
-
|
597
|
+
end
|
229
598
|
|
230
|
-
|
599
|
+
```
|
600
|
+
`app/matestack/components/my_vue_js_component.rb`
|
231
601
|
|
232
|
-
|
602
|
+
```ruby
|
603
|
+
class Components::MyVueJsComponent < Matestack::Ui::VueJsComponent
|
233
604
|
|
234
|
-
|
605
|
+
vue_js_component_name "my-vue-js-component"
|
235
606
|
|
236
|
-
|
607
|
+
def response
|
608
|
+
div class: "my-vue-js-component" do
|
609
|
+
button attributes: {"@click": "increaseValue"}
|
610
|
+
br
|
611
|
+
plain "{{ dynamicValue }}!"
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
end
|
616
|
+
```
|
617
|
+
|
618
|
+
`app/matestack/components/my_vue_js_component.js`
|
619
|
+
|
620
|
+
```javascript
|
621
|
+
MatestackUiCore.Vue.component('my-vue-js-component', {
|
622
|
+
mixins: [MatestackUiCore.componentMixin],
|
623
|
+
data: () => {
|
624
|
+
return {
|
625
|
+
dynamicValue: 0
|
626
|
+
};
|
627
|
+
},
|
628
|
+
methods: {
|
629
|
+
increaseValue(){
|
630
|
+
this.dynamicValue++
|
631
|
+
MatestackUiCore.matestackEventHub.$emit("some_event")
|
632
|
+
}
|
633
|
+
}
|
634
|
+
});
|
635
|
+
```
|
636
|
+
|
637
|
+
### 3. Create whole SPA-like apps in pure Ruby
|
638
|
+
|
639
|
+
The last step in order to leverage the full Matestack power: Create app (~Rails layout) and page (Rails ~view) classes and implement dynamic page transitions without any JavaScript implementation required.
|
640
|
+
|
641
|
+
#### Create your layouts and views in pure Ruby
|
642
|
+
|
643
|
+
The app class is used to define a layout, usually containing some kind of header, footer and navigation. The page class is used to define a view. Following the same principles as seen on components, you can use components (core or your own) in order to create the UI.
|
644
|
+
The \"transition\" component enables dynamic page transition, replacing the content within \"yield_page\" with new serverside rendered content.
|
645
|
+
|
646
|
+
`app/matestack/some_app/app.rb`
|
647
|
+
|
648
|
+
```ruby
|
649
|
+
|
650
|
+
class SomeApp::App < Matestack::Ui::App
|
651
|
+
|
652
|
+
def response
|
653
|
+
nav do
|
654
|
+
transition path: page1_path do
|
655
|
+
button text: "Page 1"
|
656
|
+
end
|
657
|
+
transition path: page2_path do
|
658
|
+
button text: "Page 2"
|
659
|
+
end
|
660
|
+
end
|
661
|
+
main do
|
662
|
+
div class: "container" do
|
663
|
+
yield_page
|
664
|
+
end
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
end
|
669
|
+
|
670
|
+
```
|
671
|
+
|
672
|
+
`app/matestack/some_app/pages/page1.rb`
|
673
|
+
|
674
|
+
```ruby
|
675
|
+
class SomeApp::Pages::Page1 < Matestack::Ui::Page
|
676
|
+
|
677
|
+
def response
|
678
|
+
div class: "row" do
|
679
|
+
div class: "col" do
|
680
|
+
plain "Page 1"
|
681
|
+
end
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
685
|
+
end
|
686
|
+
|
687
|
+
```
|
688
|
+
|
689
|
+
`app/matestack/some_app/pages/page2.rb`
|
690
|
+
|
691
|
+
```ruby
|
692
|
+
class SomeApp::Pages::Page2 < Matestack::Ui::Page
|
693
|
+
|
694
|
+
def response
|
695
|
+
div class: "row" do
|
696
|
+
div class: "col" do
|
697
|
+
plain "Page 2"
|
698
|
+
end
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
end
|
703
|
+
|
704
|
+
```
|
705
|
+
|
706
|
+
#### Apps and pages are referenced in your Rails controllers and actions
|
707
|
+
|
708
|
+
Instead of referencing Rails layouts and views on your controllers, you just use apps and pages as substitutes.
|
709
|
+
Work with controllers, actions and routing as you're used to! Controller hooks (e.g. devise's authenticate_user) would still work!
|
710
|
+
|
711
|
+
`app/controllers/some_controller.rb`
|
712
|
+
|
713
|
+
```ruby
|
714
|
+
|
715
|
+
class SomeController < ApplicationController
|
716
|
+
|
717
|
+
include Matestack::Ui::Core::ApplicationHelper
|
718
|
+
include Components::Registry
|
719
|
+
|
720
|
+
matestack_app SomeApp::App
|
721
|
+
|
722
|
+
def page1
|
723
|
+
render SomeApp::Page1
|
724
|
+
end
|
725
|
+
|
726
|
+
def page2
|
727
|
+
render SomeApp::Page2
|
728
|
+
end
|
729
|
+
|
730
|
+
end
|
731
|
+
|
732
|
+
```
|
733
|
+
|
734
|
+
`app/config/routes.rb`
|
735
|
+
|
736
|
+
```ruby
|
737
|
+
Rails.application.routes.draw do
|
738
|
+
|
739
|
+
root to: 'some#page1'
|
740
|
+
|
741
|
+
get :page1, to: 'some#page1'
|
742
|
+
get :page2, to: 'some#page2'
|
743
|
+
|
744
|
+
end
|
745
|
+
|
746
|
+
```
|
747
|
+
|
748
|
+
#### Use CSS animations for fancy page transition animations
|
749
|
+
|
750
|
+
Use matestack's css classes applied to the wrapping DOM structure of a page in order to add CSS animiations, whenever a page transition is performed."
|
751
|
+
You can even inject a loading state element, enriching your page transition effect.
|
752
|
+
|
753
|
+
`app/matestack/some_app/app.rb`
|
754
|
+
|
755
|
+
```ruby
|
756
|
+
|
757
|
+
class SomeApp::App < Matestack::Ui::App
|
758
|
+
|
759
|
+
def response
|
760
|
+
nav do
|
761
|
+
transition path: page1_path do
|
762
|
+
button text: "Page 1"
|
763
|
+
end
|
764
|
+
transition path: page2_path do
|
765
|
+
button text: "Page 2"
|
766
|
+
end
|
767
|
+
end
|
768
|
+
main do
|
769
|
+
div class: "container" do
|
770
|
+
yield_page slots: { loading_state: loading_state_element }
|
771
|
+
end
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
def loading_state_element
|
776
|
+
slot do
|
777
|
+
div class: 'some-loading-element-styles'
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
end
|
782
|
+
|
783
|
+
```
|
784
|
+
|
785
|
+
`app/assets/stylesheets/application.scss`
|
786
|
+
|
787
|
+
```scss
|
788
|
+
|
789
|
+
.matestack-page-container{
|
790
|
+
|
791
|
+
.matestack-page-wrapper {
|
792
|
+
opacity: 1;
|
793
|
+
transition: opacity 0.2s ease-in-out;
|
794
|
+
|
795
|
+
&.loading {
|
796
|
+
opacity: 0;
|
797
|
+
}
|
798
|
+
}
|
799
|
+
|
800
|
+
.loading-state-element-wrapper{
|
801
|
+
opacity: 0;
|
802
|
+
transition: opacity 0.3s ease-in-out;
|
803
|
+
|
804
|
+
&.loading {
|
805
|
+
opacity: 1;
|
806
|
+
}
|
807
|
+
}
|
808
|
+
|
809
|
+
}
|
810
|
+
|
811
|
+
```
|
237
812
|
|
238
|
-
|
239
|
-
|
240
|
-
[MIT License](https://opensource.org/licenses/MIT).
|
813
|
+
## License
|
814
|
+
matestack-ui-core is an Open Source project licensed under the terms of the [LGPLv3 license](./LICENSE)
|