voom-presenters 0.2.0 → 2.0.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 (440) 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 +39 -0
  7. data/.gitignore +3 -2
  8. data/.releaserc +8 -0
  9. data/.ruby-version +2 -1
  10. data/CHANGELOG.md +64 -114
  11. data/CONTRIBUTING.md +60 -0
  12. data/Gemfile +12 -3
  13. data/Gemfile.lock +83 -45
  14. data/Procfile +1 -0
  15. data/README.md +41 -39
  16. data/app/demo/component_status.pom +1 -1
  17. data/app/demo/components/avatars.pom +40 -0
  18. data/app/demo/components/cards.pom +11 -4
  19. data/app/demo/components/chips.pom +61 -54
  20. data/app/demo/components/content.pom +96 -16
  21. data/app/demo/components/dialogs.pom +175 -6
  22. data/app/demo/components/file_inputs.pom +38 -2
  23. data/app/demo/components/google_maps.pom +6 -1
  24. data/app/demo/components/headers.pom +80 -20
  25. data/app/demo/components/icons.pom +86 -55
  26. data/app/demo/components/image_lists.pom +100 -0
  27. data/app/demo/components/images.pom +45 -0
  28. data/app/demo/components/layouts.pom +3 -25
  29. data/app/demo/components/lists.pom +24 -4
  30. data/app/demo/components/menus.pom +14 -4
  31. data/app/demo/components/nav/menu.pom +38 -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 +44 -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/nav/top_nav.pom +12 -0
  56. data/app/demo/patterns/drag_drop.pom +89 -0
  57. data/app/demo/patterns/floating_card.pom +29 -0
  58. data/app/demo/patterns/search_select.pom +9 -7
  59. data/app/demo/plugins/chart.pom +254 -0
  60. data/app/demo/plugins/image_crop.pom +44 -0
  61. data/app/demo/plugins/index.pom +29 -0
  62. data/app/demo/plugins/nav/drawer.pom +19 -0
  63. data/app/demo/shared/context_list.pom +1 -1
  64. data/app/demo/styles.pom +3 -1
  65. data/bin/console +4 -4
  66. data/bin/presenters +3 -0
  67. data/component-status.yml +15 -15
  68. data/config.ru +20 -10
  69. data/docs/settings.md +81 -0
  70. data/lib/hash_ext/traverse.rb +14 -0
  71. data/lib/voom.rb +25 -0
  72. data/lib/voom/container_methods.rb +2 -2
  73. data/lib/voom/engine.rb +5 -0
  74. data/lib/voom/presenters/api/app.rb +31 -11
  75. data/lib/voom/presenters/api/router.rb +3 -49
  76. data/lib/voom/presenters/app.rb +3 -3
  77. data/lib/voom/presenters/cli.rb +28 -0
  78. data/lib/voom/presenters/demo/dragon_drop.rb +48 -0
  79. data/lib/voom/presenters/demo/echo.rb +2 -0
  80. data/lib/voom/presenters/demo/slow.rb +18 -0
  81. data/lib/voom/presenters/dsl/components/actions/autocomplete.rb +15 -0
  82. data/lib/voom/presenters/dsl/components/actions/base.rb +36 -8
  83. data/lib/voom/presenters/dsl/components/actions/clear.rb +0 -2
  84. data/lib/voom/presenters/dsl/components/actions/close_dialog.rb +17 -0
  85. data/lib/voom/presenters/dsl/components/actions/deletes.rb +0 -2
  86. data/lib/voom/presenters/dsl/components/actions/dialog.rb +0 -2
  87. data/lib/voom/presenters/dsl/components/actions/loads.rb +5 -6
  88. data/lib/voom/presenters/dsl/components/actions/navigates.rb +0 -2
  89. data/lib/voom/presenters/dsl/components/actions/post_message.rb +17 -0
  90. data/lib/voom/presenters/dsl/components/actions/posts.rb +5 -2
  91. data/lib/voom/presenters/dsl/components/actions/prompt_if_dirty.rb +15 -0
  92. data/lib/voom/presenters/dsl/components/actions/remove.rb +0 -2
  93. data/lib/voom/presenters/dsl/components/actions/replaces.rb +4 -4
  94. data/lib/voom/presenters/dsl/components/actions/snackbar.rb +0 -2
  95. data/lib/voom/presenters/dsl/components/actions/stepper.rb +0 -2
  96. data/lib/voom/presenters/dsl/components/actions/toggle_disabled.rb +15 -0
  97. data/lib/voom/presenters/dsl/components/actions/toggle_visibility.rb +0 -2
  98. data/lib/voom/presenters/dsl/components/actions/updates.rb +5 -2
  99. data/lib/voom/presenters/dsl/components/avatar.rb +4 -8
  100. data/lib/voom/presenters/dsl/components/badge.rb +0 -2
  101. data/lib/voom/presenters/dsl/components/base.rb +25 -18
  102. data/lib/voom/presenters/dsl/components/button.rb +15 -11
  103. data/lib/voom/presenters/dsl/components/card.rb +49 -36
  104. data/lib/voom/presenters/dsl/components/checkbox.rb +0 -2
  105. data/lib/voom/presenters/dsl/components/chip.rb +5 -7
  106. data/lib/voom/presenters/dsl/components/chipset.rb +33 -0
  107. data/lib/voom/presenters/dsl/components/content.rb +28 -18
  108. data/lib/voom/presenters/dsl/components/datetime_base.rb +0 -2
  109. data/lib/voom/presenters/dsl/components/datetime_field.rb +0 -2
  110. data/lib/voom/presenters/dsl/components/dialog.rb +36 -12
  111. data/lib/voom/presenters/dsl/components/drawer.rb +9 -6
  112. data/lib/voom/presenters/dsl/components/event.rb +106 -65
  113. data/lib/voom/presenters/dsl/components/event_base.rb +1 -3
  114. data/lib/voom/presenters/dsl/components/expansion_panel.rb +0 -3
  115. data/lib/voom/presenters/dsl/components/file_input.rb +18 -6
  116. data/lib/voom/presenters/dsl/components/footer.rb +2 -2
  117. data/lib/voom/presenters/dsl/components/form.rb +2 -17
  118. data/lib/voom/presenters/dsl/components/grid.rb +52 -50
  119. data/lib/voom/presenters/dsl/components/header.rb +17 -1
  120. data/lib/voom/presenters/dsl/components/hidden_field.rb +0 -2
  121. data/lib/voom/presenters/dsl/components/icon.rb +2 -4
  122. data/lib/voom/presenters/dsl/components/icon_base.rb +5 -7
  123. data/lib/voom/presenters/dsl/components/icon_toggle.rb +2 -4
  124. data/lib/voom/presenters/dsl/components/image.rb +61 -13
  125. data/lib/voom/presenters/dsl/components/image_list.rb +43 -0
  126. data/lib/voom/presenters/dsl/components/input.rb +14 -5
  127. data/lib/voom/presenters/dsl/components/link.rb +33 -0
  128. data/lib/voom/presenters/dsl/components/list.rb +6 -13
  129. data/lib/voom/presenters/dsl/components/lists/action.rb +9 -11
  130. data/lib/voom/presenters/dsl/components/lists/actions.rb +0 -3
  131. data/lib/voom/presenters/dsl/components/lists/line.rb +27 -15
  132. data/lib/voom/presenters/dsl/components/menu.rb +51 -9
  133. data/lib/voom/presenters/dsl/components/mixins/append.rb +2 -2
  134. data/lib/voom/presenters/dsl/components/mixins/attaches.rb +0 -2
  135. data/lib/voom/presenters/dsl/components/mixins/avatar.rb +1 -3
  136. data/lib/voom/presenters/dsl/components/mixins/chips.rb +0 -2
  137. data/lib/voom/presenters/dsl/components/mixins/chipset.rb +19 -0
  138. data/lib/voom/presenters/dsl/components/mixins/common.rb +13 -14
  139. data/lib/voom/presenters/dsl/components/mixins/dialogs.rb +0 -2
  140. data/lib/voom/presenters/dsl/components/mixins/event.rb +0 -2
  141. data/lib/voom/presenters/dsl/components/mixins/image_lists.rb +15 -0
  142. data/lib/voom/presenters/dsl/components/mixins/last_response.rb +48 -0
  143. data/lib/voom/presenters/dsl/components/mixins/padding.rb +42 -0
  144. data/lib/voom/presenters/dsl/components/mixins/progress.rb +16 -0
  145. data/lib/voom/presenters/dsl/components/mixins/tab_bars.rb +2 -0
  146. data/lib/voom/presenters/dsl/components/mixins/tables.rb +15 -0
  147. data/lib/voom/presenters/dsl/components/mixins/text_fields.rb +5 -0
  148. data/lib/voom/presenters/dsl/components/mixins/toggles.rb +0 -2
  149. data/lib/voom/presenters/dsl/components/mixins/typography.rb +55 -8
  150. data/lib/voom/presenters/dsl/components/mixins/yield_to.rb +2 -2
  151. data/lib/voom/presenters/dsl/components/number_field.rb +20 -0
  152. data/lib/voom/presenters/dsl/components/page_title.rb +31 -0
  153. data/lib/voom/presenters/dsl/components/progress.rb +27 -0
  154. data/lib/voom/presenters/dsl/components/radio_button.rb +0 -1
  155. data/lib/voom/presenters/dsl/components/rich_text_area.rb +5 -11
  156. data/lib/voom/presenters/dsl/components/select.rb +21 -9
  157. data/lib/voom/presenters/dsl/components/separator.rb +21 -0
  158. data/lib/voom/presenters/dsl/components/slider.rb +6 -7
  159. data/lib/voom/presenters/dsl/components/stepper.rb +0 -10
  160. data/lib/voom/presenters/dsl/components/switch.rb +0 -2
  161. data/lib/voom/presenters/dsl/components/tab_bar.rb +0 -3
  162. data/lib/voom/presenters/dsl/components/table.rb +39 -20
  163. data/lib/voom/presenters/dsl/components/text_area.rb +1 -3
  164. data/lib/voom/presenters/dsl/components/text_field.rb +54 -11
  165. data/lib/voom/presenters/dsl/components/time_field.rb +0 -2
  166. data/lib/voom/presenters/dsl/components/toggle_base.rb +8 -6
  167. data/lib/voom/presenters/dsl/components/typography.rb +4 -4
  168. data/lib/voom/presenters/dsl/components/unordered_list.rb +50 -0
  169. data/lib/voom/presenters/dsl/definer.rb +0 -4
  170. data/lib/voom/presenters/dsl/definition.rb +6 -5
  171. data/lib/voom/presenters/dsl/protect_from_forgery.rb +43 -0
  172. data/lib/voom/presenters/dsl/user_interface.rb +37 -22
  173. data/lib/voom/presenters/errors.rb +1 -0
  174. data/lib/voom/presenters/errors/invalid_dsl.rb +8 -0
  175. data/lib/voom/presenters/errors/parameter_validation.rb +1 -3
  176. data/lib/voom/presenters/generators/inflectors.rb +59 -0
  177. data/lib/voom/presenters/generators/plugin.rb +115 -0
  178. data/lib/voom/presenters/generators/templates/plugin/.gitignore +12 -0
  179. data/lib/voom/presenters/generators/templates/plugin/Gemfile +6 -0
  180. data/lib/voom/presenters/generators/templates/plugin/LICENSE.txt.tt +21 -0
  181. data/lib/voom/presenters/generators/templates/plugin/README.md +253 -0
  182. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/actions/action.rb.tt +16 -0
  183. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/actions/dsl.rb.tt +22 -0
  184. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/component.rb.tt +18 -0
  185. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/components/dsl.rb.tt +19 -0
  186. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/helpers/helper.rb.tt +15 -0
  187. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/plugin.rb.tt +9 -0
  188. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/web_client/components/actions/data.rb.tt +17 -0
  189. data/lib/voom/presenters/generators/templates/plugin/lib/voom/presenters/plugins/web_client/components/render.rb.tt +23 -0
  190. data/lib/voom/presenters/generators/templates/plugin/presenter_plugin.gemspec.tt +21 -0
  191. data/lib/voom/presenters/generators/templates/plugin/views/assets/css/components/component.css.tt +21 -0
  192. data/lib/voom/presenters/generators/templates/plugin/views/assets/js/components/actions/action.js.tt +15 -0
  193. data/lib/voom/presenters/generators/templates/plugin/views/assets/js/components/component.js.tt +39 -0
  194. data/lib/voom/presenters/generators/templates/plugin/views/components/component.erb.tt +14 -0
  195. data/lib/voom/presenters/generators/templates/plugin/views/components/component_header.erb.tt +20 -0
  196. data/lib/voom/presenters/helpers.rb +2 -8
  197. data/lib/voom/presenters/helpers/inflector.rb +1 -1
  198. data/lib/voom/presenters/helpers/rails.rb +15 -8
  199. data/lib/voom/presenters/helpers/redact.rb +13 -0
  200. data/lib/voom/presenters/helpers/route.rb +12 -5
  201. data/lib/voom/presenters/pluggable.rb +37 -0
  202. data/lib/voom/presenters/plugins.rb +7 -0
  203. data/lib/voom/presenters/plugins/google_maps.rb +24 -0
  204. data/lib/voom/presenters/plugins/google_maps/google_map.erb +10 -0
  205. data/lib/voom/presenters/{dsl/components → plugins/google_maps}/google_map.rb +4 -3
  206. data/lib/voom/presenters/{dsl.rb → registry.rb} +13 -15
  207. data/lib/voom/presenters/router.rb +59 -0
  208. data/lib/voom/presenters/settings.rb +18 -8
  209. data/lib/voom/presenters/version.rb +1 -1
  210. data/lib/voom/presenters/web_client/app.rb +86 -29
  211. data/lib/voom/presenters/web_client/component_decorator_factory.rb +27 -0
  212. data/lib/voom/presenters/web_client/component_html_decorator.rb +50 -0
  213. data/lib/voom/presenters/web_client/component_renderer.rb +49 -0
  214. data/lib/voom/presenters/web_client/custom_css.rb +65 -0
  215. data/lib/voom/presenters/web_client/{markdown_render.rb → custom_render.rb} +5 -3
  216. data/lib/voom/presenters/web_client/helpers/expand_hash.rb +19 -0
  217. data/lib/voom/presenters/web_client/helpers/form_helpers.rb +14 -0
  218. data/lib/voom/presenters/web_client/helpers/padding_helpers.rb +21 -0
  219. data/lib/voom/presenters/web_client/plugin_headers.rb +37 -0
  220. data/lib/voom/presenters/web_client/router.rb +3 -54
  221. data/lib/voom/railtie.rb +37 -0
  222. data/lib/voom/symbol/to_str.rb +3 -3
  223. data/lib/voom/trace.rb +0 -2
  224. data/presenters.gemspec +8 -4
  225. data/public/bundle.css +18221 -0
  226. data/public/bundle.js +59949 -0
  227. data/public/img/demo/avatar.jpg +0 -0
  228. data/public/presenters/custom_css.css +26 -0
  229. data/public/wc.js +52704 -0
  230. data/scripts/build.sh +10 -0
  231. data/views/mdc/.eslintrc.yml +1 -0
  232. data/views/mdc/.nvmrc +1 -0
  233. data/views/mdc/assets/js/app.js +13 -2
  234. data/views/mdc/assets/js/components/base-component.js +147 -12
  235. data/views/mdc/assets/js/components/base-container.js +54 -14
  236. data/views/mdc/assets/js/components/base-toggle.js +56 -0
  237. data/views/mdc/assets/js/components/button.js +74 -5
  238. data/views/mdc/assets/js/components/cards.js +3 -3
  239. data/views/mdc/assets/js/components/checkboxes.js +7 -30
  240. data/views/mdc/assets/js/components/chips.js +76 -12
  241. data/views/mdc/assets/js/components/content.js +5 -4
  242. data/views/mdc/assets/js/components/data-tables.js +11 -34
  243. data/views/mdc/assets/js/components/datetime.js +29 -6
  244. data/views/mdc/assets/js/components/dialogs.js +128 -31
  245. data/views/mdc/assets/js/components/drag_n_drop.js +182 -0
  246. data/views/mdc/assets/js/components/drawer.js +43 -0
  247. data/views/mdc/assets/js/components/events.js +190 -73
  248. data/views/mdc/assets/js/components/events/action_parameter.js +62 -0
  249. data/views/mdc/assets/js/components/events/action_parameter.test.js +62 -0
  250. data/views/mdc/assets/js/components/events/autocomplete.js +94 -0
  251. data/views/mdc/assets/js/components/events/base.js +139 -23
  252. data/views/mdc/assets/js/components/events/clears.js +15 -12
  253. data/views/mdc/assets/js/components/events/close_dialog.js +50 -0
  254. data/views/mdc/assets/js/components/events/dialog.js +32 -14
  255. data/views/mdc/assets/js/components/events/encode.js +8 -0
  256. data/views/mdc/assets/js/components/events/errors.js +175 -92
  257. data/views/mdc/assets/js/components/events/loads.js +50 -11
  258. data/views/mdc/assets/js/components/events/navigates.js +17 -15
  259. data/views/mdc/assets/js/components/events/plugin.js +18 -0
  260. data/views/mdc/assets/js/components/events/post_message.js +21 -0
  261. data/views/mdc/assets/js/components/events/posts.js +147 -65
  262. data/views/mdc/assets/js/components/events/prompt_if_dirty.js +67 -0
  263. data/views/mdc/assets/js/components/events/removes.js +7 -6
  264. data/views/mdc/assets/js/components/events/replaces.js +87 -33
  265. data/views/mdc/assets/js/components/events/snackbar.js +10 -10
  266. data/views/mdc/assets/js/components/events/stepper.js +8 -10
  267. data/views/mdc/assets/js/components/events/toggle_disabled.js +41 -0
  268. data/views/mdc/assets/js/components/events/toggle_visibility.js +57 -15
  269. data/views/mdc/assets/js/components/file-inputs.js +68 -21
  270. data/views/mdc/assets/js/components/form-fields.js +16 -0
  271. data/views/mdc/assets/js/components/forms.js +3 -3
  272. data/views/mdc/assets/js/components/get_event_target.js +15 -0
  273. data/views/mdc/assets/js/components/grid.js +7 -6
  274. data/views/mdc/assets/js/components/header.js +20 -0
  275. data/views/mdc/assets/js/components/hidden-fields.js +19 -8
  276. data/views/mdc/assets/js/components/icon-toggles.js +7 -7
  277. data/views/mdc/assets/js/components/images.js +19 -0
  278. data/views/mdc/assets/js/components/initialize.js +52 -27
  279. data/views/mdc/assets/js/components/lists.js +9 -4
  280. data/views/mdc/assets/js/components/menus.js +60 -13
  281. data/views/mdc/assets/js/components/mixins/dirtyable.js +22 -0
  282. data/views/mdc/assets/js/components/mixins/event-handler.js +7 -7
  283. data/views/mdc/assets/js/components/mixins/visibility-observer.js +22 -21
  284. data/views/mdc/assets/js/components/plugins.js +86 -0
  285. data/views/mdc/assets/js/components/progress.js +31 -0
  286. data/views/mdc/assets/js/components/radios.js +6 -31
  287. data/views/mdc/assets/js/components/rich-text-area.js +217 -33
  288. data/views/mdc/assets/js/components/rich-text-area/horizontal-rule-blot.js +23 -0
  289. data/views/mdc/assets/js/components/root_document.js +5 -0
  290. data/views/mdc/assets/js/components/selects.js +18 -8
  291. data/views/mdc/assets/js/components/sliders.js +23 -12
  292. data/views/mdc/assets/js/components/snackbar.js +11 -8
  293. data/views/mdc/assets/js/components/steppers.js +3 -3
  294. data/views/mdc/assets/js/components/switches.js +6 -29
  295. data/views/mdc/assets/js/components/tab-bars.js +18 -4
  296. data/views/mdc/assets/js/components/text-fields.js +94 -22
  297. data/views/mdc/assets/js/components/tooltip.js +17 -0
  298. data/views/mdc/assets/js/components/typography.js +28 -0
  299. data/views/mdc/assets/js/components/uninitialize.js +7 -0
  300. data/views/mdc/assets/js/wc.js +111 -0
  301. data/views/mdc/assets/scss/app.scss +12 -5
  302. data/views/mdc/assets/scss/components/avatar.scss +51 -7
  303. data/views/mdc/assets/scss/components/button.scss +7 -9
  304. data/views/mdc/assets/scss/components/card.scss +6 -5
  305. data/views/mdc/assets/scss/components/chip.scss +4 -0
  306. data/views/mdc/assets/scss/components/content.scss +25 -0
  307. data/views/mdc/assets/scss/components/data-table.scss +12 -1
  308. data/views/mdc/assets/scss/components/datetime.scss +1 -2
  309. data/views/mdc/assets/scss/components/dialog.scss +7 -2
  310. data/views/mdc/assets/scss/components/drag_n_drop.scss +17 -0
  311. data/views/mdc/assets/scss/components/drawer.scss +82 -0
  312. data/views/mdc/assets/scss/components/expansion-panel.scss +2 -2
  313. data/views/mdc/assets/scss/components/fab.scss +23 -5
  314. data/views/mdc/assets/scss/components/file-input.scss +10 -14
  315. data/views/mdc/assets/scss/components/grid.scss +32 -17
  316. data/views/mdc/assets/scss/components/header.scss +21 -0
  317. data/views/mdc/assets/scss/components/icon-button-toggles.scss +2 -0
  318. data/views/mdc/assets/scss/components/icon.scss +23 -0
  319. data/views/mdc/assets/scss/components/image-list.scss +18 -0
  320. data/views/mdc/assets/scss/components/image.scss +13 -21
  321. data/views/mdc/assets/scss/components/list.scss +9 -3
  322. data/views/mdc/assets/scss/components/menu.scss +13 -3
  323. data/views/mdc/assets/scss/components/progress.scss +1 -0
  324. data/views/mdc/assets/scss/components/rich-text-area.scss +38 -2
  325. data/views/mdc/assets/scss/components/select.scss +6 -3
  326. data/views/mdc/assets/scss/components/separator.scss +3 -0
  327. data/views/mdc/assets/scss/components/switch.scss +10 -0
  328. data/views/mdc/assets/scss/components/textfield.scss +8 -4
  329. data/views/mdc/assets/scss/components/tooltip.scss +3 -0
  330. data/views/mdc/assets/scss/components/typography.scss +6 -0
  331. data/views/mdc/assets/scss/components/unordered-lists.scss +17 -0
  332. data/views/mdc/assets/scss/material.blue_grey-orange.min.css +1 -1
  333. data/views/mdc/assets/scss/media.scss +39 -0
  334. data/views/mdc/assets/scss/palette.scss +16 -0
  335. data/views/mdc/assets/scss/styles.scss +39 -1
  336. data/views/mdc/assets/scss/theme.scss +19 -2
  337. data/views/mdc/body/dismissable-drawer.erb +34 -0
  338. data/views/mdc/body/drawer/divider.erb +1 -0
  339. data/views/mdc/body/drawer/item.erb +13 -0
  340. data/views/mdc/body/drawer/label.erb +1 -0
  341. data/views/mdc/body/drawers/menu.erb +1 -1
  342. data/views/mdc/body/footers/menu_item.erb +2 -2
  343. data/views/mdc/body/header.erb +38 -31
  344. data/views/mdc/body/modal-drawer.erb +35 -0
  345. data/views/mdc/body/snackbar.erb +11 -5
  346. data/views/mdc/components/actions/autocomplete.rb +8 -0
  347. data/views/mdc/components/actions/close_dialog.rb +10 -0
  348. data/views/mdc/components/actions/loads.rb +7 -1
  349. data/views/mdc/components/actions/navigates.rb +1 -1
  350. data/views/mdc/components/actions/post.rb +4 -7
  351. data/views/mdc/components/actions/post_message.rb +10 -0
  352. data/views/mdc/components/actions/prompt_if_dirty.rb +17 -0
  353. data/views/mdc/components/actions/replaces.rb +5 -1
  354. data/views/mdc/components/actions/resolver.rb +39 -0
  355. data/views/mdc/components/actions/snackbar.rb +3 -1
  356. data/views/mdc/components/actions/toggle_disabled.rb +10 -0
  357. data/views/mdc/components/avatar.erb +12 -7
  358. data/views/mdc/components/badge.erb +1 -1
  359. data/views/mdc/components/button.erb +2 -3
  360. data/views/mdc/components/buttons/button.erb +12 -12
  361. data/views/mdc/components/buttons/fab.erb +3 -2
  362. data/views/mdc/components/buttons/icon.erb +5 -5
  363. data/views/mdc/components/buttons/image.erb +4 -3
  364. data/views/mdc/components/card.erb +67 -44
  365. data/views/mdc/components/checkbox.erb +32 -35
  366. data/views/mdc/components/chip.erb +38 -30
  367. data/views/mdc/components/chipset.erb +18 -0
  368. data/views/mdc/components/content.erb +35 -14
  369. data/views/mdc/components/datetime.erb +6 -19
  370. data/views/mdc/components/dialog.erb +45 -25
  371. data/views/mdc/components/drag_and_drop/drag_and_drop.rb +16 -0
  372. data/views/mdc/components/event.erb +3 -5
  373. data/views/mdc/components/expansion_panel.erb +8 -6
  374. data/views/mdc/components/file_input.erb +14 -10
  375. data/views/mdc/components/form.erb +4 -19
  376. data/views/mdc/components/grid.erb +20 -17
  377. data/views/mdc/components/hidden_field.erb +3 -4
  378. data/views/mdc/components/icon.erb +7 -5
  379. data/views/mdc/components/icon_toggle.erb +9 -8
  380. data/views/mdc/components/image.erb +23 -5
  381. data/views/mdc/components/image_list.erb +38 -0
  382. data/views/mdc/components/link.erb +3 -13
  383. data/views/mdc/components/list.erb +4 -2
  384. data/views/mdc/components/list/avatar.erb +2 -1
  385. data/views/mdc/components/list/header.erb +5 -3
  386. data/views/mdc/components/list/hidden_field.erb +3 -0
  387. data/views/mdc/components/list/icon.erb +2 -1
  388. data/views/mdc/components/list/line.erb +19 -9
  389. data/views/mdc/components/list/menu.erb +7 -2
  390. data/views/mdc/components/list/separator.erb +1 -1
  391. data/views/mdc/components/menu.erb +14 -6
  392. data/views/mdc/components/number_field.erb +38 -0
  393. data/views/mdc/components/page_title.erb +2 -2
  394. data/views/mdc/components/progress.erb +11 -0
  395. data/views/mdc/components/radio_button.erb +5 -6
  396. data/views/mdc/components/render.erb +2 -3
  397. data/views/mdc/components/rich_text_area.erb +13 -10
  398. data/views/mdc/components/select.erb +28 -12
  399. data/views/mdc/components/separator.erb +3 -0
  400. data/views/mdc/components/shared/hint_error_display.erb +9 -0
  401. data/views/mdc/components/shared/input_label.erb +7 -0
  402. data/views/mdc/components/slider.erb +3 -1
  403. data/views/mdc/components/stepper.erb +1 -1
  404. data/views/mdc/components/stepper/step.erb +1 -1
  405. data/views/mdc/components/switch.erb +8 -7
  406. data/views/mdc/components/tab_bar.erb +7 -1
  407. data/views/mdc/components/table.erb +26 -13
  408. data/views/mdc/components/table/checkbox.erb +6 -3
  409. data/views/mdc/components/table/column.erb +18 -0
  410. data/views/mdc/components/table/footer.erb +8 -0
  411. data/views/mdc/components/table/header.erb +5 -4
  412. data/views/mdc/components/table/pagination.erb +2 -6
  413. data/views/mdc/components/table/row.erb +5 -5
  414. data/views/mdc/components/text_area.erb +9 -11
  415. data/views/mdc/components/text_field.erb +29 -37
  416. data/views/mdc/components/tooltip.erb +2 -2
  417. data/views/mdc/components/typography.erb +7 -5
  418. data/views/mdc/components/unordered_list.erb +10 -0
  419. data/views/mdc/components/unordered_list/icon.erb +3 -0
  420. data/views/mdc/components/unordered_list/list_item.erb +7 -0
  421. data/views/mdc/layout.erb +41 -29
  422. data/views/mdc/package-lock.json +2222 -1327
  423. data/views/mdc/package.json +47 -29
  424. data/views/mdc/web.erb +4 -0
  425. data/views/mdc/webpack.config.js +13 -1
  426. metadata +218 -26
  427. data/lib/voom-presenters.rb +0 -9
  428. data/lib/voom/presenters-engine.rb +0 -44
  429. data/lib/voom/presenters.rb +0 -19
  430. data/public/.gitignore +0 -2
  431. data/scripts/bump.sh +0 -5
  432. data/scripts/changelog.sh +0 -5
  433. data/scripts/deploy-demo.sh +0 -3
  434. data/scripts/release.sh +0 -5
  435. data/scripts/tag.sh +0 -5
  436. data/views/mdc/assets/js/dialog-polyfill.js +0 -738
  437. data/views/mdc/assets/scss/components/icon-toggles.scss +0 -9
  438. data/views/mdc/assets/scss/components/vendor/flatpickr.min.css +0 -13
  439. data/views/mdc/body/drawer.erb +0 -18
  440. data/views/mdc/components/google_map.erb +0 -9
@@ -0,0 +1,182 @@
1
+ /*
2
+ A drag data store (DragEvent.prototype.dataTransfer.items) can be in one of
3
+ three modes:
4
+
5
+ 1. read/write, during a `dragstart` event: items can be read and added
6
+ 2. read-only, during a `drop` event: items can be read, but not added
7
+ 3. protected, during all other types of DragEvent: items cannot be read
8
+ or added.
9
+
10
+ (see https://html.spec.whatwg.org/multipage/dnd.html#concept-dnd-rw)
11
+
12
+ Thus, attempting to mutate the store during events other than `dragstart`
13
+ fails silently: no error is raised, but items are not added.
14
+
15
+
16
+ To read items in protected mode, serialize data as a string and store it as
17
+ a key instead of as a value. This makes it accessible via
18
+ `dataTransfer.types`:
19
+
20
+ // in a dragstart handler:
21
+ event.dataTransfer.setData(JSON.stringify(foo), '');
22
+
23
+ // in a later read-only or protected DragEvent handler:
24
+ const json = event.dataTransfer.types[someIndex];
25
+ const foo = JSON.stringify(json);
26
+
27
+
28
+ There is no workaround for attempting to mutate a drag data store not in
29
+ read/write mode.
30
+ */
31
+
32
+ import {getRootNode} from './base-component';
33
+
34
+ export const EVENT_DROPPED = 'dropped';
35
+
36
+ const DRAG_DATA_MIME_TYPE = 'application/x.voom-drag-data+json';
37
+ const ELEMENT_ID_MIME_TYPE = 'text/x.voom-element-id';
38
+
39
+ function createDragStartHandler(root, element) {
40
+ return function(event) {
41
+ const dragParamData = event.target.dataset.drag_params;
42
+
43
+ if (dragParamData) {
44
+ event.dataTransfer.setData(DRAG_DATA_MIME_TYPE, dragParamData);
45
+
46
+ const zone = JSON.parse(dragParamData).zone;
47
+
48
+ if (zone) {
49
+ event.dataTransfer.setData(zone, '');
50
+ }
51
+
52
+ event.dataTransfer.effectAllowed = 'move';
53
+ event.target.classList.remove('v-dnd-draggable');
54
+ event.target.classList.add('v-dnd-moving');
55
+
56
+ event.dataTransfer.setData(ELEMENT_ID_MIME_TYPE, element.id);
57
+ }
58
+ };
59
+ }
60
+
61
+ function createDragOverHandler(root, element) {
62
+ return function(event) {
63
+ const dropZone = element.dataset.dropzone;
64
+
65
+ if (dropZone == null || event.dataTransfer.types.includes(dropZone)) {
66
+ if (event.preventDefault) {
67
+ event.preventDefault();
68
+ }
69
+ element.classList.add('v-dnd-over');
70
+ }
71
+ else {
72
+ element.classList.remove('v-dnd-over');
73
+ }
74
+ };
75
+ }
76
+
77
+ function createDragLeaveHandler(root, element) {
78
+ return function(event) {
79
+ element.classList.remove('v-dnd-over');
80
+ };
81
+ }
82
+
83
+ function createDropHandler(root, element) {
84
+ // When an element is upgraded to a Voom component after being replaced via
85
+ // `replaces`, root may refer to the replaced element itself instead of the
86
+ // element's root node.
87
+ // Since a valid drop zone may exist anywhere on the page, it is not
88
+ // guaranteed that root contains the element being dragged.
89
+ // getRootNode will fetch `root`'s actual root node (document or shadow
90
+ // DOM root).
91
+ const trueRoot = getRootNode(root);
92
+
93
+ return function(event) {
94
+ event.stopPropagation();
95
+ event.preventDefault();
96
+
97
+ const id = event.dataTransfer.getData(ELEMENT_ID_MIME_TYPE);
98
+ const draggedElement = id ? trueRoot.querySelector(`#${id}`) : null;
99
+ let dragParams = {};
100
+
101
+ if (draggedElement) {
102
+ dragParams = JSON.parse(draggedElement.dataset.drag_params);
103
+ }
104
+
105
+ element.classList.remove('v-dnd-over', 'v-dnd-moving');
106
+ element.classList.add('v-dnd-draggable');
107
+
108
+ // Emit a "dropped" event for the element being dragged:
109
+ // The drag_params of the dragged element are merged with the
110
+ // drop_params of the drop zone.
111
+ const dropZoneParams = JSON.parse(element.dataset.drop_params);
112
+ const params = Object.assign({}, dragParams, dropZoneParams);
113
+ const droppedEvent = new CustomEvent(EVENT_DROPPED, {detail: params});
114
+
115
+ draggedElement.dispatchEvent(droppedEvent);
116
+
117
+ return false;
118
+ };
119
+ }
120
+
121
+ function createDragEndHandler(root, element) {
122
+ return function(event) {
123
+ element.classList.remove('v-dnd-over', 'v-dnd-moving');
124
+ element.classList.add('v-dnd-draggable');
125
+ };
126
+ }
127
+
128
+ const DRAGGABLE_SELECTOR = '[draggable=true]';
129
+ const DROP_ZONE_SELECTOR = '[data-dropzone]';
130
+
131
+ export function initDragAndDrop(root) {
132
+ const draggables = Array.from(root.querySelectorAll(DRAGGABLE_SELECTOR));
133
+
134
+ if (typeof root.matches === 'function' && root.matches(DRAGGABLE_SELECTOR)) {
135
+ draggables.unshift(root);
136
+ }
137
+
138
+ for (const elem of draggables) {
139
+ elem.addEventListener('dragstart', createDragStartHandler(root, elem));
140
+ elem.addEventListener('dragend', createDragEndHandler(root, elem));
141
+ }
142
+
143
+ const dropZones = Array.from(root.querySelectorAll(DROP_ZONE_SELECTOR));
144
+
145
+ if (typeof root.matches === 'function' && root.matches(DROP_ZONE_SELECTOR)) {
146
+ dropZones.unshift(root);
147
+ }
148
+
149
+ for (const elem of dropZones) {
150
+ elem.addEventListener('dragover', createDragOverHandler(root, elem));
151
+ elem.addEventListener('drop', createDropHandler(root, elem));
152
+ elem.addEventListener('dragleave', createDragLeaveHandler(root, elem));
153
+ }
154
+ }
155
+
156
+ /**
157
+ * hasDragDropData determines whether the provided event has previously-set
158
+ * drag-n-drop data available.
159
+ * @param {Event} event
160
+ * @return {Boolean}
161
+ */
162
+ export function hasDragDropData(event) {
163
+ return event.type === 'drop' && event.dataTransfer
164
+ || event.type === EVENT_DROPPED && event.detail;
165
+ }
166
+
167
+ /**
168
+ * extractDragDropData attempts to extract a payload of drag-n-drop data from
169
+ * the provided event previously set during a `dragstart` event.
170
+ * @param {Event} event
171
+ * @return {Object}
172
+ */
173
+ export function extractDragDropData(event) {
174
+ if (event.type === 'drop' && event.dataTransfer) {
175
+ return JSON.parse(event.dataTransfer.getData(DRAG_DATA_MIME_TYPE));
176
+ }
177
+ else if (event.type === EVENT_DROPPED) {
178
+ return event.detail;
179
+ }
180
+
181
+ return {};
182
+ }
@@ -0,0 +1,43 @@
1
+ import {MDCDrawer} from '@material/drawer';
2
+ import {VBaseComponent} from './base-component';
3
+ import {hookupComponents} from './base-component';
4
+ import {eventHandlerMixin} from './mixins/event-handler';
5
+
6
+ export function initDrawer(e) {
7
+ console.debug('\tDrawer');
8
+ hookupComponents(e, '.v-drawer__modal', VModalDrawer, MDCDrawer);
9
+ hookupComponents(e, '.v-drawer__dismissible', VDismissibleDrawer, MDCDrawer);
10
+ }
11
+
12
+ class VDrawer extends eventHandlerMixin(VBaseComponent) {
13
+ constructor(element, mdcComponent) {
14
+ super(element, mdcComponent);
15
+ const header = this.root.querySelector('.v-header');
16
+ if (header) {
17
+ header.addEventListener('MDCTopAppBar:nav',
18
+ () => {
19
+ if (this.isActive()) {
20
+ this.mdcComponent.open = !this.mdcComponent.open;
21
+ }
22
+ });
23
+ }
24
+ }
25
+
26
+ isActive() {
27
+ return (getComputedStyle(this.element).
28
+ getPropertyValue('--v-drawer-active') !== 'no');
29
+ }
30
+ }
31
+
32
+ export class VModalDrawer extends VDrawer {
33
+ constructor(element, mdcComponent) {
34
+ super(element, mdcComponent);
35
+ this.mdcComponent.open = false;
36
+ }
37
+ }
38
+
39
+ export class VDismissibleDrawer extends VDrawer {
40
+ constructor(element, mdcComponent) {
41
+ super(element, mdcComponent);
42
+ }
43
+ }
@@ -4,157 +4,274 @@ import {VReplaces} from './events/replaces';
4
4
  import {VDialog} from './events/dialog';
5
5
  import {VErrors} from './events/errors';
6
6
  import {VToggleVisibility} from './events/toggle_visibility';
7
+ import {VToggleDisabled} from './events/toggle_disabled';
8
+ import {VAutoComplete} from './events/autocomplete';
9
+ import {VPromptIfDirty} from './events/prompt_if_dirty';
7
10
  import {VSnackbarEvent} from './events/snackbar';
8
- import {VNavigates} from './events/navigates';
9
11
  import {VClears} from './events/clears';
12
+ import {VCloseDialog} from './events/close_dialog';
13
+ import {VPostMessage} from './events/post_message';
10
14
  import {VRemoves} from './events/removes';
11
15
  import {VStepperEvent} from './events/stepper';
16
+ import {VNavigates} from './events/navigates';
17
+ import {VPluginEventAction} from './events/plugin';
18
+ import getRoot from './root_document';
19
+ import {hasDragDropData, extractDragDropData} from './drag_n_drop';
20
+ import {getEventTarget} from './get_event_target';
21
+
22
+ const EVENTS_SELECTOR = '[data-events]';
12
23
 
13
24
  export class VEvents {
14
- //[[type, url, target, params]]
15
- constructor(actions, event) {
25
+ // [[type, url, target, params]]
26
+ constructor(actions, event, root, vComponent) {
16
27
  this.event = event;
28
+ this.root = root;
17
29
  this.actions = actions.map((action) => {
18
- return this.constructor.action_class(action, event);
30
+ return this.constructor.action_class(action, event, root);
19
31
  });
32
+ this.vComponent = vComponent;
20
33
  }
21
34
 
22
35
  call() {
36
+ const event = this.event;
37
+ const target = getEventTarget(event);
38
+ let eventParams = {};
39
+
40
+ if (hasDragDropData(event)) {
41
+ eventParams = Object.assign(eventParams, extractDragDropData(event));
42
+ }
43
+ else if (event.detail && event.detail.constructor === Object) {
44
+ eventParams = Object.assign(eventParams, event.detail);
45
+ }
46
+
23
47
  // Adapted from http://www.datchley.name/promise-patterns-anti-patterns/#executingpromisesinseries
24
- var fnlist = this.actions.map((action) => {
25
- return function (results) {
26
- return Promise.resolve(action.call(results));
48
+ const fnlist = this.actions.map((action) => {
49
+ return function(results) {
50
+ return Promise.resolve(action.call(results, eventParams));
27
51
  };
28
52
  });
29
53
 
30
54
  // Execute a list of Promise return functions in series
31
55
  function pseries(list) {
32
- var p = Promise.resolve([]);
33
- return list.reduce(function (pacc, fn) {
56
+ const p = Promise.resolve([]);
57
+ return list.reduce(function(pacc, fn) {
34
58
  return pacc = pacc.then(fn);
35
59
  }, p);
36
60
  }
37
61
 
38
- var event = this.event;
62
+ const ev = new CustomEvent('V:eventsStarted', {
63
+ bubbles: true,
64
+ cancelable: false,
65
+ detail: this,
66
+ });
67
+ target.dispatchEvent(ev);
68
+
69
+ if (this.vComponent) {
70
+ this.vComponent.actionsStarted(this);
71
+ }
39
72
 
40
- pseries(fnlist)
41
- .then(function (results) {
42
- var result = results.pop();
43
- var contentType = result.contentType;
44
- var responseURL = result.responseURL;
45
73
 
46
- if (event.target.dialog) {
47
- event.target.dialog.close();
48
- }
49
- if (contentType && contentType.indexOf("text/html") !== -1 && typeof responseURL !== 'undefined') {
50
- window.location = responseURL;
51
- }
74
+ new VErrors(this.root).clearErrors();
75
+
76
+ pseries(fnlist).then((results) => {
77
+ const result = results.pop();
78
+ const contentType = result.contentType;
79
+ const responseURL = result.responseURL;
80
+
81
+ if (contentType && contentType.indexOf('text/html') !== -1 &&
82
+ typeof responseURL !== 'undefined') {
83
+ window.location = responseURL;
84
+ }
85
+
86
+ const ev = new CustomEvent('V:eventsSucceeded', {
87
+ bubbles: true,
88
+ cancelable: false,
89
+ detail: this,
90
+ });
91
+ target.dispatchEvent(ev);
92
+
93
+ if (this.vComponent) {
94
+ this.vComponent.actionsSucceeded(this);
95
+ }
96
+ }).catch((results) => {
97
+ console.log('If you got here it may not be what you think:',
98
+ results);
99
+
100
+ let result = results;
101
+
102
+ if (typeof results.pop === 'function') {
103
+ result = results.pop();
104
+ }
105
+
106
+ if (!result.squelch) {
107
+ new VErrors(this.root, target).displayErrors(result);
108
+ }
52
109
 
53
- }).catch(function (results) {
54
- console.log("If you got here it may not be what you think:", results);
110
+ const ev = new CustomEvent('V:eventsHalted', {
111
+ bubbles: true,
112
+ cancelable: false,
113
+ detail: this,
114
+ });
115
+ target.dispatchEvent(ev);
55
116
 
56
- var result = results.pop();
57
- new VErrors(event).displayErrors(result);
117
+ if (this.vComponent) {
118
+ this.vComponent.actionsHalted(this);
119
+ }
120
+ }).finally(() => {
121
+ const ev = new CustomEvent('V:eventsFinished', {
122
+ bubbles: true,
123
+ cancelable: false,
124
+ detail: this,
125
+ });
126
+ target.dispatchEvent(ev);
127
+
128
+ if (this.vComponent) {
129
+ this.vComponent.actionsFinished(this);
130
+ }
58
131
  });
59
132
  }
60
133
 
61
- static action_class(action, event) {
62
- var action_type = action[0];
63
- var url = action[1];
64
- var options = action[2];
65
- var params = action[3];
134
+ static action_class(action, event, root) {
135
+ const action_type = action[0];
136
+ const url = action[1];
137
+ const options = action[2];
138
+ const params = action[3];
66
139
 
67
140
  switch (action_type) {
68
141
  case 'loads':
69
- return new VLoads(options, url, params, event);
142
+ return new VLoads(options, url, params, event, root);
70
143
  case 'replaces':
71
- return new VReplaces(options, url, params, event);
144
+ return new VReplaces(options, url, params, event, root);
72
145
  case 'post':
73
- return new VPosts(options, url, params, 'POST', event);
146
+ return new VPosts(options, url, params, 'POST', event, root);
74
147
  case 'update':
75
- return new VPosts(options, url, params, 'PUT', event);
148
+ return new VPosts(options, url, params, 'PUT', event, root);
76
149
  case 'delete':
77
- return new VPosts(options, url, params, 'DELETE', event);
150
+ return new VPosts(options, url, params, 'DELETE', event, root);
78
151
  case 'dialog':
79
- return new VDialog(options, params, event);
152
+ return new VDialog(options, params, event, root);
80
153
  case 'toggle_visibility':
81
- return new VToggleVisibility(options, params, event);
154
+ return new VToggleVisibility(options, params, event, root);
155
+ case 'toggle_disabled':
156
+ return new VToggleDisabled(options, params, event, root);
157
+ case 'prompt_if_dirty':
158
+ return new VPromptIfDirty(options, params, event, root);
82
159
  case 'remove':
83
- return new VRemoves(options, params, event);
160
+ return new VRemoves(options, params, event, root);
84
161
  case 'snackbar':
85
- return new VSnackbarEvent(options, params, event);
86
- case 'navigates':
87
- return new VNavigates(options, params, event);
162
+ return new VSnackbarEvent(options, params, event, root);
163
+ case 'autocomplete':
164
+ return new VAutoComplete(options, url, params, event, root);
88
165
  case 'clear':
89
- return new VClears(options, params, event);
166
+ return new VClears(options, params, event, root);
167
+ case 'close_dialog':
168
+ return new VCloseDialog(options, params, event, root);
169
+ case 'post_message':
170
+ return new VPostMessage(options, params, event, root);
90
171
  case 'stepper':
91
- return new VStepperEvent(options, params, event);
172
+ return new VStepperEvent(options, params, event, root);
173
+ case 'navigates':
174
+ return new VNavigates(options, params, event, root);
92
175
  default:
93
- throw action_type + ' is not supported.';
176
+ return new VPluginEventAction(action_type, options, params,
177
+ event, root);
94
178
  }
95
179
  }
96
-
97
180
  }
98
181
 
99
182
  // This is used to get a proper binding of the actionData
100
183
  // https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
101
- function createEventHandler(actionsData) {
102
- return function (event) {
103
- event.stopPropagation();
104
- new VEvents(actionsData, event).call();
184
+ function createEventHandler(actionsData, root, vComponent) {
185
+ return function(event) {
186
+ event.stopPropagation();
187
+ new VEvents(actionsData, event, root, vComponent).call();
105
188
  };
106
189
  }
107
190
 
108
- export function initEvents() {
109
- console.log('\tEvents');
191
+ function getEventElements(root) {
192
+ const elements = Array.from(root.querySelectorAll(EVENTS_SELECTOR));
110
193
 
111
- var events = document.querySelectorAll('[data-events]');
112
- for (var i = 0; i < events.length; i++) {
113
- var eventElem = events[i];
194
+ // Include `root` if it has events:
195
+ if (typeof root.matches === 'function' && root.matches(EVENTS_SELECTOR)) {
196
+ elements.unshift(root);
197
+ }
198
+
199
+ return elements;
200
+ }
201
+
202
+ export function initEvents(e) {
203
+ console.debug('\tEvents');
204
+
205
+ for (const eventElem of getEventElements(e)) {
114
206
  var eventsData = JSON.parse(eventElem.dataset.events);
115
207
  for (var j = 0; j < eventsData.length; j++) {
116
208
  var eventData = eventsData[j];
117
209
  var eventName = eventData[0];
118
210
  var eventOptions = eventData[2];
211
+ eventOptions.passive = true;
119
212
  var actionsData = eventData[1];
120
- var eventHandler = createEventHandler(actionsData);
121
- // allow overide of event handler by component
122
- if (eventElem.vComponent && eventElem.vComponent.createEventHandler) {
123
- eventHandler = eventElem.vComponent.createEventHandler(actionsData);
213
+ const vComponent = eventElem.vComponent;
214
+ var eventHandler = createEventHandler(actionsData, getRoot(e),
215
+ vComponent);
216
+ // allow override of event handler by component
217
+ if (vComponent && vComponent.createEventHandler) {
218
+ eventHandler = vComponent.createEventHandler(
219
+ actionsData, getRoot(e), vComponent);
124
220
  }
125
221
  // Delegate to the component if possible
126
- if (eventElem.vComponent && eventElem.vComponent.initEventListener) {
127
- eventElem.vComponent.initEventListener(eventName, eventHandler);
128
- } else {
222
+ if (vComponent &&
223
+ vComponent.initEventListener) {
224
+ vComponent.initEventListener(eventName, eventHandler,
225
+ eventOptions);
226
+ }
227
+ else {
129
228
  if (typeof eventElem.eventsHandler === 'undefined') {
130
229
  eventElem.eventsHandler = {};
131
230
  }
132
- if (!eventElem.eventsHandler[eventName]) {
133
- // Delegate to the component if possible
134
- eventElem.eventsHandler[eventName] = eventHandler;
135
- eventElem.addEventListener(eventName, eventHandler, eventOptions);
231
+ if (typeof eventElem.eventsHandler[eventName] === 'undefined') {
232
+ eventElem.eventsHandler[eventName] = [];
136
233
  }
234
+ eventElem.eventsHandler[eventName].push(eventHandler);
235
+ eventElem.addEventListener(eventName, eventHandler,
236
+ eventOptions);
237
+ }
238
+
239
+ if (vComponent) {
240
+ vComponent.afterInit();
137
241
  }
138
242
  }
139
243
  }
140
- fireAfterLoad();
244
+ fireAfterLoad(e);
141
245
  }
142
246
 
143
- function fireAfterLoad() {
144
- var events = document.querySelectorAll('[data-events]');
145
- for (var i = 0; i < events.length; i++) {
146
- var eventElem = events[i];
247
+ export function removeEvents(elem) {
248
+ console.debug('\tuninitEvents');
249
+
250
+ for (const eventElem of getEventElements(elem)) {
251
+ let eventsData = JSON.parse(eventElem.dataset.events);
252
+ for (var j = 0; j < eventsData.length; j++) {
253
+ let eventData = eventsData[j];
254
+ let eventName = eventData[0];
255
+ let eventOptions = eventData[2];
256
+ eventOptions.passive = true;
257
+ for (const handler of eventElem.eventsHandler[eventName]) {
258
+ eventElem.removeEventListener(eventName, handler, eventOptions);
259
+ }
260
+ }
261
+ }
262
+ }
263
+
264
+ function fireAfterLoad(e) {
265
+ for (const eventElem of getEventElements(e)) {
147
266
  var eventsData = JSON.parse(eventElem.dataset.events);
148
267
  for (var j = 0; j < eventsData.length; j++) {
149
268
  var eventData = eventsData[j];
150
269
  var eventName = eventData[0];
151
270
  if (eventName === 'after_init') {
152
- var event = new Event('after_init');
271
+ var event = new Event('after_init', { composed: true });
153
272
  // Dispatch the event.
154
273
  eventElem.dispatchEvent(event);
155
274
  }
156
275
  }
157
276
  }
158
277
  }
159
-
160
-