voom-presenters 0.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (447) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/ISSUE_TEMPLATE/questions-support.md +10 -0
  6. data/.github/workflows/semantic-release.yml +42 -0
  7. data/.gitignore +3 -2
  8. data/.releaserc +15 -0
  9. data/.ruby-version +2 -1
  10. data/CHANGELOG.md +71 -108
  11. data/CONTRIBUTING.md +60 -0
  12. data/Gemfile +14 -4
  13. data/Gemfile.lock +93 -46
  14. data/Procfile +1 -0
  15. data/README.md +48 -39
  16. data/app/demo/components/avatars.pom +40 -0
  17. data/app/demo/components/cards.pom +11 -4
  18. data/app/demo/components/chips.pom +61 -54
  19. data/app/demo/components/content.pom +96 -16
  20. data/app/demo/components/dialogs.pom +175 -6
  21. data/app/demo/components/file_inputs.pom +38 -2
  22. data/app/demo/components/google_maps.pom +6 -1
  23. data/app/demo/components/headers.pom +80 -20
  24. data/app/demo/components/icons.pom +86 -55
  25. data/app/demo/components/image_lists.pom +100 -0
  26. data/app/demo/components/images.pom +45 -0
  27. data/app/demo/components/layouts.pom +3 -25
  28. data/app/demo/components/lists.pom +24 -4
  29. data/app/demo/components/menus.pom +14 -4
  30. data/app/demo/components/multi_selects.pom +29 -0
  31. data/app/demo/components/nav/menu.pom +39 -7
  32. data/app/demo/components/nav/pattern_menu.pom +2 -2
  33. data/app/demo/components/number_fields.pom +53 -0
  34. data/app/demo/components/padding.pom +96 -0
  35. data/app/demo/components/progress.pom +71 -0
  36. data/app/demo/components/selects.pom +45 -5
  37. data/app/demo/components/sliders.pom +5 -0
  38. data/app/demo/components/tab_bars.pom +15 -0
  39. data/app/demo/components/tables.pom +51 -40
  40. data/app/demo/components/text_areas.pom +23 -16
  41. data/app/demo/components/text_fields.pom +61 -15
  42. data/app/demo/components/toggles.pom +35 -4
  43. data/app/demo/components/tooltips.pom +8 -4
  44. data/app/demo/components/unordered_list.pom +81 -0
  45. data/app/demo/custom_css.pom +37 -0
  46. data/app/demo/events/actions/autocomplete.pom +32 -0
  47. data/app/demo/events/actions/clear.pom +5 -3
  48. data/app/demo/events/actions/dialogs/discard.pom +9 -0
  49. data/app/demo/events/actions/dialogs/show_dialog.pom +4 -2
  50. data/app/demo/events/actions/last_response.pom +40 -0
  51. data/app/demo/events/actions/prompt_if_dirty.pom +54 -0
  52. data/app/demo/events/content_as_form.pom +313 -0
  53. data/app/demo/events/nav/drawer.pom +7 -3
  54. data/app/demo/events/parallel.pom +44 -0
  55. data/app/demo/index.pom +5 -5
  56. data/app/demo/nav/top_nav.pom +10 -4
  57. data/app/demo/patterns/drag_drop.pom +89 -0
  58. data/app/demo/patterns/floating_card.pom +29 -0
  59. data/app/demo/patterns/search_select.pom +9 -7
  60. data/app/demo/plugins/chart.pom +254 -0
  61. data/app/demo/plugins/image_crop.pom +44 -0
  62. data/app/demo/plugins/index.pom +29 -0
  63. data/app/demo/plugins/nav/drawer.pom +19 -0
  64. data/app/demo/shared/context_list.pom +1 -1
  65. data/app/demo/styles.pom +3 -1
  66. data/bin/console +4 -4
  67. data/component-status.yml +15 -15
  68. data/config.ru +20 -10
  69. data/docs/settings.md +81 -0
  70. data/exe/presenters +3 -0
  71. data/lib/hash_ext/traverse.rb +14 -0
  72. data/lib/voom.rb +25 -0
  73. data/lib/voom/container_methods.rb +2 -2
  74. data/lib/voom/engine.rb +5 -0
  75. data/lib/voom/presenters/api/app.rb +31 -11
  76. data/lib/voom/presenters/api/router.rb +3 -49
  77. data/lib/voom/presenters/app.rb +3 -3
  78. data/lib/voom/presenters/cli.rb +28 -0
  79. data/lib/voom/presenters/demo/dragon_drop.rb +48 -0
  80. data/lib/voom/presenters/demo/echo.rb +2 -0
  81. data/lib/voom/presenters/demo/slow.rb +18 -0
  82. data/lib/voom/presenters/dsl/components/actions/autocomplete.rb +15 -0
  83. data/lib/voom/presenters/dsl/components/actions/base.rb +36 -8
  84. data/lib/voom/presenters/dsl/components/actions/clear.rb +0 -2
  85. data/lib/voom/presenters/dsl/components/actions/close_dialog.rb +17 -0
  86. data/lib/voom/presenters/dsl/components/actions/deletes.rb +0 -2
  87. data/lib/voom/presenters/dsl/components/actions/dialog.rb +0 -2
  88. data/lib/voom/presenters/dsl/components/actions/loads.rb +5 -6
  89. data/lib/voom/presenters/dsl/components/actions/navigates.rb +0 -2
  90. data/lib/voom/presenters/dsl/components/actions/post_message.rb +17 -0
  91. data/lib/voom/presenters/dsl/components/actions/posts.rb +5 -2
  92. data/lib/voom/presenters/dsl/components/actions/prompt_if_dirty.rb +15 -0
  93. data/lib/voom/presenters/dsl/components/actions/remove.rb +0 -2
  94. data/lib/voom/presenters/dsl/components/actions/replaces.rb +4 -4
  95. data/lib/voom/presenters/dsl/components/actions/snackbar.rb +0 -2
  96. data/lib/voom/presenters/dsl/components/actions/stepper.rb +0 -2
  97. data/lib/voom/presenters/dsl/components/actions/toggle_disabled.rb +15 -0
  98. data/lib/voom/presenters/dsl/components/actions/toggle_visibility.rb +0 -2
  99. data/lib/voom/presenters/dsl/components/actions/updates.rb +5 -2
  100. data/lib/voom/presenters/dsl/components/avatar.rb +4 -8
  101. data/lib/voom/presenters/dsl/components/badge.rb +0 -2
  102. data/lib/voom/presenters/dsl/components/base.rb +25 -18
  103. data/lib/voom/presenters/dsl/components/button.rb +15 -11
  104. data/lib/voom/presenters/dsl/components/card.rb +49 -36
  105. data/lib/voom/presenters/dsl/components/checkbox.rb +0 -2
  106. data/lib/voom/presenters/dsl/components/chip.rb +5 -7
  107. data/lib/voom/presenters/dsl/components/chipset.rb +33 -0
  108. data/lib/voom/presenters/dsl/components/content.rb +28 -18
  109. data/lib/voom/presenters/dsl/components/datetime_base.rb +0 -2
  110. data/lib/voom/presenters/dsl/components/datetime_field.rb +0 -2
  111. data/lib/voom/presenters/dsl/components/dialog.rb +36 -12
  112. data/lib/voom/presenters/dsl/components/drawer.rb +9 -6
  113. data/lib/voom/presenters/dsl/components/event.rb +106 -65
  114. data/lib/voom/presenters/dsl/components/event_base.rb +1 -3
  115. data/lib/voom/presenters/dsl/components/expansion_panel.rb +0 -3
  116. data/lib/voom/presenters/dsl/components/file_input.rb +18 -6
  117. data/lib/voom/presenters/dsl/components/footer.rb +2 -2
  118. data/lib/voom/presenters/dsl/components/form.rb +2 -17
  119. data/lib/voom/presenters/dsl/components/grid.rb +52 -50
  120. data/lib/voom/presenters/dsl/components/header.rb +17 -1
  121. data/lib/voom/presenters/dsl/components/hidden_field.rb +0 -2
  122. data/lib/voom/presenters/dsl/components/icon.rb +2 -4
  123. data/lib/voom/presenters/dsl/components/icon_base.rb +5 -7
  124. data/lib/voom/presenters/dsl/components/icon_toggle.rb +2 -4
  125. data/lib/voom/presenters/dsl/components/image.rb +61 -13
  126. data/lib/voom/presenters/dsl/components/image_list.rb +43 -0
  127. data/lib/voom/presenters/dsl/components/input.rb +14 -5
  128. data/lib/voom/presenters/dsl/components/link.rb +33 -0
  129. data/lib/voom/presenters/dsl/components/list.rb +6 -13
  130. data/lib/voom/presenters/dsl/components/lists/action.rb +9 -11
  131. data/lib/voom/presenters/dsl/components/lists/actions.rb +0 -3
  132. data/lib/voom/presenters/dsl/components/lists/line.rb +27 -15
  133. data/lib/voom/presenters/dsl/components/menu.rb +51 -9
  134. data/lib/voom/presenters/dsl/components/mixins/append.rb +2 -2
  135. data/lib/voom/presenters/dsl/components/mixins/attaches.rb +0 -2
  136. data/lib/voom/presenters/dsl/components/mixins/avatar.rb +1 -3
  137. data/lib/voom/presenters/dsl/components/mixins/chips.rb +0 -2
  138. data/lib/voom/presenters/dsl/components/mixins/chipset.rb +19 -0
  139. data/lib/voom/presenters/dsl/components/mixins/common.rb +13 -14
  140. data/lib/voom/presenters/dsl/components/mixins/dialogs.rb +0 -2
  141. data/lib/voom/presenters/dsl/components/mixins/event.rb +0 -2
  142. data/lib/voom/presenters/dsl/components/mixins/image_lists.rb +15 -0
  143. data/lib/voom/presenters/dsl/components/mixins/last_response.rb +48 -0
  144. data/lib/voom/presenters/dsl/components/mixins/padding.rb +42 -0
  145. data/lib/voom/presenters/dsl/components/mixins/progress.rb +16 -0
  146. data/lib/voom/presenters/dsl/components/mixins/selects.rb +6 -0
  147. data/lib/voom/presenters/dsl/components/mixins/tab_bars.rb +2 -0
  148. data/lib/voom/presenters/dsl/components/mixins/tables.rb +15 -0
  149. data/lib/voom/presenters/dsl/components/mixins/text_fields.rb +5 -0
  150. data/lib/voom/presenters/dsl/components/mixins/toggles.rb +0 -2
  151. data/lib/voom/presenters/dsl/components/mixins/typography.rb +55 -8
  152. data/lib/voom/presenters/dsl/components/mixins/yield_to.rb +2 -2
  153. data/lib/voom/presenters/dsl/components/multi_select.rb +56 -0
  154. data/lib/voom/presenters/dsl/components/number_field.rb +20 -0
  155. data/lib/voom/presenters/dsl/components/page_title.rb +31 -0
  156. data/lib/voom/presenters/dsl/components/progress.rb +27 -0
  157. data/lib/voom/presenters/dsl/components/radio_button.rb +0 -1
  158. data/lib/voom/presenters/dsl/components/rich_text_area.rb +5 -11
  159. data/lib/voom/presenters/dsl/components/select.rb +18 -9
  160. data/lib/voom/presenters/dsl/components/separator.rb +21 -0
  161. data/lib/voom/presenters/dsl/components/slider.rb +6 -7
  162. data/lib/voom/presenters/dsl/components/stepper.rb +0 -10
  163. data/lib/voom/presenters/dsl/components/switch.rb +0 -2
  164. data/lib/voom/presenters/dsl/components/tab_bar.rb +0 -3
  165. data/lib/voom/presenters/dsl/components/table.rb +39 -20
  166. data/lib/voom/presenters/dsl/components/text_area.rb +1 -3
  167. data/lib/voom/presenters/dsl/components/text_field.rb +54 -11
  168. data/lib/voom/presenters/dsl/components/time_field.rb +0 -2
  169. data/lib/voom/presenters/dsl/components/toggle_base.rb +8 -6
  170. data/lib/voom/presenters/dsl/components/typography.rb +4 -4
  171. data/lib/voom/presenters/dsl/components/unordered_list.rb +50 -0
  172. data/lib/voom/presenters/dsl/definer.rb +0 -4
  173. data/lib/voom/presenters/dsl/definition.rb +6 -5
  174. data/lib/voom/presenters/dsl/protect_from_forgery.rb +43 -0
  175. data/lib/voom/presenters/dsl/user_interface.rb +37 -22
  176. data/lib/voom/presenters/errors.rb +1 -0
  177. data/lib/voom/presenters/errors/invalid_dsl.rb +8 -0
  178. data/lib/voom/presenters/errors/parameter_validation.rb +1 -3
  179. data/lib/voom/presenters/generators/inflectors.rb +59 -0
  180. data/lib/voom/presenters/generators/plugin.rb +115 -0
  181. data/lib/voom/presenters/generators/templates/plugin/.gitignore +12 -0
  182. data/lib/voom/presenters/generators/templates/plugin/Gemfile +6 -0
  183. data/lib/voom/presenters/generators/templates/plugin/LICENSE.txt.tt +21 -0
  184. data/lib/voom/presenters/generators/templates/plugin/README.md +253 -0
  185. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/actions/action.rb.tt +16 -0
  186. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/actions/dsl.rb.tt +22 -0
  187. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/component.rb.tt +18 -0
  188. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/dsl.rb.tt +19 -0
  189. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/helpers/helper.rb.tt +15 -0
  190. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/plugin.rb.tt +9 -0
  191. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/web_client/components/actions/data.rb.tt +17 -0
  192. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/web_client/components/render.rb.tt +23 -0
  193. data/lib/voom/presenters/generators/templates/plugin/presenter_plugin.gemspec.tt +21 -0
  194. data/lib/voom/presenters/generators/templates/plugin/views/assets/css/components/component.css.tt +21 -0
  195. data/lib/voom/presenters/generators/templates/plugin/views/assets/js/components/actions/action.js.tt +15 -0
  196. data/lib/voom/presenters/generators/templates/plugin/views/assets/js/components/component.js.tt +39 -0
  197. data/lib/voom/presenters/generators/templates/plugin/views/components/component.erb.tt +14 -0
  198. data/lib/voom/presenters/generators/templates/plugin/views/components/component_header.erb.tt +20 -0
  199. data/lib/voom/presenters/helpers.rb +2 -8
  200. data/lib/voom/presenters/helpers/inflector.rb +1 -1
  201. data/lib/voom/presenters/helpers/rails.rb +15 -8
  202. data/lib/voom/presenters/helpers/redact.rb +13 -0
  203. data/lib/voom/presenters/helpers/route.rb +12 -5
  204. data/lib/voom/presenters/pluggable.rb +37 -0
  205. data/lib/voom/presenters/plugins.rb +7 -0
  206. data/lib/voom/presenters/plugins/google_maps.rb +24 -0
  207. data/lib/voom/presenters/plugins/google_maps/google_map.erb +10 -0
  208. data/lib/voom/presenters/{dsl/components → plugins/google_maps}/google_map.rb +4 -3
  209. data/lib/voom/presenters/{dsl.rb → registry.rb} +13 -15
  210. data/lib/voom/presenters/router.rb +59 -0
  211. data/lib/voom/presenters/settings.rb +18 -8
  212. data/lib/voom/presenters/version.rb +3 -1
  213. data/lib/voom/presenters/web_client/app.rb +86 -29
  214. data/lib/voom/presenters/web_client/component_decorator_factory.rb +27 -0
  215. data/lib/voom/presenters/web_client/component_html_decorator.rb +50 -0
  216. data/lib/voom/presenters/web_client/component_renderer.rb +49 -0
  217. data/lib/voom/presenters/web_client/custom_css.rb +65 -0
  218. data/lib/voom/presenters/web_client/{markdown_render.rb → custom_render.rb} +5 -3
  219. data/lib/voom/presenters/web_client/helpers/expand_hash.rb +19 -0
  220. data/lib/voom/presenters/web_client/helpers/form_helpers.rb +14 -0
  221. data/lib/voom/presenters/web_client/helpers/padding_helpers.rb +21 -0
  222. data/lib/voom/presenters/web_client/plugin_headers.rb +37 -0
  223. data/lib/voom/presenters/web_client/router.rb +3 -54
  224. data/lib/voom/railtie.rb +37 -0
  225. data/lib/voom/symbol/to_str.rb +3 -3
  226. data/lib/voom/trace.rb +0 -2
  227. data/presenters.gemspec +10 -6
  228. data/public/bundle.css +18256 -0
  229. data/public/bundle.js +60106 -0
  230. data/public/img/demo/avatar.jpg +0 -0
  231. data/public/presenters/custom_css.css +26 -0
  232. data/public/wc.js +52861 -0
  233. data/scripts/build.sh +10 -0
  234. data/views/mdc/.eslintrc.yml +1 -0
  235. data/views/mdc/.nvmrc +1 -0
  236. data/views/mdc/assets/js/app.js +13 -2
  237. data/views/mdc/assets/js/components/base-component.js +147 -12
  238. data/views/mdc/assets/js/components/base-container.js +54 -14
  239. data/views/mdc/assets/js/components/base-toggle.js +56 -0
  240. data/views/mdc/assets/js/components/button.js +74 -5
  241. data/views/mdc/assets/js/components/cards.js +3 -3
  242. data/views/mdc/assets/js/components/checkboxes.js +7 -30
  243. data/views/mdc/assets/js/components/chips.js +76 -12
  244. data/views/mdc/assets/js/components/content.js +5 -4
  245. data/views/mdc/assets/js/components/data-tables.js +11 -34
  246. data/views/mdc/assets/js/components/datetime.js +29 -6
  247. data/views/mdc/assets/js/components/dialogs.js +128 -31
  248. data/views/mdc/assets/js/components/drag_n_drop.js +182 -0
  249. data/views/mdc/assets/js/components/drawer.js +43 -0
  250. data/views/mdc/assets/js/components/events.js +190 -73
  251. data/views/mdc/assets/js/components/events/action_parameter.js +62 -0
  252. data/views/mdc/assets/js/components/events/action_parameter.test.js +62 -0
  253. data/views/mdc/assets/js/components/events/autocomplete.js +94 -0
  254. data/views/mdc/assets/js/components/events/base.js +139 -23
  255. data/views/mdc/assets/js/components/events/clears.js +15 -12
  256. data/views/mdc/assets/js/components/events/close_dialog.js +50 -0
  257. data/views/mdc/assets/js/components/events/dialog.js +32 -14
  258. data/views/mdc/assets/js/components/events/encode.js +8 -0
  259. data/views/mdc/assets/js/components/events/errors.js +175 -92
  260. data/views/mdc/assets/js/components/events/loads.js +50 -11
  261. data/views/mdc/assets/js/components/events/navigates.js +17 -15
  262. data/views/mdc/assets/js/components/events/plugin.js +18 -0
  263. data/views/mdc/assets/js/components/events/post_message.js +21 -0
  264. data/views/mdc/assets/js/components/events/posts.js +147 -65
  265. data/views/mdc/assets/js/components/events/prompt_if_dirty.js +67 -0
  266. data/views/mdc/assets/js/components/events/removes.js +7 -6
  267. data/views/mdc/assets/js/components/events/replaces.js +87 -33
  268. data/views/mdc/assets/js/components/events/snackbar.js +10 -10
  269. data/views/mdc/assets/js/components/events/stepper.js +8 -10
  270. data/views/mdc/assets/js/components/events/toggle_disabled.js +41 -0
  271. data/views/mdc/assets/js/components/events/toggle_visibility.js +57 -15
  272. data/views/mdc/assets/js/components/file-inputs.js +68 -21
  273. data/views/mdc/assets/js/components/form-fields.js +16 -0
  274. data/views/mdc/assets/js/components/forms.js +3 -3
  275. data/views/mdc/assets/js/components/get_event_target.js +15 -0
  276. data/views/mdc/assets/js/components/grid.js +7 -6
  277. data/views/mdc/assets/js/components/header.js +20 -0
  278. data/views/mdc/assets/js/components/hidden-fields.js +19 -8
  279. data/views/mdc/assets/js/components/icon-toggles.js +7 -7
  280. data/views/mdc/assets/js/components/images.js +19 -0
  281. data/views/mdc/assets/js/components/initialize.js +54 -27
  282. data/views/mdc/assets/js/components/lists.js +9 -4
  283. data/views/mdc/assets/js/components/menus.js +60 -13
  284. data/views/mdc/assets/js/components/mixins/dirtyable.js +22 -0
  285. data/views/mdc/assets/js/components/mixins/event-handler.js +7 -7
  286. data/views/mdc/assets/js/components/mixins/visibility-observer.js +22 -21
  287. data/views/mdc/assets/js/components/multi-select.js +75 -0
  288. data/views/mdc/assets/js/components/plugins.js +86 -0
  289. data/views/mdc/assets/js/components/progress.js +31 -0
  290. data/views/mdc/assets/js/components/radios.js +6 -31
  291. data/views/mdc/assets/js/components/rich-text-area.js +217 -33
  292. data/views/mdc/assets/js/components/rich-text-area/horizontal-rule-blot.js +23 -0
  293. data/views/mdc/assets/js/components/root_document.js +5 -0
  294. data/views/mdc/assets/js/components/selects.js +18 -8
  295. data/views/mdc/assets/js/components/sliders.js +23 -12
  296. data/views/mdc/assets/js/components/snackbar.js +11 -8
  297. data/views/mdc/assets/js/components/steppers.js +3 -3
  298. data/views/mdc/assets/js/components/switches.js +6 -29
  299. data/views/mdc/assets/js/components/tab-bars.js +18 -4
  300. data/views/mdc/assets/js/components/text-fields.js +94 -22
  301. data/views/mdc/assets/js/components/tooltip.js +17 -0
  302. data/views/mdc/assets/js/components/typography.js +28 -0
  303. data/views/mdc/assets/js/components/uninitialize.js +7 -0
  304. data/views/mdc/assets/js/wc.js +111 -0
  305. data/views/mdc/assets/scss/app.scss +13 -5
  306. data/views/mdc/assets/scss/components/avatar.scss +51 -7
  307. data/views/mdc/assets/scss/components/button.scss +7 -9
  308. data/views/mdc/assets/scss/components/card.scss +6 -5
  309. data/views/mdc/assets/scss/components/chip.scss +4 -0
  310. data/views/mdc/assets/scss/components/content.scss +25 -0
  311. data/views/mdc/assets/scss/components/data-table.scss +12 -1
  312. data/views/mdc/assets/scss/components/datetime.scss +1 -2
  313. data/views/mdc/assets/scss/components/dialog.scss +7 -2
  314. data/views/mdc/assets/scss/components/drag_n_drop.scss +17 -0
  315. data/views/mdc/assets/scss/components/drawer.scss +82 -0
  316. data/views/mdc/assets/scss/components/expansion-panel.scss +2 -2
  317. data/views/mdc/assets/scss/components/fab.scss +23 -5
  318. data/views/mdc/assets/scss/components/file-input.scss +10 -14
  319. data/views/mdc/assets/scss/components/grid.scss +32 -17
  320. data/views/mdc/assets/scss/components/header.scss +21 -0
  321. data/views/mdc/assets/scss/components/icon-button-toggles.scss +2 -0
  322. data/views/mdc/assets/scss/components/icon.scss +23 -0
  323. data/views/mdc/assets/scss/components/image-list.scss +18 -0
  324. data/views/mdc/assets/scss/components/image.scss +13 -21
  325. data/views/mdc/assets/scss/components/list.scss +9 -3
  326. data/views/mdc/assets/scss/components/menu.scss +13 -3
  327. data/views/mdc/assets/scss/components/multi-select.scss +44 -0
  328. data/views/mdc/assets/scss/components/progress.scss +1 -0
  329. data/views/mdc/assets/scss/components/rich-text-area.scss +38 -2
  330. data/views/mdc/assets/scss/components/select.scss +6 -3
  331. data/views/mdc/assets/scss/components/separator.scss +3 -0
  332. data/views/mdc/assets/scss/components/switch.scss +10 -0
  333. data/views/mdc/assets/scss/components/textfield.scss +8 -4
  334. data/views/mdc/assets/scss/components/tooltip.scss +3 -0
  335. data/views/mdc/assets/scss/components/typography.scss +6 -0
  336. data/views/mdc/assets/scss/components/unordered-lists.scss +17 -0
  337. data/views/mdc/assets/scss/material.blue_grey-orange.min.css +1 -1
  338. data/views/mdc/assets/scss/media.scss +39 -0
  339. data/views/mdc/assets/scss/palette.scss +16 -0
  340. data/views/mdc/assets/scss/styles.scss +39 -1
  341. data/views/mdc/assets/scss/theme.scss +19 -2
  342. data/views/mdc/body/dismissable-drawer.erb +34 -0
  343. data/views/mdc/body/drawer/divider.erb +1 -0
  344. data/views/mdc/body/drawer/item.erb +13 -0
  345. data/views/mdc/body/drawer/label.erb +1 -0
  346. data/views/mdc/body/drawers/menu.erb +1 -1
  347. data/views/mdc/body/footers/menu_item.erb +2 -2
  348. data/views/mdc/body/header.erb +38 -31
  349. data/views/mdc/body/modal-drawer.erb +35 -0
  350. data/views/mdc/body/snackbar.erb +11 -5
  351. data/views/mdc/components/actions/autocomplete.rb +8 -0
  352. data/views/mdc/components/actions/close_dialog.rb +10 -0
  353. data/views/mdc/components/actions/loads.rb +7 -1
  354. data/views/mdc/components/actions/navigates.rb +1 -1
  355. data/views/mdc/components/actions/post.rb +4 -7
  356. data/views/mdc/components/actions/post_message.rb +10 -0
  357. data/views/mdc/components/actions/prompt_if_dirty.rb +17 -0
  358. data/views/mdc/components/actions/replaces.rb +5 -1
  359. data/views/mdc/components/actions/resolver.rb +39 -0
  360. data/views/mdc/components/actions/snackbar.rb +3 -1
  361. data/views/mdc/components/actions/toggle_disabled.rb +10 -0
  362. data/views/mdc/components/avatar.erb +12 -7
  363. data/views/mdc/components/badge.erb +1 -1
  364. data/views/mdc/components/button.erb +2 -3
  365. data/views/mdc/components/buttons/button.erb +12 -12
  366. data/views/mdc/components/buttons/fab.erb +3 -2
  367. data/views/mdc/components/buttons/icon.erb +5 -5
  368. data/views/mdc/components/buttons/image.erb +4 -3
  369. data/views/mdc/components/card.erb +67 -44
  370. data/views/mdc/components/checkbox.erb +32 -35
  371. data/views/mdc/components/chip.erb +38 -30
  372. data/views/mdc/components/chipset.erb +18 -0
  373. data/views/mdc/components/content.erb +35 -14
  374. data/views/mdc/components/datetime.erb +6 -19
  375. data/views/mdc/components/dialog.erb +45 -25
  376. data/views/mdc/components/drag_and_drop/drag_and_drop.rb +16 -0
  377. data/views/mdc/components/event.erb +3 -5
  378. data/views/mdc/components/expansion_panel.erb +8 -6
  379. data/views/mdc/components/file_input.erb +14 -10
  380. data/views/mdc/components/form.erb +4 -19
  381. data/views/mdc/components/grid.erb +20 -17
  382. data/views/mdc/components/hidden_field.erb +3 -4
  383. data/views/mdc/components/icon.erb +7 -5
  384. data/views/mdc/components/icon_toggle.erb +9 -8
  385. data/views/mdc/components/image.erb +23 -5
  386. data/views/mdc/components/image_list.erb +38 -0
  387. data/views/mdc/components/link.erb +3 -13
  388. data/views/mdc/components/list.erb +4 -2
  389. data/views/mdc/components/list/avatar.erb +2 -1
  390. data/views/mdc/components/list/header.erb +5 -3
  391. data/views/mdc/components/list/hidden_field.erb +3 -0
  392. data/views/mdc/components/list/icon.erb +2 -1
  393. data/views/mdc/components/list/line.erb +19 -9
  394. data/views/mdc/components/list/menu.erb +7 -2
  395. data/views/mdc/components/list/separator.erb +1 -1
  396. data/views/mdc/components/menu.erb +14 -6
  397. data/views/mdc/components/multi_select.erb +33 -0
  398. data/views/mdc/components/number_field.erb +38 -0
  399. data/views/mdc/components/page_title.erb +2 -2
  400. data/views/mdc/components/progress.erb +11 -0
  401. data/views/mdc/components/radio_button.erb +5 -6
  402. data/views/mdc/components/render.erb +2 -3
  403. data/views/mdc/components/rich_text_area.erb +13 -10
  404. data/views/mdc/components/select.erb +28 -12
  405. data/views/mdc/components/separator.erb +3 -0
  406. data/views/mdc/components/shared/hint_error_display.erb +9 -0
  407. data/views/mdc/components/shared/input_label.erb +7 -0
  408. data/views/mdc/components/slider.erb +3 -1
  409. data/views/mdc/components/stepper.erb +1 -1
  410. data/views/mdc/components/stepper/step.erb +1 -1
  411. data/views/mdc/components/switch.erb +8 -7
  412. data/views/mdc/components/tab_bar.erb +7 -1
  413. data/views/mdc/components/table.erb +26 -13
  414. data/views/mdc/components/table/checkbox.erb +6 -3
  415. data/views/mdc/components/table/column.erb +18 -0
  416. data/views/mdc/components/table/footer.erb +8 -0
  417. data/views/mdc/components/table/header.erb +5 -4
  418. data/views/mdc/components/table/pagination.erb +2 -6
  419. data/views/mdc/components/table/row.erb +5 -5
  420. data/views/mdc/components/text_area.erb +9 -11
  421. data/views/mdc/components/text_field.erb +29 -37
  422. data/views/mdc/components/tooltip.erb +2 -2
  423. data/views/mdc/components/typography.erb +7 -5
  424. data/views/mdc/components/unordered_list.erb +10 -0
  425. data/views/mdc/components/unordered_list/icon.erb +3 -0
  426. data/views/mdc/components/unordered_list/list_item.erb +7 -0
  427. data/views/mdc/layout.erb +41 -29
  428. data/views/mdc/package-lock.json +2241 -1332
  429. data/views/mdc/package.json +47 -29
  430. data/views/mdc/web.erb +4 -0
  431. data/views/mdc/webpack.config.js +13 -1
  432. metadata +228 -32
  433. data/app/demo/component_status.pom +0 -76
  434. data/lib/voom-presenters.rb +0 -9
  435. data/lib/voom/presenters-engine.rb +0 -44
  436. data/lib/voom/presenters.rb +0 -19
  437. data/public/.gitignore +0 -2
  438. data/scripts/bump.sh +0 -5
  439. data/scripts/changelog.sh +0 -5
  440. data/scripts/deploy-demo.sh +0 -3
  441. data/scripts/release.sh +0 -5
  442. data/scripts/tag.sh +0 -5
  443. data/views/mdc/assets/js/dialog-polyfill.js +0 -738
  444. data/views/mdc/assets/scss/components/icon-toggles.scss +0 -9
  445. data/views/mdc/assets/scss/components/vendor/flatpickr.min.css +0 -13
  446. data/views/mdc/body/drawer.erb +0 -18
  447. data/views/mdc/components/google_map.erb +0 -9
@@ -1,23 +1,22 @@
1
- include Voom::Trace
2
- trace {"Loading Presenters Settings"}
3
- require 'voom/presenters/helpers/route'
1
+ #include Voom::Trace
2
+ #trace {"Loading Presenters Settings"}
3
+ require 'dry-configurable'
4
4
 
5
5
  unless defined?(Voom::Presenters::Settings)
6
6
  module Voom
7
7
  module Presenters
8
8
  class Settings
9
- extend Dry::Configurable
9
+ extend ::Dry::Configurable
10
10
  setting :presenters do
11
11
  setting :root, []
12
12
  # You can add helpers that will automatically be included
13
13
  # For example:
14
- # For example:
15
14
  # Voom::Presenters::Settings.configure do |config|
16
15
  # config.presenters.helpers << YourHelperModule # Passing a module
17
16
  # config.presenters.helpers << &->{ def foo; :foo; end } # Passing a block
18
17
  # end
19
18
  setting :helpers, [Voom::Presenters::Helpers::Route]
20
- setting :deep_freeze, true
19
+ setting :deep_freeze, false
21
20
  setting :id_generator, ->(node) {"id-#{SecureRandom.hex}"}
22
21
  setting :web_client do
23
22
  # Add lambda's to modify the context for the presenters
@@ -29,8 +28,11 @@ unless defined?(Voom::Presenters::Settings)
29
28
  # }
30
29
  # end
31
30
  setting :prepare_context, []
32
- setting :custom_css, 'public/presenters/*.css'
31
+ # Relative to the root
32
+ setting :custom_css, '../public/presenters'
33
+ setting :protect_from_forgery, false
33
34
  end
35
+ setting :plugins, [:google_maps]
34
36
  setting :components do
35
37
  setting :defaults do
36
38
  setting :datetime do
@@ -56,10 +58,18 @@ unless defined?(Voom::Presenters::Settings)
56
58
  setting :level, 6
57
59
  end
58
60
  setting :rich_text_area do
59
- setting :rows, 25
61
+ setting :rows, 6
60
62
  end
61
63
  end
62
64
  end
65
+ setting :error_logger, ->(file, e, _params, _presenter_name) {
66
+ msg = [
67
+ "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{e.class} - #{e.message}:",
68
+ *e.backtrace
69
+ ].join("\n\t")
70
+ file.puts(msg)
71
+ }
72
+ setting :before_render, [] # an array of `#call`ables
63
73
  end
64
74
 
65
75
  def self.default(type, key)
@@ -1,5 +1,7 @@
1
1
  module Voom
2
2
  module Presenters
3
- VERSION = '0.2.0'.freeze
3
+ module Version
4
+ VERSION = '2.1.0'
5
+ end
4
6
  end
5
7
  end
@@ -1,12 +1,8 @@
1
1
  require 'sinatra'
2
+ require 'honeybadger' if ENV['HONEYBADGER_API_KEY']
2
3
  require 'uri'
3
4
  require 'redcarpet'
4
- require "dry/inflector"
5
- require 'voom/trace'
6
- require 'voom/presenters/app'
7
- require 'voom/presenters/web_client/router'
8
- require 'voom/presenters/web_client/markdown_render'
9
- require 'voom/presenters/errors/unprocessable'
5
+ require 'dry/inflector'
10
6
 
11
7
  module Voom
12
8
  module Presenters
@@ -17,11 +13,19 @@ module Voom
17
13
  set :router_, WebClient::Router
18
14
  set :bind, '0.0.0.0'
19
15
  set :views, Proc.new {File.join(root, "views", ENV['VIEW_ENGINE'] || 'mdc')}
16
+ set :dump_errors, false
17
+ set :protection, :except => :frame_options
20
18
  configure do
21
19
  enable :logging
22
20
  end
23
-
21
+ helpers Helpers::FormHelpers
22
+ helpers Helpers::PaddingHelpers
23
+ helpers Helpers::ExpandHash
24
24
  helpers do
25
+ def render_component(scope, comp, components, index)
26
+ ComponentRenderer.new(comp, render: method(:render), scope: scope, components: components, index: index).render
27
+ end
28
+
25
29
  def markdown(text)
26
30
  unless @markdown
27
31
  renderer = CustomRender.new(hard_wrap: false, filter_html: true)
@@ -48,21 +52,43 @@ module Voom
48
52
  attrib.to_s == value.to_s
49
53
  end
50
54
 
55
+ def h(text)
56
+ Rack::Utils.escape_html(text)
57
+ end
58
+
59
+ def include?(array, value)
60
+ array.map(&:to_s).include?(value.to_s)
61
+ end
62
+
63
+ def includes_one?(array1, array2)
64
+ (array2.map(&:to_sym)-array1.map(&:to_sym)).size != array2.size
65
+ end
66
+
51
67
  def unique_id(comp)
52
68
  "#{comp.id}-#{SecureRandom.hex(4)}"
53
69
  end
54
70
 
55
- def expand_text(text)
56
- self.markdown(Array(text).join("\n\n")) #.gsub("\n\n", "<br/>")
71
+ def expand_text(text, markdown: true)
72
+ if markdown
73
+ self.markdown(Array(text).join("\n\n")) #.gsub("\n\n", "<br/>")
74
+ else
75
+ Array(text).join('<br/>')
76
+ end
57
77
  end
58
78
 
59
- def color_classname(comp)
60
- return "v-#{comp.type}__primary" if eq(comp.color, :primary)
61
- "v-#{comp.type}__secondary" if eq(comp.color, :secondary)
79
+ def color_classname(comp, affects = nil, color_attr = :color)
80
+ color = comp&.public_send(color_attr)
81
+ return unless color
82
+
83
+ return "v-#{comp.type}__primary" if eq(color, :primary)
84
+ return "v-#{comp.type}__secondary" if eq(color, :secondary)
85
+
86
+ "v-#{affects}color__#{color}"
62
87
  end
63
88
 
64
- def color_style(comp, affects = nil)
65
- "#{affects}color: #{comp.color};" unless %w(primary secondary).include?(comp.color.to_s) || comp.color.nil?
89
+ def color_style(comp, affects = nil, color_attr = :color)
90
+ color = comp.public_send(color_attr)
91
+ "#{affects}color: #{color};" unless %w(primary secondary).include?(color.to_s) || color.nil?
66
92
  end
67
93
 
68
94
  def snake_to_camel(hash, except: [])
@@ -91,20 +117,29 @@ module Voom
91
117
  end
92
118
  end
93
119
 
94
- def custom_css
95
- custom_css_path = Presenters::Settings.config.presenters.web_client.custom_css
96
- Dir.glob(custom_css_path).map do |file|
97
- _build_css_link_(file)
98
- end.join("\n") if custom_css_path
120
+ def plugin_headers(pom)
121
+ PluginHeaders.new(pom: pom, render: method(:render)).render
122
+ end
123
+
124
+ def custom_css(path, host=nil)
125
+ CustomCss.new(path, root: Presenters::Settings.config.presenters.root, host: host).render
99
126
  end
100
127
 
101
- def _build_css_link_(path)
102
- (<<~CSS)
103
- <link rel="stylesheet" href="#{env['SCRIPT_NAME']}#{path.sub('public/','')}">
104
- CSS
128
+ def custom_js
129
+ custom_js_path = Presenters::Settings.config.presenters.web_client.custom_js
130
+ Dir.glob(custom_js_path).map do |file|
131
+ _build_script_tag_(file)
132
+ end.join("\n") if custom_js_path
133
+ end
134
+
135
+ def _build_script_tag_(path)
136
+ (<<~JS)
137
+ <script defer src="#{env['SCRIPT_NAME']}#{path.sub('public/','')}"></script>
138
+ JS
105
139
  end
106
140
  end
107
141
 
142
+
108
143
  get '/' do
109
144
  pass unless Presenters::App.registered?('index')
110
145
  presenter = Presenters::App['index'].call
@@ -137,20 +172,42 @@ module Voom
137
172
  post '/__post__/:presenter' do
138
173
  @pom = JSON.parse(request.body.read, object_class: OpenStruct)
139
174
  @grid_nesting = Integer(params[:grid_nesting] || 0)
175
+ @base_url = request.base_url
140
176
  layout = !(request.env['HTTP_X_NO_LAYOUT'] == 'true')
141
177
  erb :web, layout: layout
142
178
  end
143
179
 
144
180
  private
145
181
 
182
+ # analogous to Voom::Presenters::Api::App#render_presenter
146
183
  def render_presenter(presenter)
147
184
  @grid_nesting = Integer(params[:grid_nesting] || 0)
148
185
 
149
186
  begin
150
- @pom = presenter.expand(router: router, context: prepare_context)
187
+ before_render = Presenters::Settings.config.presenters.before_render
188
+ render_instead, ctx = before_render
189
+ .lazy
190
+ .map { |p| p.call(request) }
191
+ .detect(&:itself)
192
+
193
+ if Presenters::App.registered?(render_instead)
194
+ presenter = Presenters::App[render_instead].call
195
+ end
196
+
197
+ p = params.merge(ctx || {})
198
+ @pom = presenter.expand(router: router, context: prepare_context(p))
199
+ @base_url = request.base_url
151
200
  layout = !(request.env['HTTP_X_NO_LAYOUT'] == 'true')
152
- response.headers['X-Frame-Options'] = 'ALLOWALL' if ENV['ALLOWALL_FRAME_OPTIONS']
201
+ response.headers['X-Frame-Options'] = ENV['ALLOWALL_FRAME_OPTIONS'] || presenter.options.fetch(:allow_all_frame_options, false) ? 'ALLOWALL' : 'SAMEORIGIN'
153
202
  erb :web, layout: layout
203
+ rescue StandardError => e
204
+ Presenters::Settings.config.presenters.error_logger.call(
205
+ @env['rack.errors'],
206
+ e,
207
+ params,
208
+ presenter.name
209
+ )
210
+ raise e
154
211
  rescue Presenters::Errors::Unprocessable => e
155
212
  content_type :json
156
213
  status 422
@@ -159,13 +216,13 @@ module Voom
159
216
  end
160
217
 
161
218
  def router
162
- settings.router_.new(base_url: "#{request.script_name}")
219
+ settings.router_.new(base_url: "#{request.base_url}")
163
220
  end
164
221
 
165
- def prepare_context
222
+ def prepare_context(base_params = params)
166
223
  prepare_context = Presenters::Settings.config.presenters.web_client.prepare_context.dup
167
224
  prepare_context.push(method(:scrub_context))
168
- context = params.dup
225
+ context = base_params.dup
169
226
  prepare_context.reduce(context) do |params, context_proc|
170
227
  context = context_proc.call(params, session, env)
171
228
  end
@@ -173,7 +230,7 @@ module Voom
173
230
  end
174
231
 
175
232
  def scrub_context(params, _session, _env)
176
- %i(splat captures _presenter_ grid_nesting input_tag _namespace1_ _namespace2_).each do |key|
233
+ %i(splat captures grid_nesting input_tag).each do |key|
177
234
  params.delete(key) {params.delete(key.to_s)}
178
235
  end
179
236
  params
@@ -0,0 +1,27 @@
1
+ require "dry/inflector"
2
+
3
+ module Voom
4
+ module Presenters
5
+ module WebClient
6
+ class ComponentDecoratorFactory
7
+
8
+ def self.build(component)
9
+ comp_class = "#{inflector.camelize(component.type)}HtmlDecorator"
10
+ klass = if const_defined?(comp_class)
11
+ const_get(comp_class)
12
+ else
13
+ ComponentHtmlDecorator
14
+ end
15
+ klass.new(component)
16
+ end
17
+
18
+ private
19
+
20
+ def self.inflector
21
+ @inflector ||= Dry::Inflector.new
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ require 'delegate'
2
+
3
+ module Voom
4
+ module Presenters
5
+ module WebClient
6
+ class ComponentHtmlDecorator < SimpleDelegator
7
+
8
+ def _plugins_
9
+ __getobj__.send(:_plugins_)
10
+ end
11
+
12
+ def method_missing(meth, *args, &block)
13
+ if respond_to?(meth)
14
+ super
15
+ else
16
+ nil
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ HTML_ESCAPED_ATTRIBUTES = %i(
23
+ id
24
+ type
25
+ )
26
+
27
+ def self.html_escape_attribute(attr)
28
+ define_method(attr) do
29
+ self.class.html_escape(super())
30
+ end
31
+ end
32
+
33
+ HTML_ESCAPED_ATTRIBUTES.each do |attr|
34
+ html_escape_attribute(attr)
35
+ end
36
+
37
+ def self.inherited(subclass)
38
+ subclass::HTML_ESCAPED_ATTRIBUTES.each do |attr|
39
+ html_escape_attribute(attr)
40
+ end
41
+ end
42
+
43
+ def self.html_escape(text)
44
+ Rack::Utils.escape_html(text)
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ require 'erb'
2
+
3
+ module Voom
4
+ module Presenters
5
+ module WebClient
6
+ # This class renders a given component.
7
+ # First it looks for plugins that override default behavior
8
+ # If they don't exist then it renders the base components
9
+ class ComponentRenderer
10
+ extend Pluggable
11
+ include_plugins(:WebClientComponents)
12
+
13
+ def initialize(comp,
14
+ render:,
15
+ components:,
16
+ index:,
17
+ scope: nil)
18
+ @comp = comp
19
+ @index = index
20
+ @components = components
21
+ @scope = scope
22
+ @render = render
23
+ initialize_plugins
24
+ end
25
+
26
+ def render
27
+ comp = ComponentDecoratorFactory.build(@comp)
28
+ components = @components.map { |c| ComponentDecoratorFactory.build(c) }
29
+
30
+ return public_send(:"render_#{@scope ? "_#{@scope}_" : nil}#{@comp.type}",
31
+ comp,
32
+ components: components,
33
+ index: @index,
34
+ render: @render) if respond_to?(:"render_#{@comp.type}")
35
+
36
+ @render.call :erb, :"components#{@scope ? "/#{@scope}" : nil}/#{@comp.type}",
37
+ :locals => {comp: comp,
38
+ components: components, index: @index}
39
+ end
40
+
41
+ private
42
+
43
+ def initialize_plugins
44
+ self.class.include_plugins(:WebClientComponents, plugins: @comp.send(:_plugins_))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,65 @@
1
+ module Voom
2
+ module Presenters
3
+ module WebClient
4
+ # This class renders custom CSS for the layout
5
+ # It looks for public/presenters/global.css first
6
+ # It then looks for public/presenters/#{env['REQUEST_PATH']}.css
7
+ class CustomCss
8
+
9
+ attr_reader :path, :root, :host
10
+ private :path, :root, :host
11
+
12
+ def initialize(path, root:, host:)
13
+ @path = path
14
+ @root = root
15
+ @host = host
16
+ end
17
+
18
+ def render
19
+ return unless custom_css_path
20
+ [global_css, global_namespace_css(path), presenter_css(path)].join
21
+ end
22
+
23
+ private
24
+
25
+ def custom_css_path
26
+ Presenters::Settings.config.presenters.web_client.custom_css
27
+ end
28
+
29
+ # loads a global css file - by default located at `public/presenters/global.css`
30
+ def global_css
31
+ css_file = File.join(custom_css_path, 'global.css')
32
+ full_path = File.join(root, css_file)
33
+ _build_css_link_(css_file) if File.exists?(full_path)
34
+ end
35
+
36
+ def global_namespace_css(path)
37
+ return unless custom_css_path && path
38
+ namespace_path = path.split('/').reject { |c| c.empty? }.first
39
+ css_file = File.join(custom_css_path, namespace_path ? namespace_path : '')
40
+ css_file = File.join(css_file, 'global.css')
41
+ full_path = File.join(root, css_file)
42
+ trace {"Loading global namespace: #{full_path}"}
43
+ _build_css_link_(css_file) if File.exists?(full_path)
44
+ end
45
+
46
+ # loads a custom css file that matches the presenter namespace/presenter.css
47
+ # by default located at public/presenters/#{namespace}/#{presenter}.css
48
+ def presenter_css(path)
49
+ return unless custom_css_path && path
50
+ css_file = File.join(custom_css_path, path)
51
+ css_file = File.join(css_file, 'index') if path == '/'
52
+ css_file = "#{css_file}.css"
53
+ full_path = File.join(root, css_file)
54
+ _build_css_link_(css_file) if File.exists?(full_path)
55
+ end
56
+
57
+ def _build_css_link_(path)
58
+ (<<~CSS)
59
+ <link rel="stylesheet" type="text/css" href="#{host}/#{path.sub('public/', '')}">
60
+ CSS
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end