trestle 0.9.9 → 0.10.0.pre

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 (328) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +31 -3
  3. data/.gitignore +3 -0
  4. data/Gemfile +5 -1
  5. data/README.md +2 -1
  6. data/app/assets/bundle/trestle/admin.css +23 -0
  7. data/app/assets/bundle/trestle/admin.js +83 -0
  8. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  10. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  11. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  12. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  13. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  14. data/app/assets/bundle/trestle/locale/cs.js +110 -0
  15. data/app/assets/bundle/trestle/locale/de.js +116 -0
  16. data/app/assets/bundle/trestle/locale/en.js +329 -0
  17. data/app/assets/bundle/trestle/locale/es-MX.js +109 -0
  18. data/app/assets/bundle/trestle/locale/es.js +109 -0
  19. data/app/assets/bundle/trestle/locale/fr.js +111 -0
  20. data/app/assets/bundle/trestle/locale/ko.js +111 -0
  21. data/app/assets/bundle/trestle/locale/lv.js +109 -0
  22. data/app/assets/bundle/trestle/locale/nl.js +96 -0
  23. data/app/assets/bundle/trestle/locale/pl.js +99 -0
  24. data/app/assets/bundle/trestle/locale/pt-BR.js +98 -0
  25. data/app/assets/bundle/trestle/locale/vi.js +116 -0
  26. data/app/assets/bundle/trestle/locale/zh-CN.js +109 -0
  27. data/app/assets/bundle/trestle/photoswipe-7aa1aec9c3c1fd65c382.digested.js +6 -0
  28. data/app/assets/sprockets/trestle/custom.css +1 -0
  29. data/app/assets/sprockets/trestle/icons/font-awesome.css.erb +32 -0
  30. data/app/assets/sprockets/trestle/manifest.js +4 -0
  31. data/app/assets/stylesheets/trestle/custom.css +6 -1
  32. data/app/controllers/concerns/trestle/controller/helpers.rb +2 -0
  33. data/app/controllers/concerns/trestle/controller/location.rb +1 -6
  34. data/app/controllers/concerns/trestle/controller/modal.rb +23 -0
  35. data/app/controllers/concerns/trestle/controller/turbo.rb +21 -0
  36. data/app/controllers/concerns/trestle/resource/controller/actions.rb +39 -28
  37. data/app/controllers/concerns/trestle/resource/controller/redirection.rb +5 -5
  38. data/app/controllers/trestle/application_controller.rb +2 -1
  39. data/app/helpers/trestle/flash_helper.rb +10 -0
  40. data/app/helpers/trestle/form_helper.rb +3 -2
  41. data/app/helpers/trestle/format_helper.rb +2 -1
  42. data/app/helpers/trestle/i18n_helper.rb +46 -7
  43. data/app/helpers/trestle/modal_helper.rb +34 -0
  44. data/app/helpers/trestle/tab_helper.rb +1 -1
  45. data/app/helpers/trestle/turbo_frame_helper.rb +34 -0
  46. data/app/helpers/trestle/url_helper.rb +7 -4
  47. data/app/views/layouts/trestle/admin.html.erb +16 -18
  48. data/app/views/layouts/trestle/admin.turbo_stream.erb +11 -0
  49. data/app/views/layouts/trestle/modal.html.erb +5 -0
  50. data/app/views/trestle/_i18n.html.erb +12 -0
  51. data/app/views/trestle/_theme.html.erb +15 -0
  52. data/app/views/trestle/application/_header.html.erb +1 -1
  53. data/app/views/trestle/application/_layout.html.erb +6 -3
  54. data/app/views/trestle/application/_modal.html.erb +36 -0
  55. data/app/views/trestle/application/_tabs.html.erb +4 -4
  56. data/app/views/trestle/flash/_alert.html.erb +1 -1
  57. data/app/views/trestle/flash/_debug.html.erb +1 -1
  58. data/app/views/trestle/resource/_form.html.erb +5 -0
  59. data/app/views/trestle/resource/create.turbo_stream.erb +5 -0
  60. data/app/views/trestle/resource/destroy.turbo_stream.erb +1 -0
  61. data/app/views/trestle/resource/edit.html.erb +4 -2
  62. data/app/views/trestle/resource/index.html.erb +12 -10
  63. data/app/views/trestle/resource/new.html.erb +4 -2
  64. data/app/views/trestle/resource/show.html.erb +4 -2
  65. data/app/views/trestle/resource/update.turbo_stream.erb +5 -0
  66. data/app/views/trestle/shared/_sidebar.html.erb +9 -9
  67. data/frontend/css/components/_alerts.scss +19 -17
  68. data/frontend/css/components/_background.scss +7 -35
  69. data/frontend/css/components/_badges.scss +31 -0
  70. data/frontend/css/components/_breadcrumbs.scss +4 -4
  71. data/frontend/css/components/_buttons.scss +5 -4
  72. data/frontend/css/components/_datepicker.scss +12 -8
  73. data/frontend/css/components/_dropdown.scss +23 -3
  74. data/frontend/css/components/{_fields.scss → _forms.scss} +16 -3
  75. data/frontend/css/components/_media-grid.scss +52 -44
  76. data/frontend/css/components/_modal.scss +33 -4
  77. data/frontend/css/components/_pagination.scss +1 -1
  78. data/frontend/css/components/_photoswipe.scss +8 -0
  79. data/frontend/css/components/_popover.scss +1 -0
  80. data/frontend/css/components/_scopes.scss +1 -1
  81. data/frontend/css/components/_select.scss +161 -31
  82. data/frontend/css/components/_table.scss +60 -65
  83. data/frontend/css/components/_tabs.scss +10 -3
  84. data/frontend/css/components/_tags.scss +71 -16
  85. data/frontend/css/components/_toolbars.scss +16 -11
  86. data/frontend/css/components/_turbo.scss +3 -0
  87. data/frontend/css/core/_bootstrap.scss +46 -0
  88. data/frontend/css/core/_dependencies.scss +4 -3
  89. data/frontend/css/core/_functions.scss +39 -0
  90. data/frontend/css/core/_mixins.scss +2 -36
  91. data/frontend/css/core/_theme.scss +258 -0
  92. data/frontend/css/core/_typography.scss +10 -1
  93. data/frontend/css/icons/_fontawesome.scss +3 -15
  94. data/frontend/css/index.scss +12 -6
  95. data/frontend/css/layout/_base.scss +3 -3
  96. data/frontend/css/layout/_content.scss +10 -6
  97. data/frontend/css/layout/_footer.scss +1 -1
  98. data/frontend/css/layout/_header.scss +5 -3
  99. data/frontend/css/layout/_navigation.scss +2 -2
  100. data/frontend/css/layout/_sidebar.scss +19 -9
  101. data/frontend/css/support/_sprockets.scss +2 -0
  102. data/frontend/css/support/_webpack.scss +2 -0
  103. data/frontend/css/variables/_bootstrap.scss +134 -40
  104. data/frontend/css/variables/_maps.scss +15 -0
  105. data/frontend/css/variables/_trestle.scss +55 -26
  106. data/frontend/js/controllers/application_controller.js +17 -0
  107. data/frontend/js/controllers/checkbox_select_controller.js +43 -0
  108. data/frontend/js/controllers/confirm_controller.js +115 -0
  109. data/frontend/js/controllers/confirm_delete_controller.js +11 -0
  110. data/frontend/js/controllers/datepicker_controller.js +12 -0
  111. data/frontend/js/controllers/datetimepicker_controller.js +13 -0
  112. data/frontend/js/controllers/deprecated/init_controller.js +9 -0
  113. data/frontend/js/controllers/flatpickr_controller.js +50 -0
  114. data/frontend/js/controllers/follow_url_controller.js +36 -0
  115. data/frontend/js/controllers/form_error_controller.js +24 -0
  116. data/frontend/js/controllers/form_loading_controller.js +50 -0
  117. data/frontend/js/controllers/gallery_controller.js +10 -0
  118. data/frontend/js/controllers/index.js +19 -0
  119. data/frontend/js/controllers/keyboard_submit_controller.js +25 -0
  120. data/frontend/js/controllers/lightbox_controller.js +160 -0
  121. data/frontend/js/controllers/mobile_sidebar_controller.js +30 -0
  122. data/frontend/js/controllers/modal_controller.js +36 -0
  123. data/frontend/js/controllers/modal_frame_controller.js +11 -0
  124. data/frontend/js/controllers/modal_trigger_controller.js +74 -0
  125. data/frontend/js/{components/navigation.js → controllers/navigation_controller.js} +14 -10
  126. data/frontend/js/controllers/navigation_tooltip_controller.js +32 -0
  127. data/frontend/js/controllers/popover_controller.js +87 -0
  128. data/frontend/js/controllers/reloadable_controller.js +34 -0
  129. data/frontend/js/controllers/select_controller.js +49 -0
  130. data/frontend/js/controllers/sidebar_controller.js +33 -0
  131. data/frontend/js/controllers/tab_errors_controller.js +45 -0
  132. data/frontend/js/controllers/tabs_controller.js +45 -0
  133. data/frontend/js/controllers/timepicker_controller.js +14 -0
  134. data/frontend/js/controllers/toggle_attr_controller.js +27 -0
  135. data/frontend/js/controllers/toggle_class_controller.js +27 -0
  136. data/frontend/js/controllers/tooltip_controller.js +13 -0
  137. data/frontend/js/controllers/wrapper_controller.js +43 -0
  138. data/frontend/js/core/backdrop.js +100 -0
  139. data/frontend/js/core/error_modal.js +65 -0
  140. data/frontend/js/core/fetch.js +32 -0
  141. data/frontend/js/core/i18n.js +24 -10
  142. data/frontend/js/core/modal.js +52 -0
  143. data/frontend/js/core/stream_actions.js +56 -0
  144. data/frontend/js/core/turbo_errors.js +9 -0
  145. data/frontend/js/{core → deprecated}/events.js +1 -8
  146. data/frontend/js/deprecated/tooltip.js +8 -0
  147. data/frontend/js/index.js +28 -40
  148. data/frontend/js/mixins/index.js +5 -0
  149. data/frontend/js/mixins/photoswipe.js +10 -0
  150. data/frontend/js/util/bootstrap.js +93 -0
  151. data/i18n/config.yml +14 -0
  152. data/i18n/environment.rb +8 -0
  153. data/i18n/export +3 -0
  154. data/i18n/template.erb +1 -0
  155. data/lib/generators/trestle/install/install_generator.rb +3 -8
  156. data/lib/generators/trestle/install/templates/trestle.rb.erb +5 -5
  157. data/lib/trestle/color.rb +113 -0
  158. data/lib/trestle/configuration.rb +16 -8
  159. data/lib/trestle/engine.rb +23 -17
  160. data/lib/trestle/form/fields/check_box_helpers.rb +7 -18
  161. data/lib/trestle/form/fields/collection_select.rb +1 -1
  162. data/lib/trestle/form/fields/color_field.rb +4 -0
  163. data/lib/trestle/form/fields/date_field.rb +4 -0
  164. data/lib/trestle/form/fields/date_picker.rb +10 -4
  165. data/lib/trestle/form/fields/date_select.rb +1 -1
  166. data/lib/trestle/form/fields/datetime_field.rb +4 -0
  167. data/lib/trestle/form/fields/datetime_select.rb +1 -1
  168. data/lib/trestle/form/fields/file_field.rb +3 -28
  169. data/lib/trestle/form/fields/form_control.rb +2 -2
  170. data/lib/trestle/form/fields/form_group.rb +1 -1
  171. data/lib/trestle/form/fields/grouped_collection_select.rb +1 -1
  172. data/lib/trestle/form/fields/radio_button_helpers.rb +5 -17
  173. data/lib/trestle/form/fields/range_field.rb +1 -5
  174. data/lib/trestle/form/fields/select.rb +17 -1
  175. data/lib/trestle/form/fields/time_field.rb +4 -0
  176. data/lib/trestle/form/fields/time_select.rb +1 -1
  177. data/lib/trestle/form/fields/time_zone_select.rb +1 -1
  178. data/lib/trestle/form/renderer.rb +3 -0
  179. data/lib/trestle/form.rb +16 -1
  180. data/lib/trestle/resource/toolbar.rb +2 -2
  181. data/lib/trestle/table/actions_column.rb +2 -2
  182. data/lib/trestle/table/row.rb +2 -1
  183. data/lib/trestle/table/select_column.rb +3 -6
  184. data/lib/trestle/table.rb +6 -1
  185. data/lib/trestle/toolbar/item.rb +1 -1
  186. data/lib/trestle/toolbar/menu.rb +3 -6
  187. data/lib/trestle/version.rb +1 -1
  188. data/lib/trestle.rb +2 -23
  189. data/package.json +31 -27
  190. data/trestle.gemspec +2 -3
  191. data/webpack.config.js +10 -10
  192. data/yarn.lock +1456 -1194
  193. metadata +166 -164
  194. data/app/assets/bundle/trestle/bundle.css +0 -12
  195. data/app/assets/bundle/trestle/bundle.js +0 -89
  196. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  197. data/app/assets/bundle/trestle/fa-brands-400.svg +0 -3717
  198. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  199. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  200. data/app/assets/bundle/trestle/fa-regular-400.svg +0 -801
  201. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  202. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  203. data/app/assets/bundle/trestle/fa-solid-900.svg +0 -5034
  204. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  205. data/app/assets/javascripts/trestle/admin.js +0 -3
  206. data/app/assets/javascripts/trestle/i18n.js.erb +0 -8
  207. data/app/assets/stylesheets/trestle/admin.css +0 -2
  208. data/app/assets/stylesheets/trestle/icons/_font-awesome.css.erb +0 -40
  209. data/app/controllers/concerns/trestle/controller/dialog.rb +0 -16
  210. data/app/views/trestle/application/_dialog.html.erb +0 -34
  211. data/frontend/css/components/_color-vars.scss +0 -10
  212. data/frontend/css/components/_custom-forms.scss +0 -35
  213. data/frontend/css/components/_magnific-popup.scss +0 -36
  214. data/frontend/css/components/_turbolinks.scss +0 -3
  215. data/frontend/js/components/confirmation.js +0 -32
  216. data/frontend/js/components/datepicker.js +0 -69
  217. data/frontend/js/components/dialog.js +0 -149
  218. data/frontend/js/components/file.js +0 -7
  219. data/frontend/js/components/form.js +0 -100
  220. data/frontend/js/components/gallery.js +0 -33
  221. data/frontend/js/components/pagination.js +0 -51
  222. data/frontend/js/components/select.js +0 -18
  223. data/frontend/js/components/sidebar.js +0 -75
  224. data/frontend/js/components/table.js +0 -61
  225. data/frontend/js/components/tabs.js +0 -59
  226. data/frontend/js/components/tooltips.js +0 -25
  227. data/frontend/js/core/contexts.js +0 -17
  228. data/frontend/js/core/turbolinks.js +0 -3
  229. data/frontend/js/core/visit.js +0 -16
  230. data/frontend/theme/trestle/_theme.scss +0 -4
  231. data/frontend/theme/trestle/_variables.scss +0 -4
  232. data/frontend/theme/trestle/theme/_defaults.scss +0 -152
  233. data/frontend/theme/trestle/theme/_functions.scss +0 -44
  234. data/frontend/theme/trestle/theme/_variables.scss +0 -15
  235. data/frontend/theme/trestle/theme/bootstrap/_alert.scss +0 -19
  236. data/frontend/theme/trestle/theme/bootstrap/_badge.scss +0 -25
  237. data/frontend/theme/trestle/theme/bootstrap/_buttons.scss +0 -93
  238. data/frontend/theme/trestle/theme/bootstrap/_color-vars.scss +0 -11
  239. data/frontend/theme/trestle/theme/bootstrap/_custom-forms.scss +0 -93
  240. data/frontend/theme/trestle/theme/bootstrap/_dropdown.scss +0 -6
  241. data/frontend/theme/trestle/theme/bootstrap/_forms.scss +0 -6
  242. data/frontend/theme/trestle/theme/bootstrap/_links.scss +0 -7
  243. data/frontend/theme/trestle/theme/bootstrap/_list-group.scss +0 -31
  244. data/frontend/theme/trestle/theme/bootstrap/_nav.scss +0 -6
  245. data/frontend/theme/trestle/theme/bootstrap/_pagination.scss +0 -18
  246. data/frontend/theme/trestle/theme/bootstrap/_progress.scss +0 -3
  247. data/frontend/theme/trestle/theme/bootstrap/_tables.scss +0 -41
  248. data/frontend/theme/trestle/theme/bootstrap/_utilities.scss +0 -3
  249. data/frontend/theme/trestle/theme/bootstrap/utilities/_background.scss +0 -17
  250. data/frontend/theme/trestle/theme/bootstrap/utilities/_borders.scss +0 -5
  251. data/frontend/theme/trestle/theme/bootstrap/utilities/_text.scss +0 -18
  252. data/frontend/theme/trestle/theme/trestle/_background.scss +0 -61
  253. data/frontend/theme/trestle/theme/trestle/_datepicker.scss +0 -58
  254. data/frontend/theme/trestle/theme/trestle/_headers.scss +0 -4
  255. data/frontend/theme/trestle/theme/trestle/_navbar.scss +0 -15
  256. data/frontend/theme/trestle/theme/trestle/_navigation.scss +0 -5
  257. data/frontend/theme/trestle/theme/trestle/_select2.scss +0 -22
  258. data/frontend/theme/trestle/theme/trestle/_tags.scss +0 -12
  259. data/frontend/theme/trestle/theme/trestle/_turbolinks.scss +0 -3
  260. data/frontend/theme/trestle/theme.scss +0 -29
  261. data/lib/generators/trestle/install/templates/_theme.scss +0 -13
  262. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ar-dz.js +0 -0
  263. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ar.js +0 -0
  264. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/at.js +0 -0
  265. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/az.js +0 -0
  266. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/be.js +0 -0
  267. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/bg.js +0 -0
  268. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/bn.js +0 -0
  269. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/bs.js +0 -0
  270. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/cat.js +0 -0
  271. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ckb.js +0 -0
  272. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/cs.js +0 -0
  273. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/cy.js +0 -0
  274. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/da.js +0 -0
  275. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/de.js +0 -0
  276. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/default.js +0 -0
  277. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/eo.js +0 -0
  278. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/es.js +0 -0
  279. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/et.js +0 -0
  280. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fa.js +0 -0
  281. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fi.js +0 -0
  282. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fo.js +0 -0
  283. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fr.js +0 -0
  284. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ga.js +0 -0
  285. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/gr.js +0 -0
  286. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/he.js +0 -0
  287. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hi.js +0 -0
  288. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hr.js +0 -0
  289. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hu.js +0 -0
  290. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hy.js +0 -0
  291. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/id.js +0 -0
  292. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/is.js +0 -0
  293. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/it.js +0 -0
  294. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ja.js +0 -0
  295. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ka.js +0 -0
  296. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/km.js +0 -0
  297. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ko.js +0 -0
  298. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/kz.js +0 -0
  299. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/lt.js +0 -0
  300. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/lv.js +0 -0
  301. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/mk.js +0 -0
  302. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/mn.js +0 -0
  303. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ms.js +0 -0
  304. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/my.js +0 -0
  305. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/nl.js +0 -0
  306. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/nn.js +0 -0
  307. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/no.js +0 -0
  308. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/pa.js +0 -0
  309. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/pl.js +0 -0
  310. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/pt.js +0 -0
  311. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ro.js +0 -0
  312. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ru.js +0 -0
  313. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/si.js +0 -0
  314. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sk.js +0 -0
  315. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sl.js +0 -0
  316. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sq.js +0 -0
  317. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sr-cyr.js +0 -0
  318. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sr.js +0 -0
  319. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sv.js +0 -0
  320. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/th.js +0 -0
  321. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/tr.js +0 -0
  322. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/uk.js +0 -0
  323. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/uz.js +0 -0
  324. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/uz_latn.js +0 -0
  325. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/vn.js +0 -0
  326. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/zh-tw.js +0 -0
  327. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/zh.js +0 -0
  328. /data/app/assets/{stylesheets → sprockets}/trestle/_custom.css +0 -0
@@ -0,0 +1,50 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import flatpickr from 'flatpickr'
4
+
5
+ export default class extends ApplicationController {
6
+ connect () {
7
+ this.flatpickr = flatpickr(this.element, {
8
+ ...this.options,
9
+ onReady: this.setup.bind(this)
10
+ })
11
+ }
12
+
13
+ disconnect () {
14
+ this.flatpickr.destroy()
15
+ }
16
+
17
+ clear () {
18
+ const isDisabled = this.element.disabled || this.element.classList.contains('disabled')
19
+
20
+ if (!isDisabled) {
21
+ this.flatpickr.clear()
22
+ }
23
+ }
24
+
25
+ setup (selectedDates, dateStr, instance) {
26
+ this._createClearButton(instance)
27
+ }
28
+
29
+ get options () {
30
+ return {
31
+ allowInput: true,
32
+ altInput: true
33
+ }
34
+ }
35
+
36
+ _createClearButton (instance) {
37
+ if (this.element.dataset.allowClear) {
38
+ const clearButton = document.createElement('button')
39
+
40
+ clearButton.classList.add('clear-datepicker')
41
+
42
+ clearButton.addEventListener('click', (e) => {
43
+ e.preventDefault()
44
+ this.clear()
45
+ })
46
+
47
+ instance.altInput.parentNode.insertBefore(clearButton, instance.altInput)
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,36 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import { visit } from '@hotwired/turbo'
4
+ import Modal from '../core/modal'
5
+
6
+ export default class extends ApplicationController {
7
+ follow (e) {
8
+ if (this.ignoreElement(e.target) || !this.url) {
9
+ return
10
+ }
11
+
12
+ if (this.isModal) {
13
+ Modal.load(this.url)
14
+ } else if (e.metaKey || e.ctrlKey) {
15
+ window.open(this.url, '_blank')
16
+ } else {
17
+ visit(this.url)
18
+ }
19
+ }
20
+
21
+ get url () {
22
+ if (this.element.dataset.url === 'auto') {
23
+ return this.element.querySelector('td:not(.table-actions) a').href
24
+ } else {
25
+ return this.element.dataset.url
26
+ }
27
+ }
28
+
29
+ get isModal () {
30
+ return this.element.dataset.modal
31
+ }
32
+
33
+ ignoreElement (node) {
34
+ return node.matches('a, input, button, .select-row')
35
+ }
36
+ }
@@ -0,0 +1,24 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import ErrorModal from '../core/error_modal'
4
+
5
+ export default class extends ApplicationController {
6
+ connect () {
7
+ this.element.addEventListener('turbo:before-fetch-response', this.handleFormResponse)
8
+ }
9
+
10
+ disconnect () {
11
+ this.element.removeEventListener('turbo:before-fetch-response', this.handleFormResponse)
12
+ }
13
+
14
+ handleFormResponse (e) {
15
+ const response = e.detail.fetchResponse.response
16
+
17
+ if (response.status >= 500) {
18
+ e.preventDefault()
19
+
20
+ const title = `${response.status} (${response.statusText})`
21
+ response.text().then(content => ErrorModal.show({ title, content }))
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,50 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ const SUBMIT_BUTTON_SELECTOR = 'input[type="submit"], button[type="submit"]'
4
+
5
+ export default class extends ApplicationController {
6
+ initialize () {
7
+ this.boundSubmit = this.submit.bind(this)
8
+ this.boundReset = this.reset.bind(this)
9
+ }
10
+
11
+ connect () {
12
+ this.element.addEventListener('submit', this.boundSubmit)
13
+ this.element.addEventListener('turbo:before-fetch-response', this.boundReset)
14
+ }
15
+
16
+ disconnect () {
17
+ this.element.removeEventListener('submit', this.boundSubmit)
18
+ this.element.removeEventListener('turbo:before-fetch-response', this.boundReset)
19
+ }
20
+
21
+ submit (e) {
22
+ this.disableButtons()
23
+ this.setLoading(e.submitter || this.element.querySelector(SUBMIT_BUTTON_SELECTOR))
24
+ }
25
+
26
+ reset (e) {
27
+ this.restoreButtons()
28
+ }
29
+
30
+ setLoading (button) {
31
+ button.classList.add('loading')
32
+ }
33
+
34
+ disableButtons (e) {
35
+ this.submitButtons.forEach(button => {
36
+ button.disabled = true
37
+ })
38
+ }
39
+
40
+ restoreButtons () {
41
+ this.submitButtons.forEach(button => {
42
+ button.classList.remove('loading')
43
+ button.disabled = false
44
+ })
45
+ }
46
+
47
+ get submitButtons () {
48
+ return this.element.querySelectorAll(SUBMIT_BUTTON_SELECTOR)
49
+ }
50
+ }
@@ -0,0 +1,10 @@
1
+ import LightboxController from './lightbox_controller'
2
+
3
+ export default class extends LightboxController {
4
+ get options () {
5
+ return {
6
+ ...super.options,
7
+ children: this.imageTargets
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,19 @@
1
+ import { Application } from '@hotwired/stimulus'
2
+ import { definitionsFromContext } from '@hotwired/stimulus-webpack-helpers'
3
+
4
+ import ApplicationController from './application_controller'
5
+
6
+ window.Stimulus = Application.start()
7
+
8
+ const context = require.context('.', true, /\.js$/)
9
+ const controllerDefinitions = definitionsFromContext(context)
10
+ Stimulus.load(controllerDefinitions)
11
+
12
+ const Controllers = controllerDefinitions.reduce((result, definition) => {
13
+ return { ...result, [definition.identifier]: definition.controllerConstructor }
14
+ }, {})
15
+
16
+ export {
17
+ ApplicationController,
18
+ Controllers
19
+ }
@@ -0,0 +1,25 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ initialize () {
5
+ this.boundHandleKeyDown = this.handleKeyDown.bind(this)
6
+ }
7
+
8
+ connect () {
9
+ this.element.addEventListener('keydown', this.boundHandleKeyDown)
10
+ }
11
+
12
+ disconnect () {
13
+ this.element.removeEventListener('keydown', this.boundHandleKeyDown)
14
+ }
15
+
16
+ handleKeyDown (e) {
17
+ if (e.key === 'Enter' && this.preventEnterKey(e.target)) {
18
+ e.preventDefault()
19
+ }
20
+ }
21
+
22
+ preventEnterKey (el) {
23
+ return el.matches('input:not([type="submit"])')
24
+ }
25
+ }
@@ -0,0 +1,160 @@
1
+ import ApplicationController from './application_controller'
2
+ import usePhotoSwipe from '../mixins/photoswipe'
3
+
4
+ import PhotoSwipeLightbox from 'photoswipe/lightbox'
5
+ import getVideoId from 'get-video-id'
6
+
7
+ const waitForImageDimensions = (element) => {
8
+ return new Promise((resolve, reject) => {
9
+ const timeout = setInterval(() => {
10
+ if (element.naturalWidth && element.naturalHeight) {
11
+ clearInterval(timeout)
12
+ resolve(element)
13
+ }
14
+ }, 0)
15
+
16
+ element.addEventListener('error', () => {
17
+ clearInterval(timeout)
18
+ reject(element)
19
+ })
20
+ })
21
+ }
22
+
23
+ const VideoIframeUrl = {
24
+ youtube: (id) => `https://www.youtube.com/embed/${id}`,
25
+ vimeo: (id) => `https://player.vimeo.com/video/${id}`
26
+ }
27
+
28
+ export default class extends ApplicationController {
29
+ static targets = ["image"]
30
+
31
+ static values = {
32
+ animationType: { type: String, default: 'zoom' },
33
+ animationDuration: { type: Number, default: 150 },
34
+ padding: { type: Object, default: { top: 20, bottom: 20, left: 20, right: 20 } },
35
+
36
+ defaultVideoWidth: { type: Number, default: 800 },
37
+ defaultVideoHeight: { type: Number, default: 450 }
38
+ }
39
+
40
+ initialize () {
41
+ usePhotoSwipe(this)
42
+ }
43
+
44
+ connect () {
45
+ this.lightbox = new PhotoSwipeLightbox(this.options)
46
+ this.addFilters()
47
+ this.lightbox.init()
48
+ }
49
+
50
+ disconnect () {
51
+ this.lightbox.destroy()
52
+ }
53
+
54
+ addFilters () {
55
+ this.lightbox.on('contentLoadImage', this.contentLoadImageHandler.bind(this))
56
+ this.lightbox.on('contentActivate', this.contentActivateHandler.bind(this))
57
+ this.lightbox.on('contentDeactivate', this.contentDeactivateHandler.bind(this))
58
+
59
+ this.lightbox.addFilter('domItemData', this.domItemDimensionsFilter.bind(this))
60
+ this.lightbox.addFilter('domItemData', this.domItemVideoFilter.bind(this))
61
+ this.lightbox.addFilter('domItemData', this.domItemEmbedFilter.bind(this))
62
+ this.lightbox.addFilter('useContentPlaceholder', this.useContentPlaceholderFilter.bind(this))
63
+ }
64
+
65
+ // If the image width and height is not set, try to set it as soon
66
+ // as the image element has a naturalWidth/naturalHeight
67
+ contentLoadImageHandler ({ content }) {
68
+ if (content.width == 0 || content.height == 0) {
69
+ const imgEl = content.element
70
+ const linkEl = content.data.element
71
+
72
+ waitForImageDimensions(imgEl).then((imgEl) => {
73
+ linkEl.dataset.width = imgEl.naturalWidth
74
+ linkEl.dataset.height = imgEl.naturalHeight
75
+
76
+ content.instance.refreshSlideContent(content.index)
77
+ }).catch(() => {})
78
+ }
79
+ }
80
+
81
+ // Append HTML slide content when slide is reactivated
82
+ contentActivateHandler({ content }) {
83
+ if (content.type == 'html') {
84
+ content.append()
85
+ }
86
+ }
87
+
88
+ // Remove HTML slide content when slide is deactivated
89
+ contentDeactivateHandler ({ content }) {
90
+ if (content.type == 'html') {
91
+ content.remove()
92
+ }
93
+ }
94
+
95
+ // Sets the width and height from data-width and data-height attributes on the link element
96
+ domItemDimensionsFilter (itemData, element, linkEl) {
97
+ if (linkEl) {
98
+ const width = linkEl.dataset.width
99
+ const height = linkEl.dataset.height
100
+
101
+ if (width) itemData.w = Number(width)
102
+ if (height) itemData.h = Number(height)
103
+ }
104
+
105
+ return itemData
106
+ }
107
+
108
+ // Use <video> tag to play media when data-type="video"
109
+ domItemVideoFilter (itemData, element, linkEl) {
110
+ if (linkEl && linkEl.dataset.type == 'video') {
111
+ itemData.type = 'html'
112
+ itemData.html = `<video controls><source src="${itemData.src}"></video>`
113
+
114
+ this.setDefaultVideoDimensions(itemData)
115
+ }
116
+
117
+ return itemData
118
+ }
119
+
120
+ // Automatically detect video links and convert to an iframe
121
+ domItemEmbedFilter (itemData, element, linkEl) {
122
+ if (linkEl && !itemData.type) {
123
+ const video = getVideoId(itemData.src)
124
+
125
+ if (video.service && VideoIframeUrl[video.service]) {
126
+ const src = VideoIframeUrl[video.service](video.id)
127
+
128
+ itemData.type = 'html'
129
+ itemData.html = `<iframe src="${src}" allowfullscreen></iframe>`
130
+
131
+ this.setDefaultVideoDimensions(itemData)
132
+ }
133
+ }
134
+
135
+ return itemData
136
+ }
137
+
138
+ // Use the thumbnail as the content placeholder only when an explicit width/height is set
139
+ useContentPlaceholderFilter (useContentPlaceholder, content) {
140
+ return content.width && content.height && content.type !== 'html'
141
+ }
142
+
143
+ get options () {
144
+ return {
145
+ gallery: this.element,
146
+ pswpModule: this.loadPhotoSwipe,
147
+
148
+ padding: this.paddingValue,
149
+
150
+ showHideAnimationType: this.animationTypeValue,
151
+ showAnimationDuration: this.animationDurationValue,
152
+ hideAnimationDuration: this.animationDurationValue
153
+ }
154
+ }
155
+
156
+ setDefaultVideoDimensions(itemData) {
157
+ itemData.w ||= this.defaultVideoWidthValue
158
+ itemData.h ||= this.defaultVideoHeightValue
159
+ }
160
+ }
@@ -0,0 +1,30 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ show () {
5
+ this.wrapperController.animate()
6
+ document.body.classList.add('mobile-nav-expanded')
7
+ }
8
+
9
+ hide () {
10
+ this.wrapperController.animate()
11
+ document.body.classList.remove('mobile-nav-expanded')
12
+ }
13
+
14
+ toggle () {
15
+ this.wrapperController.animate()
16
+ document.body.classList.toggle('mobile-nav-expanded')
17
+ }
18
+
19
+ get isExpanded () {
20
+ return document.body.classList.contains('mobile-nav-expanded')
21
+ }
22
+
23
+ get wrapperElement () {
24
+ return document.getElementById('app-wrapper')
25
+ }
26
+
27
+ get wrapperController () {
28
+ return this.application.getControllerForElementAndIdentifier(this.wrapperElement, 'wrapper')
29
+ }
30
+ }
@@ -0,0 +1,36 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import Modal from '../core/modal'
4
+
5
+ export default class extends ApplicationController {
6
+ connect () {
7
+ this.modal = new Modal(this.element)
8
+ this.modal.show()
9
+
10
+ this.element.addEventListener('hidden.bs.modal', () => this.remove())
11
+ }
12
+
13
+ disconnect () {
14
+ this.modal.dispose()
15
+ }
16
+
17
+ remove () {
18
+ this.element.remove()
19
+ }
20
+
21
+ hide () {
22
+ this.modal.hide()
23
+ }
24
+
25
+ submit (detail) {
26
+ let event = this.dispatch('submit', { detail: detail })
27
+ if (event.defaultPrevented) return
28
+
29
+ if (this.modalTrigger) {
30
+ event = this.modalTrigger.dispatch('submit', { detail: detail })
31
+ if (event.defaultPrevented) return
32
+ }
33
+
34
+ this.hide()
35
+ }
36
+ }
@@ -0,0 +1,11 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ connect () {
5
+ this.element.addEventListener('turbo:before-fetch-request', this.addTrestleModalHeader)
6
+ }
7
+
8
+ addTrestleModalHeader (event) {
9
+ event.detail.fetchOptions.headers['X-Trestle-Modal'] = true
10
+ }
11
+ }
@@ -0,0 +1,74 @@
1
+ /* global FormData */
2
+
3
+ import ApplicationController from './application_controller'
4
+
5
+ import Modal from '../core/modal'
6
+
7
+ export default class extends ApplicationController {
8
+ initialize () {
9
+ this.boundLoad = this.load.bind(this)
10
+ }
11
+
12
+ connect () {
13
+ this.element.addEventListener('click', this.boundLoad)
14
+ }
15
+
16
+ disconnect () {
17
+ this.element.removeEventListener('click', this.boundLoad)
18
+ }
19
+
20
+ load (e) {
21
+ e.preventDefault()
22
+
23
+ this.dispatch('loading')
24
+
25
+ Modal.load(this.url, this.fetchParams)
26
+ .then((modal) => {
27
+ this.modal = modal
28
+
29
+ const modalController = this._getModalController(modal)
30
+ modalController.modalTrigger = this
31
+
32
+ this.dispatch('loaded', { detail: modal })
33
+ })
34
+ }
35
+
36
+ get url () {
37
+ if (this.isLink) {
38
+ return this.element.href
39
+ } else {
40
+ const form = this.element.closest('form')
41
+
42
+ if (form) {
43
+ return form.action
44
+ } else {
45
+ throw new Error('Unable to determine modal trigger URL')
46
+ }
47
+ }
48
+ }
49
+
50
+ get fetchParams () {
51
+ if (this.isLink) {
52
+ return {}
53
+ } else {
54
+ const form = this.element.closest('form')
55
+
56
+ if (form) {
57
+ return {
58
+ method: form.method,
59
+ body: new FormData(form)
60
+ }
61
+ } else {
62
+ return {}
63
+ }
64
+ }
65
+ }
66
+
67
+ get isLink () {
68
+ return this.element.nodeName === 'A'
69
+ }
70
+
71
+ _getModalController (modal) {
72
+ return this.application.getControllerForElementAndIdentifier(modal, 'modal')
73
+ }
74
+ }
@@ -1,3 +1,5 @@
1
+ import ApplicationController from './application_controller'
2
+
1
3
  import cookie from '../core/cookie'
2
4
 
3
5
  const PREFIX = 'trestle:navigation'
@@ -28,13 +30,17 @@ class NavigationCookieStore {
28
30
  }
29
31
  }
30
32
 
31
- class Navigation {
32
- constructor () {
33
+ export default class extends ApplicationController {
34
+ initialize () {
33
35
  this.store = new NavigationCookieStore()
34
36
  }
35
37
 
36
- toggle (list) {
37
- if (list.hasClass('collapsed')) {
38
+ toggle (e) {
39
+ e.preventDefault()
40
+
41
+ const list = e.target.closest('ul')
42
+
43
+ if (list.classList.contains('collapsed')) {
38
44
  this.expand(list)
39
45
  } else {
40
46
  this.collapse(list)
@@ -42,22 +48,20 @@ class Navigation {
42
48
  }
43
49
 
44
50
  expand (list) {
45
- list.removeClass('collapsed')
51
+ list.classList.remove('collapsed')
46
52
 
47
- const id = list.data('group')
53
+ const id = list.dataset.group
48
54
 
49
55
  this.store.addGroup(id, 'expanded')
50
56
  this.store.removeGroup(id, 'collapsed')
51
57
  }
52
58
 
53
59
  collapse (list) {
54
- list.addClass('collapsed')
60
+ list.classList.add('collapsed')
55
61
 
56
- const id = list.data('group')
62
+ const id = list.dataset.group
57
63
 
58
64
  this.store.addGroup(id, 'collapsed')
59
65
  this.store.removeGroup(id, 'expanded')
60
66
  }
61
67
  }
62
-
63
- export default new Navigation()
@@ -0,0 +1,32 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import { Tooltip } from 'bootstrap'
4
+
5
+ const TEMPLATE = `
6
+ <div class="tooltip nav-tooltip" role="tooltip">
7
+ <div class="tooltip-arrow"></div>
8
+ <div class="tooltip-inner"></div>
9
+ </div>
10
+ `
11
+
12
+ export default class extends ApplicationController {
13
+ static targets = ["label"]
14
+
15
+ connect () {
16
+ this.tooltip = new Tooltip(this.element, {
17
+ trigger: 'hover',
18
+ placement: 'right',
19
+ boundary: 'window',
20
+ template: TEMPLATE,
21
+ title: () => this.labelText
22
+ })
23
+ }
24
+
25
+ disconnect () {
26
+ this.tooltip.dispose()
27
+ }
28
+
29
+ get labelText () {
30
+ return this.labelTarget.innerText
31
+ }
32
+ }