pageflow 17.1.0 → 17.2.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 (302) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +319 -345
  3. data/README.md +3 -4
  4. data/admins/pageflow/accounts.rb +6 -6
  5. data/admins/pageflow/entry.rb +10 -8
  6. data/admins/pageflow/membership.rb +11 -11
  7. data/admins/pageflow/translations.rb +5 -5
  8. data/app/assets/images/pageflow/admin/icons/comment.svg +1 -0
  9. data/app/assets/javascripts/pageflow/dist/ui.js +1350 -630
  10. data/app/assets/javascripts/pageflow/editor/vendor.js +0 -1
  11. data/app/assets/javascripts/pageflow/ui.js +0 -1
  12. data/app/assets/stylesheets/pageflow/admin/entry_comments_indicator.scss +45 -0
  13. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +8 -1
  14. data/app/assets/stylesheets/pageflow/admin.scss +1 -0
  15. data/app/assets/stylesheets/pageflow/animations/spin.scss +9 -0
  16. data/app/assets/stylesheets/pageflow/animations.scss +1 -0
  17. data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +21 -5
  18. data/app/assets/stylesheets/pageflow/editor/base.scss +9 -1
  19. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +13 -1
  20. data/app/assets/stylesheets/pageflow/editor/edit_configuration_view.scss +5 -0
  21. data/app/assets/stylesheets/pageflow/editor/file_folders.scss +127 -0
  22. data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +0 -1
  23. data/app/assets/stylesheets/pageflow/editor/file_meta_data_overlay.scss +45 -0
  24. data/app/assets/stylesheets/pageflow/editor/file_preview.scss +138 -0
  25. data/app/assets/stylesheets/pageflow/editor/file_references.scss +68 -0
  26. data/app/assets/stylesheets/pageflow/editor/file_settings_dialog.scss +1 -1
  27. data/app/assets/stylesheets/pageflow/editor/file_stage_icons.scss +17 -0
  28. data/app/assets/stylesheets/pageflow/editor/file_stages.scss +25 -32
  29. data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +31 -48
  30. data/app/assets/stylesheets/pageflow/editor/file_type_pills.scss +73 -0
  31. data/app/assets/stylesheets/pageflow/editor/files.scss +230 -50
  32. data/app/assets/stylesheets/pageflow/editor/filtered_files.scss +142 -14
  33. data/app/assets/stylesheets/pageflow/editor/folder_breadcrumb.scss +40 -0
  34. data/app/assets/stylesheets/pageflow/editor/info_box.scss +12 -0
  35. data/app/assets/stylesheets/pageflow/editor/inputs/edit_defaults_button.scss +15 -0
  36. data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
  37. data/app/assets/stylesheets/pageflow/editor/list.scss +88 -38
  38. data/app/assets/stylesheets/pageflow/editor/manage_files.scss +9 -0
  39. data/app/assets/stylesheets/pageflow/editor/menu.scss +14 -0
  40. data/app/assets/stylesheets/pageflow/editor/move_to_folder_dialog.scss +83 -0
  41. data/app/assets/stylesheets/pageflow/mixins/pageflow.scss +9 -5
  42. data/app/assets/stylesheets/pageflow/ui/color_picker.scss +230 -0
  43. data/app/assets/stylesheets/pageflow/ui/forms.scss +34 -4
  44. data/app/assets/stylesheets/pageflow/ui/functions.scss +12 -2
  45. data/app/assets/stylesheets/pageflow/ui/input/color_input.scss +9 -16
  46. data/app/assets/stylesheets/pageflow/ui/input/text_area_input.scss +15 -0
  47. data/app/assets/stylesheets/pageflow/ui/overrides.scss +8 -0
  48. data/app/assets/stylesheets/pageflow/ui/properties.scss +29 -0
  49. data/app/assets/stylesheets/pageflow/ui/tabs_view.scss +8 -3
  50. data/app/assets/stylesheets/pageflow/ui.scss +4 -2
  51. data/app/controllers/pageflow/editor/entries_controller.rb +1 -0
  52. data/app/controllers/pageflow/editor/file_folders_controller.rb +80 -0
  53. data/app/controllers/pageflow/editor/file_import_controller.rb +1 -0
  54. data/app/controllers/pageflow/editor/files_controller.rb +15 -6
  55. data/app/controllers/pageflow/editor/oembeds_controller.rb +21 -0
  56. data/app/controllers/pageflow/entries_controller.rb +17 -13
  57. data/app/controllers/pageflow/review/comment_thread_reads_controller.rb +30 -0
  58. data/app/controllers/pageflow/review/comment_threads_controller.rb +60 -0
  59. data/app/controllers/pageflow/review/comments_controller.rb +53 -0
  60. data/app/controllers/pageflow/revisions_controller.rb +4 -1
  61. data/app/helpers/pageflow/admin/entries_helper.rb +40 -0
  62. data/app/helpers/pageflow/admin/widgets_helper.rb +2 -2
  63. data/app/helpers/pageflow/common_entry_seed_helper.rb +5 -3
  64. data/app/helpers/pageflow/editor/config_helper.rb +3 -1
  65. data/app/helpers/pageflow/entries_helper.rb +24 -42
  66. data/app/helpers/pageflow/entry_json_seed_helper.rb +4 -4
  67. data/app/helpers/pageflow/public_i18n_helper.rb +9 -8
  68. data/app/helpers/pageflow/structured_data_helper.rb +4 -1
  69. data/app/helpers/pageflow/themes_helper.rb +1 -3
  70. data/app/helpers/pageflow/widgets_helper.rb +2 -1
  71. data/app/inputs/pageflow_permalink_input.rb +6 -2
  72. data/app/models/concerns/pageflow/auto_generated_perma_id.rb +11 -4
  73. data/app/models/concerns/pageflow/reusable_file.rb +1 -1
  74. data/app/models/concerns/pageflow/serialization_blacklist.rb +2 -4
  75. data/app/models/concerns/pageflow/translated_attributes.rb +101 -0
  76. data/app/models/concerns/pageflow/uploadable_file.rb +1 -1
  77. data/app/models/pageflow/comment.rb +30 -0
  78. data/app/models/pageflow/comment_thread.rb +65 -0
  79. data/app/models/pageflow/comment_thread_read.rb +22 -0
  80. data/app/models/pageflow/customized_theme.rb +3 -2
  81. data/app/models/pageflow/draft_entry.rb +20 -8
  82. data/app/models/pageflow/entry.rb +2 -0
  83. data/app/models/pageflow/entry_at_revision.rb +9 -1
  84. data/app/models/pageflow/entry_comment_summary.rb +114 -0
  85. data/app/models/pageflow/file_folder.rb +74 -0
  86. data/app/models/pageflow/file_reuse.rb +3 -2
  87. data/app/models/pageflow/file_usage.rb +8 -0
  88. data/app/models/pageflow/image_file.rb +24 -20
  89. data/app/models/pageflow/image_file_url_templates.rb +3 -3
  90. data/app/models/pageflow/legal_info.rb +38 -0
  91. data/app/models/pageflow/nested_revision_component_copy.rb +1 -1
  92. data/app/models/pageflow/permalink.rb +1 -0
  93. data/app/models/pageflow/revision.rb +6 -2
  94. data/app/models/pageflow/site.rb +10 -0
  95. data/app/models/pageflow/used_file.rb +8 -2
  96. data/app/models/pageflow/widget.rb +2 -2
  97. data/app/views/pageflow/audio_files/_audio_file.json.jbuilder +0 -1
  98. data/app/views/pageflow/editor/config/_seeds.json.jbuilder +4 -2
  99. data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
  100. data/app/views/pageflow/editor/entries/seed.json.erb +1 -0
  101. data/app/views/pageflow/editor/file_folders/_file_folder.json.jbuilder +5 -0
  102. data/app/views/pageflow/editor/file_folders/create.json.jbuilder +1 -0
  103. data/app/views/pageflow/editor/file_folders/index.json.jbuilder +3 -0
  104. data/app/views/pageflow/editor/files/_file.json.jbuilder +2 -1
  105. data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +3 -0
  106. data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +3 -0
  107. data/app/views/pageflow/files/_file.json.jbuilder +2 -0
  108. data/app/views/pageflow/image_files/_image_file.json.jbuilder +0 -1
  109. data/app/views/pageflow/review/comment_threads/_comment_thread.json.jbuilder +20 -0
  110. data/app/views/pageflow/review/comment_threads/create.json.jbuilder +2 -0
  111. data/app/views/pageflow/review/comment_threads/index.json.jbuilder +13 -0
  112. data/app/views/pageflow/review/comments/_comment.json.jbuilder +13 -0
  113. data/app/views/pageflow/review/comments/create.json.jbuilder +1 -0
  114. data/app/views/pageflow/structured_data/_entry.json.jbuilder +2 -3
  115. data/app/views/pageflow/video_files/_video_file.json.jbuilder +0 -1
  116. data/config/locales/de.yml +152 -14
  117. data/config/locales/en.yml +150 -14
  118. data/config/routes.rb +14 -0
  119. data/db/migrate/20140418225525_setup_schema.rb +2 -2
  120. data/db/migrate/20251015000000_add_structured_data_type_name_to_revisions.rb +5 -0
  121. data/db/migrate/20251029142849_convert_legacy_social_embeds_to_unified_social_embed.rb +38 -0
  122. data/db/migrate/20251119083347_fix_main_storyline_positions.rb +16 -0
  123. data/db/migrate/20251119083348_ensure_scrolled_entries_have_excursion_storyline.rb +15 -0
  124. data/db/migrate/20260303000000_add_layout_version_to_revisions.rb +6 -0
  125. data/db/migrate/20260323000000_create_comment_threads_and_comments.rb +30 -0
  126. data/db/migrate/20260414000000_add_subject_range_to_comment_threads.rb +5 -0
  127. data/db/migrate/20260415000000_add_section_perma_id_to_comment_threads.rb +5 -0
  128. data/db/migrate/20260727000000_add_quote_to_comments.rb +5 -0
  129. data/db/migrate/20260728000000_create_file_folders.rb +17 -0
  130. data/db/migrate/20260805000000_add_attribute_translations_to_sites.rb +5 -0
  131. data/db/migrate/20260806000000_add_edited_at_to_comments.rb +5 -0
  132. data/db/migrate/20260810000000_create_pageflow_scrolled_lottie_files.rb +24 -0
  133. data/db/migrate/20260817000000_create_comment_thread_reads.rb +16 -0
  134. data/db/migrate/20260819000000_add_unread_comments_since_at_to_users.rb +18 -0
  135. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +8665 -3890
  136. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +979 -3571
  137. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +20199 -28120
  138. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +18652 -26584
  139. data/entry_types/scrolled/app/assets/stylesheets/pageflow_scrolled/ui.scss +2 -0
  140. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +33 -3
  141. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +2 -3
  142. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +21 -1
  143. data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +3 -3
  144. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +7 -5
  145. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +5 -2
  146. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +13 -5
  147. data/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +28 -13
  148. data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +26 -11
  149. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +2 -2
  150. data/entry_types/scrolled/app/helpers/pageflow_scrolled/sprockets_helper.rb +16 -0
  151. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +174 -3
  152. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +49 -7
  153. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file.rb +6 -0
  154. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file_url_templates.rb +16 -0
  155. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +1 -0
  156. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +13 -12
  157. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +30 -10
  158. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +9 -0
  159. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +1 -1
  160. data/entry_types/scrolled/config/configuration_schemas/pageflow-scrolled.json +414 -0
  161. data/entry_types/scrolled/config/locales/de.yml +512 -65
  162. data/entry_types/scrolled/config/locales/en.yml +518 -52
  163. data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +2 -2
  164. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +51 -6
  165. data/entry_types/scrolled/lib/pageflow_scrolled/configuration_schemas.rb +91 -0
  166. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +2 -1
  167. data/entry_types/scrolled/lib/pageflow_scrolled/entry_file_reference_locations.rb +71 -0
  168. data/entry_types/scrolled/lib/pageflow_scrolled/entry_structured_data_types/faq_page.rb +58 -0
  169. data/entry_types/scrolled/lib/pageflow_scrolled/file_reference_locations.rb +69 -0
  170. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +205 -22
  171. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +2 -4
  172. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +56 -36
  173. data/entry_types/scrolled/lib/pageflow_scrolled/theme_options_default_scale.rb +35 -0
  174. data/entry_types/scrolled/lib/pageflow_scrolled.rb +13 -0
  175. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +19 -1
  176. data/entry_types/scrolled/package/config/configurationSchemas.js +70 -0
  177. data/entry_types/scrolled/package/config/rollup/configurationSchemas.js +19 -0
  178. data/entry_types/scrolled/package/config/webpack.js +72 -0
  179. data/entry_types/scrolled/package/contentElements/hotspots-frontend.css +1 -1
  180. data/entry_types/scrolled/package/contentElements/hotspots-frontend.js +1181 -915
  181. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.css +1 -0
  182. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.js +219 -0
  183. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.css +1 -0
  184. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.js +244 -0
  185. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.css +1 -0
  186. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.js +823 -0
  187. data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.js +71 -21
  188. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.css +1 -0
  189. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.js +277 -0
  190. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.css +1 -0
  191. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.js +244 -0
  192. data/entry_types/scrolled/package/contentElements-editor.js +1915 -1097
  193. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  194. data/entry_types/scrolled/package/contentElements-frontend.js +3093 -1679
  195. data/entry_types/scrolled/package/editor.css +1 -0
  196. data/entry_types/scrolled/package/editor.js +8667 -4077
  197. data/entry_types/scrolled/package/entryState.js +1600 -0
  198. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-20c600de.js +1979 -0
  199. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-58189220.js +2538 -0
  200. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-9f76033e.js → PhonePlatformContext-035a99fa.js} +7 -12
  201. data/entry_types/scrolled/package/frontend/PhonePlatformContext-9da43797.js +33 -0
  202. data/entry_types/scrolled/package/frontend/Placeholder.module-bf0966b4.js +5267 -0
  203. data/entry_types/scrolled/package/frontend/Placeholder.module-d22a9335.js +4180 -0
  204. data/entry_types/scrolled/package/frontend/ThemeIcon-ab834849.js +754 -0
  205. data/entry_types/scrolled/package/frontend/ThemeIcon-f6cb3a8f.js +773 -0
  206. data/entry_types/scrolled/package/frontend/{ToggleFullscreenCornerButton-788e9cdb.js → ToggleFullscreenCornerButton-30fd1124.js} +6 -6
  207. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-61c25224.js +72 -0
  208. data/entry_types/scrolled/package/frontend/Viewer-1074fd59.js +147 -0
  209. data/entry_types/scrolled/package/frontend/Viewer-1482ca34.js +480 -0
  210. data/entry_types/scrolled/package/frontend/Viewer-70504231.js +210 -0
  211. data/entry_types/scrolled/package/frontend/{Viewer-0345ce57.js → Viewer-cc8d4072.js} +84 -92
  212. data/entry_types/scrolled/package/frontend/Wavesurfer-656e3c36.js +302 -0
  213. data/entry_types/scrolled/package/frontend/Wavesurfer-b753b838.js +385 -0
  214. data/entry_types/scrolled/package/frontend/commenting.css +1 -0
  215. data/entry_types/scrolled/package/frontend/extensions-167ae143.js +1455 -0
  216. data/entry_types/scrolled/package/frontend/extensions-2318f92b.js +5918 -0
  217. data/entry_types/scrolled/package/frontend/extensions-a461fd13.js +4890 -0
  218. data/entry_types/scrolled/package/frontend/extensions-c98269fd.js +1982 -0
  219. data/entry_types/scrolled/package/frontend/i18n-493cd2a6.js +93 -0
  220. data/entry_types/scrolled/package/frontend/i18n-e06cac14.js +100 -0
  221. data/entry_types/scrolled/package/frontend/{index-eb670c2f.js → index-2e5546f7.js} +36 -44
  222. data/entry_types/scrolled/package/frontend/index-de2b418d.js +130 -0
  223. data/entry_types/scrolled/package/frontend/index.css +1 -1
  224. data/entry_types/scrolled/package/frontend/index.js +1870 -875
  225. data/entry_types/scrolled/package/frontend/inlineEditing.css +1 -0
  226. data/entry_types/scrolled/package/frontend/useContentElementEditorState-a084912e.js +25 -0
  227. data/entry_types/scrolled/package/frontend/useDelayedBoolean-a387d85b.js +24 -0
  228. data/entry_types/scrolled/package/frontend/{usePhonePlatform-c2ba875d.js → usePhonePlatform-4ecb96d4.js} +1 -1
  229. data/entry_types/scrolled/package/frontend/usePhonePlatform-ce9ff08d.js +8 -0
  230. data/entry_types/scrolled/package/frontend-server.js +20 -209
  231. data/entry_types/scrolled/package/package.json +5 -3
  232. data/entry_types/scrolled/package/review.css +1 -0
  233. data/entry_types/scrolled/package/review.js +3306 -0
  234. data/entry_types/scrolled/package/testHelpers.js +836 -359
  235. data/entry_types/scrolled/package/widgets/consentBar.css +1 -1
  236. data/entry_types/scrolled/package/widgets/consentBar.js +269 -290
  237. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  238. data/entry_types/scrolled/package/widgets/defaultNavigation.js +911 -352
  239. data/entry_types/scrolled/package/widgets/excursionSheet.css +1 -1
  240. data/entry_types/scrolled/package/widgets/excursionSheet.js +87 -124
  241. data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -1
  242. data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +62 -29
  243. data/entry_types/scrolled/package/widgets/iconScrollIndicator.js +32 -13
  244. data/entry_types/scrolled/package/widgets/mainStorylineSheet.css +1 -1
  245. data/entry_types/scrolled/package/widgets/mainStorylineSheet.js +56 -100
  246. data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -1
  247. data/entry_types/scrolled/package/widgets/textInlineFileRights.js +33 -28
  248. data/entry_types/scrolled/package/widgets-server.js +1 -0
  249. data/entry_types/scrolled/spec/factories/lottie_files.rb +29 -0
  250. data/entry_types/scrolled/spec/fixtures/animation.lottie +0 -0
  251. data/entry_types/scrolled/spec/fixtures/font.woff +0 -0
  252. data/entry_types/scrolled/spec/fixtures/font.woff2 +0 -0
  253. data/lib/generators/pageflow/resque/resque_generator.rb +0 -2
  254. data/lib/pageflow/configuration.rb +49 -7
  255. data/lib/pageflow/deprecation.rb +19 -0
  256. data/lib/pageflow/engine.rb +1 -1
  257. data/lib/pageflow/entries_controller_env_helper.rb +32 -2
  258. data/lib/pageflow/entry_export_import/entry_serialization.rb +4 -4
  259. data/lib/pageflow/entry_export_import/page_type_versions.rb +2 -2
  260. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +10 -0
  261. data/lib/pageflow/entry_export_import/revision_serialization.rb +3 -0
  262. data/lib/pageflow/entry_structured_data_types.rb +43 -0
  263. data/lib/pageflow/entry_type_configuration.rb +1 -0
  264. data/lib/pageflow/file_type.rb +2 -2
  265. data/lib/pageflow/file_types.rb +1 -1
  266. data/lib/pageflow/oembed_providers.rb +42 -0
  267. data/lib/pageflow/primary_domain_entry_redirect.rb +6 -0
  268. data/lib/pageflow/rails_version.rb +13 -2
  269. data/lib/pageflow/themes.rb +41 -0
  270. data/lib/pageflow/user_mixin.rb +12 -0
  271. data/lib/pageflow/version.rb +1 -1
  272. data/lib/pageflow.rb +1 -0
  273. data/package/config/eslint-rules/documented-in-toc.js +125 -0
  274. data/package/config/jest/index.js +0 -1
  275. data/package/config/webpack.js +0 -1
  276. data/package/config/webpack5.js +0 -1
  277. data/package/editor.js +4378 -1897
  278. data/package/frontend.js +647 -886
  279. data/package/package.json +2 -1
  280. data/package/review.js +384 -0
  281. data/package/testHelpers.js +248 -188
  282. data/package/ui.js +1346 -630
  283. data/package/vendor/stubs/wysihtml5.js +2 -0
  284. data/spec/factories/comment_thread_reads.rb +10 -0
  285. data/spec/factories/comment_threads.rb +10 -0
  286. data/spec/factories/comments.rb +9 -0
  287. data/spec/factories/file_folders.rb +8 -0
  288. data/spec/factories/published_entries.rb +2 -0
  289. metadata +188 -67
  290. data/app/assets/stylesheets/pageflow/editor/select_button.scss +0 -51
  291. data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +0 -55
  292. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-51914be7.js +0 -5439
  293. data/entry_types/scrolled/package/frontend/ThemeIcon-81f2f066.js +0 -1932
  294. data/entry_types/scrolled/package/frontend/Viewer-cdc549cc.js +0 -147
  295. data/entry_types/scrolled/package/frontend/Wavesurfer-1cdc3925.js +0 -313
  296. data/entry_types/scrolled/package/frontend/components-96660ffd.js +0 -3803
  297. data/entry_types/scrolled/package/frontend/inherits-539844a6.js +0 -99
  298. data/entry_types/scrolled/package/frontend/useContentElementEditorState-77fe6c79.js +0 -51
  299. data/entry_types/scrolled/package/widgets/excursionDialog.css +0 -1
  300. data/entry_types/scrolled/package/widgets/excursionDialog.js +0 -109
  301. data/lib/generators/pageflow/resque/templates/resque_enqueue_after_commit_patch.rb +0 -25
  302. data/package/vendor/jquery.minicolors.js +0 -1108
@@ -1,5 +1,5 @@
1
1
  this.pageflow = this.pageflow || {};
2
- this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, Backbone, ChildViewContainer, IScroll, jquery_minicolors, wysihtml5, jqueryUi, Cocktail) {
2
+ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, Backbone, ChildViewContainer, IScroll, wysihtml5, jqueryUi, Cocktail) {
3
3
  'use strict';
4
4
 
5
5
  Marionette = Marionette && Marionette.hasOwnProperty('default') ? Marionette['default'] : Marionette;
@@ -143,64 +143,6 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
143
143
  translationKeysWithSuffix: translationKeysWithSuffix
144
144
  });
145
145
 
146
- function _arrayWithHoles(arr) {
147
- if (Array.isArray(arr)) return arr;
148
- }
149
-
150
- function _iterableToArrayLimit(arr, i) {
151
- if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
152
- var _arr = [];
153
- var _n = true;
154
- var _d = false;
155
- var _e = undefined;
156
-
157
- try {
158
- for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
159
- _arr.push(_s.value);
160
-
161
- if (i && _arr.length === i) break;
162
- }
163
- } catch (err) {
164
- _d = true;
165
- _e = err;
166
- } finally {
167
- try {
168
- if (!_n && _i["return"] != null) _i["return"]();
169
- } finally {
170
- if (_d) throw _e;
171
- }
172
- }
173
-
174
- return _arr;
175
- }
176
-
177
- function _arrayLikeToArray(arr, len) {
178
- if (len == null || len > arr.length) len = arr.length;
179
-
180
- for (var i = 0, arr2 = new Array(len); i < len; i++) {
181
- arr2[i] = arr[i];
182
- }
183
-
184
- return arr2;
185
- }
186
-
187
- function _unsupportedIterableToArray(o, minLen) {
188
- if (!o) return;
189
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
190
- var n = Object.prototype.toString.call(o).slice(8, -1);
191
- if (n === "Object" && o.constructor) n = o.constructor.name;
192
- if (n === "Map" || n === "Set") return Array.from(n);
193
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
194
- }
195
-
196
- function _nonIterableRest() {
197
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
198
- }
199
-
200
- function _slicedToArray(arr, i) {
201
- return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
202
- }
203
-
204
146
  /**
205
147
  * Create object that can be passed to Marionette ui property from CSS
206
148
  * module object.
@@ -240,11 +182,8 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
240
182
  *
241
183
  * @memberof cssModulesUtils
242
184
  */
243
- function ui(styles) {
244
- for (var _len = arguments.length, classNames = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
245
- classNames[_key - 1] = arguments[_key];
246
- }
247
- return classNames.reduce(function (result, className) {
185
+ function ui(styles, ...classNames) {
186
+ return classNames.reduce((result, className) => {
248
187
  result[className] = selector(styles, className);
249
188
  return result;
250
189
  }, {});
@@ -288,12 +227,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
288
227
  * @memberof cssModulesUtils
289
228
  */
290
229
  function events(styles, mapping) {
291
- return Object.keys(mapping).reduce(function (result, key) {
292
- var _key$split = key.split(' '),
293
- _key$split2 = _slicedToArray(_key$split, 2),
294
- event = _key$split2[0],
295
- className = _key$split2[1];
296
- result["".concat(event, " ").concat(selector(styles, className))] = mapping[key];
230
+ return Object.keys(mapping).reduce((result, key) => {
231
+ const [event, className] = key.split(' ');
232
+ result[`${event} ${selector(styles, className)}`] = mapping[key];
297
233
  return result;
298
234
  }, {});
299
235
  }
@@ -311,11 +247,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
311
247
  * @memberof cssModulesUtils
312
248
  */
313
249
  function selector(styles, className) {
314
- var classNames = styles[className];
250
+ const classNames = styles[className];
315
251
  if (!classNames) {
316
- throw new Error("Unknown class name ".concat(className, " in mapping. Knwon names: ").concat(Object.keys(styles).join(', '), "."));
252
+ throw new Error(`Unknown class name ${className} in mapping. Knwon names: ${Object.keys(styles).join(', ')}.`);
317
253
  }
318
- return ".".concat(classNames.replace(/ /g, '.'));
254
+ return `.${classNames.replace(/ /g, '.')}`;
319
255
  }
320
256
 
321
257
  var cssModulesUtils = /*#__PURE__*/Object.freeze({
@@ -325,6 +261,56 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
325
261
  selector: selector
326
262
  });
327
263
 
264
+ function setup({
265
+ binding,
266
+ model,
267
+ listener,
268
+ callback,
269
+ normalize = value => value,
270
+ option,
271
+ bindingValue
272
+ }) {
273
+ if (binding) {
274
+ _.flatten([binding]).forEach(attribute => {
275
+ listener.listenTo(model, 'change:' + attribute, update);
276
+ });
277
+ }
278
+ update();
279
+ function update() {
280
+ callback(resolve({
281
+ binding,
282
+ model,
283
+ normalize,
284
+ option,
285
+ bindingValue
286
+ }));
287
+ }
288
+ }
289
+ function resolve({
290
+ binding,
291
+ model,
292
+ normalize = value => value,
293
+ option,
294
+ bindingValue
295
+ }) {
296
+ const boundValue = Array.isArray(binding) ? binding.map(attribute => model.get(attribute)) : model.get(binding);
297
+ if (bindingValue !== undefined) {
298
+ return boundValue === bindingValue;
299
+ } else if (typeof option === 'function') {
300
+ return normalize(option(boundValue));
301
+ } else if (option !== undefined) {
302
+ return normalize(option);
303
+ } else if (binding) {
304
+ return normalize(boundValue);
305
+ }
306
+ }
307
+
308
+ var attributeBindingUtils = /*#__PURE__*/Object.freeze({
309
+ __proto__: null,
310
+ setup: setup,
311
+ resolve: resolve
312
+ });
313
+
328
314
  // Class-y constructor by github.com/opensas
329
315
  // https://github.com/jashkenas/backbone/issues/2601
330
316
 
@@ -332,24 +318,23 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
332
318
  this.initialize.apply(this, arguments);
333
319
  }
334
320
  _.extend(BaseObject.prototype, Backbone.Events, {
335
- initialize: function initialize(options) {}
321
+ initialize: function (options) {}
336
322
  });
337
323
 
338
324
  // The self-propagating extend function that Backbone classes use.
339
325
  BaseObject.extend = Backbone.Model.extend;
340
326
 
341
- var serverSideValidation = {
342
- initialize: function initialize() {
343
- var _this = this;
327
+ const serverSideValidation = {
328
+ initialize() {
344
329
  this.validationErrors = {};
345
- this.listenTo(this, 'error', function (model, request) {
330
+ this.listenTo(this, 'error', (model, request) => {
346
331
  if (request.status === 422) {
347
- _this.validationErrors = JSON.parse(request.responseText).errors;
348
- _this.trigger('invalid');
332
+ this.validationErrors = JSON.parse(request.responseText).errors;
333
+ this.trigger('invalid');
349
334
  }
350
335
  });
351
- this.listenTo(this, 'sync', function () {
352
- _this.validationErrors = {};
336
+ this.listenTo(this, 'sync', () => {
337
+ this.validationErrors = {};
353
338
  });
354
339
  }
355
340
  };
@@ -3004,8 +2989,8 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3004
2989
  Sortable.mount(new AutoScrollPlugin());
3005
2990
  Sortable.mount(Remove, Revert);
3006
2991
 
3007
- var CollectionView = Marionette.View.extend({
3008
- initialize: function initialize() {
2992
+ const CollectionView = Marionette.View.extend({
2993
+ initialize: function () {
3009
2994
  this.rendered = false;
3010
2995
  this.itemViews = new ChildViewContainer();
3011
2996
  this.collection.map(this.addItem, this);
@@ -3023,7 +3008,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3023
3008
  });
3024
3009
  }
3025
3010
  },
3026
- render: function render() {
3011
+ render: function () {
3027
3012
  if (!this.rendered) {
3028
3013
  this.$el.append(this.itemViews.map(function (itemView) {
3029
3014
  itemView.$el.data('view', itemView);
@@ -3034,11 +3019,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3034
3019
  }
3035
3020
  return this;
3036
3021
  },
3037
- onClose: function onClose() {
3022
+ onClose: function () {
3038
3023
  this.itemViews.call('close');
3039
3024
  this.closePlaceHolderView();
3040
3025
  },
3041
- addItem: function addItem(item) {
3026
+ addItem: function (item) {
3042
3027
  var view = new this.options.itemViewConstructor(_.extend({
3043
3028
  model: item
3044
3029
  }, this.getItemViewOptions(item)));
@@ -3055,7 +3040,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3055
3040
  this.togglePlaceHolder();
3056
3041
  }
3057
3042
  },
3058
- removeItem: function removeItem(item) {
3043
+ removeItem: function (item) {
3059
3044
  var view = this.itemViews.findByModel(item);
3060
3045
  if (view) {
3061
3046
  this.itemViews.remove(view);
@@ -3063,7 +3048,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3063
3048
  this.togglePlaceHolder();
3064
3049
  }
3065
3050
  },
3066
- sort: function sort() {
3051
+ sort: function () {
3067
3052
  var last = null;
3068
3053
  this.collection.each(function (item) {
3069
3054
  var itemView = this.itemViews.findByModel(item);
@@ -3080,31 +3065,36 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3080
3065
  last = element;
3081
3066
  }, this);
3082
3067
  },
3083
- getItemViewOptions: function getItemViewOptions(item) {
3068
+ getItemViewOptions: function (item) {
3084
3069
  if (typeof this.options.itemViewOptions === 'function') {
3085
3070
  return this.options.itemViewOptions(item);
3086
3071
  } else {
3087
3072
  return this.options.itemViewOptions || {};
3088
3073
  }
3089
3074
  },
3090
- closePlaceHolderView: function closePlaceHolderView() {
3075
+ closePlaceHolderView: function () {
3091
3076
  if (this.placeHolderView) {
3092
3077
  this.placeHolderView.close();
3093
3078
  this.placeHolderView = null;
3094
3079
  }
3095
3080
  },
3096
- togglePlaceHolder: function togglePlaceHolder() {
3081
+ togglePlaceHolder: function () {
3097
3082
  var lastPlaceholderConstructor = this.placeHolderConstructor;
3098
3083
  this.placeHolderConstructor = this.getPlaceHolderConstructor();
3099
3084
  if (this.itemViews.length || !this.placeHolderConstructor) {
3100
3085
  this.closePlaceHolderView();
3101
3086
  } else if (!this.placeHolderView || lastPlaceholderConstructor !== this.placeHolderConstructor) {
3102
3087
  this.closePlaceHolderView();
3103
- this.placeHolderView = new this.placeHolderConstructor();
3088
+ this.placeHolderView = new this.placeHolderConstructor(this.getPlaceHolderViewOptions());
3104
3089
  this.$el.append(this.placeHolderView.render().el);
3105
3090
  }
3106
3091
  },
3107
- getPlaceHolderConstructor: function getPlaceHolderConstructor() {
3092
+ getPlaceHolderViewOptions: function () {
3093
+ if (this.placeHolderConstructor === this.options.blankSlateViewConstructor) {
3094
+ return this.options.blankSlateViewOptions;
3095
+ }
3096
+ },
3097
+ getPlaceHolderConstructor: function () {
3108
3098
  if (this.loading && this.options.loadingViewConstructor) {
3109
3099
  return this.options.loadingViewConstructor;
3110
3100
  } else if (this.options.blankSlateViewConstructor) {
@@ -3113,9 +3103,8 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3113
3103
  }
3114
3104
  });
3115
3105
 
3116
- var SortableCollectionView = CollectionView.extend({
3117
- render: function render() {
3118
- var _this = this;
3106
+ const SortableCollectionView = CollectionView.extend({
3107
+ render: function () {
3119
3108
  CollectionView.prototype.render.call(this);
3120
3109
  this.sortable = Sortable.create(this.el, {
3121
3110
  group: this.options.connectWith,
@@ -3123,125 +3112,90 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3123
3112
  ghostClass: 'sortable-placeholder',
3124
3113
  forceFallback: this.options.forceDraggableFallback,
3125
3114
  fallbackTolerance: 3,
3126
- onEnd: function onEnd(event) {
3127
- var item = $(event.item);
3128
- if (item.parent().is(_this.el)) {
3129
- _this.updateOrder();
3115
+ onEnd: event => {
3116
+ const item = $(event.item);
3117
+ if (item.parent().is(this.el)) {
3118
+ this.updateOrder();
3130
3119
  }
3131
3120
  },
3132
- onRemove: function onRemove(event) {
3133
- var view = $(event.item).data('view');
3134
- _this.itemViews.remove(view);
3135
- _this.collection.remove(view.model);
3121
+ onRemove: event => {
3122
+ const view = $(event.item).data('view');
3123
+ this.itemViews.remove(view);
3124
+ this.collection.remove(view.model);
3136
3125
  },
3137
- onSort: function onSort(event) {
3138
- if (event.from !== event.to && event.to === _this.el) {
3139
- var view = $(event.item).data('view');
3140
- _this.reindexPositions();
3141
- _this.itemViews.add(view);
3142
- _this.collection.add(view.model);
3143
- _this.collection.saveOrder();
3126
+ onSort: event => {
3127
+ if (event.from !== event.to && event.to === this.el) {
3128
+ const view = $(event.item).data('view');
3129
+ this.reindexPositions();
3130
+ this.itemViews.add(view);
3131
+ this.collection.add(view.model);
3132
+ this.collection.saveOrder();
3144
3133
  }
3145
3134
  }
3146
3135
  });
3147
3136
  return this;
3148
3137
  },
3149
- onClose: function onClose() {
3138
+ onClose() {
3150
3139
  CollectionView.prototype.onClose.call(this);
3151
3140
  this.sortable.destroy();
3152
3141
  },
3153
- disableSorting: function disableSorting() {
3142
+ disableSorting() {
3154
3143
  this.sortable.option('disabled', true);
3155
3144
  },
3156
- enableSorting: function enableSorting() {
3145
+ enableSorting() {
3157
3146
  this.sortable.option('disabled', false);
3158
3147
  },
3159
- addItem: function addItem(item) {
3148
+ addItem: function (item) {
3160
3149
  if (!this.itemViews.findByModel(item)) {
3161
3150
  CollectionView.prototype.addItem.call(this, item);
3162
3151
  }
3163
3152
  },
3164
- removeItem: function removeItem(item) {
3153
+ removeItem: function (item) {
3165
3154
  if (this.itemViews.findByModel(item)) {
3166
3155
  CollectionView.prototype.removeItem.call(this, item);
3167
3156
  }
3168
3157
  },
3169
- updateOrder: function updateOrder() {
3158
+ updateOrder: function () {
3170
3159
  this.reindexPositions();
3171
3160
  this.collection.sort();
3172
3161
  this.collection.saveOrder();
3173
3162
  },
3174
- reindexPositions: function reindexPositions() {
3163
+ reindexPositions: function () {
3175
3164
  this.$el.children().each(function (index) {
3176
3165
  $(this).data('view').model.set('position', index);
3177
3166
  });
3178
3167
  }
3179
3168
  });
3180
3169
 
3181
- function _objectWithoutPropertiesLoose$1(source, excluded) {
3182
- if (source == null) return {};
3183
- var target = {};
3184
- var sourceKeys = Object.keys(source);
3185
- var key, i;
3186
-
3187
- for (i = 0; i < sourceKeys.length; i++) {
3188
- key = sourceKeys[i];
3189
- if (excluded.indexOf(key) >= 0) continue;
3190
- target[key] = source[key];
3191
- }
3192
-
3193
- return target;
3194
- }
3195
-
3196
- function _objectWithoutProperties$1(source, excluded) {
3197
- if (source == null) return {};
3198
- var target = _objectWithoutPropertiesLoose$1(source, excluded);
3199
- var key, i;
3200
-
3201
- if (Object.getOwnPropertySymbols) {
3202
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
3203
-
3204
- for (i = 0; i < sourceSymbolKeys.length; i++) {
3205
- key = sourceSymbolKeys[i];
3206
- if (excluded.indexOf(key) >= 0) continue;
3207
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
3208
- target[key] = source[key];
3209
- }
3210
- }
3211
-
3212
- return target;
3213
- }
3214
-
3215
- var _excluded$1 = ["ignoreUndefined"];
3216
- var ConfigurationEditorTabView = Marionette.View.extend({
3170
+ const ConfigurationEditorTabView = Marionette.View.extend({
3217
3171
  className: 'configuration_editor_tab',
3218
- initialize: function initialize() {
3172
+ initialize: function () {
3219
3173
  this.inputs = new ChildViewContainer();
3220
3174
  this.groups = this.options.groups || ConfigurationEditorTabView.groups;
3221
3175
  },
3222
- input: function input(propertyName, view, options) {
3176
+ input: function (propertyName, view, options) {
3223
3177
  this.view(view, _.extend({
3224
3178
  placeholderModel: this.options.placeholderModel,
3225
3179
  propertyName: propertyName,
3226
3180
  attributeTranslationKeyPrefixes: this.options.attributeTranslationKeyPrefixes
3227
3181
  }, options || {}));
3228
3182
  },
3229
- view: function view(_view, options) {
3230
- this.inputs.add(new _view(_.extend({
3183
+ view: function (view, options) {
3184
+ this.inputs.add(new view(_.extend({
3231
3185
  model: this.model,
3232
3186
  parentTab: this.options.tab
3233
3187
  }, options || {})));
3234
3188
  },
3235
- group: function group(name, options) {
3189
+ group: function (name, options) {
3236
3190
  this.groups.apply(name, this, options);
3237
3191
  },
3238
- render: function render() {
3192
+ render: function () {
3239
3193
  this.inputs.each(function (input) {
3240
3194
  this.$el.append(input.render().el);
3241
3195
  }, this);
3242
3196
  return this;
3243
3197
  },
3244
- onClose: function onClose() {
3198
+ onClose: function () {
3245
3199
  if (this.inputs) {
3246
3200
  this.inputs.call('close');
3247
3201
  }
@@ -3255,10 +3209,10 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3255
3209
  }
3256
3210
  groups[name] = fn;
3257
3211
  };
3258
- this.apply = function (name, context) {
3259
- var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
3260
- ignoreUndefined = _ref.ignoreUndefined,
3261
- options = _objectWithoutProperties$1(_ref, _excluded$1);
3212
+ this.apply = function (name, context, {
3213
+ ignoreUndefined,
3214
+ ...options
3215
+ } = {}) {
3262
3216
  if (!(name in groups)) {
3263
3217
  if (ignoreUndefined) {
3264
3218
  return;
@@ -3272,7 +3226,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3272
3226
 
3273
3227
  function template(data) {
3274
3228
  var __p = '';
3275
- __p += '<div class="tabs_view-scroller">\n <ul class="tabs_view-headers"></ul>\n</div>\n<div class="tabs_view-container"></div>\n';
3229
+ __p += '<div class="tabs_view-scroller">\n <div class="tabs_view-tabs" role="tablist" aria-orientation="horizontal"></div>\n</div>\n<div class="tabs_view-container"></div>\n';
3276
3230
  return __p
3277
3231
  }
3278
3232
 
@@ -3298,36 +3252,43 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3298
3252
  *
3299
3253
  * @class
3300
3254
  */
3301
- var TabsView = Marionette.Layout.extend( /* @lends TabView.prototype */{
3302
- template: template,
3255
+ const TabsView = Marionette.Layout.extend( /* @lends TabView.prototype */{
3256
+ template,
3303
3257
  className: 'tabs_view',
3304
3258
  ui: {
3305
- headers: '.tabs_view-headers',
3306
- scroller: '.tabs_view-scroller'
3259
+ tabs: '.tabs_view-tabs',
3260
+ scroller: '.tabs_view-scroller',
3261
+ container: '.tabs_view-container'
3307
3262
  },
3308
3263
  regions: {
3309
3264
  container: '.tabs_view-container'
3310
3265
  },
3311
3266
  events: {
3312
- 'click .tabs_view-headers > li': function clickTabs_viewHeadersLi(event) {
3313
- this.changeTab($(event.target).data('tab-name'));
3267
+ 'click .tabs_view-tab': function (event) {
3268
+ this.changeTab($(event.currentTarget).data('tab-name'));
3269
+ },
3270
+ 'keydown .tabs_view-tab': function (event) {
3271
+ this._handleKeyDown(event);
3314
3272
  }
3315
3273
  },
3316
- initialize: function initialize() {
3274
+ initialize: function () {
3317
3275
  this.tabFactoryFns = {};
3318
3276
  this.tabNames = [];
3319
3277
  this.currentTabName = null;
3320
3278
  this._refreshScrollerOnSideBarResize();
3321
3279
  },
3322
- tab: function tab(name, factoryFn) {
3280
+ tab: function (name, factoryFn) {
3323
3281
  this.tabFactoryFns[name] = factoryFn;
3324
3282
  this.tabNames.push(name);
3325
3283
  },
3326
- onRender: function onRender() {
3284
+ onRender: function () {
3327
3285
  _.each(this.tabNames, function (name) {
3328
3286
  var label = findTranslation(this._labelTranslationKeys(name));
3329
- this.ui.headers.append($('<li />').attr('data-tab-name', name).text(label));
3287
+ var tabId = this._tabId(name);
3288
+ var button = $('<button />').attr('type', 'button').attr('role', 'tab').attr('id', tabId).attr('data-tab-name', name).attr('tabindex', '-1').attr('aria-selected', 'false').addClass('tabs_view-tab').text(label);
3289
+ this.ui.tabs.append(button);
3330
3290
  }, this);
3291
+ this.ui.container.attr('id', this._panelId()).attr('role', 'tabpanel');
3331
3292
  this.scroller = new IScroll(this.ui.scroller[0], {
3332
3293
  scrollX: true,
3333
3294
  scrollY: false,
@@ -3335,14 +3296,22 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3335
3296
  mouseWheel: true,
3336
3297
  preventDefault: false
3337
3298
  });
3338
- this.changeTab(this.defaultTab());
3299
+ this.changeTab(this.defaultTab(), {
3300
+ refresh: true
3301
+ });
3339
3302
  },
3340
- changeTab: function changeTab(name) {
3341
- this.container.show(this.tabFactoryFns[name]());
3342
- this._updateActiveHeader(name);
3303
+ changeTab: function (name, options = {}) {
3304
+ if (!this.tabFactoryFns[name]) {
3305
+ return;
3306
+ }
3307
+ if (this.currentTabName !== name || options.refresh) {
3308
+ this.container.show(this.tabFactoryFns[name]());
3309
+ }
3343
3310
  this.currentTabName = name;
3311
+ this._updateActiveTab(name, options.focusTab);
3312
+ this._updateActivePanel(name);
3344
3313
  },
3345
- defaultTab: function defaultTab() {
3314
+ defaultTab: function () {
3346
3315
  if (_.include(this.tabNames, this.options.defaultTab)) {
3347
3316
  return this.options.defaultTab;
3348
3317
  } else {
@@ -3352,19 +3321,23 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3352
3321
  /**
3353
3322
  * Rerender current tab.
3354
3323
  */
3355
- refresh: function refresh() {
3356
- this.changeTab(this.currentTabName);
3324
+ refresh: function () {
3325
+ if (this.currentTabName) {
3326
+ this.changeTab(this.currentTabName, {
3327
+ refresh: true
3328
+ });
3329
+ }
3357
3330
  },
3358
3331
  /**
3359
3332
  * Adjust tabs scroller to changed width of view.
3360
3333
  */
3361
- refreshScroller: function refreshScroller() {
3334
+ refreshScroller: function () {
3362
3335
  this.scroller.refresh();
3363
3336
  },
3364
- toggleSpinnerOnTab: function toggleSpinnerOnTab(name, visible) {
3337
+ toggleSpinnerOnTab: function (name, visible) {
3365
3338
  this.$('[data-tab-name=' + name + ']').toggleClass('spinner', visible);
3366
3339
  },
3367
- _labelTranslationKeys: function _labelTranslationKeys(name) {
3340
+ _labelTranslationKeys: function (name) {
3368
3341
  var result = _.map(this.options.translationKeyPrefixes, function (prefix) {
3369
3342
  return prefix + '.' + name;
3370
3343
  });
@@ -3376,23 +3349,85 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3376
3349
  }
3377
3350
  return result;
3378
3351
  },
3379
- _updateActiveHeader: function _updateActiveHeader(activeTabName) {
3352
+ _updateActiveTab: function (activeTabName, focusTab) {
3380
3353
  var scroller = this.scroller;
3381
- this.ui.headers.children().each(function () {
3382
- if ($(this).data('tab-name') === activeTabName) {
3354
+ var panelId = this._panelId();
3355
+ this.ui.tabs.children().each(function () {
3356
+ var button = $(this);
3357
+ var isActive = button.data('tab-name') === activeTabName;
3358
+ if (isActive) {
3383
3359
  scroller.scrollToElement(this, 200, true);
3384
- $(this).addClass('active');
3360
+ button.addClass('active');
3361
+ button.attr('aria-selected', 'true');
3362
+ button.attr('aria-controls', panelId);
3363
+ button.attr('tabindex', '0');
3364
+ if (focusTab) {
3365
+ button.focus();
3366
+ }
3385
3367
  } else {
3386
- $(this).removeClass('active');
3368
+ button.removeClass('active');
3369
+ button.attr('aria-selected', 'false');
3370
+ button.attr('tabindex', '-1');
3387
3371
  }
3388
3372
  });
3389
3373
  },
3390
- _refreshScrollerOnSideBarResize: function _refreshScrollerOnSideBarResize() {
3374
+ _updateActivePanel: function (activeTabName) {
3375
+ this.ui.container.attr('aria-labelledby', this._tabId(activeTabName));
3376
+ },
3377
+ _handleKeyDown: function (event) {
3378
+ var tabName = $(event.currentTarget).data('tab-name');
3379
+ var nextTabName;
3380
+ switch (event.key) {
3381
+ case 'ArrowLeft':
3382
+ case 'ArrowUp':
3383
+ nextTabName = this._previousTabName(tabName);
3384
+ break;
3385
+ case 'ArrowRight':
3386
+ case 'ArrowDown':
3387
+ nextTabName = this._nextTabName(tabName);
3388
+ break;
3389
+ case 'Home':
3390
+ nextTabName = _.first(this.tabNames);
3391
+ break;
3392
+ case 'End':
3393
+ nextTabName = _.last(this.tabNames);
3394
+ break;
3395
+ case 'Enter':
3396
+ case ' ':
3397
+ nextTabName = tabName;
3398
+ break;
3399
+ default:
3400
+ return;
3401
+ }
3402
+ event.preventDefault();
3403
+ if (nextTabName) {
3404
+ this.changeTab(nextTabName, {
3405
+ focusTab: true
3406
+ });
3407
+ }
3408
+ },
3409
+ _previousTabName: function (currentTabName) {
3410
+ var currentIndex = _.indexOf(this.tabNames, currentTabName);
3411
+ var previousIndex = (currentIndex - 1 + this.tabNames.length) % this.tabNames.length;
3412
+ return this.tabNames[previousIndex];
3413
+ },
3414
+ _nextTabName: function (currentTabName) {
3415
+ var currentIndex = _.indexOf(this.tabNames, currentTabName);
3416
+ var nextIndex = (currentIndex + 1) % this.tabNames.length;
3417
+ return this.tabNames[nextIndex];
3418
+ },
3419
+ _refreshScrollerOnSideBarResize: function () {
3391
3420
  if (pageflow.app) {
3392
3421
  this.listenTo(pageflow.app, 'resize', function () {
3393
3422
  this.scroller.refresh();
3394
3423
  });
3395
3424
  }
3425
+ },
3426
+ _tabId: function (name) {
3427
+ return this.cid + '-tab-' + name;
3428
+ },
3429
+ _panelId: function () {
3430
+ return this.cid + '-panel';
3396
3431
  }
3397
3432
  });
3398
3433
 
@@ -3421,9 +3456,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3421
3456
  *
3422
3457
  * @class
3423
3458
  */
3424
- var ConfigurationEditorView = Marionette.View.extend({
3459
+ const ConfigurationEditorView = Marionette.View.extend({
3425
3460
  className: 'configuration_editor',
3426
- initialize: function initialize() {
3461
+ initialize: function () {
3427
3462
  this.tabsView = new TabsView({
3428
3463
  translationKeyPrefixes: this.options.tabTranslationKeyPrefixes || [this.options.tabTranslationKeyPrefix],
3429
3464
  fallbackTranslationKeyPrefix: 'pageflow.ui.configuration_editor.tabs',
@@ -3431,10 +3466,10 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3431
3466
  });
3432
3467
  this.configure();
3433
3468
  },
3434
- configure: function configure() {},
3435
- tab: function tab(name, callbackOrOptions, callback) {
3469
+ configure: function () {},
3470
+ tab: function (name, callbackOrOptions, callback) {
3436
3471
  callback = callback || callbackOrOptions;
3437
- var options = callback ? callbackOrOptions : {};
3472
+ const options = callback ? callbackOrOptions : {};
3438
3473
  this.tabsView.tab(name, _.bind(function () {
3439
3474
  var tabView = new ConfigurationEditorTabView({
3440
3475
  model: options.model || this.model,
@@ -3449,23 +3484,23 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3449
3484
  /**
3450
3485
  * Rerender current tab.
3451
3486
  */
3452
- refresh: function refresh() {
3487
+ refresh: function () {
3453
3488
  this.tabsView.refresh();
3454
3489
  },
3455
3490
  /**
3456
3491
  * Adjust tabs scroller to changed width of view.
3457
3492
  */
3458
- refreshScroller: function refreshScroller() {
3493
+ refreshScroller: function () {
3459
3494
  this.tabsView.refreshScroller();
3460
3495
  },
3461
- render: function render() {
3496
+ render: function () {
3462
3497
  this.$el.append(this.subview(this.tabsView).el);
3463
3498
  return this;
3464
3499
  }
3465
3500
  });
3466
3501
  _.extend(ConfigurationEditorView, {
3467
3502
  repository: {},
3468
- register: function register(pageTypeName, prototype) {
3503
+ register: function (pageTypeName, prototype) {
3469
3504
  this.repository[pageTypeName] = ConfigurationEditorView.extend(prototype);
3470
3505
  }
3471
3506
  });
@@ -3490,13 +3525,13 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3490
3525
  *
3491
3526
  * @since 12.0
3492
3527
  */
3493
- var TableCellView = Marionette.ItemView.extend({
3528
+ const TableCellView = Marionette.ItemView.extend({
3494
3529
  tagName: 'td',
3495
3530
  template: template$1,
3496
- className: function className() {
3531
+ className: function () {
3497
3532
  return this.options.className;
3498
3533
  },
3499
- onRender: function onRender() {
3534
+ onRender: function () {
3500
3535
  this.listenTo(this.getModel(), 'change:' + this.options.column.name, this.update);
3501
3536
  this.setupContentBinding();
3502
3537
  this.update();
@@ -3504,20 +3539,20 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3504
3539
  /**
3505
3540
  * Override in concrete cell view.
3506
3541
  */
3507
- update: function update() {
3542
+ update: function () {
3508
3543
  throw 'Not implemented';
3509
3544
  },
3510
3545
  /**
3511
3546
  * Returns the column attribute's value in the row model.
3512
3547
  */
3513
- attributeValue: function attributeValue() {
3548
+ attributeValue: function () {
3514
3549
  if (typeof this.options.column.value == 'function') {
3515
3550
  return this.options.column.value(this.model);
3516
3551
  } else {
3517
3552
  return this.getModel().get(this.options.column.name);
3518
3553
  }
3519
3554
  },
3520
- getModel: function getModel() {
3555
+ getModel: function () {
3521
3556
  if (this.options.column.configurationAttribute) {
3522
3557
  return this.model.configuration;
3523
3558
  } else {
@@ -3542,10 +3577,10 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3542
3577
  * // Looks for keys of the form:
3543
3578
  * // <table_view_translation_key_prefix>.<column_attribute>.cell_title
3544
3579
  */
3545
- attributeTranslation: function attributeTranslation(keyName, options) {
3580
+ attributeTranslation: function (keyName, options) {
3546
3581
  return findTranslation(this.attributeTranslationKeys(keyName), options);
3547
3582
  },
3548
- attributeTranslationKeys: function attributeTranslationKeys(keyName) {
3583
+ attributeTranslationKeys: function (keyName) {
3549
3584
  return _(this.options.attributeTranslationKeyPrefixes || []).map(function (prefix) {
3550
3585
  return prefix + '.' + this.options.column.name + '.' + keyName;
3551
3586
  }, this);
@@ -3559,7 +3594,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3559
3594
  *
3560
3595
  * @protected
3561
3596
  */
3562
- setupContentBinding: function setupContentBinding() {
3597
+ setupContentBinding: function () {
3563
3598
  if (this.options.column.contentBinding) {
3564
3599
  this.listenTo(this.getModel(), 'change:' + this.options.column.contentBinding, this.update);
3565
3600
  this.update();
@@ -3567,30 +3602,30 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3567
3602
  }
3568
3603
  });
3569
3604
 
3570
- var TableHeaderCellView = TableCellView.extend({
3605
+ const TableHeaderCellView = TableCellView.extend({
3571
3606
  tagName: 'th',
3572
- render: function render() {
3607
+ render: function () {
3573
3608
  this.$el.text(this.options.column.headerText || this.attributeTranslation('column_header'));
3574
3609
  this.$el.data('columnName', this.options.column.name);
3575
3610
  return this;
3576
3611
  }
3577
3612
  });
3578
3613
 
3579
- var TableRowView = Marionette.View.extend({
3614
+ const TableRowView = Marionette.View.extend({
3580
3615
  tagName: 'tr',
3581
3616
  events: {
3582
- 'click': function click() {
3617
+ 'click': function () {
3583
3618
  if (this.options.selection) {
3584
3619
  this.options.selection.set(this.selectionAttribute(), this.model);
3585
3620
  }
3586
3621
  }
3587
3622
  },
3588
- initialize: function initialize() {
3623
+ initialize: function () {
3589
3624
  if (this.options.selection) {
3590
3625
  this.listenTo(this.options.selection, 'change', this.updateClassName);
3591
3626
  }
3592
3627
  },
3593
- render: function render() {
3628
+ render: function () {
3594
3629
  _(this.options.columns).each(function (column) {
3595
3630
  this.appendSubview(new column.cellView(_.extend({
3596
3631
  model: this.model,
@@ -3601,13 +3636,13 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3601
3636
  this.updateClassName();
3602
3637
  return this;
3603
3638
  },
3604
- updateClassName: function updateClassName() {
3639
+ updateClassName: function () {
3605
3640
  this.$el.toggleClass('is_selected', this.isSelected());
3606
3641
  },
3607
- isSelected: function isSelected() {
3642
+ isSelected: function () {
3608
3643
  return this.options.selection && this.options.selection.get(this.selectionAttribute()) === this.model;
3609
3644
  },
3610
- selectionAttribute: function selectionAttribute() {
3645
+ selectionAttribute: function () {
3611
3646
  return this.options.selectionAttribute || 'current';
3612
3647
  }
3613
3648
  });
@@ -3628,7 +3663,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3628
3663
  return __p
3629
3664
  }
3630
3665
 
3631
- var TableView = Marionette.ItemView.extend({
3666
+ const TableView = Marionette.ItemView.extend({
3632
3667
  tagName: 'table',
3633
3668
  className: 'table_view',
3634
3669
  template: template$2,
@@ -3636,7 +3671,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3636
3671
  headRow: 'thead tr',
3637
3672
  body: 'tbody'
3638
3673
  },
3639
- onRender: function onRender() {
3674
+ onRender: function () {
3640
3675
  var view = this;
3641
3676
  _(this.options.columns).each(function (column) {
3642
3677
  this.ui.headRow.append(this.subview(new TableHeaderCellView({
@@ -3658,7 +3693,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3658
3693
  tagName: 'tr',
3659
3694
  className: 'blank_slate',
3660
3695
  template: blankSlateTemplate,
3661
- serializeData: function serializeData() {
3696
+ serializeData: function () {
3662
3697
  return {
3663
3698
  blankSlateText: view.options.blankSlateText,
3664
3699
  colSpan: view.options.columns.length
@@ -3675,18 +3710,18 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3675
3710
  return __p
3676
3711
  }
3677
3712
 
3678
- var TooltipView = Marionette.ItemView.extend({
3713
+ const TooltipView = Marionette.ItemView.extend({
3679
3714
  template: template$3,
3680
3715
  className: 'tooltip',
3681
3716
  ui: {
3682
3717
  label: '.label'
3683
3718
  },
3684
- hide: function hide() {
3719
+ hide: function () {
3685
3720
  this.visible = false;
3686
3721
  clearTimeout(this.timeout);
3687
3722
  this.$el.removeClass('visible');
3688
3723
  },
3689
- show: function show(text, position, options) {
3724
+ show: function (text, position, options) {
3690
3725
  options = options || {};
3691
3726
  this.visible = true;
3692
3727
  clearTimeout(this.timeout);
@@ -3716,99 +3751,36 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3716
3751
  }
3717
3752
  });
3718
3753
 
3719
- function _defineProperty$1(obj, key, value) {
3720
- if (key in obj) {
3721
- Object.defineProperty(obj, key, {
3722
- value: value,
3723
- enumerable: true,
3724
- configurable: true,
3725
- writable: true
3726
- });
3727
- } else {
3728
- obj[key] = value;
3729
- }
3730
-
3731
- return obj;
3732
- }
3733
-
3734
- function ownKeys$1(object, enumerableOnly) {
3735
- var keys = Object.keys(object);
3736
-
3737
- if (Object.getOwnPropertySymbols) {
3738
- var symbols = Object.getOwnPropertySymbols(object);
3739
- if (enumerableOnly) symbols = symbols.filter(function (sym) {
3740
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
3741
- });
3742
- keys.push.apply(keys, symbols);
3743
- }
3744
-
3745
- return keys;
3746
- }
3747
-
3748
- function _objectSpread2$1(target) {
3749
- for (var i = 1; i < arguments.length; i++) {
3750
- var source = arguments[i] != null ? arguments[i] : {};
3751
-
3752
- if (i % 2) {
3753
- ownKeys$1(Object(source), true).forEach(function (key) {
3754
- _defineProperty$1(target, key, source[key]);
3755
- });
3756
- } else if (Object.getOwnPropertyDescriptors) {
3757
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
3758
- } else {
3759
- ownKeys$1(Object(source)).forEach(function (key) {
3760
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
3761
- });
3762
- }
3763
- }
3764
-
3765
- return target;
3766
- }
3767
-
3768
- var attributeBinding = {
3769
- setupBooleanAttributeBinding: function setupBooleanAttributeBinding(optionName, updateMethod) {
3754
+ const attributeBinding = {
3755
+ setupBooleanAttributeBinding(optionName, updateMethod) {
3770
3756
  this.setupAttributeBinding(optionName, updateMethod, Boolean);
3771
3757
  },
3772
- getBooleanAttributBoundOption: function getBooleanAttributBoundOption(optionName) {
3758
+ getBooleanAttributBoundOption(optionName) {
3773
3759
  return this.getAttributeBoundOption(optionName, Boolean);
3774
3760
  },
3775
- setupAttributeBinding: function setupAttributeBinding(optionName, updateMethod) {
3776
- var _this = this;
3777
- var normalize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function (value) {
3778
- return value;
3779
- };
3780
- var binding = this.options["".concat(optionName, "Binding")];
3781
- var model = this.options["".concat(optionName, "BindingModel")] || this.model;
3782
- var view = this;
3783
- if (binding) {
3784
- _.flatten([binding]).forEach(function (attribute) {
3785
- _this.listenTo(model, 'change:' + attribute, update);
3786
- });
3787
- }
3788
- update();
3789
- function update() {
3790
- updateMethod.call(view, view.getAttributeBoundOption(optionName, normalize));
3791
- }
3761
+ setupAttributeBinding(optionName, updateMethod, normalize = value => value) {
3762
+ const binding = this.options[`${optionName}Binding`];
3763
+ const model = this.options[`${optionName}BindingModel`] || this.model;
3764
+ setup({
3765
+ binding,
3766
+ model,
3767
+ listener: this,
3768
+ normalize,
3769
+ option: this.options[optionName],
3770
+ bindingValue: this.options[`${optionName}BindingValue`],
3771
+ callback: value => updateMethod.call(this, value)
3772
+ });
3792
3773
  },
3793
- getAttributeBoundOption: function getAttributeBoundOption(optionName) {
3794
- var normalize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (value) {
3795
- return value;
3796
- };
3797
- var binding = this.options["".concat(optionName, "Binding")];
3798
- var model = this.options["".concat(optionName, "BindingModel")] || this.model;
3799
- var bindingValueOptionName = "".concat(optionName, "BindingValue");
3800
- var value = Array.isArray(binding) ? binding.map(function (attribute) {
3801
- return model.get(attribute);
3802
- }) : model.get(binding);
3803
- if (bindingValueOptionName in this.options) {
3804
- return value === this.options[bindingValueOptionName];
3805
- } else if (typeof this.options[optionName] === 'function') {
3806
- return normalize(this.options[optionName](value));
3807
- } else if (optionName in this.options) {
3808
- return normalize(this.options[optionName]);
3809
- } else if (binding) {
3810
- return normalize(value);
3811
- }
3774
+ getAttributeBoundOption(optionName, normalize = value => value) {
3775
+ const binding = this.options[`${optionName}Binding`];
3776
+ const model = this.options[`${optionName}BindingModel`] || this.model;
3777
+ return resolve({
3778
+ binding,
3779
+ model,
3780
+ normalize,
3781
+ option: this.options[optionName],
3782
+ bindingValue: this.options[`${optionName}BindingValue`]
3783
+ });
3812
3784
  }
3813
3785
  };
3814
3786
 
@@ -3901,6 +3873,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3901
3873
  * An array of prefixes to lookup translations for labels and
3902
3874
  * inline help texts based on attribute names.
3903
3875
  *
3876
+ * @param {string} [options.attributeTranslationPropertyName]
3877
+ * Use this property name instead of `propertyName` for looking up
3878
+ * translations. Useful when the property name has been transformed
3879
+ * but translations should use the original name.
3880
+ *
3904
3881
  * @param {string} [options.additionalInlineHelpText]
3905
3882
  * A text that will be appended to the translation based inline
3906
3883
  * text.
@@ -3946,7 +3923,8 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3946
3923
  *
3947
3924
  * @mixin
3948
3925
  */
3949
- var inputView = _objectSpread2$1(_objectSpread2$1({}, attributeBinding), {}, {
3926
+ const inputView = {
3927
+ ...attributeBinding,
3950
3928
  ui: {
3951
3929
  label: 'label',
3952
3930
  labelText: 'label .name',
@@ -3974,19 +3952,22 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3974
3952
  * @since 0.9
3975
3953
  * @member
3976
3954
  */
3977
- attributeTranslationKeys: function attributeTranslationKeys$1(keyName, options) {
3978
- return attributeTranslationKeys(this.options.propertyName, keyName, _.extend({
3955
+ attributeTranslationKeys: function (keyName, options) {
3956
+ return attributeTranslationKeys(this.options.attributeTranslationPropertyName || this.options.propertyName, keyName, _.extend({
3979
3957
  prefixes: this.options.attributeTranslationKeyPrefixes,
3980
3958
  fallbackModelI18nKey: this.model.i18nKey
3981
3959
  }, options || {}));
3982
3960
  },
3983
- onRender: function onRender() {
3961
+ onRender: function () {
3984
3962
  this.$el.addClass('input');
3985
3963
  this.$el.addClass(this.model.modelName + '_' + this.options.propertyName);
3986
3964
  this.$el.data('inputPropertyName', this.options.propertyName);
3987
3965
  this.$el.data('labelText', this.labelText());
3988
3966
  this.$el.data('inlineHelpText', this.inlineHelpText());
3989
3967
  this.ui.labelText.text(this.labelText());
3968
+ if (this.options.hideLabel) {
3969
+ this.ui.label.addClass('visually_hidden');
3970
+ }
3990
3971
  this.updateInlineHelp();
3991
3972
  this.setLabelFor();
3992
3973
  this.setupBooleanAttributeBinding('disabled', this.updateDisabled);
@@ -3996,15 +3977,15 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
3996
3977
  * The label to display in the form.
3997
3978
  * @return {string}
3998
3979
  */
3999
- labelText: function labelText() {
3980
+ labelText: function () {
4000
3981
  return this.options.label || this.localizedAttributeName();
4001
3982
  },
4002
- localizedAttributeName: function localizedAttributeName() {
3983
+ localizedAttributeName: function () {
4003
3984
  return findTranslation(this.attributeTranslationKeys('label', {
4004
3985
  fallbackPrefix: 'activerecord.attributes'
4005
3986
  }));
4006
3987
  },
4007
- updateInlineHelp: function updateInlineHelp() {
3988
+ updateInlineHelp: function () {
4008
3989
  this.ui.inlineHelp.html(this.inlineHelpText());
4009
3990
  if (!this.inlineHelpText()) {
4010
3991
  this.ui.inlineHelp.hide();
@@ -4014,7 +3995,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4014
3995
  * The inline help text for the form field.
4015
3996
  * @return {string}
4016
3997
  */
4017
- inlineHelpText: function inlineHelpText() {
3998
+ inlineHelpText: function () {
4018
3999
  var keys = this.attributeTranslationKeys('inline_help', {
4019
4000
  fallbackPrefix: 'pageflow.ui.inline_help'
4020
4001
  });
@@ -4026,34 +4007,34 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4026
4007
  html: true
4027
4008
  }), this.options.additionalInlineHelpText]).join(' ');
4028
4009
  },
4029
- setLabelFor: function setLabelFor() {
4010
+ setLabelFor() {
4030
4011
  if (this.ui.input && this.ui.label.length === 1 && !this.ui.input.attr('id')) {
4031
- var id = 'input_' + this.model.modelName + '_' + this.options.propertyName;
4012
+ const id = 'input_' + this.model.modelName + '_' + this.options.propertyName;
4032
4013
  this.ui.input.attr('id', id);
4033
4014
  this.ui.label.attr('for', id);
4034
4015
  }
4035
4016
  },
4036
- isDisabled: function isDisabled() {
4017
+ isDisabled: function () {
4037
4018
  return this.getBooleanAttributBoundOption('disabled');
4038
4019
  },
4039
- updateDisabled: function updateDisabled() {
4020
+ updateDisabled: function () {
4040
4021
  this.$el.toggleClass('input-disabled', !!this.isDisabled());
4041
4022
  this.updateInlineHelp();
4042
4023
  if (this.ui.input) {
4043
4024
  this.updateDisabledAttribute(this.ui.input);
4044
4025
  }
4045
4026
  },
4046
- updateDisabledAttribute: function updateDisabledAttribute(element) {
4027
+ updateDisabledAttribute: function (element) {
4047
4028
  if (this.isDisabled()) {
4048
4029
  element.attr('disabled', true);
4049
4030
  } else {
4050
4031
  element.removeAttr('disabled');
4051
4032
  }
4052
4033
  },
4053
- updateVisible: function updateVisible() {
4034
+ updateVisible: function () {
4054
4035
  this.$el.toggleClass('hidden_via_binding', this.getBooleanAttributBoundOption('visible') === false);
4055
4036
  }
4056
- });
4037
+ };
4057
4038
 
4058
4039
  function template$4(data) {
4059
4040
  var __p = '';
@@ -4069,7 +4050,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4069
4050
  *
4070
4051
  * @class
4071
4052
  */
4072
- var CheckBoxGroupInputView = Marionette.ItemView.extend({
4053
+ const CheckBoxGroupInputView = Marionette.ItemView.extend({
4073
4054
  mixins: [inputView],
4074
4055
  template: template$4,
4075
4056
  className: 'check_box_group_input',
@@ -4080,7 +4061,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4080
4061
  label: 'label',
4081
4062
  container: '.check_boxes_container'
4082
4063
  },
4083
- initialize: function initialize() {
4064
+ initialize: function () {
4084
4065
  if (!this.options.texts) {
4085
4066
  if (!this.options.translationKeys) {
4086
4067
  var translationKeyPrefix = this.options.translationKeyPrefix || findKeyWithTranslation(this.attributeTranslationKeys('values', {
@@ -4095,26 +4076,26 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4095
4076
  });
4096
4077
  }
4097
4078
  },
4098
- onRender: function onRender() {
4079
+ onRender: function () {
4099
4080
  this.ui.label.attr('for', this.cid);
4100
4081
  this.appendOptions();
4101
4082
  this.load();
4102
4083
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
4103
4084
  },
4104
- appendOptions: function appendOptions() {
4085
+ appendOptions: function () {
4105
4086
  _.each(this.options.values, function (value, index) {
4106
4087
  var option = '<div class="check_box">' + '<label><input type="checkbox" name="' + value + '" />' + this.options.texts[index] + '</label></div>';
4107
4088
  this.ui.container.append($(option));
4108
4089
  }, this);
4109
4090
  },
4110
- save: function save() {
4091
+ save: function () {
4111
4092
  var configured = {};
4112
4093
  _.each(this.ui.container.find('input'), function (input) {
4113
4094
  configured[$(input).attr('name')] = $(input).prop('checked');
4114
4095
  });
4115
4096
  this.model.set(this.options.propertyName, configured);
4116
4097
  },
4117
- load: function load() {
4098
+ load: function () {
4118
4099
  if (!this.isClosed) {
4119
4100
  _.each(this.options.values, function (value) {
4120
4101
  this.ui.container.find('input[name="' + value + '"]').prop('checked', this.model.get(this.options.propertyName)[value]);
@@ -4142,7 +4123,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4142
4123
  *
4143
4124
  * @class
4144
4125
  */
4145
- var UrlDisplayView = Marionette.ItemView.extend({
4126
+ const UrlDisplayView = Marionette.ItemView.extend({
4146
4127
  mixins: [inputView],
4147
4128
  template: template$5,
4148
4129
  ui: {
@@ -4152,43 +4133,21 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4152
4133
  'change': 'update'
4153
4134
  },
4154
4135
  events: {
4155
- 'click a': function clickA(event) {
4136
+ 'click a': function (event) {
4156
4137
  // Ensure default is not prevented by parent event listener.
4157
4138
  event.stopPropagation();
4158
4139
  }
4159
4140
  },
4160
- onRender: function onRender() {
4141
+ onRender: function () {
4161
4142
  this.update();
4162
4143
  },
4163
- update: function update() {
4144
+ update: function () {
4164
4145
  var url = this.model.get(this.options.propertyName || 'original_url');
4165
4146
  this.$el.toggle(this.model.isUploaded() && !_.isEmpty(url));
4166
4147
  this.ui.link.attr('href', url);
4167
4148
  }
4168
4149
  });
4169
4150
 
4170
- function _classCallCheck(instance, Constructor) {
4171
- if (!(instance instanceof Constructor)) {
4172
- throw new TypeError("Cannot call a class as a function");
4173
- }
4174
- }
4175
-
4176
- function _defineProperties(target, props) {
4177
- for (var i = 0; i < props.length; i++) {
4178
- var descriptor = props[i];
4179
- descriptor.enumerable = descriptor.enumerable || false;
4180
- descriptor.configurable = true;
4181
- if ("value" in descriptor) descriptor.writable = true;
4182
- Object.defineProperty(target, descriptor.key, descriptor);
4183
- }
4184
- }
4185
-
4186
- function _createClass(Constructor, protoProps, staticProps) {
4187
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
4188
- if (staticProps) _defineProperties(Constructor, staticProps);
4189
- return Constructor;
4190
- }
4191
-
4192
4151
  /**
4193
4152
  * Input view for a number.
4194
4153
  *
@@ -4201,84 +4160,73 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4201
4160
  *
4202
4161
  * @class
4203
4162
  */
4204
- var NumberInputView = Marionette.ItemView.extend({
4163
+ const NumberInputView = Marionette.ItemView.extend({
4205
4164
  mixins: [inputView],
4206
- template: function template() {
4207
- return "\n <label>\n <span class=\"name\"></span>\n <span class=\"inline_help\"></span>\n </label>\n <input type=\"text\" dir=\"auto\" />\n ";
4208
- },
4165
+ template: () => `
4166
+ <label>
4167
+ <span class="name"></span>
4168
+ <span class="inline_help"></span>
4169
+ </label>
4170
+ <input type="text" dir="auto" />
4171
+ `,
4209
4172
  ui: {
4210
4173
  input: 'input'
4211
4174
  },
4212
4175
  events: {
4213
4176
  'change': 'onChange'
4214
4177
  },
4215
- initialize: function initialize() {
4178
+ initialize() {
4216
4179
  this.parser = new NumberParser(this.options.locale);
4217
4180
  },
4218
- onRender: function onRender() {
4181
+ onRender: function () {
4219
4182
  this.load();
4220
4183
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
4221
4184
  },
4222
- onChange: function onChange() {
4185
+ onChange: function () {
4223
4186
  this.save();
4224
4187
  this.load();
4225
4188
  },
4226
- onClose: function onClose() {
4189
+ onClose: function () {
4227
4190
  this.save();
4228
4191
  },
4229
- save: function save() {
4230
- var inputValue = this.ui.input.val();
4192
+ save: function () {
4193
+ const inputValue = this.ui.input.val();
4231
4194
  this.model.set(this.options.propertyName, this.parser.parse(inputValue) || 0);
4232
4195
  },
4233
- load: function load() {
4234
- var input = this.ui.input;
4235
- var value = this.model.get(this.options.propertyName) || 0;
4196
+ load: function () {
4197
+ const input = this.ui.input;
4198
+ const value = this.model.get(this.options.propertyName) || 0;
4236
4199
  input.val(value.toLocaleString(this.options.locale, {
4237
4200
  useGrouping: false
4238
4201
  }));
4239
4202
  },
4240
- displayValidationError: function displayValidationError(message) {
4203
+ displayValidationError: function (message) {
4241
4204
  this.$el.addClass('invalid');
4242
4205
  this.ui.input.attr('title', message);
4243
4206
  },
4244
- resetValidationError: function resetValidationError(message) {
4207
+ resetValidationError: function (message) {
4245
4208
  this.$el.removeClass('invalid');
4246
4209
  this.ui.input.attr('title', '');
4247
4210
  }
4248
4211
  });
4249
- var NumberParser = /*#__PURE__*/function () {
4250
- function NumberParser(locale) {
4251
- _classCallCheck(this, NumberParser);
4252
- var format = new Intl.NumberFormat(locale);
4253
- var parts = format.formatToParts(12345.6);
4254
- var numerals = Array.from({
4212
+ class NumberParser {
4213
+ constructor(locale) {
4214
+ const format = new Intl.NumberFormat(locale);
4215
+ const parts = format.formatToParts(12345.6);
4216
+ const numerals = Array.from({
4255
4217
  length: 10
4256
- }).map(function (_, i) {
4257
- return format.format(i);
4258
- });
4259
- var index = new Map(numerals.map(function (d, i) {
4260
- return [d, i];
4261
- }));
4262
- this._group = new RegExp("[".concat(parts.find(function (d) {
4263
- return d.type === "group";
4264
- }).value, "]"), "g");
4265
- this._decimal = new RegExp("[".concat(parts.find(function (d) {
4266
- return d.type === "decimal";
4267
- }).value, "]"));
4268
- this._numeral = new RegExp("[".concat(numerals.join(""), "]"), "g");
4269
- this._index = function (d) {
4270
- return index.get(d);
4271
- };
4218
+ }).map((_, i) => format.format(i));
4219
+ const index = new Map(numerals.map((d, i) => [d, i]));
4220
+ this._group = new RegExp(`[${parts.find(d => d.type === "group").value}]`, "g");
4221
+ this._decimal = new RegExp(`[${parts.find(d => d.type === "decimal").value}]`);
4222
+ this._numeral = new RegExp(`[${numerals.join("")}]`, "g");
4223
+ this._index = d => index.get(d);
4272
4224
  }
4273
- _createClass(NumberParser, [{
4274
- key: "parse",
4275
- value: function parse(string) {
4276
- string = string.trim().replace(this._group, "").replace(this._decimal, ".").replace(this._numeral, this._index);
4277
- return string ? +string : NaN;
4278
- }
4279
- }]);
4280
- return NumberParser;
4281
- }();
4225
+ parse(string) {
4226
+ string = string.trim().replace(this._group, "").replace(this._decimal, ".").replace(this._numeral, this._index);
4227
+ return string ? +string : NaN;
4228
+ }
4229
+ }
4282
4230
 
4283
4231
  /**
4284
4232
  * Text based input view that can display a placeholder.
@@ -4301,20 +4249,20 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4301
4249
  * Obtain placeholder by looking up the configured `propertyName`
4302
4250
  * inside a given model.
4303
4251
  */
4304
- var inputWithPlaceholderText = {
4305
- onRender: function onRender() {
4252
+ const inputWithPlaceholderText = {
4253
+ onRender: function () {
4306
4254
  this.updatePlaceholder();
4307
4255
  if (this.options.placeholderBinding) {
4308
4256
  this.listenTo(this.model, 'change:' + this.options.placeholderBinding, this.updatePlaceholder);
4309
4257
  }
4310
4258
  },
4311
- updateDisabled: function updateDisabled() {
4259
+ updateDisabled: function () {
4312
4260
  this.updatePlaceholder();
4313
4261
  },
4314
- updatePlaceholder: function updatePlaceholder() {
4262
+ updatePlaceholder: function () {
4315
4263
  this.ui.input.attr('placeholder', this.placeholderText());
4316
4264
  },
4317
- placeholderText: function placeholderText() {
4265
+ placeholderText: function () {
4318
4266
  if (!this.isDisabled() || !this.options.hidePlaceholderIfDisabled) {
4319
4267
  if (this.options.placeholder) {
4320
4268
  if (typeof this.options.placeholder == 'function') {
@@ -4328,25 +4276,22 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4328
4276
  }
4329
4277
  return '';
4330
4278
  },
4331
- placeholderModelValue: function placeholderModelValue() {
4279
+ placeholderModelValue: function () {
4332
4280
  return this.options.placeholderModel && this.options.placeholderModel.get(this.options.propertyName);
4333
4281
  }
4334
4282
  };
4335
4283
 
4336
- var viewWithValidationErrorMessages = {
4337
- onRender: function onRender() {
4284
+ const viewWithValidationErrorMessages = {
4285
+ onRender() {
4338
4286
  this.listenTo(this.model, 'invalid sync', this.updateValidationErrorMessages);
4339
4287
  this.updateValidationErrorMessages();
4340
4288
  },
4341
- updateValidationErrorMessages: function updateValidationErrorMessages() {
4342
- var _this = this;
4343
- var errors = this.model.validationErrors && this.model.validationErrors[this.options.propertyName] || [];
4289
+ updateValidationErrorMessages() {
4290
+ const errors = this.model.validationErrors && this.model.validationErrors[this.options.propertyName] || [];
4344
4291
  if (errors.length) {
4345
4292
  this.validationErrorList = this.validationErrorList || $('<ul class="validation_error_messages" />').appendTo(this.el);
4346
4293
  this.validationErrorList.html('');
4347
- errors.forEach(function (error) {
4348
- return _this.validationErrorList.append("<li>".concat(error, "</li>"));
4349
- });
4294
+ errors.forEach(error => this.validationErrorList.append(`<li>${error}</li>`));
4350
4295
  this.$el.addClass('invalid');
4351
4296
  } else if (this.validationErrorList) {
4352
4297
  this.validationErrorList.remove();
@@ -4381,7 +4326,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4381
4326
  *
4382
4327
  * @class
4383
4328
  */
4384
- var TextInputView = Marionette.ItemView.extend({
4329
+ const TextInputView = Marionette.ItemView.extend({
4385
4330
  mixins: [inputView, inputWithPlaceholderText, viewWithValidationErrorMessages],
4386
4331
  template: template$6,
4387
4332
  ui: {
@@ -4390,25 +4335,25 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4390
4335
  events: {
4391
4336
  'change': 'onChange'
4392
4337
  },
4393
- onRender: function onRender() {
4338
+ onRender: function () {
4394
4339
  this.load();
4395
4340
  this.validate();
4396
4341
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
4397
4342
  },
4398
- onChange: function onChange() {
4343
+ onChange: function () {
4399
4344
  if (this.validate()) {
4400
4345
  this.save();
4401
4346
  }
4402
4347
  },
4403
- onClose: function onClose() {
4348
+ onClose: function () {
4404
4349
  if (this.validate()) {
4405
4350
  this.save();
4406
4351
  }
4407
4352
  },
4408
- save: function save() {
4353
+ save: function () {
4409
4354
  this.model.set(this.options.propertyName, this.ui.input.val());
4410
4355
  },
4411
- load: function load() {
4356
+ load: function () {
4412
4357
  var input = this.ui.input;
4413
4358
  input.val(this.model.get(this.options.propertyName));
4414
4359
 
@@ -4418,7 +4363,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4418
4363
  // for new and maxLength-conforming data: add validation
4419
4364
  this.validateMaxLength = input.val().length <= this.options.maxLength;
4420
4365
  },
4421
- validate: function validate() {
4366
+ validate: function () {
4422
4367
  var input = this.ui.input;
4423
4368
  if (this.options.required && !input.val()) {
4424
4369
  this.displayValidationError(I18n$1.t('pageflow.ui.views.inputs.text_input_view.required_field'));
@@ -4434,11 +4379,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4434
4379
  return true;
4435
4380
  }
4436
4381
  },
4437
- displayValidationError: function displayValidationError(message) {
4382
+ displayValidationError: function (message) {
4438
4383
  this.$el.addClass('invalid');
4439
4384
  this.ui.input.attr('title', message);
4440
4385
  },
4441
- resetValidationError: function resetValidationError(message) {
4386
+ resetValidationError: function (message) {
4442
4387
  this.$el.removeClass('invalid');
4443
4388
  this.ui.input.attr('title', '');
4444
4389
  }
@@ -4450,31 +4395,640 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4450
4395
  return __p
4451
4396
  }
4452
4397
 
4453
- var FileNameInputView = TextInputView.extend({
4398
+ const FileNameInputView = TextInputView.extend({
4454
4399
  template: template$7,
4455
4400
  className: 'file_name_input',
4456
4401
  ui: Object.assign({}, TextInputView.prototype.ui, {
4457
4402
  extension: '.file_name_input-extension'
4458
4403
  }),
4459
- onRender: function onRender() {
4404
+ onRender: function () {
4460
4405
  TextInputView.prototype.onRender.call(this);
4461
4406
  },
4462
- save: function save() {
4463
- var baseName = this.ui.input.val();
4464
- var extension = this.ui.extension.text();
4407
+ save: function () {
4408
+ const baseName = this.ui.input.val();
4409
+ const extension = this.ui.extension.text();
4465
4410
  this.model.set(this.options.propertyName, baseName + extension);
4466
4411
  },
4467
- load: function load() {
4468
- var fullName = this.model.get(this.options.propertyName) || '';
4469
- var match = fullName.match(/^(.*?)(\.[^.]+)?$/);
4470
- var baseName = match ? match[1] : fullName;
4471
- var extension = match && match[2] ? match[2] : '';
4412
+ load: function () {
4413
+ const fullName = this.model.get(this.options.propertyName) || '';
4414
+ const match = fullName.match(/^(.*?)(\.[^.]+)?$/);
4415
+ const baseName = match ? match[1] : fullName;
4416
+ const extension = match && match[2] ? match[2] : '';
4472
4417
  this.ui.input.val(baseName);
4473
4418
  this.ui.extension.text(extension);
4474
4419
  this.options.maxLength = this.options.maxLength || 255;
4475
4420
  }
4476
4421
  });
4477
4422
 
4423
+ // Inspired by https://github.com/mdbassit/Coloris
4424
+ const ctx = typeof OffscreenCanvas !== 'undefined' && new OffscreenCanvas(1, 1).getContext('2d');
4425
+ const DEFAULT_DISPLAY_COLOR = {
4426
+ r: 255,
4427
+ g: 255,
4428
+ b: 255,
4429
+ a: 1
4430
+ };
4431
+ let nextDescriptionId = 0;
4432
+ const PICKER_HTML = '<div class="color_picker-gradient" role="application">' + '<div class="color_picker-marker" tabindex="0"></div>' + '</div>' + '<div class="color_picker-hue">' + '<input type="range" min="0" max="360" step="1">' + '<div></div>' + '</div>' + '<div class="color_picker-alpha">' + '<input type="range" min="0" max="100" step="1">' + '<div></div>' + '<span></span>' + '</div>' + '<div class="color_picker-swatches"></div>';
4433
+ class ColorPicker {
4434
+ constructor(input, options = {}) {
4435
+ this._input = input;
4436
+ this._colorAreaDims = {};
4437
+ this._alpha = options.alpha || false;
4438
+ this._onChange = options.onChange;
4439
+ this._defaultColor = strToRGBA(options.defaultValue);
4440
+ this._fallbackColor = strToRGBA(options.fallbackColor);
4441
+ this._fallbackColorDescription = options.fallbackColorDescription;
4442
+ this._swatches = options.swatches || [];
4443
+ this._wrapInput();
4444
+ this._createPicker();
4445
+ this._renderSwatches();
4446
+ this._bindEvents();
4447
+ this._updateColor(strToRGBA(this._input.value), {
4448
+ silent: true
4449
+ });
4450
+ }
4451
+ setValue(str) {
4452
+ this._input.value = str || '';
4453
+ this._updateColor(strToRGBA(str), {
4454
+ silent: true
4455
+ });
4456
+ }
4457
+ update(options) {
4458
+ if ('defaultValue' in options) {
4459
+ this._defaultColor = strToRGBA(options.defaultValue);
4460
+ }
4461
+ if ('fallbackColor' in options) {
4462
+ this._fallbackColor = strToRGBA(options.fallbackColor);
4463
+ this._updateColor(this._currentColor, {
4464
+ silent: true
4465
+ });
4466
+ }
4467
+ if (options.swatches) {
4468
+ this._swatches = options.swatches;
4469
+ this._renderSwatches();
4470
+ }
4471
+ }
4472
+ destroy() {
4473
+ this._close();
4474
+ this._unbindEvents();
4475
+ this._picker.remove();
4476
+ this._unwrapInput();
4477
+ }
4478
+
4479
+ // Setup
4480
+
4481
+ _createPicker() {
4482
+ this._picker = document.createElement('div');
4483
+ this._picker.className = 'color_picker';
4484
+ this._picker.classList.toggle('color_picker-no_alpha', !this._alpha);
4485
+ this._picker.innerHTML = PICKER_HTML;
4486
+ this._input.parentNode.appendChild(this._picker);
4487
+ this._colorArea = this._picker.querySelector('.color_picker-gradient');
4488
+ this._colorMarker = this._picker.querySelector('.color_picker-marker');
4489
+ this._hueSlider = this._picker.querySelector('.color_picker-hue input');
4490
+ this._hueMarker = this._picker.querySelector('.color_picker-hue div');
4491
+ this._alphaSlider = this._picker.querySelector('.color_picker-alpha input');
4492
+ this._alphaMarker = this._picker.querySelector('.color_picker-alpha div');
4493
+ this._swatchesContainer = this._picker.querySelector('.color_picker-swatches');
4494
+ this._hueSlider.setAttribute('aria-label', I18n$1.t('pageflow.ui.color_picker.hue'));
4495
+ if (this._alpha) {
4496
+ this._alphaSlider.setAttribute('aria-label', I18n$1.t('pageflow.ui.color_picker.opacity'));
4497
+ }
4498
+ }
4499
+ _wrapInput() {
4500
+ const parent = this._input.parentNode;
4501
+ if (!parent.classList.contains('color_picker-field')) {
4502
+ const wrapper = document.createElement('div');
4503
+ wrapper.innerHTML = '<span></span>';
4504
+ parent.insertBefore(wrapper, this._input);
4505
+ wrapper.className = 'color_picker-field';
4506
+ wrapper.appendChild(this._input);
4507
+ if (this._fallbackColorDescription) {
4508
+ this._descriptionElement = document.createElement('span');
4509
+ this._descriptionElement.hidden = true;
4510
+ this._descriptionElement.id = 'color_picker_desc_' + nextDescriptionId++;
4511
+ wrapper.appendChild(this._descriptionElement);
4512
+ this._input.setAttribute('aria-describedby', this._descriptionElement.id);
4513
+ }
4514
+ }
4515
+ }
4516
+ _unwrapInput() {
4517
+ const wrapper = this._input.parentNode;
4518
+ if (wrapper && wrapper.classList.contains('color_picker-field')) {
4519
+ const parent = wrapper.parentNode;
4520
+ parent.insertBefore(this._input, wrapper);
4521
+ parent.removeChild(wrapper);
4522
+ }
4523
+ }
4524
+ _renderSwatches() {
4525
+ const swatches = this._swatches.map(normalizeSwatch).filter(swatch => this._alpha || !isTranslucentSwatch(swatch.value));
4526
+ this._swatchesContainer.textContent = '';
4527
+ this._swatchesContainer.classList.toggle('color_picker-empty', !swatches.length);
4528
+ if (!swatches.length) {
4529
+ return;
4530
+ }
4531
+ groupSwatches(swatches).forEach((group, index) => {
4532
+ if (index > 0) {
4533
+ const divider = document.createElement('span');
4534
+ divider.className = 'color_picker-swatch_divider';
4535
+ this._swatchesContainer.appendChild(divider);
4536
+ }
4537
+ group.swatches.forEach(({
4538
+ value,
4539
+ text
4540
+ }) => {
4541
+ const button = document.createElement('button');
4542
+ button.setAttribute('type', 'button');
4543
+ button.title = text;
4544
+ button.style.color = value;
4545
+ button.textContent = value;
4546
+ this._swatchesContainer.appendChild(button);
4547
+ });
4548
+ });
4549
+ }
4550
+
4551
+ // Lifecycle
4552
+
4553
+ _open() {
4554
+ if (this._picker.classList.contains('color_picker-open')) {
4555
+ return;
4556
+ }
4557
+ this._picker.classList.add('color_picker-open');
4558
+ this._updatePosition();
4559
+ this._setColorFromStr(this._input.value);
4560
+ this._addDocListeners();
4561
+ }
4562
+ _close() {
4563
+ if (!this._picker.classList.contains('color_picker-open')) {
4564
+ return;
4565
+ }
4566
+ this._picker.classList.remove('color_picker-open');
4567
+ this._removeDocListeners();
4568
+ }
4569
+ _updatePosition() {
4570
+ const margin = 2;
4571
+ const pickerHeight = this._picker.offsetHeight;
4572
+ const pickerWidth = this._picker.offsetWidth;
4573
+ const inputRect = this._input.getBoundingClientRect();
4574
+ const clipRect = getClipRect(this._input);
4575
+ const spaceBelow = clipRect.bottom - inputRect.bottom;
4576
+ const flipTop = pickerHeight + margin > spaceBelow && pickerHeight + margin <= inputRect.top - clipRect.top;
4577
+ this._picker.classList.toggle('color_picker-top', flipTop);
4578
+ if (flipTop) {
4579
+ this._picker.style.top = 'auto';
4580
+ this._picker.style.bottom = `calc(100% + ${margin}px)`;
4581
+ } else {
4582
+ this._picker.style.top = `calc(100% + ${margin}px)`;
4583
+ this._picker.style.bottom = '';
4584
+ }
4585
+ if (inputRect.left + pickerWidth > clipRect.right) {
4586
+ this._picker.style.left = 'auto';
4587
+ this._picker.style.right = '0';
4588
+ } else {
4589
+ this._picker.style.left = '0';
4590
+ this._picker.style.right = '';
4591
+ }
4592
+ const areaRect = this._colorArea.getBoundingClientRect();
4593
+ this._colorAreaDims = {
4594
+ width: this._colorArea.offsetWidth,
4595
+ height: this._colorArea.offsetHeight,
4596
+ x: areaRect.x + window.scrollX,
4597
+ y: areaRect.y + window.scrollY
4598
+ };
4599
+ }
4600
+
4601
+ // Color interaction
4602
+
4603
+ _setColorFromStr(str, options) {
4604
+ this._updateColor(strToRGBA(str), options);
4605
+ const {
4606
+ h,
4607
+ s,
4608
+ v,
4609
+ a
4610
+ } = rgbaToHSVA(this._displayColor);
4611
+ this._hueSlider.value = h;
4612
+ this._picker.style.color = `hsl(${h}, 100%, 50%)`;
4613
+ this._hueMarker.style.left = `${h / 360 * 100}%`;
4614
+ this._colorMarker.style.left = `${this._colorAreaDims.width * s / 100}px`;
4615
+ this._colorMarker.style.top = `${this._colorAreaDims.height - this._colorAreaDims.height * v / 100}px`;
4616
+ this._alphaSlider.value = a * 100;
4617
+ this._alphaMarker.style.left = `${a * 100}%`;
4618
+ }
4619
+ _moveMarker(event) {
4620
+ let x = event.pageX - this._colorAreaDims.x;
4621
+ let y = event.pageY - this._colorAreaDims.y;
4622
+ this._setMarkerPosition(x, y);
4623
+ event.preventDefault();
4624
+ event.stopPropagation();
4625
+ }
4626
+ _moveMarkerOnKeydown(dx, dy) {
4627
+ let x = this._colorMarker.style.left.replace('px', '') * 1 + dx;
4628
+ let y = this._colorMarker.style.top.replace('px', '') * 1 + dy;
4629
+ this._setMarkerPosition(x, y);
4630
+ }
4631
+ _setHue() {
4632
+ const hue = this._hueSlider.value * 1;
4633
+ const x = this._colorMarker.style.left.replace('px', '') * 1;
4634
+ const y = this._colorMarker.style.top.replace('px', '') * 1;
4635
+ this._picker.style.color = `hsl(${hue}, 100%, 50%)`;
4636
+ this._hueMarker.style.left = `${hue / 360 * 100}%`;
4637
+ this._setColorAtPosition(x, y);
4638
+ }
4639
+ _setAlpha() {
4640
+ const alpha = this._alphaSlider.value / 100;
4641
+ this._alphaMarker.style.left = `${alpha * 100}%`;
4642
+ this._updateColor({
4643
+ a: alpha
4644
+ });
4645
+ this._syncInput();
4646
+ }
4647
+ _setMarkerPosition(x, y) {
4648
+ x = x < 0 ? 0 : x > this._colorAreaDims.width ? this._colorAreaDims.width : x;
4649
+ y = y < 0 ? 0 : y > this._colorAreaDims.height ? this._colorAreaDims.height : y;
4650
+ this._colorMarker.style.left = `${x}px`;
4651
+ this._colorMarker.style.top = `${y}px`;
4652
+ this._setColorAtPosition(x, y);
4653
+ this._colorMarker.focus();
4654
+ }
4655
+ _setColorAtPosition(x, y) {
4656
+ const hsva = {
4657
+ h: this._hueSlider.value * 1,
4658
+ s: x / this._colorAreaDims.width * 100,
4659
+ v: 100 - y / this._colorAreaDims.height * 100,
4660
+ a: this._alphaSlider.value / 100
4661
+ };
4662
+ const rgba = hsvaToRGBA(hsva);
4663
+ this._updateColor(rgba);
4664
+ this._syncInput();
4665
+ }
4666
+ _updateColor(rgba, {
4667
+ silent
4668
+ } = {}) {
4669
+ rgba = rgba || this._defaultColor;
4670
+ if (rgba && !this._alpha) rgba.a = 1;
4671
+ this._currentColor = rgba && {
4672
+ ...this._displayColor,
4673
+ ...rgba
4674
+ };
4675
+ this._displayColor = this._currentColor || this._fallbackColor || DEFAULT_DISPLAY_COLOR;
4676
+ const hex = rgbaToHex(this._displayColor);
4677
+ const opaqueHex = hex.substring(0, 7);
4678
+ this._colorMarker.style.color = opaqueHex;
4679
+ this._alphaMarker.parentNode.style.color = opaqueHex;
4680
+ this._alphaMarker.style.color = hex;
4681
+ const formatted = this._formatHex(this._currentColor);
4682
+ const fallbackHex = this._formatHex(this._fallbackColor);
4683
+ const wrapper = this._input.parentNode;
4684
+ if (wrapper && wrapper.classList.contains('color_picker-field')) {
4685
+ wrapper.style.color = formatted || fallbackHex || '';
4686
+ }
4687
+ if (this._descriptionElement) {
4688
+ this._descriptionElement.textContent = !formatted && fallbackHex ? `${this._fallbackColorDescription}: ${fallbackHex}` : '';
4689
+ }
4690
+
4691
+ // Force repaint the color and alpha gradients (Chrome workaround)
4692
+ this._colorArea.style.display = 'none';
4693
+ this._colorArea.offsetHeight;
4694
+ this._colorArea.style.display = '';
4695
+ this._alphaMarker.nextElementSibling.style.display = 'none';
4696
+ this._alphaMarker.nextElementSibling.offsetHeight;
4697
+ this._alphaMarker.nextElementSibling.style.display = '';
4698
+ if (!silent && this._onChange) this._onChange(formatted);
4699
+ }
4700
+ _syncInput() {
4701
+ this._input.value = this._formatHex(this._currentColor) || '';
4702
+ }
4703
+ _formatHex(rgba) {
4704
+ if (!rgba) return null;
4705
+ const hex = rgbaToHex(rgba);
4706
+ return rgba.a < 1 ? hex : hex.substring(0, 7);
4707
+ }
4708
+ _normalizeInputValue() {
4709
+ const hex = this._formatHex(this._currentColor) || '';
4710
+ if (hex !== this._input.value) {
4711
+ this._input.value = hex;
4712
+ }
4713
+ }
4714
+
4715
+ // Event wiring
4716
+
4717
+ _bindEvents() {
4718
+ this._onInputClick = () => {
4719
+ this._open();
4720
+ };
4721
+ this._onInputKeydown = event => {
4722
+ if (event.key === 'Enter') {
4723
+ this._normalizeInputValue();
4724
+ }
4725
+ if (this._picker.classList.contains('color_picker-open')) {
4726
+ return;
4727
+ }
4728
+ if (event.key === 'Enter' || event.key === 'ArrowDown' && event.altKey) {
4729
+ this._open();
4730
+ event.stopPropagation();
4731
+ }
4732
+ };
4733
+ this._onPickerMousedown = event => {
4734
+ this._picker.classList.remove('color_picker-keyboard_nav');
4735
+ event.stopPropagation();
4736
+ };
4737
+ this._onAreaPointerdown = event => {
4738
+ event.preventDefault();
4739
+ this._colorArea.setPointerCapture(event.pointerId);
4740
+ this._dragging = true;
4741
+ };
4742
+ this._onAreaPointermove = event => {
4743
+ if (this._dragging) {
4744
+ this._moveMarker(event);
4745
+ }
4746
+ };
4747
+ this._onAreaPointerup = () => {
4748
+ this._dragging = false;
4749
+ };
4750
+ this._onInputEvent = () => {
4751
+ if (this._picker.classList.contains('color_picker-open')) {
4752
+ this._setColorFromStr(this._input.value);
4753
+ } else {
4754
+ this._updateColor(strToRGBA(this._input.value));
4755
+ }
4756
+ };
4757
+ this._onSwatchClick = event => {
4758
+ if (event.target.closest('.color_picker-swatches button')) {
4759
+ this._setColorFromStr(event.target.closest('.color_picker-swatches button').textContent);
4760
+ this._syncInput();
4761
+ }
4762
+ };
4763
+ this._onMarkerKeydown = event => {
4764
+ const movements = {
4765
+ ArrowUp: [0, -1],
4766
+ ArrowDown: [0, 1],
4767
+ ArrowLeft: [-1, 0],
4768
+ ArrowRight: [1, 0]
4769
+ };
4770
+ if (movements[event.key]) {
4771
+ this._moveMarkerOnKeydown(...movements[event.key]);
4772
+ event.preventDefault();
4773
+ }
4774
+ };
4775
+ this._onAreaClick = event => this._moveMarker(event);
4776
+ this._onHueInput = () => this._setHue();
4777
+ this._onAlphaInput = () => this._setAlpha();
4778
+ const wrapper = this._input.parentNode;
4779
+ this._onFocusout = event => {
4780
+ if (event.target === this._input) {
4781
+ this._normalizeInputValue();
4782
+ }
4783
+ if (this._picker.classList.contains('color_picker-open')) {
4784
+ if (event.relatedTarget && !wrapper.contains(event.relatedTarget)) {
4785
+ this._close();
4786
+ }
4787
+ }
4788
+ };
4789
+ this._input.addEventListener('click', this._onInputClick);
4790
+ this._input.addEventListener('keydown', this._onInputKeydown);
4791
+ this._input.addEventListener('input', this._onInputEvent);
4792
+ wrapper.addEventListener('focusout', this._onFocusout);
4793
+ this._picker.addEventListener('mousedown', this._onPickerMousedown);
4794
+ this._colorArea.addEventListener('pointerdown', this._onAreaPointerdown);
4795
+ this._colorArea.addEventListener('pointermove', this._onAreaPointermove);
4796
+ this._colorArea.addEventListener('pointerup', this._onAreaPointerup);
4797
+ this._swatchesContainer.addEventListener('click', this._onSwatchClick);
4798
+ this._colorMarker.addEventListener('keydown', this._onMarkerKeydown);
4799
+ this._colorArea.addEventListener('click', this._onAreaClick);
4800
+ this._hueSlider.addEventListener('input', this._onHueInput);
4801
+ this._alphaSlider.addEventListener('input', this._onAlphaInput);
4802
+ }
4803
+ _unbindEvents() {
4804
+ this._input.removeEventListener('click', this._onInputClick);
4805
+ this._input.removeEventListener('keydown', this._onInputKeydown);
4806
+ this._input.removeEventListener('input', this._onInputEvent);
4807
+ const wrapper = this._input.parentNode;
4808
+ if (wrapper && wrapper.classList.contains('color_picker-field')) {
4809
+ wrapper.removeEventListener('focusout', this._onFocusout);
4810
+ }
4811
+ this._picker.removeEventListener('mousedown', this._onPickerMousedown);
4812
+ this._colorArea.removeEventListener('pointerdown', this._onAreaPointerdown);
4813
+ this._colorArea.removeEventListener('pointermove', this._onAreaPointermove);
4814
+ this._colorArea.removeEventListener('pointerup', this._onAreaPointerup);
4815
+ this._swatchesContainer.removeEventListener('click', this._onSwatchClick);
4816
+ this._colorMarker.removeEventListener('keydown', this._onMarkerKeydown);
4817
+ this._colorArea.removeEventListener('click', this._onAreaClick);
4818
+ this._hueSlider.removeEventListener('input', this._onHueInput);
4819
+ this._alphaSlider.removeEventListener('input', this._onAlphaInput);
4820
+ this._removeDocListeners();
4821
+ }
4822
+ _addDocListeners() {
4823
+ this._onDocMousedown = event => {
4824
+ this._picker.classList.remove('color_picker-keyboard_nav');
4825
+ if (!this._input.parentNode.contains(event.target)) {
4826
+ this._close();
4827
+ }
4828
+ };
4829
+ this._onDocKeydown = event => {
4830
+ if (event.key === 'Escape' || event.key === 'Enter' && event.target.tagName !== 'BUTTON') {
4831
+ this._close();
4832
+ this._input.focus({
4833
+ preventScroll: true
4834
+ });
4835
+ return;
4836
+ }
4837
+ const navKeys = ['Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
4838
+ if (navKeys.includes(event.key)) {
4839
+ this._picker.classList.add('color_picker-keyboard_nav');
4840
+ }
4841
+ };
4842
+ document.addEventListener('mousedown', this._onDocMousedown);
4843
+ document.addEventListener('keydown', this._onDocKeydown);
4844
+ }
4845
+ _removeDocListeners() {
4846
+ if (this._onDocMousedown) {
4847
+ document.removeEventListener('mousedown', this._onDocMousedown);
4848
+ document.removeEventListener('keydown', this._onDocKeydown);
4849
+ }
4850
+ }
4851
+ }
4852
+ function strToRGBA(str) {
4853
+ if (!str) return null;
4854
+ const regex = /^((rgba)|rgb)[\D]+([\d.]+)[\D]+([\d.]+)[\D]+([\d.]+)[\D]*?([\d.]+|$)/i;
4855
+ let match, rgba;
4856
+ if (!ctx) {
4857
+ match = regex.exec(str);
4858
+ if (match) {
4859
+ return {
4860
+ r: match[3] * 1,
4861
+ g: match[4] * 1,
4862
+ b: match[5] * 1,
4863
+ a: match[6] * 1 || 1
4864
+ };
4865
+ }
4866
+ if (!/^#[0-9a-f]{3,8}$/i.test(str)) return null;
4867
+ let hex = str.replace('#', '');
4868
+ if (hex.length === 3 || hex.length === 4) {
4869
+ hex = hex.split('').map(c => c + c).join('');
4870
+ }
4871
+ if (hex.length !== 6 && hex.length !== 8) return null;
4872
+ match = hex.match(/.{2}/g).map(h => parseInt(h, 16));
4873
+ return {
4874
+ r: match[0],
4875
+ g: match[1],
4876
+ b: match[2],
4877
+ a: match[3] !== undefined ? match[3] / 255 : 1
4878
+ };
4879
+ }
4880
+ ctx.fillStyle = '#010101';
4881
+ ctx.fillStyle = str;
4882
+ if (ctx.fillStyle === '#010101') {
4883
+ ctx.fillStyle = '#020202';
4884
+ ctx.fillStyle = str;
4885
+ if (ctx.fillStyle === '#020202') return null;
4886
+ }
4887
+ match = regex.exec(ctx.fillStyle);
4888
+ if (match) {
4889
+ rgba = {
4890
+ r: match[3] * 1,
4891
+ g: match[4] * 1,
4892
+ b: match[5] * 1,
4893
+ a: match[6] * 1
4894
+ };
4895
+ } else {
4896
+ match = ctx.fillStyle.replace('#', '').match(/.{2}/g).map(h => parseInt(h, 16));
4897
+ rgba = {
4898
+ r: match[0],
4899
+ g: match[1],
4900
+ b: match[2],
4901
+ a: 1
4902
+ };
4903
+ }
4904
+ return rgba;
4905
+ }
4906
+ function rgbaToHSVA(rgba) {
4907
+ const red = rgba.r / 255;
4908
+ const green = rgba.g / 255;
4909
+ const blue = rgba.b / 255;
4910
+ const xmax = Math.max(red, green, blue);
4911
+ const xmin = Math.min(red, green, blue);
4912
+ const chroma = xmax - xmin;
4913
+ const value = xmax;
4914
+ let hue = 0;
4915
+ let saturation = 0;
4916
+ if (chroma) {
4917
+ if (xmax === red) {
4918
+ hue = (green - blue) / chroma;
4919
+ }
4920
+ if (xmax === green) {
4921
+ hue = 2 + (blue - red) / chroma;
4922
+ }
4923
+ if (xmax === blue) {
4924
+ hue = 4 + (red - green) / chroma;
4925
+ }
4926
+ if (xmax) {
4927
+ saturation = chroma / xmax;
4928
+ }
4929
+ }
4930
+ hue = Math.floor(hue * 60);
4931
+ return {
4932
+ h: hue < 0 ? hue + 360 : hue,
4933
+ s: Math.round(saturation * 100),
4934
+ v: Math.round(value * 100),
4935
+ a: rgba.a
4936
+ };
4937
+ }
4938
+ function hsvaToRGBA(hsva) {
4939
+ const saturation = hsva.s / 100;
4940
+ const value = hsva.v / 100;
4941
+ let chroma = saturation * value;
4942
+ let hueBy60 = hsva.h / 60;
4943
+ let x = chroma * (1 - Math.abs(hueBy60 % 2 - 1));
4944
+ let m = value - chroma;
4945
+ chroma = chroma + m;
4946
+ x = x + m;
4947
+ const index = Math.floor(hueBy60) % 6;
4948
+ const red = [chroma, x, m, m, x, chroma][index];
4949
+ const green = [x, chroma, chroma, x, m, m][index];
4950
+ const blue = [m, m, x, chroma, chroma, x][index];
4951
+ return {
4952
+ r: Math.round(red * 255),
4953
+ g: Math.round(green * 255),
4954
+ b: Math.round(blue * 255),
4955
+ a: hsva.a
4956
+ };
4957
+ }
4958
+ function rgbaToHex(rgba) {
4959
+ let R = rgba.r.toString(16);
4960
+ let G = rgba.g.toString(16);
4961
+ let B = rgba.b.toString(16);
4962
+ let A = Math.round(rgba.a * 255).toString(16);
4963
+ if (rgba.r < 16) {
4964
+ R = '0' + R;
4965
+ }
4966
+ if (rgba.g < 16) {
4967
+ G = '0' + G;
4968
+ }
4969
+ if (rgba.b < 16) {
4970
+ B = '0' + B;
4971
+ }
4972
+ if (rgba.a * 255 < 16) {
4973
+ A = '0' + A;
4974
+ }
4975
+ return '#' + R + G + B + A;
4976
+ }
4977
+ function getClipRect(element) {
4978
+ const viewport = {
4979
+ top: 0,
4980
+ left: 0,
4981
+ right: document.documentElement.clientWidth,
4982
+ bottom: document.documentElement.clientHeight
4983
+ };
4984
+ let ancestor = element.parentElement;
4985
+ while (ancestor && ancestor !== document.documentElement) {
4986
+ const overflow = getComputedStyle(ancestor).overflow;
4987
+ if (overflow !== 'visible') {
4988
+ const rect = ancestor.getBoundingClientRect();
4989
+ return {
4990
+ top: Math.max(viewport.top, rect.top),
4991
+ left: Math.max(viewport.left, rect.left),
4992
+ right: Math.min(viewport.right, rect.right),
4993
+ bottom: Math.min(viewport.bottom, rect.bottom)
4994
+ };
4995
+ }
4996
+ ancestor = ancestor.parentElement;
4997
+ }
4998
+ return viewport;
4999
+ }
5000
+ function isTranslucentSwatch(str) {
5001
+ return str.length > 7 && str.slice(-2).toLowerCase() !== 'ff';
5002
+ }
5003
+ function normalizeSwatch(swatch) {
5004
+ return typeof swatch === 'string' ? {
5005
+ value: swatch,
5006
+ text: swatch
5007
+ } : {
5008
+ value: swatch.value,
5009
+ text: swatch.text || swatch.value,
5010
+ group: swatch.group
5011
+ };
5012
+ }
5013
+ function groupSwatches(swatches) {
5014
+ const groups = [];
5015
+ const groupsByKey = new Map();
5016
+ swatches.forEach(swatch => {
5017
+ const key = swatch.group || '';
5018
+ let group = groupsByKey.get(key);
5019
+ if (!group) {
5020
+ group = {
5021
+ key,
5022
+ swatches: []
5023
+ };
5024
+ groupsByKey.set(key, group);
5025
+ groups.push(group);
5026
+ }
5027
+ group.swatches.push(swatch);
5028
+ });
5029
+ return groups;
5030
+ }
5031
+
4478
5032
  function template$8(data) {
4479
5033
  var __p = '';
4480
5034
  __p += '<label>\n <span class="name"></span>\n <span class="inline_help"></span>\n</label>\n<input type="text" dir="auto" autocomplete="off" />\n';
@@ -4509,75 +5063,75 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4509
5063
  * is used as placeholderColor option, it will be passed the value of the
4510
5064
  * placeholderColorBinding attribute each time it changes.
4511
5065
  *
4512
- * @param {string[]} [options.swatches]
4513
- * Preset color values to be displayed inside the picker drop
4514
- * down. The default value, if present, is always used as the
4515
- * first swatch automatically.
5066
+ * @param {boolean} [options.alpha]
5067
+ * Allow picking colors with alpha channel. When enabled, translucent
5068
+ * colors are stored in `#rrggbbaa` format. Fully opaque colors still
5069
+ * use `#rrggbb`.
5070
+ *
5071
+ * @param {Array<string|{value: string, text: string, group: string}>} [options.swatches]
5072
+ * Preset colors to be displayed inside the picker drop down. Each
5073
+ * entry is either a color string or an object with a `value` color,
5074
+ * a `text` label shown as the swatch's tooltip and an optional
5075
+ * `group` key. Consecutive swatches with a different `group` are
5076
+ * separated by a divider in the picker. The default value, if
5077
+ * present, is always used as the first swatch automatically. Swatches
5078
+ * are deduplicated by value.
4516
5079
  *
4517
5080
  * @class
4518
5081
  */
4519
- var ColorInputView = Marionette.ItemView.extend({
5082
+ const ColorInputView = Marionette.ItemView.extend({
4520
5083
  mixins: [inputView, inputWithPlaceholderText],
4521
5084
  template: template$8,
4522
5085
  className: 'color_input',
4523
5086
  ui: {
4524
5087
  input: 'input'
4525
5088
  },
4526
- events: {
4527
- 'mousedown': 'refreshPicker'
4528
- },
4529
- onRender: function onRender() {
5089
+ onRender: function () {
4530
5090
  this.setupAttributeBinding('placeholderColor', this.updatePlaceholderColor);
4531
- this.ui.input.minicolors({
4532
- changeDelay: 200,
4533
- change: _.bind(function (color) {
4534
- this._saving = true;
4535
- if (color === this.defaultValue()) {
4536
- this.model.unset(this.options.propertyName);
4537
- } else {
4538
- this.model.set(this.options.propertyName, color);
4539
- }
4540
- this._saving = false;
4541
- }, this)
5091
+ this._colorPicker = new ColorPicker(this.ui.input[0], {
5092
+ alpha: this.options.alpha,
5093
+ defaultValue: this.defaultValue(),
5094
+ fallbackColor: this.getAttributeBoundOption('placeholderColor'),
5095
+ fallbackColorDescription: this.options.placeholderColorDescription,
5096
+ swatches: this.getSwatches(),
5097
+ onChange: this._debouncedOnChange()
4542
5098
  });
4543
5099
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
4544
5100
  if (this.options.defaultValueBinding) {
4545
5101
  this.listenTo(this.model, 'change:' + this.options.defaultValueBinding, this.updateSettings);
4546
5102
  }
4547
- this.updateSettings();
5103
+ this.load();
4548
5104
  },
4549
- updatePlaceholderColor: function updatePlaceholderColor(value) {
4550
- this.el.style.setProperty('--placeholder-color', value);
5105
+ updatePlaceholderColor(value) {
5106
+ if (this._colorPicker) {
5107
+ this._colorPicker.update({
5108
+ fallbackColor: value
5109
+ });
5110
+ }
4551
5111
  },
4552
- updateSettings: function updateSettings() {
4553
- this.resetSwatchesInStoredSettings();
4554
- this.ui.input.minicolors('settings', {
5112
+ updateSettings: function () {
5113
+ this._colorPicker.update({
4555
5114
  defaultValue: this.defaultValue(),
4556
5115
  swatches: this.getSwatches()
4557
5116
  });
4558
5117
  this.load();
4559
5118
  },
4560
- // see https://github.com/claviska/jquery-minicolors/issues/287
4561
- resetSwatchesInStoredSettings: function resetSwatchesInStoredSettings() {
4562
- var settings = this.ui.input.data('minicolors-settings');
4563
- if (settings) {
4564
- delete settings.swatches;
4565
- this.ui.input.data('minicolors-settings', settings);
4566
- }
4567
- },
4568
- load: function load() {
5119
+ load: function () {
5120
+ var color = this.model.get(this.options.propertyName) || this.defaultValue() || '';
4569
5121
  if (!this._saving) {
4570
- this.ui.input.minicolors('value', this.model.get(this.options.propertyName) || this.defaultValue());
5122
+ this._colorPicker.setValue(color);
4571
5123
  }
4572
5124
  this.$el.toggleClass('is_default', !this.model.has(this.options.propertyName));
4573
5125
  },
4574
- refreshPicker: function refreshPicker() {
4575
- this.ui.input.minicolors('value', {});
5126
+ onBeforeClose: function () {
5127
+ this._colorPicker.destroy();
4576
5128
  },
4577
- getSwatches: function getSwatches() {
4578
- return _.chain([this.defaultValue(), this.options.swatches]).flatten().uniq().compact().value();
5129
+ getSwatches: function () {
5130
+ return _.chain([this.defaultValue(), this.options.swatches]).flatten().compact().map(swatch => typeof swatch === 'string' ? {
5131
+ value: swatch
5132
+ } : swatch).uniq(swatch => swatch.value).value();
4579
5133
  },
4580
- defaultValue: function defaultValue() {
5134
+ defaultValue: function () {
4581
5135
  var bindingValue;
4582
5136
  if (this.options.defaultValueBinding) {
4583
5137
  bindingValue = this.model.get(this.options.defaultValueBinding);
@@ -4589,6 +5143,19 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4589
5143
  } else {
4590
5144
  return bindingValue;
4591
5145
  }
5146
+ },
5147
+ _debouncedOnChange: function () {
5148
+ const handler = _.bind(this._onChange, this);
5149
+ return this.options.disableChangeDebounce ? handler : _.debounce(handler, 200);
5150
+ },
5151
+ _onChange: function (color) {
5152
+ this._saving = true;
5153
+ if (!color || color === this.defaultValue()) {
5154
+ this.model.unset(this.options.propertyName);
5155
+ } else {
5156
+ this.model.set(this.options.propertyName, color);
5157
+ }
5158
+ this._saving = false;
4592
5159
  }
4593
5160
  });
4594
5161
 
@@ -4604,8 +5171,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4604
5171
  *
4605
5172
  * @param {Object} [options]
4606
5173
  *
4607
- * @param {string[]} [options.values]
4608
- * List of possible values to persist in the attribute.
5174
+ * @param {string[]|function} [options.values]
5175
+ * List of possible values to persist in the attribute. Pass a
5176
+ * function returning the list to defer reading the values.
4609
5177
  *
4610
5178
  * @param {number} [options.defaultValue]
4611
5179
  * Default value to display if property is not set.
@@ -4682,7 +5250,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4682
5250
  *
4683
5251
  * @class
4684
5252
  */
4685
- var SelectInputView = Marionette.ItemView.extend({
5253
+ const SelectInputView = Marionette.ItemView.extend({
4686
5254
  mixins: [inputView],
4687
5255
  template: template$9,
4688
5256
  events: {
@@ -4692,7 +5260,8 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4692
5260
  select: 'select',
4693
5261
  input: 'select'
4694
5262
  },
4695
- initialize: function initialize() {
5263
+ initialize: function () {
5264
+ this.options.values = _.result(this.options, 'values');
4696
5265
  if (this.options.collection) {
4697
5266
  this.options.values = _.pluck(this.options.collection, this.options.valueProperty);
4698
5267
  if (this.options.textProperty) {
@@ -4726,7 +5295,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4726
5295
  }
4727
5296
  this.optGroups = {};
4728
5297
  },
4729
- onRender: function onRender() {
5298
+ onRender: function () {
4730
5299
  this.appendBlank();
4731
5300
  this.appendPlaceholder();
4732
5301
  this.appendOptions();
@@ -4736,7 +5305,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4736
5305
  this.save();
4737
5306
  }
4738
5307
  },
4739
- appendBlank: function appendBlank() {
5308
+ appendBlank: function () {
4740
5309
  if (!this.options.includeBlank) {
4741
5310
  return;
4742
5311
  }
@@ -4753,7 +5322,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4753
5322
  option.text = blankText;
4754
5323
  this.ui.select.append(option);
4755
5324
  },
4756
- appendPlaceholder: function appendPlaceholder() {
5325
+ appendPlaceholder: function () {
4757
5326
  if (!this.options.placeholderModel && !this.options.placeholderValue) {
4758
5327
  return;
4759
5328
  }
@@ -4768,7 +5337,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4768
5337
  this.ui.select.append(option);
4769
5338
  }
4770
5339
  },
4771
- appendOptions: function appendOptions() {
5340
+ appendOptions: function () {
4772
5341
  _.each(this.options.values, function (value, index) {
4773
5342
  var option = document.createElement('option');
4774
5343
  var group = this.options.groups[index];
@@ -4785,7 +5354,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4785
5354
  }
4786
5355
  }, this);
4787
5356
  },
4788
- findOrCreateOptGroup: function findOrCreateOptGroup(label) {
5357
+ findOrCreateOptGroup: function (label) {
4789
5358
  if (!this.optGroups[label]) {
4790
5359
  this.optGroups[label] = $('<optgroup />', {
4791
5360
  label: label
@@ -4793,15 +5362,15 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4793
5362
  }
4794
5363
  return this.optGroups[label];
4795
5364
  },
4796
- save: function save() {
4797
- var value = this.ui.select.val();
5365
+ save: function () {
5366
+ const value = this.ui.select.val();
4798
5367
  if ('defaultValue' in this.options && value === this.options.defaultValue) {
4799
5368
  this.model.unset(this.options.propertyName);
4800
5369
  } else {
4801
5370
  this.model.set(this.options.propertyName, value);
4802
5371
  }
4803
5372
  },
4804
- load: function load() {
5373
+ load: function () {
4805
5374
  if (!this.isClosed) {
4806
5375
  var value = this.model.get(this.options.propertyName);
4807
5376
  if (this.model.has(this.options.propertyName) && this.ui.select.find('option[value="' + value + '"]:not([disabled])').length) {
@@ -4815,9 +5384,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4815
5384
  }
4816
5385
  });
4817
5386
 
4818
- var ExtendedSelectInputView = SelectInputView.extend({
5387
+ const ExtendedSelectInputView = SelectInputView.extend({
4819
5388
  className: 'extended_select_input',
4820
- initialize: function initialize() {
5389
+ initialize: function () {
4821
5390
  SelectInputView.prototype.initialize.apply(this, arguments);
4822
5391
  if (this.options.collection) {
4823
5392
  if (this.options.descriptionProperty) {
@@ -4832,18 +5401,18 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4832
5401
  });
4833
5402
  }
4834
5403
  },
4835
- onRender: function onRender() {
5404
+ onRender: function () {
4836
5405
  var view = this,
4837
5406
  options = this.options;
4838
5407
  SelectInputView.prototype.onRender.apply(this, arguments);
4839
5408
  $.widget("custom.extendedselectmenu", $.ui.selectmenu, {
4840
- _renderItem: function _renderItem(ul, item) {
5409
+ _renderItem: function (ul, item) {
4841
5410
  var widget = this;
4842
5411
  var li = $('<li>', {
4843
- "class": item.value
5412
+ class: item.value
4844
5413
  });
4845
5414
  var container = $('<div>', {
4846
- "class": 'text-container'
5415
+ class: 'text-container'
4847
5416
  }).appendTo(li);
4848
5417
  var index = options.values.indexOf(item.value);
4849
5418
  if (item.disabled) {
@@ -4851,16 +5420,16 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4851
5420
  }
4852
5421
  if (options.pictogramClass) {
4853
5422
  $('<span>', {
4854
- "class": options.pictogramClass
5423
+ class: options.pictogramClass
4855
5424
  }).prependTo(li);
4856
5425
  }
4857
5426
  $('<p>', {
4858
5427
  text: item.label,
4859
- "class": 'item-text'
5428
+ class: 'item-text'
4860
5429
  }).appendTo(container);
4861
5430
  $('<p>', {
4862
5431
  text: options.descriptions[index],
4863
- "class": 'item-description'
5432
+ class: 'item-description'
4864
5433
  }).appendTo(container);
4865
5434
  if (options.helpLinkClicked) {
4866
5435
  $('<a>', {
@@ -4874,7 +5443,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4874
5443
  }
4875
5444
  return li.appendTo(ul);
4876
5445
  },
4877
- _resizeMenu: function _resizeMenu() {
5446
+ _resizeMenu: function () {
4878
5447
  this.menuWrap.addClass('extended_select_input_menu');
4879
5448
  var menuHeight = this.menu.height(),
4880
5449
  menuOffset = this.button.offset().top + this.button.outerHeight(),
@@ -4900,7 +5469,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4900
5469
  }
4901
5470
  });
4902
5471
  },
4903
- select: function select(event, ui) {
5472
+ select: function (event, ui) {
4904
5473
  this.ui.select.val(ui.item.value);
4905
5474
  this.save();
4906
5475
  }
@@ -4963,7 +5532,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4963
5532
  *
4964
5533
  * @class
4965
5534
  */
4966
- var TextAreaInputView = Marionette.ItemView.extend({
5535
+ const TextAreaInputView = Marionette.ItemView.extend({
4967
5536
  mixins: [inputView, inputWithPlaceholderText],
4968
5537
  template: template$a,
4969
5538
  className: 'text_area_input',
@@ -4989,7 +5558,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
4989
5558
  'change .open_in_new_tab': 'setTargetFromOpenInNewTabCheckBox',
4990
5559
  'change .display_url': 'setUrlFromDisplayUrl'
4991
5560
  },
4992
- onRender: function onRender() {
5561
+ onRender: function () {
4993
5562
  this.ui.input.addClass(this.options.size);
4994
5563
  this.load();
4995
5564
  this.updatePlaceholder();
@@ -5058,16 +5627,26 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5058
5627
  this.editor.on('change', _.bind(this.save, this));
5059
5628
  this.editor.on('aftercommand:composer', _.bind(this.save, this));
5060
5629
  },
5061
- onClose: function onClose() {
5630
+ onClose: function () {
5062
5631
  this.editor.fire('destroy:composer');
5063
5632
  },
5064
- save: function save() {
5633
+ updateDisabled: function () {
5634
+ inputView.updateDisabled.call(this);
5635
+ if (this.isDisabled()) {
5636
+ this.editor.disable();
5637
+ this.$el.attr('inert', true);
5638
+ } else {
5639
+ this.editor.enable();
5640
+ this.$el.removeAttr('inert');
5641
+ }
5642
+ },
5643
+ save: function () {
5065
5644
  this.model.set(this.options.propertyName, this.editor.getValue());
5066
5645
  },
5067
- load: function load() {
5646
+ load: function () {
5068
5647
  this.ui.input.val(this.model.get(this.options.propertyName));
5069
5648
  },
5070
- setupUrlLinkPanel: function setupUrlLinkPanel() {
5649
+ setupUrlLinkPanel: function () {
5071
5650
  this.editor.on('show:dialog', _.bind(function () {
5072
5651
  this.ui.linkDialog.toggleClass('for_existing_link', this.ui.linkButton.hasClass('wysihtml5-command-active'));
5073
5652
  var currentUrl = this.ui.urlInput.val();
@@ -5080,7 +5659,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5080
5659
  }
5081
5660
  }, this));
5082
5661
  },
5083
- setupFragmentLinkPanel: function setupFragmentLinkPanel() {
5662
+ setupFragmentLinkPanel: function () {
5084
5663
  if (this.options.fragmentLinkInputView) {
5085
5664
  this.fragmentLinkModel = new Backbone.Model();
5086
5665
  this.listenTo(this.fragmentLinkModel, 'change', function (model, options) {
@@ -5108,7 +5687,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5108
5687
  this.ui.fragmentLinkPanel.hide();
5109
5688
  }
5110
5689
  },
5111
- initLinkTypePanels: function initLinkTypePanels(isUrlLink) {
5690
+ initLinkTypePanels: function (isUrlLink) {
5112
5691
  if (isUrlLink) {
5113
5692
  this.ui.urlLinkRadioButton.prop('checked', true);
5114
5693
  } else {
@@ -5116,23 +5695,23 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5116
5695
  }
5117
5696
  this.ui.toolbar.toggleClass('fragment_link_panel_active', !isUrlLink);
5118
5697
  },
5119
- showUrlLinkPanel: function showUrlLinkPanel() {
5698
+ showUrlLinkPanel: function () {
5120
5699
  this.ui.toolbar.removeClass('fragment_link_panel_active');
5121
5700
  this.setUrlFromDisplayUrl();
5122
5701
  this.setTargetFromOpenInNewTabCheckBox();
5123
5702
  },
5124
- showFragmentLinkPanel: function showFragmentLinkPanel() {
5703
+ showFragmentLinkPanel: function () {
5125
5704
  this.ui.toolbar.addClass('fragment_link_panel_active');
5126
5705
  this.setInputsFromFragmentLinkModel();
5127
5706
  },
5128
- setInputsFromFragmentLinkModel: function setInputsFromFragmentLinkModel() {
5707
+ setInputsFromFragmentLinkModel: function () {
5129
5708
  this.ui.urlInput.val('#' + (this.fragmentLinkModel.get('linkId') || ''));
5130
5709
  this.ui.targetInput.val('_self');
5131
5710
  },
5132
- setUrlFromDisplayUrl: function setUrlFromDisplayUrl() {
5711
+ setUrlFromDisplayUrl: function () {
5133
5712
  this.ui.urlInput.val(this.ui.displayUrlInput.val());
5134
5713
  },
5135
- setTargetFromOpenInNewTabCheckBox: function setTargetFromOpenInNewTabCheckBox() {
5714
+ setTargetFromOpenInNewTabCheckBox: function () {
5136
5715
  this.ui.targetInput.val(this.ui.openInNewTabCheckBox.is(':checked') ? '_blank' : '_self');
5137
5716
  }
5138
5717
  });
@@ -5160,7 +5739,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5160
5739
  *
5161
5740
  * @class
5162
5741
  */
5163
- var UrlInputView = Marionette.Layout.extend( /** @lends UrlInputView.prototype */{
5742
+ const UrlInputView = Marionette.Layout.extend( /** @lends UrlInputView.prototype */{
5164
5743
  mixins: [inputView],
5165
5744
  template: template$b,
5166
5745
  ui: {
@@ -5170,74 +5749,85 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5170
5749
  events: {
5171
5750
  'change': 'onChange'
5172
5751
  },
5173
- onRender: function onRender() {
5752
+ onRender: function () {
5174
5753
  this.ui.validation.hide();
5175
5754
  this.load();
5176
5755
  this.validate();
5756
+ this.listenTo(this.model, 'change:' + this.options.displayPropertyName, this.load);
5177
5757
  },
5178
- onChange: function onChange() {
5179
- var _this = this;
5180
- this.validate().then(function () {
5181
- return _this.save();
5182
- }, function () {
5183
- return _this.saveDisplayProperty();
5184
- });
5758
+ onChange: function () {
5759
+ var value = this.ui.input.val();
5760
+ this.validate().then(() => this.save(value), () => this.saveDisplayProperty(value));
5185
5761
  },
5186
- saveDisplayProperty: function saveDisplayProperty() {
5762
+ saveDisplayProperty: function (value) {
5187
5763
  this.model.unset(this.options.propertyName, {
5188
5764
  silent: true
5189
5765
  });
5190
- this.model.set(this.options.displayPropertyName, this.ui.input.val());
5766
+ this.model.set(this.options.displayPropertyName, value);
5191
5767
  },
5192
- save: function save() {
5193
- var _this2 = this;
5194
- var value = this.ui.input.val();
5195
- $.when(this.transformPropertyValue(value)).then(function (transformedValue) {
5196
- _this2.model.set(_defineProperty$1(_defineProperty$1({}, _this2.options.displayPropertyName, value), _this2.options.propertyName, transformedValue));
5768
+ save: function (value) {
5769
+ $.when(this.transformPropertyValue(value, this.lastValidationResult)).then(transformedValue => {
5770
+ this.model.set({
5771
+ [this.options.displayPropertyName]: value,
5772
+ [this.options.propertyName]: transformedValue
5773
+ });
5197
5774
  });
5198
5775
  },
5199
- load: function load() {
5776
+ load: function () {
5200
5777
  this.ui.input.val(this.model.has(this.options.displayPropertyName) ? this.model.get(this.options.displayPropertyName) : this.model.get(this.options.propertyName));
5201
5778
  this.onLoad();
5202
5779
  },
5203
5780
  /**
5204
5781
  * Override to be notified when the input has been loaded.
5205
5782
  */
5206
- onLoad: function onLoad() {},
5783
+ onLoad: function () {},
5207
5784
  /**
5208
5785
  * Override to validate the untransformed url. Validation error
5209
5786
  * message can be passed as rejected promise. Progress notifications
5210
5787
  * are displayed. Only valid urls are stored in the configuration.
5211
5788
  *
5789
+ * Can optionally return a value when the promise resolves. This
5790
+ * value will be passed to transformPropertyValue as the second
5791
+ * parameter.
5792
+ *
5212
5793
  * @return Promise
5213
5794
  */
5214
- validateUrl: function validateUrl(url) {
5795
+ validateUrl: function (url) {
5215
5796
  return $.Deferred().resolve().promise();
5216
5797
  },
5217
5798
  /**
5218
5799
  * Override to transform the property value before it is stored.
5219
5800
  *
5801
+ * @param {String} value - The URL value to transform
5802
+ * @param {*} validationResult - Optional result returned by validateUrl
5220
5803
  * @return Promise | String
5221
5804
  */
5222
- transformPropertyValue: function transformPropertyValue(value) {
5805
+ transformPropertyValue: function (value, validationResult) {
5223
5806
  return value;
5224
5807
  },
5225
5808
  /**
5226
5809
  * Override to change the list of supported host names.
5227
5810
  */
5228
- supportedHosts: function supportedHosts() {
5811
+ supportedHosts: function () {
5229
5812
  return this.options.supportedHosts;
5230
5813
  },
5814
+ /**
5815
+ * Override to enable HTTPS URLs by default.
5816
+ * @return {boolean}
5817
+ */
5818
+ permitHttps: function () {
5819
+ return this.options.permitHttps;
5820
+ },
5231
5821
  // Host names used to be expected to include protocols. Remove
5232
5822
  // protocols for backwards compatilbity. Since supportedHosts
5233
5823
  // is supposed to be overridden in subclasses, we do it in a
5234
5824
  // separate method.
5235
- supportedHostsWithoutLegacyProtocols: function supportedHostsWithoutLegacyProtocols() {
5825
+ supportedHostsWithoutLegacyProtocols: function () {
5236
5826
  return _.map(this.supportedHosts(), function (host) {
5237
5827
  return host.replace(/^https?:\/\//, '');
5238
5828
  });
5239
5829
  },
5240
- validate: function validate(success) {
5830
+ validate: function (success) {
5241
5831
  var view = this;
5242
5832
  var options = this.options;
5243
5833
  var value = this.ui.input.val();
@@ -5245,7 +5835,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5245
5835
  displayValidationError(I18n$1.t('pageflow.ui.views.inputs.url_input_view.required_field'));
5246
5836
  } else if (value && !isValidUrl(value)) {
5247
5837
  var errorMessage = I18n$1.t('pageflow.ui.views.inputs.url_input_view.url_hint');
5248
- if (options.permitHttps) {
5838
+ if (view.permitHttps()) {
5249
5839
  errorMessage = I18n$1.t('pageflow.ui.views.inputs.url_input_view.url_hint_https');
5250
5840
  }
5251
5841
  displayValidationError(errorMessage);
@@ -5255,16 +5845,24 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5255
5845
  }).join(''));
5256
5846
  } else {
5257
5847
  return view.validateUrl(value).progress(function (message) {
5258
- displayValidationPending(message);
5259
- }).done(function () {
5260
- resetValidationError();
5848
+ if (!view.isClosed) {
5849
+ displayValidationPending(message);
5850
+ }
5851
+ }).done(function (result) {
5852
+ view.lastValidationResult = result;
5853
+ if (!view.isClosed) {
5854
+ resetValidationError();
5855
+ }
5261
5856
  }).fail(function (error) {
5262
- displayValidationError(error);
5857
+ view.lastValidationResult = undefined;
5858
+ if (!view.isClosed) {
5859
+ displayValidationError(error);
5860
+ }
5263
5861
  });
5264
5862
  }
5265
5863
  return $.Deferred().reject().promise();
5266
5864
  function isValidUrl(url) {
5267
- return options.permitHttps ? url.match(/^https?:\/\//i) : url.match(/^http:\/\//i);
5865
+ return view.permitHttps() ? url.match(/^https?:\/\//i) : url.match(/^http:\/\//i);
5268
5866
  }
5269
5867
  function hasSupportedHost(url) {
5270
5868
  return _.any(view.supportedHostsWithoutLegacyProtocols(), function (host) {
@@ -5284,6 +5882,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5284
5882
  function resetValidationError(message) {
5285
5883
  view.$el.removeClass('invalid');
5286
5884
  view.ui.input.attr('aria-invalid', 'false');
5885
+ view.ui.validation.text('');
5287
5886
  view.ui.validation.hide();
5288
5887
  }
5289
5888
  }
@@ -5335,9 +5934,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5335
5934
  *
5336
5935
  * @class
5337
5936
  */
5338
- var ProxyUrlInputView = UrlInputView.extend( /** @lends ProxyUrlInputView.prototype */{
5937
+ const ProxyUrlInputView = UrlInputView.extend( /** @lends ProxyUrlInputView.prototype */{
5339
5938
  // @override
5340
- validateUrl: function validateUrl(url) {
5939
+ validateUrl: function (url) {
5341
5940
  var view = this;
5342
5941
  return $.Deferred(function (deferred) {
5343
5942
  deferred.notify(I18n$1.t('pageflow.ui.views.inputs.proxy_url_input_view.url_validation'));
@@ -5352,14 +5951,14 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5352
5951
  }).promise();
5353
5952
  },
5354
5953
  // override
5355
- transformPropertyValue: function transformPropertyValue(url) {
5954
+ transformPropertyValue: function (url) {
5356
5955
  return this.rewriteUrl(url);
5357
5956
  },
5358
5957
  // override
5359
- supportedHosts: function supportedHosts() {
5958
+ supportedHosts: function () {
5360
5959
  return _.pluck(this.options.proxies, 'url');
5361
5960
  },
5362
- rewriteUrl: function rewriteUrl(url) {
5961
+ rewriteUrl: function (url) {
5363
5962
  _.each(this.options.proxies, function (proxy) {
5364
5963
  url = url.replace(new RegExp('^' + proxy.url + '/?'), proxy.base_path + '/');
5365
5964
  });
@@ -5368,8 +5967,12 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5368
5967
  });
5369
5968
 
5370
5969
  function template$c(data) {
5371
- var __p = '';
5372
- __p += '<label>\n <span class="name"></span>\n <span class="inline_help"></span>\n</label>\n<div class="value"></div>\n<div class="slider"></div>\n';
5970
+ var __t, __p = '';
5971
+ __p += '<label>\n <span class="name"></span>\n <span class="inline_help"></span>\n</label>\n<div class="slider_wrapper">\n ';
5972
+ if (data.icon) {__p += '<img class="icon" src="' +
5973
+ ((__t = ( data.icon )) == null ? '' : __t) +
5974
+ '" width="18" height="18" />';
5975
+ }__p += '\n <div class="value"></div>\n <div class="slider"></div>\n</div>\n';
5373
5976
  return __p
5374
5977
  }
5375
5978
 
@@ -5398,39 +6001,48 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5398
6001
  * Already update the model while dragging the handle - not only after
5399
6002
  * handle has been released.
5400
6003
  *
6004
+ * @param {string} [options.icon]
6005
+ * Path to an icon image to display before the label.
6006
+ *
5401
6007
  * @class
5402
6008
  */
5403
- var SliderInputView = Marionette.ItemView.extend({
6009
+ const SliderInputView = Marionette.ItemView.extend({
5404
6010
  mixins: [inputView],
5405
6011
  className: 'slider_input',
5406
6012
  template: template$c,
6013
+ serializeData() {
6014
+ return {
6015
+ icon: this.options.icon
6016
+ };
6017
+ },
5407
6018
  ui: {
5408
6019
  widget: '.slider',
5409
6020
  value: '.value'
5410
6021
  },
5411
6022
  events: {
6023
+ 'slidestart': 'handleSlideStart',
5412
6024
  'slidechange': 'save',
5413
6025
  'slide': 'handleSlide'
5414
6026
  },
5415
- onRender: function onRender() {
5416
- var _this = this;
6027
+ onRender: function () {
5417
6028
  this.ui.widget.slider({
5418
6029
  animate: 'fast'
5419
6030
  });
5420
- this.setupAttributeBinding('minValue', function (value) {
5421
- return _this.updateSliderOption('min', value || 0);
5422
- });
5423
- this.setupAttributeBinding('maxValue', function (value) {
5424
- return _this.updateSliderOption('max', value !== undefined ? value : 100);
5425
- });
6031
+ if (this.options.values) {
6032
+ this.ui.widget.slider('option', 'min', 0);
6033
+ this.ui.widget.slider('option', 'max', this.options.values.length - 1);
6034
+ } else {
6035
+ this.setupAttributeBinding('minValue', value => this.updateSliderOption('min', value || 0));
6036
+ this.setupAttributeBinding('maxValue', value => this.updateSliderOption('max', value !== undefined ? value : 100));
6037
+ }
5426
6038
  this.load();
5427
6039
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
5428
6040
  },
5429
- updateSliderOption: function updateSliderOption(name, value) {
6041
+ updateSliderOption(name, value) {
5430
6042
  this.ui.widget.slider('option', name, value);
5431
6043
  this.updateText(this.ui.widget.slider('value'));
5432
6044
  },
5433
- updateDisabled: function updateDisabled(disabled) {
6045
+ updateDisabled: function (disabled) {
5434
6046
  this.$el.toggleClass('disabled', !!disabled);
5435
6047
  if (disabled) {
5436
6048
  this.ui.widget.slider('disable');
@@ -5438,33 +6050,54 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5438
6050
  this.ui.widget.slider('enable');
5439
6051
  }
5440
6052
  },
5441
- handleSlide: function handleSlide(event, ui) {
5442
- this.updateText(ui.value);
6053
+ handleSlideStart() {
6054
+ if (this.options.onInteractionStart) {
6055
+ this.options.onInteractionStart();
6056
+ }
6057
+ },
6058
+ handleSlide(event, ui) {
6059
+ var value = this.options.values ? this.options.values[ui.value] : ui.value;
6060
+ this.updateText(value);
5443
6061
  if (this.options.saveOnSlide) {
5444
6062
  this.save(event, ui);
5445
6063
  }
5446
6064
  },
5447
- save: function save(event, ui) {
5448
- this.model.set(this.options.propertyName, ui.value);
6065
+ save: function (event, ui) {
6066
+ if (this.loading) {
6067
+ return;
6068
+ }
6069
+ var value = this.options.values ? this.options.values[ui.value] : ui.value;
6070
+ this.model.set(this.options.propertyName, value);
5449
6071
  },
5450
- load: function load() {
6072
+ load: function () {
5451
6073
  var value;
5452
6074
  if (this.model.has(this.options.propertyName)) {
5453
6075
  value = this.model.get(this.options.propertyName);
5454
6076
  } else {
5455
6077
  value = 'defaultValue' in this.options ? this.options.defaultValue : 0;
5456
6078
  }
5457
- this.ui.widget.slider('option', 'value', this.clampValue(value));
6079
+ var sliderValue = this.options.values ? this.options.values.indexOf(value) : value;
6080
+ this.loading = true;
6081
+ this.ui.widget.slider('option', 'value', this.clampValue(sliderValue));
6082
+ this.loading = false;
5458
6083
  this.updateText(value);
5459
6084
  },
5460
- clampValue: function clampValue(value) {
5461
- var min = this.ui.widget.slider('option', 'min');
5462
- var max = this.ui.widget.slider('option', 'max');
6085
+ clampValue(value) {
6086
+ const min = this.ui.widget.slider('option', 'min');
6087
+ const max = this.ui.widget.slider('option', 'max');
5463
6088
  return Math.min(max, Math.max(min, value));
5464
6089
  },
5465
- updateText: function updateText(value) {
5466
- var unit = 'unit' in this.options ? this.options.unit : '%';
5467
- var text = 'displayText' in this.options ? this.options.displayText(value) : value + unit;
6090
+ updateText: function (value) {
6091
+ var text;
6092
+ if (this.options.texts) {
6093
+ var index = this.options.values.indexOf(value);
6094
+ text = this.options.texts[index];
6095
+ } else if ('displayText' in this.options) {
6096
+ text = this.options.displayText(value);
6097
+ } else {
6098
+ var unit = 'unit' in this.options ? this.options.unit : '%';
6099
+ text = value + unit;
6100
+ }
5468
6101
  this.ui.value.text(text);
5469
6102
  }
5470
6103
  });
@@ -5475,7 +6108,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5475
6108
  return __p
5476
6109
  }
5477
6110
 
5478
- var JsonInputView = Marionette.ItemView.extend({
6111
+ const JsonInputView = Marionette.ItemView.extend({
5479
6112
  mixins: [inputView],
5480
6113
  template: template$d,
5481
6114
  className: 'json_input',
@@ -5486,30 +6119,30 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5486
6119
  'change': 'onChange',
5487
6120
  'keyup': 'validate'
5488
6121
  },
5489
- onRender: function onRender() {
6122
+ onRender: function () {
5490
6123
  this.load();
5491
6124
  this.validate();
5492
6125
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
5493
6126
  },
5494
- onChange: function onChange() {
6127
+ onChange: function () {
5495
6128
  if (this.validate()) {
5496
6129
  this.save();
5497
6130
  }
5498
6131
  },
5499
- onClose: function onClose() {
6132
+ onClose: function () {
5500
6133
  if (this.validate()) {
5501
6134
  this.save();
5502
6135
  }
5503
6136
  },
5504
- save: function save() {
6137
+ save: function () {
5505
6138
  this.model.set(this.options.propertyName, this.ui.input.val() ? JSON.parse(this.ui.input.val()) : null);
5506
6139
  },
5507
- load: function load() {
6140
+ load: function () {
5508
6141
  var input = this.ui.input;
5509
6142
  var value = this.model.get(this.options.propertyName);
5510
6143
  input.val(value ? JSON.stringify(value, null, 2) : '');
5511
6144
  },
5512
- validate: function validate() {
6145
+ validate: function () {
5513
6146
  var input = this.ui.input;
5514
6147
  if (input.val() && !this.isValidJson(input.val())) {
5515
6148
  this.displayValidationError(I18n$1.t('pageflow.ui.views.inputs.json_input_view.invalid'));
@@ -5519,15 +6152,15 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5519
6152
  return true;
5520
6153
  }
5521
6154
  },
5522
- displayValidationError: function displayValidationError(message) {
6155
+ displayValidationError: function (message) {
5523
6156
  this.$el.addClass('invalid');
5524
6157
  this.ui.input.attr('title', message);
5525
6158
  },
5526
- resetValidationError: function resetValidationError(message) {
6159
+ resetValidationError: function (message) {
5527
6160
  this.$el.removeClass('invalid');
5528
6161
  this.ui.input.attr('title', '');
5529
6162
  },
5530
- isValidJson: function isValidJson(text) {
6163
+ isValidJson: function (text) {
5531
6164
  try {
5532
6165
  JSON.parse(text);
5533
6166
  return true;
@@ -5564,7 +6197,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5564
6197
  *
5565
6198
  * @class
5566
6199
  */
5567
- var CheckBoxInputView = Marionette.ItemView.extend({
6200
+ const CheckBoxInputView = Marionette.ItemView.extend({
5568
6201
  mixins: [inputView],
5569
6202
  template: template$e,
5570
6203
  className: 'check_box_input',
@@ -5575,18 +6208,18 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5575
6208
  input: 'input',
5576
6209
  label: 'label'
5577
6210
  },
5578
- onRender: function onRender() {
6211
+ onRender: function () {
5579
6212
  this.ui.label.attr('for', this.cid);
5580
6213
  this.ui.input.attr('id', this.cid);
5581
6214
  this.load();
5582
6215
  this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
5583
6216
  },
5584
- updateDisabled: function updateDisabled() {
6217
+ updateDisabled: function () {
5585
6218
  this.load();
5586
6219
  },
5587
- save: function save() {
6220
+ save: function () {
5588
6221
  if (!this.isDisabled()) {
5589
- var value = this.ui.input.is(':checked');
6222
+ const value = this.ui.input.is(':checked');
5590
6223
  if (this.options.storeInverted) {
5591
6224
  this.model.set(this.options.storeInverted, !value);
5592
6225
  } else {
@@ -5594,12 +6227,12 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5594
6227
  }
5595
6228
  }
5596
6229
  },
5597
- load: function load() {
6230
+ load: function () {
5598
6231
  if (!this.isClosed) {
5599
6232
  this.ui.input.prop('checked', !!this.displayValue());
5600
6233
  }
5601
6234
  },
5602
- displayValue: function displayValue() {
6235
+ displayValue: function () {
5603
6236
  if (this.isDisabled() && this.options.displayUncheckedIfDisabled) {
5604
6237
  return false;
5605
6238
  } else if (this.isDisabled() && this.options.displayCheckedIfDisabled) {
@@ -5612,6 +6245,86 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5612
6245
  }
5613
6246
  });
5614
6247
 
6248
+ /**
6249
+ * Input view for selecting one value from a small set of options
6250
+ * using radio buttons.
6251
+ * See {@link inputView} for further options.
6252
+ *
6253
+ * @param {Object} [options]
6254
+ *
6255
+ * @param {Array} options.values
6256
+ * Array of possible values the property can be set to.
6257
+ *
6258
+ * @param {Array} [options.texts]
6259
+ * Array of display texts for the values. If not provided,
6260
+ * translations are looked up based on the model's i18nKey.
6261
+ *
6262
+ * @class
6263
+ */
6264
+ const RadioButtonGroupInputView = Marionette.ItemView.extend({
6265
+ mixins: [inputView],
6266
+ template: () => `
6267
+ <label>
6268
+ <span class="name"></span>
6269
+ <span class="inline_help"></span>
6270
+ </label>
6271
+ `,
6272
+ className: 'radio_button_input',
6273
+ events: {
6274
+ 'change': 'save'
6275
+ },
6276
+ initialize: function () {
6277
+ if (!this.options.texts) {
6278
+ var translationKeyPrefix = findKeyWithTranslation(this.attributeTranslationKeys('values', {
6279
+ fallbackPrefix: 'activerecord.values'
6280
+ }));
6281
+ this.options.texts = _.map(this.options.values, function (value) {
6282
+ return I18n$1.t(translationKeyPrefix + '.' + value);
6283
+ });
6284
+ }
6285
+ },
6286
+ onRender: function () {
6287
+ this.appendOptions();
6288
+ this.load();
6289
+ this.listenTo(this.model, 'change:' + this.options.propertyName, this.load);
6290
+ },
6291
+ updateDisabled: function () {
6292
+ this.$el.find('input').prop('disabled', this.isDisabled());
6293
+ },
6294
+ save: function () {
6295
+ var index = this.$el.find('input').index(this.$el.find('input:checked'));
6296
+ this.model.set(this.options.propertyName, this.options.values[index]);
6297
+ },
6298
+ appendOptions: function () {
6299
+ _.each(this.options.values, function (value, index) {
6300
+ var id = this.cid + '_' + value;
6301
+ var wrapper = document.createElement('div');
6302
+ wrapper.className = 'radio_button';
6303
+ var input = document.createElement('input');
6304
+ input.type = 'radio';
6305
+ input.name = this.options.propertyName;
6306
+ input.value = value;
6307
+ input.id = id;
6308
+ var label = document.createElement('label');
6309
+ label.htmlFor = id;
6310
+ var nameSpan = document.createElement('span');
6311
+ nameSpan.className = 'name';
6312
+ nameSpan.textContent = this.options.texts[index];
6313
+ label.appendChild(nameSpan);
6314
+ wrapper.appendChild(input);
6315
+ wrapper.appendChild(document.createTextNode(' '));
6316
+ wrapper.appendChild(label);
6317
+ this.$el.append(wrapper);
6318
+ }, this);
6319
+ },
6320
+ load: function () {
6321
+ if (!this.isClosed) {
6322
+ var value = this.model.get(this.options.propertyName);
6323
+ this.$el.find('input[value="' + value + '"]').prop('checked', true);
6324
+ }
6325
+ }
6326
+ });
6327
+
5615
6328
  /**
5616
6329
  * Render a separator in a {@link ConfigurationEditorView} tab.
5617
6330
  *
@@ -5621,7 +6334,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5621
6334
  *
5622
6335
  * @class
5623
6336
  */
5624
- var SeparatorView = Marionette.View.extend({
6337
+ const SeparatorView = Marionette.View.extend({
5625
6338
  className: 'separator'
5626
6339
  });
5627
6340
 
@@ -5633,11 +6346,14 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5633
6346
  *
5634
6347
  * @class
5635
6348
  */
5636
- var LabelOnlyView = Marionette.ItemView.extend({
6349
+ const LabelOnlyView = Marionette.ItemView.extend({
5637
6350
  mixins: [inputView],
5638
- template: function template() {
5639
- return "\n <label>\n <span class=\"name\"></span>\n <span class=\"inline_help\"></span>\n </label>\n ";
5640
- },
6351
+ template: () => `
6352
+ <label>
6353
+ <span class="name"></span>
6354
+ <span class="inline_help"></span>
6355
+ </label>
6356
+ `,
5641
6357
  ui: {
5642
6358
  label: 'label'
5643
6359
  }
@@ -5658,9 +6374,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5658
6374
  *
5659
6375
  * @since 12.0
5660
6376
  */
5661
- var EnumTableCellView = TableCellView.extend({
6377
+ const EnumTableCellView = TableCellView.extend({
5662
6378
  className: 'enum_table_cell',
5663
- update: function update() {
6379
+ update: function () {
5664
6380
  this.$el.text(this.attributeTranslation('cell_text.' + (this.attributeValue() || 'blank')));
5665
6381
  this.$el.attr('title', this.attributeTranslation('cell_title.' + (this.attributeValue() || 'blank'), {
5666
6382
  defaultValue: ''
@@ -5698,7 +6414,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5698
6414
  *
5699
6415
  * @since 12.0
5700
6416
  */
5701
- var DeleteRowTableCellView = TableCellView.extend({
6417
+ const DeleteRowTableCellView = TableCellView.extend({
5702
6418
  className: 'delete_row_table_cell',
5703
6419
  template: template$f,
5704
6420
  ui: {
@@ -5706,11 +6422,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5706
6422
  },
5707
6423
  events: {
5708
6424
  'click .remove': 'destroy',
5709
- 'click': function click() {
6425
+ 'click': function () {
5710
6426
  return false;
5711
6427
  }
5712
6428
  },
5713
- showButton: function showButton() {
6429
+ showButton: function () {
5714
6430
  if (this.options.toggleDeleteButton) {
5715
6431
  var context = this.getModel();
5716
6432
  var toggle = context[this.options.toggleDeleteButton].apply(context);
@@ -5723,11 +6439,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5723
6439
  return true;
5724
6440
  }
5725
6441
  },
5726
- update: function update() {
6442
+ update: function () {
5727
6443
  this.ui.removeButton.toggleClass('remove', this.showButton());
5728
6444
  this.ui.removeButton.attr('title', this.attributeTranslation('cell_title'));
5729
6445
  },
5730
- destroy: function destroy() {
6446
+ destroy: function () {
5731
6447
  this.getModel().destroy();
5732
6448
  }
5733
6449
  });
@@ -5748,9 +6464,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5748
6464
  *
5749
6465
  * @since 12.0
5750
6466
  */
5751
- var PresenceTableCellView = TableCellView.extend({
6467
+ const PresenceTableCellView = TableCellView.extend({
5752
6468
  className: 'presence_table_cell',
5753
- update: function update() {
6469
+ update: function () {
5754
6470
  var isPresent = !!this.attributeValue();
5755
6471
  this.$el.attr('title', isPresent ? this.attributeTranslation('cell_title.present', {
5756
6472
  value: this.attributeValue()
@@ -5771,17 +6487,18 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5771
6487
  *
5772
6488
  * @param {Object} [options]
5773
6489
  *
5774
- * @param {string[]} [options.icons]
6490
+ * @param {string[]|function} [options.icons]
5775
6491
  * An array of all possible attribute values to be mapped to HTML
5776
6492
  * classes of the same name. A global mapping from those classes to
5777
6493
  * icon mixins is provided in
5778
- * pageflow/ui/table_cells/icon_table_cell.scss.
6494
+ * pageflow/ui/table_cells/icon_table_cell.scss. Pass a function
6495
+ * returning the array to defer reading the values.
5779
6496
  *
5780
6497
  * @since 12.0
5781
6498
  */
5782
- var IconTableCellView = TableCellView.extend({
6499
+ const IconTableCellView = TableCellView.extend({
5783
6500
  className: 'icon_table_cell',
5784
- update: function update() {
6501
+ update: function () {
5785
6502
  var icon = this.attributeValue();
5786
6503
  var isPresent = !!this.attributeValue();
5787
6504
  this.removeExistingIcons();
@@ -5790,8 +6507,8 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5790
6507
  }) : this.attributeTranslation('cell_title.blank'));
5791
6508
  this.$el.addClass(icon);
5792
6509
  },
5793
- removeExistingIcons: function removeExistingIcons() {
5794
- this.$el.removeClass(this.options.icons.join(' '));
6510
+ removeExistingIcons: function () {
6511
+ this.$el.removeClass(_.result(this.options, 'icons').join(' '));
5795
6512
  }
5796
6513
  });
5797
6514
 
@@ -5814,15 +6531,15 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5814
6531
  *
5815
6532
  * @since 12.0
5816
6533
  */
5817
- var TextTableCellView = TableCellView.extend({
6534
+ const TextTableCellView = TableCellView.extend({
5818
6535
  className: 'text_table_cell',
5819
- update: function update() {
6536
+ update: function () {
5820
6537
  this.$el.text(this._updateText());
5821
6538
  },
5822
- _updateText: function _updateText() {
6539
+ _updateText: function () {
5823
6540
  if (this.attributeValue()) {
5824
6541
  return this.attributeValue();
5825
- } else if (typeof this.options.column["default"] === 'function') {
6542
+ } else if (typeof this.options.column.default === 'function') {
5826
6543
  var options = {};
5827
6544
  if (this.options.column.contentBinding) {
5828
6545
  options = {
@@ -5830,27 +6547,27 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5830
6547
  model: this.getModel()
5831
6548
  };
5832
6549
  }
5833
- return this.options.column["default"](options);
6550
+ return this.options.column.default(options);
5834
6551
  } else if ('default' in this.options.column) {
5835
- return this.options.column["default"];
6552
+ return this.options.column.default;
5836
6553
  } else {
5837
6554
  return I18n$1.t('pageflow.ui.text_table_cell_view.empty');
5838
6555
  }
5839
6556
  }
5840
6557
  });
5841
6558
 
5842
- var subviewContainer = {
5843
- subview: function subview(view) {
6559
+ const subviewContainer = {
6560
+ subview: function (view) {
5844
6561
  this.subviews = this.subviews || new ChildViewContainer();
5845
6562
  this.subviews.add(view.render());
5846
6563
  return view;
5847
6564
  },
5848
- appendSubview: function appendSubview(view) {
5849
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
5850
- to = _ref.to;
6565
+ appendSubview: function (view, {
6566
+ to
6567
+ } = {}) {
5851
6568
  return (to || this.$el).append(this.subview(view).el);
5852
6569
  },
5853
- onClose: function onClose() {
6570
+ onClose: function () {
5854
6571
  if (this.subviews) {
5855
6572
  this.subviews.call('close');
5856
6573
  }
@@ -5860,9 +6577,9 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5860
6577
  Cocktail.mixin(Marionette.View, subviewContainer);
5861
6578
  }
5862
6579
 
5863
- var tooltipContainer = {
6580
+ const tooltipContainer = {
5864
6581
  events: {
5865
- 'mouseover [data-tooltip]': function mouseoverDataTooltip(event) {
6582
+ 'mouseover [data-tooltip]': function (event) {
5866
6583
  if (!this.tooltip.visible) {
5867
6584
  var target = $(event.currentTarget);
5868
6585
  var key = target.attr('data-tooltip');
@@ -5893,11 +6610,11 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5893
6610
  });
5894
6611
  }
5895
6612
  },
5896
- 'mouseleave [data-tooltip]': function mouseleaveDataTooltip() {
6613
+ 'mouseleave [data-tooltip]': function () {
5897
6614
  this.tooltip.hide();
5898
6615
  }
5899
6616
  },
5900
- onRender: function onRender() {
6617
+ onRender: function () {
5901
6618
  this.appendSubview(this.tooltip = new TooltipView());
5902
6619
  }
5903
6620
  };
@@ -5906,6 +6623,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5906
6623
  exports.CheckBoxInputView = CheckBoxInputView;
5907
6624
  exports.CollectionView = CollectionView;
5908
6625
  exports.ColorInputView = ColorInputView;
6626
+ exports.ColorPicker = ColorPicker;
5909
6627
  exports.ConfigurationEditorTabView = ConfigurationEditorTabView;
5910
6628
  exports.ConfigurationEditorView = ConfigurationEditorView;
5911
6629
  exports.DeleteRowTableCellView = DeleteRowTableCellView;
@@ -5919,6 +6637,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5919
6637
  exports.Object = BaseObject;
5920
6638
  exports.PresenceTableCellView = PresenceTableCellView;
5921
6639
  exports.ProxyUrlInputView = ProxyUrlInputView;
6640
+ exports.RadioButtonGroupInputView = RadioButtonGroupInputView;
5922
6641
  exports.SelectInputView = SelectInputView;
5923
6642
  exports.SeparatorView = SeparatorView;
5924
6643
  exports.SliderInputView = SliderInputView;
@@ -5935,6 +6654,7 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5935
6654
  exports.UrlDisplayView = UrlDisplayView;
5936
6655
  exports.UrlInputView = UrlInputView;
5937
6656
  exports.attributeBinding = attributeBinding;
6657
+ exports.attributeBindingUtils = attributeBindingUtils;
5938
6658
  exports.cssModulesUtils = cssModulesUtils;
5939
6659
  exports.i18nUtils = i18nUtils;
5940
6660
  exports.inputView = inputView;
@@ -5946,4 +6666,4 @@ this.pageflow._uiGlobalInterop = (function (exports, Marionette, _, $, I18n$1, B
5946
6666
 
5947
6667
  return exports;
5948
6668
 
5949
- }({}, Backbone.Marionette, _, jQuery, I18n, Backbone, Backbone.ChildViewContainer, IScroll, jQuery, wysihtml5, jQuery, Cocktail));
6669
+ }({}, Backbone.Marionette, _, jQuery, I18n, Backbone, Backbone.ChildViewContainer, IScroll, wysihtml5, jQuery, Cocktail));