pageflow 17.0.5 → 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 (636) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +342 -41
  3. data/README.md +3 -5
  4. data/admins/pageflow/accounts.rb +22 -20
  5. data/admins/pageflow/entry.rb +76 -26
  6. data/admins/pageflow/entry_templates.rb +10 -9
  7. data/admins/pageflow/folder.rb +1 -1
  8. data/admins/pageflow/membership.rb +15 -15
  9. data/admins/pageflow/revisions.rb +5 -5
  10. data/admins/pageflow/site_root_entry.rb +64 -0
  11. data/admins/pageflow/sites.rb +12 -3
  12. data/admins/pageflow/translations.rb +75 -0
  13. data/admins/pageflow/user.rb +21 -35
  14. data/app/assets/images/pageflow/admin/icons/comment.svg +1 -0
  15. data/app/assets/javascripts/pageflow/admin/entries.js +30 -5
  16. data/app/assets/javascripts/pageflow/dist/ui.js +4228 -900
  17. data/app/assets/javascripts/pageflow/editor/vendor.js +0 -1
  18. data/app/assets/javascripts/pageflow/ui.js +0 -1
  19. data/app/assets/stylesheets/pageflow/admin/entries/index_table.scss +2 -1
  20. data/app/assets/stylesheets/pageflow/admin/entry_comments_indicator.scss +45 -0
  21. data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +8 -0
  22. data/app/assets/stylesheets/pageflow/admin.scss +1 -0
  23. data/app/assets/stylesheets/pageflow/animations/spin.scss +9 -0
  24. data/app/assets/stylesheets/pageflow/animations.scss +1 -0
  25. data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +27 -5
  26. data/app/assets/stylesheets/pageflow/editor/base.scss +11 -1
  27. data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +20 -2
  28. data/app/assets/stylesheets/pageflow/editor/edit_configuration_view.scss +5 -0
  29. data/app/assets/stylesheets/pageflow/editor/file_folders.scss +127 -0
  30. data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +5 -2
  31. data/app/assets/stylesheets/pageflow/editor/file_meta_data_overlay.scss +45 -0
  32. data/app/assets/stylesheets/pageflow/editor/file_preview.scss +138 -0
  33. data/app/assets/stylesheets/pageflow/editor/file_references.scss +68 -0
  34. data/app/assets/stylesheets/pageflow/editor/file_settings_dialog.scss +1 -1
  35. data/app/assets/stylesheets/pageflow/editor/file_stage_icons.scss +17 -0
  36. data/app/assets/stylesheets/pageflow/editor/file_stages.scss +25 -32
  37. data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +31 -48
  38. data/app/assets/stylesheets/pageflow/editor/file_type_pills.scss +73 -0
  39. data/app/assets/stylesheets/pageflow/editor/files.scss +242 -50
  40. data/app/assets/stylesheets/pageflow/editor/filtered_files.scss +161 -9
  41. data/app/assets/stylesheets/pageflow/editor/folder_breadcrumb.scss +40 -0
  42. data/app/assets/stylesheets/pageflow/editor/info_box.scss +23 -3
  43. data/app/assets/stylesheets/pageflow/editor/inputs/edit_defaults_button.scss +15 -0
  44. data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
  45. data/app/assets/stylesheets/pageflow/editor/list.scss +89 -37
  46. data/app/assets/stylesheets/pageflow/editor/list_search_field.scss +52 -0
  47. data/app/assets/stylesheets/pageflow/editor/manage_files.scss +9 -0
  48. data/app/assets/stylesheets/pageflow/editor/menu.scss +14 -0
  49. data/app/assets/stylesheets/pageflow/editor/move_to_folder_dialog.scss +83 -0
  50. data/app/assets/stylesheets/pageflow/editor/outline.scss +0 -13
  51. data/app/assets/stylesheets/pageflow/editor/sortable.scss +12 -0
  52. data/app/assets/stylesheets/pageflow/mixins/buttons.scss +4 -4
  53. data/app/assets/stylesheets/pageflow/mixins/pageflow.scss +9 -5
  54. data/app/assets/stylesheets/pageflow/ui/color_picker.scss +230 -0
  55. data/app/assets/stylesheets/pageflow/ui/forms.scss +38 -4
  56. data/app/assets/stylesheets/pageflow/ui/functions.scss +12 -2
  57. data/app/assets/stylesheets/pageflow/ui/input/color_input.scss +9 -8
  58. data/app/assets/stylesheets/pageflow/ui/input/file_name_input.scss +37 -0
  59. data/app/assets/stylesheets/pageflow/ui/input/text_area_input.scss +15 -0
  60. data/app/assets/stylesheets/pageflow/ui/overrides.scss +8 -0
  61. data/app/assets/stylesheets/pageflow/ui/properties.scss +34 -0
  62. data/app/assets/stylesheets/pageflow/ui/tabs_view.scss +8 -3
  63. data/app/assets/stylesheets/pageflow/ui.scss +4 -1
  64. data/app/controllers/concerns/pageflow/controller_delegation.rb +1 -1
  65. data/app/controllers/concerns/pageflow/edit_locking.rb +17 -10
  66. data/app/controllers/concerns/pageflow/entry_password_protection.rb +1 -0
  67. data/app/controllers/concerns/pageflow/public_https_mode.rb +2 -1
  68. data/app/controllers/concerns/pageflow/quota_verification.rb +5 -4
  69. data/app/controllers/pageflow/admin/initial_passwords_controller.rb +1 -0
  70. data/app/controllers/pageflow/application_controller.rb +19 -19
  71. data/app/controllers/pageflow/chapters_controller.rb +3 -2
  72. data/app/controllers/pageflow/edit_locks_controller.rb +3 -2
  73. data/app/controllers/pageflow/editor/encoding_confirmations_controller.rb +1 -0
  74. data/app/controllers/pageflow/editor/entries_controller.rb +3 -1
  75. data/app/controllers/pageflow/editor/entry_publications_controller.rb +1 -0
  76. data/app/controllers/pageflow/editor/file_folders_controller.rb +80 -0
  77. data/app/controllers/pageflow/editor/file_import_controller.rb +4 -3
  78. data/app/controllers/pageflow/editor/files_controller.rb +20 -10
  79. data/app/controllers/pageflow/editor/oembeds_controller.rb +21 -0
  80. data/app/controllers/pageflow/editor/widgets_controller.rb +1 -0
  81. data/app/controllers/pageflow/entries_controller.rb +85 -21
  82. data/app/controllers/pageflow/feeds_controller.rb +1 -1
  83. data/app/controllers/pageflow/files_controller.rb +1 -0
  84. data/app/controllers/pageflow/pages_controller.rb +4 -2
  85. data/app/controllers/pageflow/review/comment_thread_reads_controller.rb +30 -0
  86. data/app/controllers/pageflow/review/comment_threads_controller.rb +60 -0
  87. data/app/controllers/pageflow/review/comments_controller.rb +53 -0
  88. data/app/controllers/pageflow/revisions_controller.rb +5 -1
  89. data/app/controllers/pageflow/sitemaps_controller.rb +1 -1
  90. data/app/controllers/pageflow/storylines_controller.rb +1 -0
  91. data/app/helpers/pageflow/admin/cutoff_modes_helper.rb +12 -0
  92. data/app/helpers/pageflow/admin/entries_helper.rb +41 -1
  93. data/app/helpers/pageflow/admin/entry_translations_helper.rb +18 -0
  94. data/app/helpers/pageflow/admin/features_helper.rb +1 -1
  95. data/app/helpers/pageflow/admin/form_helper.rb +3 -3
  96. data/app/helpers/pageflow/admin/locales_helper.rb +10 -2
  97. data/app/helpers/pageflow/admin/memberships_helper.rb +32 -32
  98. data/app/helpers/pageflow/admin/revisions_helper.rb +1 -1
  99. data/app/helpers/pageflow/admin/sites_helper.rb +22 -0
  100. data/app/helpers/pageflow/admin/users_helper.rb +7 -5
  101. data/app/helpers/pageflow/admin/widgets_helper.rb +5 -5
  102. data/app/helpers/pageflow/asset_urls_helper.rb +1 -1
  103. data/app/helpers/pageflow/audio_files_helper.rb +5 -2
  104. data/app/helpers/pageflow/background_image_helper.rb +7 -6
  105. data/app/helpers/pageflow/common_entry_seed_helper.rb +7 -7
  106. data/app/helpers/pageflow/editor/config_helper.rb +3 -1
  107. data/app/helpers/pageflow/editor/files_helper.rb +1 -1
  108. data/app/helpers/pageflow/embed_code_helper.rb +3 -3
  109. data/app/helpers/pageflow/entries_helper.rb +52 -46
  110. data/app/helpers/pageflow/entry_json_seed_helper.rb +7 -6
  111. data/app/helpers/pageflow/feeds_helper.rb +2 -2
  112. data/app/helpers/pageflow/file_background_images_helper.rb +2 -2
  113. data/app/helpers/pageflow/file_thumbnails_helper.rb +4 -3
  114. data/app/helpers/pageflow/files_helper.rb +5 -4
  115. data/app/helpers/pageflow/folders_helper.rb +8 -5
  116. data/app/helpers/pageflow/help_entries_helper.rb +2 -2
  117. data/app/helpers/pageflow/hreflang_links_helper.rb +37 -0
  118. data/app/helpers/pageflow/info_box_helper.rb +7 -11
  119. data/app/helpers/pageflow/media_query_helper.rb +3 -3
  120. data/app/helpers/pageflow/navigation_bar_helper.rb +1 -1
  121. data/app/helpers/pageflow/overview_helper.rb +1 -1
  122. data/app/helpers/pageflow/page_types_helper.rb +5 -5
  123. data/app/helpers/pageflow/pages_helper.rb +29 -15
  124. data/app/helpers/pageflow/public_i18n_helper.rb +10 -9
  125. data/app/helpers/pageflow/quota_helper.rb +4 -4
  126. data/app/helpers/pageflow/render_json_helper.rb +6 -3
  127. data/app/helpers/pageflow/revision_file_helper.rb +2 -1
  128. data/app/helpers/pageflow/sites_helper.rb +3 -3
  129. data/app/helpers/pageflow/social_share_helper.rb +24 -10
  130. data/app/helpers/pageflow/social_share_links_helper.rb +12 -9
  131. data/app/helpers/pageflow/structured_data_helper.rb +5 -2
  132. data/app/helpers/pageflow/stub_page_configuration.rb +7 -3
  133. data/app/helpers/pageflow/text_direction_helper.rb +1 -1
  134. data/app/helpers/pageflow/themes_helper.rb +2 -4
  135. data/app/helpers/pageflow/video_files_helper.rb +29 -13
  136. data/app/helpers/pageflow/widgets_helper.rb +8 -6
  137. data/app/inputs/pageflow_permalink_input.rb +8 -3
  138. data/app/jobs/pageflow/application_job.rb +1 -0
  139. data/app/jobs/pageflow/entry_export_import/upload_and_publish_file_job.rb +1 -1
  140. data/app/jobs/pageflow/poll_meta_data_from_zencoder_job.rb +1 -0
  141. data/app/jobs/pageflow/poll_zencoder_job.rb +3 -2
  142. data/app/jobs/pageflow/process_image_or_text_track_job.rb +1 -0
  143. data/app/jobs/pageflow/prune_auto_snapshots_job.rb +1 -0
  144. data/app/jobs/pageflow/request_meta_data_from_zencoder_job.rb +1 -0
  145. data/app/jobs/pageflow/submit_file_to_zencoder_job.rb +1 -0
  146. data/app/mailers/pageflow/user_mailer.rb +1 -0
  147. data/app/models/concerns/pageflow/auto_generated_perma_id.rb +20 -1
  148. data/app/models/concerns/pageflow/entry_publication_states.rb +7 -3
  149. data/app/models/concerns/pageflow/feature_target.rb +8 -4
  150. data/app/models/concerns/pageflow/output_source.rb +3 -3
  151. data/app/models/concerns/pageflow/permalinkable.rb +2 -1
  152. data/app/models/concerns/pageflow/reusable_file.rb +24 -24
  153. data/app/models/concerns/pageflow/serialization_blacklist.rb +3 -5
  154. data/app/models/concerns/pageflow/suspendable.rb +5 -3
  155. data/app/models/concerns/pageflow/theme_referencer.rb +1 -1
  156. data/app/models/concerns/pageflow/translatable.rb +62 -0
  157. data/app/models/concerns/pageflow/translated_attributes.rb +101 -0
  158. data/app/models/concerns/pageflow/uploadable_file.rb +6 -6
  159. data/app/models/pageflow/account.rb +6 -5
  160. data/app/models/pageflow/account_member_query.rb +1 -1
  161. data/app/models/pageflow/account_role_query.rb +1 -1
  162. data/app/models/pageflow/application_query.rb +1 -1
  163. data/app/models/pageflow/application_record.rb +1 -1
  164. data/app/models/pageflow/audio_file.rb +4 -4
  165. data/app/models/pageflow/audio_file_url_templates.rb +1 -1
  166. data/app/models/pageflow/authentication_token.rb +2 -2
  167. data/app/models/pageflow/chapter.rb +6 -1
  168. data/app/models/pageflow/chapter_scaffold.rb +2 -4
  169. data/app/models/pageflow/cname_site_request_scope.rb +1 -1
  170. data/app/models/pageflow/comment.rb +30 -0
  171. data/app/models/pageflow/comment_thread.rb +65 -0
  172. data/app/models/pageflow/comment_thread_read.rb +22 -0
  173. data/app/models/pageflow/customized_theme.rb +9 -8
  174. data/app/models/pageflow/draft_entry.rb +49 -9
  175. data/app/models/pageflow/edit_lock.rb +19 -21
  176. data/app/models/pageflow/encoding_confirmation.rb +2 -2
  177. data/app/models/pageflow/entries_feed.rb +2 -2
  178. data/app/models/pageflow/entry.rb +46 -30
  179. data/app/models/pageflow/entry_at_revision.rb +14 -2
  180. data/app/models/pageflow/entry_comment_summary.rb +114 -0
  181. data/app/models/pageflow/entry_duplicate.rb +8 -5
  182. data/app/models/pageflow/entry_publication.rb +2 -2
  183. data/app/models/pageflow/entry_role_query.rb +4 -4
  184. data/app/models/pageflow/entry_template.rb +4 -4
  185. data/app/models/pageflow/entry_title_or_account_name_query.rb +2 -2
  186. data/app/models/pageflow/entry_translation_group.rb +42 -0
  187. data/app/models/pageflow/file_folder.rb +74 -0
  188. data/app/models/pageflow/file_reuse.rb +5 -4
  189. data/app/models/pageflow/file_usage.rb +18 -3
  190. data/app/models/pageflow/folder.rb +2 -2
  191. data/app/models/pageflow/home_button.rb +7 -7
  192. data/app/models/pageflow/image_file.rb +44 -25
  193. data/app/models/pageflow/image_file_url_templates.rb +4 -4
  194. data/app/models/pageflow/invitation_form.rb +2 -1
  195. data/app/models/pageflow/legal_info.rb +38 -0
  196. data/app/models/pageflow/managed_user_query.rb +1 -1
  197. data/app/models/pageflow/membership.rb +5 -5
  198. data/app/models/pageflow/nested_revision_component_copy.rb +263 -0
  199. data/app/models/pageflow/null_user.rb +1 -1
  200. data/app/models/pageflow/overview_button.rb +1 -1
  201. data/app/models/pageflow/page.rb +7 -3
  202. data/app/models/pageflow/permalink.rb +24 -2
  203. data/app/models/pageflow/permalink_directory.rb +7 -0
  204. data/app/models/pageflow/permalink_redirect.rb +7 -0
  205. data/app/models/pageflow/positioned_file.rb +5 -5
  206. data/app/models/pageflow/potential_entry_translations.rb +55 -0
  207. data/app/models/pageflow/potential_memberships.rb +5 -4
  208. data/app/models/pageflow/published_entry.rb +62 -11
  209. data/app/models/pageflow/revision.rb +29 -16
  210. data/app/models/pageflow/roles.rb +14 -18
  211. data/app/models/pageflow/site.rb +46 -3
  212. data/app/models/pageflow/site_root_entry_form.rb +27 -0
  213. data/app/models/pageflow/sitemaps.rb +10 -1
  214. data/app/models/pageflow/storyline.rb +5 -2
  215. data/app/models/pageflow/storyline_scaffold.rb +1 -1
  216. data/app/models/pageflow/text_track_file.rb +1 -1
  217. data/app/models/pageflow/text_track_file_url_templates.rb +1 -1
  218. data/app/models/pageflow/theme_customization_file.rb +3 -2
  219. data/app/models/pageflow/thumbnail_file_resolver.rb +1 -1
  220. data/app/models/pageflow/url_template.rb +1 -1
  221. data/app/models/pageflow/used_file.rb +13 -3
  222. data/app/models/pageflow/user_name_query.rb +2 -2
  223. data/app/models/pageflow/video_file.rb +22 -15
  224. data/app/models/pageflow/video_file_url_templates.rb +6 -4
  225. data/app/models/pageflow/widget.rb +5 -4
  226. data/app/models/pageflow/with_file_usage_extension.rb +1 -1
  227. data/app/models/pageflow/zencoder_attachment.rb +8 -8
  228. data/app/policies/pageflow/account_policy.rb +3 -1
  229. data/app/policies/pageflow/admin/admin_only_tab_policy.rb +1 -0
  230. data/app/policies/pageflow/admin/entry_tab_policy.rb +1 -0
  231. data/app/policies/pageflow/application_policy.rb +2 -0
  232. data/app/policies/pageflow/entry_policy.rb +7 -1
  233. data/app/policies/pageflow/entry_template_policy.rb +2 -1
  234. data/app/policies/pageflow/file_policy.rb +4 -7
  235. data/app/policies/pageflow/folder_policy.rb +18 -8
  236. data/app/policies/pageflow/membership_policy.rb +6 -4
  237. data/app/policies/pageflow/site_policy.rb +10 -3
  238. data/app/policies/pageflow/user_policy.rb +6 -4
  239. data/app/state_machines/pageflow/image_and_text_track_processing_state_machine.rb +3 -2
  240. data/app/state_machines/pageflow/media_encoding_state_machine.rb +5 -4
  241. data/app/views/admin/accounts/_entry_template_details.html.arb +2 -2
  242. data/app/views/admin/entries/_attributes_table.html.arb +6 -5
  243. data/app/views/admin/entries/_form.html.erb +2 -1
  244. data/app/views/admin/entries/_permalink_inputs.html.erb +9 -2
  245. data/app/views/admin/entry_templates/_form.html.erb +1 -3
  246. data/app/views/admin/site_root_entry/choose.html.erb +19 -0
  247. data/app/views/admin/sites/_fields.html.erb +14 -1
  248. data/app/views/admin/translations/_form.html.erb +31 -0
  249. data/app/views/admin/users/_attributes_table.html.arb +13 -0
  250. data/app/views/components/pageflow/admin/add_membership_button.rb +13 -12
  251. data/app/views/components/pageflow/admin/custom_scopes_renderer.rb +1 -0
  252. data/app/views/components/pageflow/admin/embed_code_field.rb +1 -0
  253. data/app/views/components/pageflow/admin/embedded_index_table.rb +9 -10
  254. data/app/views/components/pageflow/admin/entries_tab.rb +1 -0
  255. data/app/views/components/pageflow/admin/entry_publication_state_indicator.rb +6 -5
  256. data/app/views/components/pageflow/admin/entry_templates_tab.rb +2 -1
  257. data/app/views/components/pageflow/admin/entry_translations_tab.rb +102 -0
  258. data/app/views/components/pageflow/admin/entry_user_badge_list.rb +1 -0
  259. data/app/views/components/pageflow/admin/extensible_attributes_table.rb +9 -8
  260. data/app/views/components/pageflow/admin/features_tab.rb +1 -0
  261. data/app/views/components/pageflow/admin/grouped_folder_list.rb +1 -0
  262. data/app/views/components/pageflow/admin/icon_link_to.rb +1 -0
  263. data/app/views/components/pageflow/admin/members_tab.rb +4 -3
  264. data/app/views/components/pageflow/admin/membership_role_with_tooltip.rb +3 -2
  265. data/app/views/components/pageflow/admin/revisions_tab.rb +14 -10
  266. data/app/views/components/pageflow/admin/sites_tab.rb +1 -0
  267. data/app/views/components/pageflow/admin/tabs_view.rb +1 -0
  268. data/app/views/components/pageflow/admin/timestamp.rb +6 -5
  269. data/app/views/components/pageflow/admin/user_account_badge_list.rb +2 -3
  270. data/app/views/components/pageflow/admin/user_accounts_tab.rb +1 -0
  271. data/app/views/components/pageflow/admin/user_entries_tab.rb +1 -0
  272. data/app/views/components/pageflow/admin/users_tab.rb +1 -0
  273. data/app/views/pageflow/audio_files/_audio_file.json.jbuilder +0 -1
  274. data/app/views/pageflow/editor/config/_seeds.json.jbuilder +5 -3
  275. data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
  276. data/app/views/pageflow/editor/entries/index.json.jbuilder +1 -1
  277. data/app/views/pageflow/editor/entries/seed.json.erb +1 -0
  278. data/app/views/pageflow/editor/entries/show.json.jbuilder +1 -1
  279. data/app/views/pageflow/editor/entry_publications/check.json.jbuilder +2 -2
  280. data/app/views/pageflow/editor/file_folders/_file_folder.json.jbuilder +5 -0
  281. data/app/views/pageflow/editor/file_folders/create.json.jbuilder +1 -0
  282. data/app/views/pageflow/editor/file_folders/index.json.jbuilder +3 -0
  283. data/app/views/pageflow/editor/files/_file.json.jbuilder +7 -14
  284. data/app/views/pageflow/editor/files/create.json.jbuilder +1 -1
  285. data/app/views/pageflow/editor/files/index.json.jbuilder +1 -1
  286. data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +3 -0
  287. data/app/views/pageflow/editor/sites/_site.json.jbuilder +1 -0
  288. data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +4 -3
  289. data/app/views/pageflow/entries/share_menu/_bluesky_link.html.erb +8 -0
  290. data/app/views/pageflow/entries/share_menu/_threads_link.html.erb +8 -0
  291. data/app/views/pageflow/files/_file.json.jbuilder +5 -3
  292. data/app/views/pageflow/image_files/_image_file.json.jbuilder +0 -1
  293. data/app/views/pageflow/review/comment_threads/_comment_thread.json.jbuilder +20 -0
  294. data/app/views/pageflow/review/comment_threads/create.json.jbuilder +2 -0
  295. data/app/views/pageflow/review/comment_threads/index.json.jbuilder +13 -0
  296. data/app/views/pageflow/review/comments/_comment.json.jbuilder +13 -0
  297. data/app/views/pageflow/review/comments/create.json.jbuilder +1 -0
  298. data/app/views/pageflow/sitemaps/index.xml.builder +9 -1
  299. data/app/views/pageflow/social_share/_entry_meta_tags.html.erb +1 -1
  300. data/app/views/pageflow/social_share/_page_meta_tags.html.erb +1 -1
  301. data/app/views/pageflow/structured_data/_entry.json.jbuilder +2 -3
  302. data/app/views/pageflow/video_files/_video_file.json.jbuilder +0 -1
  303. data/config/initializers/active_admin_patches.rb +3 -6
  304. data/config/initializers/admin_resource_tabs.rb +3 -0
  305. data/config/initializers/paperclip.rb +1 -0
  306. data/config/initializers/symmetric_encryption.rb +1 -1
  307. data/config/initializers/zencoder.rb +24 -13
  308. data/config/locales/de.yml +256 -12
  309. data/config/locales/en.yml +253 -15
  310. data/config/routes.rb +29 -13
  311. data/config/spring.rb +2 -1
  312. data/db/migrate/20140418225525_setup_schema.rb +2 -2
  313. data/db/migrate/20190306161431_copy_file_attributes_of_failed_uploads.rb +2 -2
  314. data/db/migrate/20190820152900_drop_accounts_themes.rb +2 -1
  315. data/db/migrate/20191202145757_create_pageflow_scrolled_sections.rb +11 -11
  316. data/db/migrate/20191202150657_create_pageflow_scrolled_chapters.rb +1 -1
  317. data/db/migrate/20191202154723_create_pageflow_scrolled_content_elements.rb +9 -9
  318. data/db/migrate/20191219143450_add_position_to_content_elements.rb +2 -1
  319. data/db/migrate/20200117133200_change_revision_appearance_option_default_and_null.rb +2 -1
  320. data/db/migrate/20200122115400_create_pageflow_entry_templates.rb +25 -25
  321. data/db/migrate/20200206134400_convert_legacy_scrolled_content_element_types.rb +3 -3
  322. data/db/migrate/20221215120856_associate_entry_templates_with_sites.rb +2 -2
  323. data/db/migrate/20230120092923_create_other_files.rb +2 -1
  324. data/db/migrate/20230419083307_create_pageflow_entry_translation_group.rb +9 -0
  325. data/db/migrate/20240612110434_add_cutoff_mode_name_to_sites.rb +5 -0
  326. data/db/migrate/20240918084059_create_pageflow_permalink_redirects.rb +14 -0
  327. data/db/migrate/20250508172234_ensure_scrolled_entries_have_main_storyline.rb +14 -0
  328. data/db/migrate/20250617090048_add_custom404_entry_to_sites.rb +5 -0
  329. data/db/migrate/20250617100000_add_perma_id_counter_to_entries.rb +28 -0
  330. data/db/migrate/20250722174123_add_perma_id_to_chapters.rb +10 -0
  331. data/db/migrate/20250725080603_add_perma_id_indexes_to_revision_components.rb +13 -0
  332. data/db/migrate/20250726000000_add_display_name_to_file_usages.rb +5 -0
  333. data/db/migrate/20251015000000_add_structured_data_type_name_to_revisions.rb +5 -0
  334. data/db/migrate/20251029142849_convert_legacy_social_embeds_to_unified_social_embed.rb +38 -0
  335. data/db/migrate/20251119083347_fix_main_storyline_positions.rb +16 -0
  336. data/db/migrate/20251119083348_ensure_scrolled_entries_have_excursion_storyline.rb +15 -0
  337. data/db/migrate/20260303000000_add_layout_version_to_revisions.rb +6 -0
  338. data/db/migrate/20260323000000_create_comment_threads_and_comments.rb +30 -0
  339. data/db/migrate/20260414000000_add_subject_range_to_comment_threads.rb +5 -0
  340. data/db/migrate/20260415000000_add_section_perma_id_to_comment_threads.rb +5 -0
  341. data/db/migrate/20260727000000_add_quote_to_comments.rb +5 -0
  342. data/db/migrate/20260728000000_create_file_folders.rb +17 -0
  343. data/db/migrate/20260805000000_add_attribute_translations_to_sites.rb +5 -0
  344. data/db/migrate/20260806000000_add_edited_at_to_comments.rb +5 -0
  345. data/db/migrate/20260810000000_create_pageflow_scrolled_lottie_files.rb +24 -0
  346. data/db/migrate/20260817000000_create_comment_thread_reads.rb +16 -0
  347. data/db/migrate/20260819000000_add_unread_comments_since_at_to_users.rb +18 -0
  348. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +12599 -5398
  349. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +1275 -4560
  350. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +20204 -22
  351. data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +18657 -19
  352. data/entry_types/paged/app/controllers/pageflow_paged/entries_controller.rb +1 -0
  353. data/entry_types/paged/app/helpers/pageflow_paged/page_background_asset_helper.rb +1 -1
  354. data/entry_types/paged/app/helpers/pageflow_paged/third_party_embed_consent_helper.rb +7 -7
  355. data/entry_types/paged/app/views/pageflow_paged/editor/entries/_seed.json.jbuilder +1 -0
  356. data/entry_types/paged/app/views/pageflow_paged/entries/show.html.erb +1 -0
  357. data/entry_types/paged/lib/pageflow_paged/plugin.rb +4 -0
  358. data/entry_types/paged/lib/pageflow_paged/react/page_type.rb +1 -1
  359. data/entry_types/paged/lib/pageflow_paged/react/widget_type.rb +3 -3
  360. data/entry_types/paged/lib/pageflow_paged.rb +1 -1
  361. data/entry_types/scrolled/app/assets/stylesheets/pageflow_scrolled/ui.scss +2 -0
  362. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +5 -3
  363. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +35 -5
  364. data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +4 -5
  365. data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +23 -2
  366. data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +3 -3
  367. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +8 -5
  368. data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +7 -3
  369. data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +72 -10
  370. data/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +28 -13
  371. data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +41 -12
  372. data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +23 -25
  373. data/entry_types/scrolled/app/helpers/pageflow_scrolled/sprockets_helper.rb +16 -0
  374. data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +189 -3
  375. data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +15 -14
  376. data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +61 -7
  377. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file.rb +6 -0
  378. data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file_url_templates.rb +16 -0
  379. data/entry_types/scrolled/app/models/pageflow_scrolled/section.rb +12 -1
  380. data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +20 -1
  381. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -0
  382. data/entry_types/scrolled/app/views/pageflow_scrolled/editor/sections/_section_with_content_elements.json.jbuilder +2 -2
  383. data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +15 -12
  384. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +45 -17
  385. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry_translations.json.jbuilder +14 -0
  386. data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +34 -5
  387. data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +1 -1
  388. data/entry_types/scrolled/app/views/pageflow_scrolled/storylines/_storyline.json.jbuilder +7 -0
  389. data/entry_types/scrolled/config/configuration_schemas/pageflow-scrolled.json +414 -0
  390. data/entry_types/scrolled/config/locales/de.yml +1094 -78
  391. data/entry_types/scrolled/config/locales/en.yml +1083 -78
  392. data/entry_types/scrolled/config/routes.rb +18 -8
  393. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +11 -11
  394. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDarkVariantDesktop.svg +56 -0
  395. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDarkVariantMobile.svg +22 -0
  396. data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/themes_plugin.rb.tt +26 -11
  397. data/entry_types/scrolled/lib/pageflow_scrolled/additional_packs.rb +27 -8
  398. data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +2 -2
  399. data/entry_types/scrolled/lib/pageflow_scrolled/additional_theme_assets.rb +27 -0
  400. data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +67 -10
  401. data/entry_types/scrolled/lib/pageflow_scrolled/configuration_schemas.rb +91 -0
  402. data/entry_types/scrolled/lib/pageflow_scrolled/content_element_consent_vendors.rb +1 -1
  403. data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +2 -1
  404. data/entry_types/scrolled/lib/pageflow_scrolled/entry_file_reference_locations.rb +71 -0
  405. data/entry_types/scrolled/lib/pageflow_scrolled/entry_structured_data_types/faq_page.rb +58 -0
  406. data/entry_types/scrolled/lib/pageflow_scrolled/file_reference_locations.rb +69 -0
  407. data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +222 -19
  408. data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +2 -4
  409. data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +76 -54
  410. data/entry_types/scrolled/lib/pageflow_scrolled/theme_options_default_scale.rb +35 -0
  411. data/entry_types/scrolled/lib/pageflow_scrolled.rb +14 -1
  412. data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +24 -5
  413. data/entry_types/scrolled/package/config/configurationSchemas.js +70 -0
  414. data/entry_types/scrolled/package/config/rollup/configurationSchemas.js +19 -0
  415. data/entry_types/scrolled/package/config/webpack.js +94 -0
  416. data/entry_types/scrolled/package/contentElements/hotspots-frontend.css +1 -0
  417. data/entry_types/scrolled/package/contentElements/hotspots-frontend.js +1795 -0
  418. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.css +1 -0
  419. data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.js +219 -0
  420. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.css +1 -0
  421. data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.js +244 -0
  422. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.css +1 -0
  423. data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.js +823 -0
  424. data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.css +1 -0
  425. data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.js +109 -0
  426. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.css +1 -0
  427. data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.js +277 -0
  428. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.css +1 -0
  429. data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.js +244 -0
  430. data/entry_types/scrolled/package/contentElements-editor.js +3155 -583
  431. data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
  432. data/entry_types/scrolled/package/contentElements-frontend.js +3375 -1585
  433. data/entry_types/scrolled/package/editor.css +1 -0
  434. data/entry_types/scrolled/package/editor.js +8452 -2867
  435. data/entry_types/scrolled/package/entryState.js +1600 -0
  436. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-20c600de.js +1979 -0
  437. data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-58189220.js +2538 -0
  438. data/entry_types/scrolled/package/frontend/{PhonePlatformContext-4ec6b2de.js → PhonePlatformContext-035a99fa.js} +9 -15
  439. data/entry_types/scrolled/package/frontend/PhonePlatformContext-9da43797.js +33 -0
  440. data/entry_types/scrolled/package/frontend/Placeholder.module-bf0966b4.js +5267 -0
  441. data/entry_types/scrolled/package/frontend/Placeholder.module-d22a9335.js +4180 -0
  442. data/entry_types/scrolled/package/frontend/ThemeIcon-ab834849.js +754 -0
  443. data/entry_types/scrolled/package/frontend/ThemeIcon-f6cb3a8f.js +773 -0
  444. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-30fd1124.js +39 -0
  445. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-61c25224.js +72 -0
  446. data/entry_types/scrolled/package/frontend/Viewer-1074fd59.js +147 -0
  447. data/entry_types/scrolled/package/frontend/Viewer-1482ca34.js +480 -0
  448. data/entry_types/scrolled/package/frontend/Viewer-70504231.js +210 -0
  449. data/entry_types/scrolled/package/frontend/{Viewer-1bb5597c.js → Viewer-cc8d4072.js} +100 -135
  450. data/entry_types/scrolled/package/frontend/Wavesurfer-656e3c36.js +302 -0
  451. data/entry_types/scrolled/package/frontend/Wavesurfer-b753b838.js +385 -0
  452. data/entry_types/scrolled/package/frontend/commenting.css +1 -0
  453. data/entry_types/scrolled/package/frontend/extensions-167ae143.js +1455 -0
  454. data/entry_types/scrolled/package/frontend/extensions-2318f92b.js +5918 -0
  455. data/entry_types/scrolled/package/frontend/extensions-a461fd13.js +4890 -0
  456. data/entry_types/scrolled/package/frontend/extensions-c98269fd.js +1982 -0
  457. data/entry_types/scrolled/package/frontend/i18n-493cd2a6.js +93 -0
  458. data/entry_types/scrolled/package/frontend/i18n-e06cac14.js +100 -0
  459. data/entry_types/scrolled/package/frontend/{index-11f32f10.js → index-2e5546f7.js} +39 -54
  460. data/entry_types/scrolled/package/frontend/index-de2b418d.js +130 -0
  461. data/entry_types/scrolled/package/frontend/index.css +1 -1
  462. data/entry_types/scrolled/package/frontend/index.js +1976 -1367
  463. data/entry_types/scrolled/package/frontend/inlineEditing.css +1 -0
  464. data/entry_types/scrolled/package/frontend/useContentElementEditorState-a084912e.js +25 -0
  465. data/entry_types/scrolled/package/frontend/useDelayedBoolean-a387d85b.js +24 -0
  466. data/entry_types/scrolled/package/frontend/usePhonePlatform-4ecb96d4.js +8 -0
  467. data/entry_types/scrolled/package/frontend/usePhonePlatform-ce9ff08d.js +8 -0
  468. data/entry_types/scrolled/package/frontend-server.js +20 -210
  469. data/entry_types/scrolled/package/package.json +22 -12
  470. data/entry_types/scrolled/package/review.css +1 -0
  471. data/entry_types/scrolled/package/review.js +3306 -0
  472. data/entry_types/scrolled/package/testHelpers.js +952 -239
  473. data/entry_types/scrolled/package/values/widgets.module.css +18 -0
  474. data/entry_types/scrolled/package/widgets/consentBar.css +1 -1
  475. data/entry_types/scrolled/package/widgets/consentBar.js +275 -315
  476. data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
  477. data/entry_types/scrolled/package/widgets/defaultNavigation.js +961 -432
  478. data/entry_types/scrolled/package/widgets/excursionSheet.css +1 -0
  479. data/entry_types/scrolled/package/widgets/excursionSheet.js +225 -0
  480. data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -1
  481. data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +62 -32
  482. data/entry_types/scrolled/package/widgets/iconScrollIndicator.css +1 -0
  483. data/entry_types/scrolled/package/widgets/iconScrollIndicator.js +67 -0
  484. data/entry_types/scrolled/package/widgets/mainStorylineSheet.css +1 -0
  485. data/entry_types/scrolled/package/widgets/mainStorylineSheet.js +100 -0
  486. data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -1
  487. data/entry_types/scrolled/package/widgets/textInlineFileRights.js +48 -26
  488. data/entry_types/scrolled/package/widgets-server.js +2 -0
  489. data/entry_types/scrolled/spec/factories/chapters.rb +14 -1
  490. data/entry_types/scrolled/spec/factories/content_elements.rb +1 -1
  491. data/entry_types/scrolled/spec/factories/lottie_files.rb +29 -0
  492. data/entry_types/scrolled/spec/fixtures/animation.lottie +0 -0
  493. data/entry_types/scrolled/spec/fixtures/font.woff +0 -0
  494. data/entry_types/scrolled/spec/fixtures/font.woff2 +0 -0
  495. data/lib/generators/pageflow/active_admin_initializer/active_admin_initializer_generator.rb +5 -3
  496. data/lib/generators/pageflow/assets/assets_generator.rb +7 -5
  497. data/lib/generators/pageflow/cancan/cancan_generator.rb +2 -1
  498. data/lib/generators/pageflow/cancan/templates/ability.rb +1 -1
  499. data/lib/generators/pageflow/error_pages/error_pages_generator.rb +2 -1
  500. data/lib/generators/pageflow/initializer/initializer_generator.rb +3 -2
  501. data/lib/generators/pageflow/install/install_generator.rb +2 -2
  502. data/lib/generators/pageflow/procfile/procfile_generator.rb +2 -1
  503. data/lib/generators/pageflow/resque/resque_generator.rb +4 -4
  504. data/lib/generators/pageflow/resque/templates/resque.rake +1 -1
  505. data/lib/generators/pageflow/routes/routes_generator.rb +4 -2
  506. data/lib/generators/pageflow/seeds/seeds_generator.rb +3 -2
  507. data/lib/generators/pageflow/seeds/templates/seeds.rb +6 -6
  508. data/lib/generators/pageflow/theme/theme_generator.rb +2 -1
  509. data/lib/generators/pageflow/user/user_generator.rb +2 -1
  510. data/lib/pageflow/ability_mixin.rb +25 -15
  511. data/lib/pageflow/active_admin_patches/views/attributes_table.rb +1 -0
  512. data/lib/pageflow/active_admin_patches/views/pages/base.rb +3 -2
  513. data/lib/pageflow/active_admin_patches/views/table_for.rb +1 -0
  514. data/lib/pageflow/additional_headers.rb +27 -0
  515. data/lib/pageflow/admin/attributes_table_rows.rb +3 -3
  516. data/lib/pageflow/admin/tabs.rb +1 -1
  517. data/lib/pageflow/built_in_file_type.rb +1 -1
  518. data/lib/pageflow/built_in_page_types_plugin.rb +1 -1
  519. data/lib/pageflow/built_in_widget_type.rb +2 -2
  520. data/lib/pageflow/built_in_widget_types_plugin.rb +2 -1
  521. data/lib/pageflow/configuration.rb +183 -18
  522. data/lib/pageflow/cutoff_modes.rb +39 -0
  523. data/lib/pageflow/deprecation.rb +19 -0
  524. data/lib/pageflow/editor_controller.rb +6 -10
  525. data/lib/pageflow/engine.rb +5 -6
  526. data/lib/pageflow/entries_controller_env_helper.rb +32 -2
  527. data/lib/pageflow/entry_export_import/attachment_files.rb +1 -1
  528. data/lib/pageflow/entry_export_import/entry_serialization.rb +9 -8
  529. data/lib/pageflow/entry_export_import/file_mappings.rb +1 -0
  530. data/lib/pageflow/entry_export_import/page_type_versions.rb +2 -2
  531. data/lib/pageflow/entry_export_import/revision_serialization/import.rb +11 -1
  532. data/lib/pageflow/entry_export_import/revision_serialization.rb +3 -0
  533. data/lib/pageflow/entry_export_import.rb +3 -3
  534. data/lib/pageflow/entry_structured_data_types.rb +43 -0
  535. data/lib/pageflow/entry_type_configuration.rb +1 -0
  536. data/lib/pageflow/entry_types.rb +2 -2
  537. data/lib/pageflow/feature.rb +1 -1
  538. data/lib/pageflow/features.rb +4 -6
  539. data/lib/pageflow/file_importers.rb +4 -4
  540. data/lib/pageflow/file_type.rb +5 -5
  541. data/lib/pageflow/file_types.rb +4 -4
  542. data/lib/pageflow/global_config_api.rb +5 -6
  543. data/lib/pageflow/help_entries.rb +7 -7
  544. data/lib/pageflow/help_entry.rb +1 -1
  545. data/lib/pageflow/hooks.rb +1 -1
  546. data/lib/pageflow/nested_revision_component.rb +9 -27
  547. data/lib/pageflow/news_item_api.rb +1 -1
  548. data/lib/pageflow/oembed_providers.rb +42 -0
  549. data/lib/pageflow/page_type.rb +2 -3
  550. data/lib/pageflow/page_types.rb +3 -3
  551. data/lib/pageflow/paperclip_interpolations/support.rb +1 -1
  552. data/lib/pageflow/paperclip_processors/vtt.rb +1 -0
  553. data/lib/pageflow/paperclip_processors/webp.rb +2 -2
  554. data/lib/pageflow/partial_editor_fragment_renderer.rb +2 -2
  555. data/lib/pageflow/plugin.rb +1 -2
  556. data/lib/pageflow/primary_domain_entry_redirect.rb +6 -0
  557. data/lib/pageflow/quota.rb +9 -5
  558. data/lib/pageflow/quotas.rb +1 -1
  559. data/lib/pageflow/rails_version.rb +14 -2
  560. data/lib/pageflow/react.rb +1 -1
  561. data/lib/pageflow/revision_component.rb +8 -40
  562. data/lib/pageflow/revision_components.rb +16 -6
  563. data/lib/pageflow/seeds.rb +12 -16
  564. data/lib/pageflow/theme.rb +1 -1
  565. data/lib/pageflow/theme_customizations.rb +10 -10
  566. data/lib/pageflow/themes.rb +44 -3
  567. data/lib/pageflow/user_mixin.rb +18 -6
  568. data/lib/pageflow/version.rb +1 -1
  569. data/lib/pageflow/widget_type.rb +4 -4
  570. data/lib/pageflow/widget_types.rb +9 -9
  571. data/lib/pageflow/zencoder_api.rb +32 -42
  572. data/lib/pageflow/zencoder_audio_output_definition.rb +14 -13
  573. data/lib/pageflow/zencoder_meta_data_output_definition.rb +3 -2
  574. data/lib/pageflow/zencoder_output_definition.rb +16 -14
  575. data/lib/pageflow/zencoder_video_output_definition.rb +140 -88
  576. data/lib/pageflow.rb +8 -2
  577. data/lib/tasks/pageflow_tasks.rake +1 -1
  578. data/package/config/eslint-rules/documented-in-toc.js +125 -0
  579. data/package/config/jest/index.js +0 -1
  580. data/package/config/webpack.js +0 -1
  581. data/package/config/webpack5.js +0 -1
  582. data/package/editor.js +4880 -2313
  583. data/package/frontend.js +710 -1223
  584. data/package/package.json +3 -1
  585. data/package/review.js +384 -0
  586. data/package/testHelpers.js +257 -243
  587. data/package/ui.js +1487 -813
  588. data/package/vendor/stubs/wysihtml5.js +2 -0
  589. data/spec/factories/accounts.rb +37 -22
  590. data/spec/factories/audio_files.rb +2 -2
  591. data/spec/factories/authentication_tokens.rb +4 -4
  592. data/spec/factories/chapters.rb +4 -4
  593. data/spec/factories/comment_thread_reads.rb +10 -0
  594. data/spec/factories/comment_threads.rb +10 -0
  595. data/spec/factories/comments.rb +9 -0
  596. data/spec/factories/draft_entries.rb +14 -6
  597. data/spec/factories/edit_locks.rb +1 -1
  598. data/spec/factories/entries.rb +28 -19
  599. data/spec/factories/entry_translation_groups.rb +6 -0
  600. data/spec/factories/file_folders.rb +8 -0
  601. data/spec/factories/file_usages.rb +2 -1
  602. data/spec/factories/folders.rb +1 -1
  603. data/spec/factories/image_files.rb +2 -2
  604. data/spec/factories/pages.rb +3 -3
  605. data/spec/factories/published_entries.rb +28 -8
  606. data/spec/factories/revisions.rb +1 -1
  607. data/spec/factories/sites.rb +6 -0
  608. data/spec/factories/test_multi_attachment_files.rb +1 -1
  609. data/spec/factories/text_track_files.rb +1 -1
  610. data/spec/factories/uploadable_files.rb +1 -1
  611. data/spec/factories/users.rb +6 -6
  612. data/spec/factories/video_files.rb +2 -2
  613. data/spec/factories/widgets.rb +1 -1
  614. data/spec/fixtures/7x15_rotated.jpg +0 -0
  615. data/vendor/assets/javascripts/wysihtml-toolbar.js +19288 -0
  616. metadata +266 -92
  617. data/app/assets/stylesheets/pageflow/editor/select_button.scss +0 -51
  618. data/config/initializers/revision_components.rb +0 -5
  619. data/config/locales/twitter_to_x.de.yml +0 -6
  620. data/config/locales/twitter_to_x.en.yml +0 -6
  621. data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +0 -55
  622. data/entry_types/scrolled/config/locales/twitter_to_x.de.yml +0 -12
  623. data/entry_types/scrolled/config/locales/twitter_to_x.en.yml +0 -12
  624. data/entry_types/scrolled/config/locales/vr_image_projection.de.yml +0 -24
  625. data/entry_types/scrolled/config/locales/vr_image_projection.en.yml +0 -24
  626. data/entry_types/scrolled/package/frontend/EditableInlineText.module-ebd22921.js +0 -5497
  627. data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-b79159cc.js +0 -107
  628. data/entry_types/scrolled/package/frontend/Viewer-1ecf3375.js +0 -154
  629. data/entry_types/scrolled/package/frontend/Wavesurfer-7d9cf1b7.js +0 -333
  630. data/entry_types/scrolled/package/frontend/arrowRight-62998af9.js +0 -77
  631. data/entry_types/scrolled/package/frontend/components-024a9893.js +0 -2853
  632. data/entry_types/scrolled/package/frontend/createSuper-d0f30da3.js +0 -115
  633. data/entry_types/scrolled/package/frontend/i18n-ce13a8bf.js +0 -1129
  634. data/entry_types/scrolled/package/frontend/useContentElementEditorState-4f4c3cf6.js +0 -52
  635. data/lib/generators/pageflow/resque/templates/resque_enqueue_after_commit_patch.rb +0 -25
  636. data/package/vendor/jquery.minicolors.js +0 -1108
@@ -0,0 +1,1455 @@
1
+ import React, { createContext, useContext, useCallback, useState, useMemo, useRef, useEffect } from 'react';
2
+ import { flushSync } from 'react-dom';
3
+ import classNames from 'classnames';
4
+ import { a as useActiveExcursion, o as useFloatingPortalRoot, d as api, w as widths, g as useContentElementAttributes, U as PlainEditableText, N as renderLeaf, V as textStyles, T as Text, R as renderElement } from './FloatingPortalRootProvider-20c600de.js';
5
+ import './useDelayedBoolean-a387d85b.js';
6
+ import 'backbone-events-standalone';
7
+ import { useEntryMetadata } from 'pageflow-scrolled/entryState';
8
+ import 'i18n-js';
9
+ import { u as useI18n } from './i18n-493cd2a6.js';
10
+ import 'react-measure';
11
+ import { review, useCommentDisplayFilter, useLocatedCommentThreads, ActivityList, useUnreadThreadCount, useStoredCommentDisplayFilter, ReviewStateProvider, LocatedCommentThreadsProvider, CommentDisplayFilterProvider, ReviewMessageHandler, ThreadsBadge, ThreadList, useLocatedCommentThreadsForSubject, useAnchoredFloating, useRangeAnchors, useCommentThreads, useCommentHighlights, decorateCommentHighlights, RangeAnchor, commentHighlightStyles } from 'pageflow-scrolled/review';
12
+ import { useFloating, offset, shift, size, autoUpdate, FloatingPortal, flip } from '@floating-ui/react';
13
+ import { Node, Point, createEditor, Editor } from 'slate';
14
+ import { ReactEditor, withReact, Slate, Editable } from 'slate-react';
15
+ import { createReviewSession } from 'pageflow/review';
16
+
17
+ // Headings carry no ranged comments since EditableInlineText has no
18
+ // commenting alternative, so every comment refers to the header as a whole
19
+ // and the quote covers all three of its texts.
20
+ review.contentElementTypes.register('heading', {
21
+ extractQuote(configuration) {
22
+ const parts = [inlineText(configuration.tagline), mainText(configuration), inlineText(configuration.subtitle)];
23
+ return parts.map(part => part.trim()).filter(Boolean).join('\n') || null;
24
+ }
25
+ });
26
+
27
+ // Mirrors how EditableInlineText picks the legacy string value, so the quote
28
+ // never contains text the heading does not display.
29
+ function mainText(configuration) {
30
+ return configuration.value ? inlineText(configuration.value) : configuration.children || '';
31
+ }
32
+ function inlineText(value) {
33
+ return value ? value.map(node => Node.string(node)).join(' ') : '';
34
+ }
35
+
36
+ review.contentElementTypes.register('textBlock', {
37
+ compareRanges(a, b) {
38
+ if (!a && !b) return 0;
39
+ if (!a) return 1;
40
+ if (!b) return -1;
41
+ return Point.compare(rangeStart(a), rangeStart(b));
42
+ },
43
+ // Element wide comments stay unquoted: the whole text is too long to serve
44
+ // as a point of reference, and any edit anywhere in it would mark the quote
45
+ // outdated.
46
+ extractQuote(configuration, range) {
47
+ if (!range) return null;
48
+ const root = {
49
+ children: configuration.value || []
50
+ };
51
+ if (!Node.has(root, range.anchor.path) || !Node.has(root, range.focus.path)) {
52
+ return null;
53
+ }
54
+ const text = Node.fragment(root, range).map(node => Node.string(node)).join('\n').trim();
55
+ return text || null;
56
+ }
57
+ });
58
+ function rangeStart(range) {
59
+ return Point.isBefore(range.anchor, range.focus) ? range.anchor : range.focus;
60
+ }
61
+
62
+ const SelectedSubjectContext = createContext({
63
+ selectedSubject: null,
64
+ setSelectedSubject: () => {},
65
+ clearSelection: () => {}
66
+ });
67
+ const CommentNavigationContext = createContext({
68
+ count: 0,
69
+ position: 0,
70
+ goToNext: () => {},
71
+ goToPrevious: () => {},
72
+ goToThread: () => {}
73
+ });
74
+ function SelectedSubjectProvider({
75
+ children
76
+ }) {
77
+ const {
78
+ resolution
79
+ } = useCommentDisplayFilter();
80
+ const {
81
+ chapters
82
+ } = useLocatedCommentThreads();
83
+ const {
84
+ activateExcursionOfSection,
85
+ returnFromExcursion
86
+ } = useActiveExcursion();
87
+ const [selectedSubject, setSelectedSubject] = useState(null);
88
+ const allTargets = useMemo(() => navigableTargets(chapters), [chapters]);
89
+ const targets = useMemo(() => allTargets.filter(target => matchesResolution(target, resolution)), [allTargets, resolution]);
90
+ const clearSelection = useCallback(() => {
91
+ setSelectedSubject(null);
92
+ }, []);
93
+ const selectTarget = useCallback((target, options) => {
94
+ if (movesToDifferentSubject(selectedSubject, target)) {
95
+ if (target.excursion) {
96
+ activateExcursionOfSection({
97
+ id: target.sectionId
98
+ });
99
+ } else {
100
+ returnFromExcursion();
101
+ }
102
+ }
103
+ setSelectedSubject({
104
+ subjectType: target.subjectType,
105
+ subjectId: target.subjectId,
106
+ subjectRange: target.subjectRange,
107
+ highlightedThreadId: target.threadId,
108
+ ...options
109
+ });
110
+ }, [selectedSubject, activateExcursionOfSection, returnFromExcursion]);
111
+ const goTo = useCallback(step => {
112
+ if (targets.length === 0) {
113
+ return;
114
+ }
115
+ const current = currentTargetIndex(targets, selectedSubject);
116
+ const next = current < 0 ? step > 0 ? 0 : targets.length - 1 : (current + step + targets.length) % targets.length;
117
+ selectTarget(targets[next]);
118
+ }, [targets, selectedSubject, selectTarget]);
119
+ const goToThread = useCallback((threadId, options) => {
120
+ const target = allTargets.find(target => target.threadId === threadId);
121
+ if (target) {
122
+ selectTarget(target, options);
123
+ }
124
+ }, [allTargets, selectTarget]);
125
+ const position = useMemo(() => currentTargetIndex(targets, selectedSubject) + 1, [targets, selectedSubject]);
126
+ const selection = useMemo(() => ({
127
+ selectedSubject,
128
+ setSelectedSubject,
129
+ clearSelection
130
+ }), [selectedSubject, clearSelection]);
131
+ const navigation = useMemo(() => {
132
+ var _selectedSubject$high;
133
+ return {
134
+ count: targets.length,
135
+ position,
136
+ highlightedThreadId: (_selectedSubject$high = selectedSubject === null || selectedSubject === void 0 ? void 0 : selectedSubject.highlightedThreadId) !== null && _selectedSubject$high !== void 0 ? _selectedSubject$high : null,
137
+ goToNext: () => goTo(1),
138
+ goToPrevious: () => goTo(-1),
139
+ goToThread
140
+ };
141
+ }, [targets.length, position, selectedSubject, goTo, goToThread]);
142
+ return /*#__PURE__*/React.createElement(SelectedSubjectContext.Provider, {
143
+ value: selection
144
+ }, /*#__PURE__*/React.createElement(CommentNavigationContext.Provider, {
145
+ value: navigation
146
+ }, children));
147
+ }
148
+ function useCommentNavigation() {
149
+ return useContext(CommentNavigationContext);
150
+ }
151
+ function useSelectedSubject(subjectType, subjectId, subjectRange) {
152
+ var _selectedSubject$high2;
153
+ const {
154
+ selectedSubject,
155
+ setSelectedSubject,
156
+ clearSelection
157
+ } = useContext(SelectedSubjectContext);
158
+ const isSelected = selectedSubject && selectedSubject.subjectType === subjectType && selectedSubject.subjectId === subjectId && (!subjectRange || JSON.stringify(selectedSubject.subjectRange) === JSON.stringify(subjectRange));
159
+ const select = useCallback(options => {
160
+ setSelectedSubject({
161
+ subjectType,
162
+ subjectId,
163
+ subjectRange,
164
+ ...options
165
+ });
166
+ }, [setSelectedSubject, subjectType, subjectId, subjectRange]);
167
+ return {
168
+ isSelected,
169
+ hasSelection: !!selectedSubject,
170
+ select,
171
+ clearSelection,
172
+ revealOnly: !!(isSelected && selectedSubject.revealOnly),
173
+ showNewForm: isSelected && selectedSubject.showNewForm,
174
+ subjectRange: isSelected ? selectedSubject.subjectRange : undefined,
175
+ highlightedThreadId: isSelected ? (_selectedSubject$high2 = selectedSubject.highlightedThreadId) !== null && _selectedSubject$high2 !== void 0 ? _selectedSubject$high2 : null : null
176
+ };
177
+ }
178
+ function movesToDifferentSubject(selectedSubject, target) {
179
+ return !selectedSubject || subjectKey(selectedSubject) !== target.key;
180
+ }
181
+ function currentTargetIndex(targets, selectedSubject) {
182
+ if (!selectedSubject) {
183
+ return -1;
184
+ }
185
+ if (selectedSubject.highlightedThreadId != null) {
186
+ return targets.findIndex(target => target.threadId === selectedSubject.highlightedThreadId);
187
+ }
188
+ const key = subjectKey(selectedSubject);
189
+ return targets.findIndex(target => target.key === key);
190
+ }
191
+ function navigableTargets(chapters) {
192
+ const targets = [];
193
+ chapters.forEach(chapter => {
194
+ chapter.sections.forEach(section => {
195
+ const location = {
196
+ sectionId: section.id,
197
+ excursion: chapter.isExcursion
198
+ };
199
+ section.threads.forEach(thread => targets.push({
200
+ key: subjectKey({
201
+ subjectType: 'Section',
202
+ subjectId: section.permaId
203
+ }),
204
+ subjectType: 'Section',
205
+ subjectId: section.permaId,
206
+ threadId: thread.id,
207
+ resolved: !!thread.resolvedAt,
208
+ ...location
209
+ }));
210
+ section.contentElements.forEach(contentElement => {
211
+ pushTargets(targets, contentElement.threads, location);
212
+ });
213
+ });
214
+ });
215
+ return targets;
216
+ }
217
+ function pushTargets(targets, threads, location) {
218
+ threads.forEach(thread => targets.push({
219
+ key: subjectKey(thread),
220
+ subjectType: thread.subjectType,
221
+ subjectId: thread.subjectId,
222
+ subjectRange: thread.subjectRange,
223
+ threadId: thread.id,
224
+ resolved: !!thread.resolvedAt,
225
+ ...location
226
+ }));
227
+ }
228
+ function matchesResolution(target, resolution) {
229
+ return resolution === 'all' || resolution === 'unresolved' && !target.resolved || resolution === 'resolved' && target.resolved;
230
+ }
231
+ function subjectKey({
232
+ subjectType,
233
+ subjectId,
234
+ subjectRange
235
+ }) {
236
+ return `${subjectType}:${subjectId}:${subjectRange ? JSON.stringify(subjectRange) : ''}`;
237
+ }
238
+
239
+ const AddCommentModeContext = createContext({
240
+ active: false,
241
+ toggle: () => {},
242
+ deactivate: () => {},
243
+ preselect: () => {},
244
+ clearPreselection: () => {}
245
+ });
246
+ function AddCommentModeProvider({
247
+ children
248
+ }) {
249
+ const [active, setActive] = useState(false);
250
+ const preselectionRef = useRef(null);
251
+ const {
252
+ select
253
+ } = useSelectedSubject();
254
+ const toggle = useCallback(() => {
255
+ if (!active && preselectionRef.current) {
256
+ select(preselectionRef.current);
257
+ preselectionRef.current = null;
258
+ return;
259
+ }
260
+ setActive(prev => !prev);
261
+ }, [active, select]);
262
+ const deactivate = useCallback(() => {
263
+ setActive(false);
264
+ }, []);
265
+ const preselect = useCallback(subject => {
266
+ preselectionRef.current = subject;
267
+ }, []);
268
+ const clearPreselection = useCallback(subjectId => {
269
+ var _preselectionRef$curr;
270
+ if (((_preselectionRef$curr = preselectionRef.current) === null || _preselectionRef$curr === void 0 ? void 0 : _preselectionRef$curr.subjectId) === subjectId) {
271
+ preselectionRef.current = null;
272
+ }
273
+ }, []);
274
+ useEffect(() => {
275
+ if (!active) return;
276
+ function handleMouseDown(event) {
277
+ if (!event.target.closest('[data-add-comment-overlay]') && !event.target.closest('[data-add-comment-toggle]')) {
278
+ setActive(false);
279
+ }
280
+ }
281
+ document.addEventListener('mousedown', handleMouseDown);
282
+ return () => {
283
+ document.removeEventListener('mousedown', handleMouseDown);
284
+ };
285
+ }, [active]);
286
+ const value = useMemo(() => ({
287
+ active,
288
+ toggle,
289
+ deactivate,
290
+ preselect,
291
+ clearPreselection
292
+ }), [active, toggle, deactivate, preselect, clearPreselection]);
293
+ return /*#__PURE__*/React.createElement(AddCommentModeContext.Provider, {
294
+ value: value
295
+ }, children);
296
+ }
297
+ function useAddCommentMode() {
298
+ return useContext(AddCommentModeContext);
299
+ }
300
+
301
+ const storageKey = 'pageflow.scrolled.commentingVisible';
302
+ const CommentingVisibilityContext = createContext({
303
+ visible: true,
304
+ toggle: () => {}
305
+ });
306
+ function CommentingVisibilityProvider({
307
+ children
308
+ }) {
309
+ const [visible, setVisible] = useState(readStoredVisibility);
310
+ const toggle = useCallback(() => {
311
+ const next = !visible;
312
+ const flip = () => setVisible(next);
313
+
314
+ // Without flushSync the transition captures the pre-toggle DOM.
315
+ if (document.startViewTransition) {
316
+ document.startViewTransition(() => flushSync(flip));
317
+ } else {
318
+ flip();
319
+ }
320
+ storeVisibility(next);
321
+ }, [visible]);
322
+ const value = useMemo(() => ({
323
+ visible,
324
+ toggle
325
+ }), [visible, toggle]);
326
+ return /*#__PURE__*/React.createElement(CommentingVisibilityContext.Provider, {
327
+ value: value
328
+ }, children);
329
+ }
330
+ function useCommentingVisibility() {
331
+ return useContext(CommentingVisibilityContext);
332
+ }
333
+ function readStoredVisibility() {
334
+ var _getLocalStorage;
335
+ return ((_getLocalStorage = getLocalStorage()) === null || _getLocalStorage === void 0 ? void 0 : _getLocalStorage[storageKey]) !== 'false';
336
+ }
337
+ function storeVisibility(visible) {
338
+ const storage = getLocalStorage();
339
+ if (storage) {
340
+ storage[storageKey] = visible;
341
+ }
342
+ }
343
+ function getLocalStorage() {
344
+ try {
345
+ return typeof window === 'undefined' ? null : window.localStorage;
346
+ } catch (e) {
347
+ // Safari throws SecurityError when accessing window.localStorage
348
+ // if cookies/website data are disabled.
349
+ return null;
350
+ }
351
+ }
352
+
353
+ function _extends() {
354
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
355
+ for (var i = 1; i < arguments.length; i++) {
356
+ var source = arguments[i];
357
+ for (var key in source) {
358
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
359
+ target[key] = source[key];
360
+ }
361
+ }
362
+ }
363
+ return target;
364
+ };
365
+ return _extends.apply(this, arguments);
366
+ }
367
+ var ActivityIcon = (({
368
+ styles = {},
369
+ ...props
370
+ }) => /*#__PURE__*/React.createElement("svg", _extends({
371
+ xmlns: "http://www.w3.org/2000/svg",
372
+ viewBox: "0 0 24 24",
373
+ fill: "none",
374
+ stroke: "currentColor",
375
+ strokeWidth: "2",
376
+ strokeLinecap: "round",
377
+ strokeLinejoin: "round",
378
+ width: "16",
379
+ height: "16"
380
+ }, props), /*#__PURE__*/React.createElement("path", {
381
+ d: "M3 12a9 9 0 109-9 9.75 9.75 0 00-6.74 2.74L3 8"
382
+ }), /*#__PURE__*/React.createElement("path", {
383
+ d: "M3 3v5h5m4-1v5l4 2"
384
+ })));
385
+
386
+ var styles = {"toolbar":"FloatingToolbar-module_toolbar__3iLrb","toggleIcon":"FloatingToolbar-module_toggleIcon__tzwy_","puck":"FloatingToolbar-module_puck__1N8t9","puckIdle":"FloatingToolbar-module_puckIdle__25dov","unreadDot":"FloatingToolbar-module_unreadDot__3Ykgi","navigation":"FloatingToolbar-module_navigation__2oEYm","button":"FloatingToolbar-module_button__2_Q49","count":"FloatingToolbar-module_count__37jUH","segmented":"FloatingToolbar-module_segmented__34nUI","chevronUp":"FloatingToolbar-module_chevronUp__tCL4E","chevronDown":"FloatingToolbar-module_chevronDown__2NELa","segment":"FloatingToolbar-module_segment__q3hcg","segmentCount":"FloatingToolbar-module_segmentCount__2Nsqk","addButton":"FloatingToolbar-module_addButton__2tgNA"};
387
+
388
+ var styles$1 = {"button":"ActivityButton-module_button__3BNt8","unseenDot":"ActivityButton-module_unseenDot__1w8QA","panel":"ActivityButton-module_panel__1tcQU","scroller":"ActivityButton-module_scroller__2RTTE"};
389
+
390
+ // Clears the default navigation: a 50px bar with an 8px progress bar.
391
+ const viewportPadding = {
392
+ top: 74,
393
+ right: 16,
394
+ bottom: 16,
395
+ left: 16
396
+ };
397
+ function ActivityButton() {
398
+ const {
399
+ t
400
+ } = useI18n({
401
+ locale: 'ui'
402
+ });
403
+ const [open, setOpen] = useState(false);
404
+ const unreadCount = useUnreadThreadCount();
405
+ const label = t('pageflow_scrolled.review.activity.toggle');
406
+ const {
407
+ clearSelection
408
+ } = useSelectedSubject();
409
+ const portalRoot = useFloatingPortalRoot();
410
+ const {
411
+ refs,
412
+ floatingStyles
413
+ } = useFloating({
414
+ open,
415
+ strategy: 'fixed',
416
+ placement: 'top-end',
417
+ middleware: [offset(8), shift({
418
+ padding: viewportPadding
419
+ }), size({
420
+ padding: viewportPadding,
421
+ apply({
422
+ availableHeight,
423
+ elements
424
+ }) {
425
+ elements.floating.style.maxHeight = `${availableHeight}px`;
426
+ }
427
+ })],
428
+ whileElementsMounted: autoUpdate
429
+ });
430
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
431
+ ref: refs.setReference,
432
+ className: classNames(styles.button, styles$1.button),
433
+ onClick: () => {
434
+ if (!open) {
435
+ clearSelection();
436
+ }
437
+ setOpen(!open);
438
+ },
439
+ "aria-expanded": open,
440
+ "aria-label": label,
441
+ title: label
442
+ }, /*#__PURE__*/React.createElement(ActivityIcon, null), unreadCount > 0 && /*#__PURE__*/React.createElement("span", {
443
+ className: styles$1.unseenDot
444
+ })), open && /*#__PURE__*/React.createElement(FloatingPortal, {
445
+ id: "floating-ui-above-navigation-widgets",
446
+ root: portalRoot
447
+ }, /*#__PURE__*/React.createElement(ActivityPanel, {
448
+ ref: refs.setFloating,
449
+ style: floatingStyles,
450
+ onClose: () => setOpen(false)
451
+ })));
452
+ }
453
+ const ActivityPanel = React.forwardRef(function ActivityPanel({
454
+ style,
455
+ onClose
456
+ }, ref) {
457
+ const {
458
+ t
459
+ } = useI18n({
460
+ locale: 'ui'
461
+ });
462
+ const {
463
+ goToThread,
464
+ highlightedThreadId
465
+ } = useCommentNavigation();
466
+ const panelRef = useRef();
467
+ const setRefs = useCallback(node => {
468
+ panelRef.current = node;
469
+ ref(node);
470
+ }, [ref]);
471
+ useEffect(() => {
472
+ function handleClick(event) {
473
+ var _panelRef$current;
474
+ if ((_panelRef$current = panelRef.current) === null || _panelRef$current === void 0 ? void 0 : _panelRef$current.contains(event.target)) return;
475
+ if (event.target.closest('[data-comment-toolbar]')) return;
476
+ onClose();
477
+ }
478
+
479
+ // An open popover would otherwise close itself on the same key.
480
+ function handleKeyDown(event) {
481
+ if (event.key === 'Escape') {
482
+ event.stopPropagation();
483
+ onClose();
484
+ }
485
+ }
486
+ document.addEventListener('mousedown', handleClick);
487
+ document.addEventListener('keydown', handleKeyDown, true);
488
+ return () => {
489
+ document.removeEventListener('mousedown', handleClick);
490
+ document.removeEventListener('keydown', handleKeyDown, true);
491
+ };
492
+ }, [onClose]);
493
+ return /*#__PURE__*/React.createElement("div", {
494
+ ref: setRefs,
495
+ className: styles$1.panel,
496
+ style: style,
497
+ role: "dialog",
498
+ "aria-label": t('pageflow_scrolled.review.activity.toggle'),
499
+ "data-comment-activity": true
500
+ }, /*#__PURE__*/React.createElement("div", {
501
+ className: styles$1.scroller
502
+ }, /*#__PURE__*/React.createElement(ActivityList, {
503
+ highlightedThreadId: highlightedThreadId,
504
+ onEntryClick: entry => goToThread(entry.threadId, {
505
+ revealOnly: true
506
+ })
507
+ })));
508
+ });
509
+
510
+ function _extends$1() {
511
+ _extends$1 = Object.assign ? Object.assign.bind() : function (target) {
512
+ for (var i = 1; i < arguments.length; i++) {
513
+ var source = arguments[i];
514
+ for (var key in source) {
515
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
516
+ target[key] = source[key];
517
+ }
518
+ }
519
+ }
520
+ return target;
521
+ };
522
+ return _extends$1.apply(this, arguments);
523
+ }
524
+ var AddCommentIcon = (({
525
+ styles = {},
526
+ ...props
527
+ }) => /*#__PURE__*/React.createElement("svg", _extends$1({
528
+ xmlns: "http://www.w3.org/2000/svg",
529
+ width: "24",
530
+ height: "24",
531
+ fill: "none",
532
+ stroke: "currentColor",
533
+ strokeWidth: "2",
534
+ strokeLinecap: "round",
535
+ strokeLinejoin: "round"
536
+ }, props), /*#__PURE__*/React.createElement("path", {
537
+ d: "M22 17a2 2 0 01-2 2H6.828a2 2 0 00-1.414.586l-2.202 2.202A.71.71 0 012 21.286V5a2 2 0 012-2h16a2 2 0 012 2zM12 8v6m-3-3h6"
538
+ })));
539
+
540
+ function _extends$2() {
541
+ _extends$2 = Object.assign ? Object.assign.bind() : function (target) {
542
+ for (var i = 1; i < arguments.length; i++) {
543
+ var source = arguments[i];
544
+ for (var key in source) {
545
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
546
+ target[key] = source[key];
547
+ }
548
+ }
549
+ }
550
+ return target;
551
+ };
552
+ return _extends$2.apply(this, arguments);
553
+ }
554
+ var CancelCommentIcon = (({
555
+ styles = {},
556
+ ...props
557
+ }) => /*#__PURE__*/React.createElement("svg", _extends$2({
558
+ xmlns: "http://www.w3.org/2000/svg",
559
+ width: "24",
560
+ height: "24",
561
+ fill: "none",
562
+ stroke: "currentColor",
563
+ strokeWidth: "2",
564
+ strokeLinecap: "round",
565
+ strokeLinejoin: "round"
566
+ }, props), /*#__PURE__*/React.createElement("path", {
567
+ d: "M22 17a2 2 0 01-2 2H6.828a2 2 0 00-1.414.586l-2.202 2.202A.71.71 0 012 21.286V5a2 2 0 012-2h16a2 2 0 012 2zm-7.5-8.5l-5 5m0-5l5 5"
568
+ })));
569
+
570
+ function _extends$3() {
571
+ _extends$3 = Object.assign ? Object.assign.bind() : function (target) {
572
+ for (var i = 1; i < arguments.length; i++) {
573
+ var source = arguments[i];
574
+ for (var key in source) {
575
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
576
+ target[key] = source[key];
577
+ }
578
+ }
579
+ }
580
+ return target;
581
+ };
582
+ return _extends$3.apply(this, arguments);
583
+ }
584
+ var ChevronIcon = (({
585
+ styles = {},
586
+ ...props
587
+ }) => /*#__PURE__*/React.createElement("svg", _extends$3({
588
+ xmlns: "http://www.w3.org/2000/svg",
589
+ viewBox: "0 0 24 24",
590
+ fill: "none",
591
+ stroke: "currentColor",
592
+ strokeWidth: "2",
593
+ strokeLinecap: "round",
594
+ strokeLinejoin: "round",
595
+ width: "16",
596
+ height: "16"
597
+ }, props), /*#__PURE__*/React.createElement("path", {
598
+ d: "M6 9l6 6 6-6"
599
+ })));
600
+
601
+ function _extends$4() {
602
+ _extends$4 = Object.assign ? Object.assign.bind() : function (target) {
603
+ for (var i = 1; i < arguments.length; i++) {
604
+ var source = arguments[i];
605
+ for (var key in source) {
606
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
607
+ target[key] = source[key];
608
+ }
609
+ }
610
+ }
611
+ return target;
612
+ };
613
+ return _extends$4.apply(this, arguments);
614
+ }
615
+ var HideCommentsIcon = (({
616
+ styles = {},
617
+ ...props
618
+ }) => /*#__PURE__*/React.createElement("svg", _extends$4({
619
+ xmlns: "http://www.w3.org/2000/svg",
620
+ viewBox: "0 0 24 24",
621
+ fill: "none",
622
+ stroke: "currentColor",
623
+ strokeWidth: "2",
624
+ strokeLinecap: "round",
625
+ strokeLinejoin: "round",
626
+ width: "16",
627
+ height: "16"
628
+ }, props), /*#__PURE__*/React.createElement("path", {
629
+ d: "M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24M1 1l22 22"
630
+ })));
631
+
632
+ function _extends$5() {
633
+ _extends$5 = Object.assign ? Object.assign.bind() : function (target) {
634
+ for (var i = 1; i < arguments.length; i++) {
635
+ var source = arguments[i];
636
+ for (var key in source) {
637
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
638
+ target[key] = source[key];
639
+ }
640
+ }
641
+ }
642
+ return target;
643
+ };
644
+ return _extends$5.apply(this, arguments);
645
+ }
646
+ var ShowCommentsIcon = (({
647
+ styles = {},
648
+ ...props
649
+ }) => /*#__PURE__*/React.createElement("svg", _extends$5({
650
+ xmlns: "http://www.w3.org/2000/svg",
651
+ viewBox: "0 0 24 24",
652
+ fill: "none",
653
+ stroke: "currentColor",
654
+ strokeWidth: "2",
655
+ strokeLinecap: "round",
656
+ strokeLinejoin: "round",
657
+ width: "16",
658
+ height: "16"
659
+ }, props), /*#__PURE__*/React.createElement("path", {
660
+ d: "M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"
661
+ })));
662
+
663
+ function FloatingToolbar() {
664
+ const {
665
+ t
666
+ } = useI18n({
667
+ locale: 'ui'
668
+ });
669
+ const {
670
+ visible
671
+ } = useCommentingVisibility();
672
+ const {
673
+ active,
674
+ deactivate
675
+ } = useAddCommentMode();
676
+ useEffect(() => {
677
+ if (!visible && active) {
678
+ deactivate();
679
+ }
680
+ }, [visible, active, deactivate]);
681
+ if (!visible) {
682
+ return /*#__PURE__*/React.createElement(ShowCommentsButton, null);
683
+ }
684
+ return /*#__PURE__*/React.createElement("div", {
685
+ className: styles.toolbar,
686
+ role: "group",
687
+ "aria-label": t('pageflow_scrolled.review.comment_toolbar'),
688
+ "data-comment-toolbar": true
689
+ }, /*#__PURE__*/React.createElement(PositionIndicator, null), /*#__PURE__*/React.createElement(ResolutionToggleButton, null), /*#__PURE__*/React.createElement(NavigationArrows, null), /*#__PURE__*/React.createElement(ActivityButton, null), /*#__PURE__*/React.createElement(HideCommentsButton, null), /*#__PURE__*/React.createElement(AddCommentButton, null));
690
+ }
691
+ function HideCommentsButton() {
692
+ const {
693
+ t
694
+ } = useI18n({
695
+ locale: 'ui'
696
+ });
697
+ const {
698
+ toggle
699
+ } = useCommentingVisibility();
700
+ const label = t('pageflow_scrolled.review.hide_comments');
701
+ return /*#__PURE__*/React.createElement("button", {
702
+ className: styles.button,
703
+ onClick: toggle,
704
+ "aria-label": label,
705
+ title: label
706
+ }, /*#__PURE__*/React.createElement(HideCommentsIcon, {
707
+ className: styles.toggleIcon
708
+ }));
709
+ }
710
+ function ShowCommentsButton() {
711
+ const {
712
+ t
713
+ } = useI18n({
714
+ locale: 'ui'
715
+ });
716
+ const {
717
+ toggle
718
+ } = useCommentingVisibility();
719
+ const unreadCount = useUnreadThreadCount();
720
+ const unread = unreadCount > 0;
721
+ const label = unread ? t('pageflow_scrolled.review.show_comments_with_unread', {
722
+ count: unreadCount
723
+ }) : t('pageflow_scrolled.review.show_comments');
724
+ return /*#__PURE__*/React.createElement("button", {
725
+ className: styles.puck,
726
+ onClick: toggle,
727
+ "aria-label": label,
728
+ title: label
729
+ }, /*#__PURE__*/React.createElement(ShowCommentsIcon, {
730
+ className: styles.toggleIcon
731
+ }), unread && /*#__PURE__*/React.createElement("span", {
732
+ className: styles.unreadDot
733
+ }));
734
+ }
735
+ function PositionIndicator() {
736
+ const {
737
+ t
738
+ } = useI18n({
739
+ locale: 'ui'
740
+ });
741
+ const {
742
+ count,
743
+ position
744
+ } = useCommentNavigation();
745
+ return /*#__PURE__*/React.createElement("span", {
746
+ className: styles.count,
747
+ title: t('pageflow_scrolled.review.comment_count', {
748
+ count
749
+ })
750
+ }, position || '–', " /");
751
+ }
752
+ function NavigationArrows() {
753
+ const {
754
+ t
755
+ } = useI18n({
756
+ locale: 'ui'
757
+ });
758
+ const {
759
+ count,
760
+ goToPrevious,
761
+ goToNext
762
+ } = useCommentNavigation();
763
+ return /*#__PURE__*/React.createElement("div", {
764
+ className: styles.navigation
765
+ }, /*#__PURE__*/React.createElement("button", {
766
+ className: styles.button,
767
+ onClick: goToPrevious,
768
+ disabled: count === 0,
769
+ "aria-label": t('pageflow_scrolled.review.previous_comment'),
770
+ title: t('pageflow_scrolled.review.previous_comment')
771
+ }, /*#__PURE__*/React.createElement(ChevronIcon, {
772
+ className: styles.chevronUp
773
+ })), /*#__PURE__*/React.createElement("button", {
774
+ className: styles.button,
775
+ onClick: goToNext,
776
+ disabled: count === 0,
777
+ "aria-label": t('pageflow_scrolled.review.next_comment'),
778
+ title: t('pageflow_scrolled.review.next_comment')
779
+ }, /*#__PURE__*/React.createElement(ChevronIcon, {
780
+ className: styles.chevronDown
781
+ })));
782
+ }
783
+ const resolutions = ['unresolved', 'all'];
784
+ function ResolutionToggleButton() {
785
+ const {
786
+ t
787
+ } = useI18n({
788
+ locale: 'ui'
789
+ });
790
+ const {
791
+ resolution,
792
+ setResolution
793
+ } = useCommentDisplayFilter();
794
+ const {
795
+ threads
796
+ } = useLocatedCommentThreads();
797
+ const counts = {
798
+ unresolved: threads.filter(thread => !thread.resolvedAt).length,
799
+ all: threads.length
800
+ };
801
+ return /*#__PURE__*/React.createElement("div", {
802
+ className: styles.segmented,
803
+ role: "group",
804
+ "aria-label": t('pageflow_scrolled.review.filter.label')
805
+ }, resolutions.map(value => /*#__PURE__*/React.createElement("button", {
806
+ key: value,
807
+ type: "button",
808
+ className: styles.segment,
809
+ "aria-pressed": resolution === value,
810
+ onClick: () => setResolution(value)
811
+ }, t(`pageflow_scrolled.review.filter.${value}`), /*#__PURE__*/React.createElement("span", {
812
+ className: styles.segmentCount,
813
+ "aria-hidden": "true"
814
+ }, counts[value]))));
815
+ }
816
+ function AddCommentButton() {
817
+ const {
818
+ t
819
+ } = useI18n({
820
+ locale: 'ui'
821
+ });
822
+ const {
823
+ active,
824
+ toggle
825
+ } = useAddCommentMode();
826
+ const Icon = active ? CancelCommentIcon : AddCommentIcon;
827
+ const label = t(active ? 'pageflow_scrolled.review.cancel_add_comment' : 'pageflow_scrolled.review.add_comment');
828
+ return /*#__PURE__*/React.createElement("button", {
829
+ className: classNames(styles.button, styles.addButton),
830
+ onClick: toggle,
831
+ "data-add-comment-toggle": true,
832
+ "aria-label": label,
833
+ title: label
834
+ }, /*#__PURE__*/React.createElement(Icon, null));
835
+ }
836
+
837
+ const resolutionStorageKey = 'pageflow.scrolled.commentsResolution';
838
+ function EntryDecorator({
839
+ commentingInitialState,
840
+ children
841
+ }) {
842
+ const commentDisplayFilter = useStoredCommentDisplayFilter(resolutionStorageKey);
843
+ return /*#__PURE__*/React.createElement(ReviewStateProvider, {
844
+ initialState: commentingInitialState
845
+ }, /*#__PURE__*/React.createElement(ReviewSessionSetup, {
846
+ initialState: commentingInitialState
847
+ }), /*#__PURE__*/React.createElement(LocatedCommentThreadsProvider, null, /*#__PURE__*/React.createElement(CommentingVisibilityProvider, null, /*#__PURE__*/React.createElement(CommentDisplayFilterProvider, commentDisplayFilter, /*#__PURE__*/React.createElement(SelectedSubjectProvider, null, /*#__PURE__*/React.createElement(AddCommentModeProvider, null, children, /*#__PURE__*/React.createElement(FloatingToolbar, null)))))));
848
+ }
849
+ function ReviewSessionSetup({
850
+ initialState
851
+ }) {
852
+ const entryMetadata = useEntryMetadata();
853
+ const entryId = entryMetadata === null || entryMetadata === void 0 ? void 0 : entryMetadata.id;
854
+ useEffect(() => {
855
+ if (!entryId) return;
856
+ const session = createReviewSession({
857
+ entryId,
858
+ initialState
859
+ });
860
+ const handler = ReviewMessageHandler.create({
861
+ session,
862
+ targetWindow: window
863
+ });
864
+ if (!initialState) {
865
+ session.fetch();
866
+ }
867
+ return () => handler.dispose();
868
+ }, [entryId, initialState]);
869
+ return null;
870
+ }
871
+
872
+ var styles$2 = {"badge":"Popover-module_badge__16NvD","threadList":"Popover-module_threadList__2nA5p"};
873
+
874
+ function Popover({
875
+ subjectType,
876
+ subjectId,
877
+ subjectRange,
878
+ placement = 'bottom-start',
879
+ strategy = 'absolute',
880
+ hideNewTopicButton
881
+ }) {
882
+ const {
883
+ isSelected,
884
+ revealOnly,
885
+ showNewForm,
886
+ select,
887
+ clearSelection,
888
+ highlightedThreadId
889
+ } = useSelectedSubject(subjectType, subjectId, subjectRange);
890
+ const {
891
+ resolution
892
+ } = useCommentDisplayFilter();
893
+ const [reference, setReference] = useState(null);
894
+ useEffect(() => {
895
+ if (isSelected && highlightedThreadId != null) {
896
+ reference === null || reference === void 0 ? void 0 : reference.scrollIntoView({
897
+ block: 'center',
898
+ behavior: 'smooth'
899
+ });
900
+ }
901
+ }, [isSelected, highlightedThreadId, reference]);
902
+ function handleBadgeClick() {
903
+ if (isSelected && !revealOnly) {
904
+ clearSelection();
905
+ } else {
906
+ select(revealOnly ? {
907
+ highlightedThreadId
908
+ } : undefined);
909
+ }
910
+ }
911
+ return /*#__PURE__*/React.createElement("span", {
912
+ ref: setReference,
913
+ className: styles$2.badge
914
+ }, /*#__PURE__*/React.createElement(ThreadsBadge, {
915
+ subjectType: subjectType,
916
+ subjectId: subjectId,
917
+ subjectRange: subjectRange,
918
+ resolution: resolution,
919
+ revealedThreadId: highlightedThreadId,
920
+ mode: isSelected ? 'active' : undefined,
921
+ onClick: handleBadgeClick
922
+ }), isSelected && !revealOnly && /*#__PURE__*/React.createElement(OpenThreadList, {
923
+ reference: reference,
924
+ subjectType: subjectType,
925
+ subjectId: subjectId,
926
+ subjectRange: subjectRange,
927
+ placement: placement,
928
+ strategy: strategy,
929
+ showNewForm: showNewForm,
930
+ hideNewTopicButton: hideNewTopicButton,
931
+ highlightedThreadId: highlightedThreadId,
932
+ expandResolved: resolution === 'all',
933
+ onDismiss: clearSelection
934
+ }));
935
+ }
936
+ function OpenThreadList({
937
+ reference,
938
+ subjectType,
939
+ subjectId,
940
+ subjectRange,
941
+ placement,
942
+ strategy,
943
+ showNewForm,
944
+ hideNewTopicButton,
945
+ highlightedThreadId,
946
+ expandResolved,
947
+ onDismiss
948
+ }) {
949
+ const portalRoot = useFloatingPortalRoot();
950
+ const {
951
+ refs,
952
+ floatingStyles
953
+ } = useFloating({
954
+ open: true,
955
+ elements: {
956
+ reference
957
+ },
958
+ placement,
959
+ strategy,
960
+ middleware: [offset(8), flip({
961
+ fallbackPlacements: [placement.startsWith('top') ? 'bottom-start' : 'top-start'],
962
+ rootBoundary: 'document'
963
+ }), shift({
964
+ padding: 8
965
+ })],
966
+ whileElementsMounted: autoUpdate
967
+ });
968
+ useEffect(() => {
969
+ function handleClick(event) {
970
+ var _refs$floating$curren;
971
+ if (reference === null || reference === void 0 ? void 0 : reference.contains(event.target)) return;
972
+ if ((_refs$floating$curren = refs.floating.current) === null || _refs$floating$curren === void 0 ? void 0 : _refs$floating$curren.contains(event.target)) return;
973
+ if (event.target.closest('[data-comment-highlight]')) return;
974
+ if (event.target.closest('[data-comment-toolbar]')) return;
975
+ if (event.target.closest('[data-comment-menu]')) return;
976
+ onDismiss();
977
+ }
978
+ function handleKeyDown(event) {
979
+ if (event.key === 'Escape') {
980
+ onDismiss();
981
+ }
982
+ }
983
+ document.addEventListener('mousedown', handleClick);
984
+ document.addEventListener('keydown', handleKeyDown);
985
+ return () => {
986
+ document.removeEventListener('mousedown', handleClick);
987
+ document.removeEventListener('keydown', handleKeyDown);
988
+ };
989
+ }, [reference, refs.floating, onDismiss]);
990
+ return /*#__PURE__*/React.createElement(FloatingPortal, {
991
+ root: portalRoot
992
+ }, /*#__PURE__*/React.createElement("div", {
993
+ ref: refs.setFloating,
994
+ "data-floating-raised": true,
995
+ className: styles$2.threadList,
996
+ style: floatingStyles
997
+ }, /*#__PURE__*/React.createElement(ThreadList, {
998
+ subjectType: subjectType,
999
+ subjectId: subjectId,
1000
+ subjectRange: subjectRange,
1001
+ highlightedThreadId: highlightedThreadId,
1002
+ expandResolved: expandResolved,
1003
+ showNewForm: showNewForm,
1004
+ hideNewTopicButton: hideNewTopicButton
1005
+ })));
1006
+ }
1007
+
1008
+ var styles$3 = {"wrapper":"SectionDecorator-module_wrapper__3oQuz","commentBadge":"SectionDecorator-module_commentBadge__2MYch","sticky":"SectionDecorator-module_sticky__M1Elo","addButton":"SectionDecorator-module_addButton__3-FuB","pill":"SectionDecorator-module_pill__1wMMW AddCommentOverlay-module_pill__K6tzV"};
1009
+
1010
+ function SectionDecorator({
1011
+ section,
1012
+ children
1013
+ }) {
1014
+ const {
1015
+ visible
1016
+ } = useCommentingVisibility();
1017
+ const {
1018
+ active
1019
+ } = useAddCommentMode();
1020
+ const {
1021
+ isSelected,
1022
+ highlightedThreadId
1023
+ } = useSelectedSubject('Section', section.permaId);
1024
+ const {
1025
+ resolution
1026
+ } = useCommentDisplayFilter();
1027
+ const threads = useLocatedCommentThreadsForSubject({
1028
+ subjectType: 'Section',
1029
+ subjectId: section.permaId,
1030
+ resolution,
1031
+ revealedThreadId: highlightedThreadId
1032
+ });
1033
+ const hasThreads = threads.length > 0;
1034
+ if (!visible) {
1035
+ return children;
1036
+ }
1037
+ return /*#__PURE__*/React.createElement("div", {
1038
+ className: styles$3.wrapper
1039
+ }, children, /*#__PURE__*/React.createElement("div", {
1040
+ className: classNames(styles$3.commentBadge, {
1041
+ [styles$3.sticky]: hasThreads || active || isSelected
1042
+ })
1043
+ }, active ? /*#__PURE__*/React.createElement(AddCommentButton$1, {
1044
+ permaId: section.permaId
1045
+ }) : /*#__PURE__*/React.createElement(Popover, {
1046
+ subjectType: "Section",
1047
+ subjectId: section.permaId,
1048
+ placement: "top-start",
1049
+ strategy: "fixed"
1050
+ })));
1051
+ }
1052
+ function AddCommentButton$1({
1053
+ permaId
1054
+ }) {
1055
+ const {
1056
+ t
1057
+ } = useI18n({
1058
+ locale: 'ui'
1059
+ });
1060
+ const {
1061
+ deactivate
1062
+ } = useAddCommentMode();
1063
+ const {
1064
+ select
1065
+ } = useSelectedSubject('Section', permaId);
1066
+ function handleClick() {
1067
+ select({
1068
+ showNewForm: true
1069
+ });
1070
+ deactivate();
1071
+ }
1072
+ return /*#__PURE__*/React.createElement("button", {
1073
+ "data-add-comment-overlay": true,
1074
+ onClick: handleClick,
1075
+ className: styles$3.addButton,
1076
+ "aria-label": t('pageflow_scrolled.review.select_section')
1077
+ }, /*#__PURE__*/React.createElement("span", {
1078
+ className: styles$3.pill
1079
+ }, /*#__PURE__*/React.createElement(AddCommentIcon, null)));
1080
+ }
1081
+
1082
+ var styles$4 = {"highlight":"AddCommentOverlay-module_highlight__1VAyf","pill":"AddCommentOverlay-module_pill__K6tzV"};
1083
+
1084
+ function AddCommentOverlay({
1085
+ permaId
1086
+ }) {
1087
+ const {
1088
+ t
1089
+ } = useI18n({
1090
+ locale: 'ui'
1091
+ });
1092
+ const {
1093
+ active,
1094
+ deactivate
1095
+ } = useAddCommentMode();
1096
+ const {
1097
+ select
1098
+ } = useSelectedSubject('ContentElement', permaId);
1099
+ if (!active) return null;
1100
+ function handleClick() {
1101
+ select({
1102
+ showNewForm: true
1103
+ });
1104
+ deactivate();
1105
+ }
1106
+ return /*#__PURE__*/React.createElement("button", {
1107
+ onClick: handleClick,
1108
+ "data-add-comment-overlay": true,
1109
+ className: styles$4.highlight,
1110
+ "aria-label": t('pageflow_scrolled.review.select_content_element'),
1111
+ title: t('pageflow_scrolled.review.select_content_element')
1112
+ }, /*#__PURE__*/React.createElement("span", {
1113
+ className: styles$4.pill
1114
+ }, /*#__PURE__*/React.createElement(AddCommentIcon, null)));
1115
+ }
1116
+
1117
+ var styles$5 = {"wrapper":"ContentElementDecorator-module_wrapper__omtl-","selected":"ContentElementDecorator-module_selected__1xIK9","badge":"ContentElementDecorator-module_badge__3RBr6","badgeFlush":"ContentElementDecorator-module_badgeFlush__1lR32"};
1118
+
1119
+ function ContentElementDecorator({
1120
+ type,
1121
+ width,
1122
+ customMargin,
1123
+ permaId,
1124
+ children
1125
+ }) {
1126
+ const {
1127
+ inlineComments
1128
+ } = api.contentElementTypes.getOptions(type) || {};
1129
+ if (inlineComments) {
1130
+ return children;
1131
+ }
1132
+ return /*#__PURE__*/React.createElement(DefaultCommentDecorator, {
1133
+ permaId: permaId,
1134
+ flush: width === widths.full || customMargin
1135
+ }, children);
1136
+ }
1137
+ function DefaultCommentDecorator({
1138
+ permaId,
1139
+ flush,
1140
+ children
1141
+ }) {
1142
+ const {
1143
+ visible
1144
+ } = useCommentingVisibility();
1145
+ const {
1146
+ active
1147
+ } = useAddCommentMode();
1148
+ const {
1149
+ isSelected
1150
+ } = useSelectedSubject('ContentElement', permaId);
1151
+ if (!visible) {
1152
+ return children;
1153
+ }
1154
+ return /*#__PURE__*/React.createElement("div", {
1155
+ className: classNames(styles$5.wrapper, {
1156
+ [styles$5.selected]: isSelected
1157
+ })
1158
+ }, /*#__PURE__*/React.createElement("div", {
1159
+ inert: active ? '' : undefined
1160
+ }, children), /*#__PURE__*/React.createElement(AddCommentOverlay, {
1161
+ permaId: permaId
1162
+ }), /*#__PURE__*/React.createElement("div", {
1163
+ className: classNames(styles$5.badge, {
1164
+ [styles$5.badgeFlush]: flush
1165
+ })
1166
+ }, /*#__PURE__*/React.createElement(Popover, {
1167
+ subjectType: "ContentElement",
1168
+ subjectId: permaId
1169
+ })));
1170
+ }
1171
+
1172
+ var styles$6 = {"hint":"AddCommentHint-module_hint__1tsMa","tooltip":"AddCommentHint-module_tooltip__28laa"};
1173
+
1174
+ function AddCommentHint() {
1175
+ const {
1176
+ t
1177
+ } = useI18n({
1178
+ locale: 'ui'
1179
+ });
1180
+ return /*#__PURE__*/React.createElement("div", {
1181
+ className: styles$6.hint
1182
+ }, /*#__PURE__*/React.createElement("span", {
1183
+ className: styles$6.tooltip
1184
+ }, t('pageflow_scrolled.review.select_text_to_comment')));
1185
+ }
1186
+
1187
+ var styles$7 = {"floating":"PopoversColumn-module_floating__2fpOt"};
1188
+
1189
+ function PopoversColumn({
1190
+ highlights,
1191
+ anchors
1192
+ }) {
1193
+ return highlights.map(highlight => /*#__PURE__*/React.createElement(PositionedPopover, {
1194
+ key: highlight.key,
1195
+ rangeKey: highlight.key,
1196
+ subjectRange: highlight.range,
1197
+ anchors: anchors
1198
+ }));
1199
+ }
1200
+ function PositionedPopover({
1201
+ rangeKey,
1202
+ subjectRange,
1203
+ anchors
1204
+ }) {
1205
+ const {
1206
+ contentElementPermaId
1207
+ } = useContentElementAttributes();
1208
+ const {
1209
+ refs,
1210
+ floatingStyles,
1211
+ hasAnchor
1212
+ } = useAnchoredFloating(rangeKey, anchors, {
1213
+ placement: 'left-end'
1214
+ });
1215
+ if (!hasAnchor) return null;
1216
+ return /*#__PURE__*/React.createElement("div", {
1217
+ ref: refs.setFloating,
1218
+ className: styles$7.floating,
1219
+ style: floatingStyles
1220
+ }, /*#__PURE__*/React.createElement(Popover, {
1221
+ subjectType: "ContentElement",
1222
+ subjectId: contentElementPermaId,
1223
+ subjectRange: subjectRange,
1224
+ hideNewTopicButton: true
1225
+ }));
1226
+ }
1227
+
1228
+ const slateSelection = {
1229
+ inEditor(editor) {
1230
+ const domSelection = window.getSelection();
1231
+ if (!domSelection || !domSelection.anchorNode || !domSelection.focusNode || domSelection.isCollapsed) return null;
1232
+ if (!ReactEditor.hasDOMNode(editor, domSelection.anchorNode) || !ReactEditor.hasDOMNode(editor, domSelection.focusNode)) return null;
1233
+ try {
1234
+ return ReactEditor.toSlateRange(editor, domSelection);
1235
+ } catch (e) {
1236
+ return null;
1237
+ }
1238
+ }
1239
+ };
1240
+
1241
+ var commentingStyles = {"activeOverlay":"EditableTextHighlight-module_activeOverlay__6krun","clickable":"EditableTextHighlight-module_clickable__1nF8U"};
1242
+
1243
+ const defaultValue = [{
1244
+ type: 'paragraph',
1245
+ children: [{
1246
+ text: ''
1247
+ }]
1248
+ }];
1249
+ const EditableText = React.memo(function EditableText(props) {
1250
+ const {
1251
+ inlineComments
1252
+ } = useContentElementAttributes();
1253
+ const {
1254
+ visible
1255
+ } = useCommentingVisibility();
1256
+ if (inlineComments && visible) {
1257
+ return /*#__PURE__*/React.createElement(CommentingEditableText, props);
1258
+ }
1259
+ return /*#__PURE__*/React.createElement(PlainEditableText, props);
1260
+ });
1261
+ function CommentingEditableText({
1262
+ value,
1263
+ className,
1264
+ scaleCategory = 'body',
1265
+ typographyVariant,
1266
+ typographySize
1267
+ }) {
1268
+ const editor = useMemo(() => withLinks(withReact(createEditor())), []);
1269
+ const {
1270
+ anchors,
1271
+ registerAnchor
1272
+ } = useRangeAnchors();
1273
+ const {
1274
+ contentElementPermaId
1275
+ } = useContentElementAttributes();
1276
+ const {
1277
+ active,
1278
+ deactivate,
1279
+ preselect,
1280
+ clearPreselection
1281
+ } = useAddCommentMode();
1282
+ const {
1283
+ subjectRange,
1284
+ select,
1285
+ highlightedThreadId
1286
+ } = useSelectedSubject('ContentElement', contentElementPermaId);
1287
+ const {
1288
+ resolution
1289
+ } = useCommentDisplayFilter();
1290
+ const threads = useCommentThreads({
1291
+ subjectType: 'ContentElement',
1292
+ subjectId: contentElementPermaId,
1293
+ resolution,
1294
+ revealedThreadId: highlightedThreadId
1295
+ });
1296
+ const highlights = useCommentHighlights(threads, subjectRange);
1297
+ usePreselection(editor, contentElementPermaId, threads, active, preselect, clearPreselection);
1298
+ const handleMouseUp = useSelectTextOnMouseUp(active, editor, threads, deactivate, select);
1299
+ const decorate = useMemo(() => decorateCommentHighlights(editor, highlights), [editor, highlights]);
1300
+ const renderLeafCb = useCallback(({
1301
+ attributes,
1302
+ children,
1303
+ leaf
1304
+ }) => {
1305
+ if (leaf.commentHighlight) {
1306
+ children = /*#__PURE__*/React.createElement(ClickableHighlight, {
1307
+ subjectRange: leaf.subjectRange
1308
+ }, children);
1309
+ }
1310
+ if (leaf.lastInRange) {
1311
+ children = /*#__PURE__*/React.createElement(RangeAnchor, {
1312
+ rangeKey: leaf.rangeKey,
1313
+ onRegister: registerAnchor
1314
+ }, children);
1315
+ }
1316
+ return renderLeaf({
1317
+ attributes,
1318
+ children,
1319
+ leaf
1320
+ });
1321
+ }, [registerAnchor]);
1322
+ return /*#__PURE__*/React.createElement("div", {
1323
+ ref: anchors.containerRef,
1324
+ className: classNames(textStyles.root, className, {
1325
+ [commentingStyles.activeOverlay]: active && !subjectRange
1326
+ }),
1327
+ "data-add-comment-overlay": true,
1328
+ style: {
1329
+ position: 'relative'
1330
+ }
1331
+ }, /*#__PURE__*/React.createElement(Text, {
1332
+ scaleCategory: scaleCategory,
1333
+ typographyVariant: typographyVariant,
1334
+ typographySize: typographySize
1335
+ }, /*#__PURE__*/React.createElement(Slate, {
1336
+ editor: editor,
1337
+ value: value || defaultValue,
1338
+ onChange: () => {}
1339
+ }, /*#__PURE__*/React.createElement(Editable, {
1340
+ key: (subjectRange ? 'highlighted' : 'plain') + threads.length,
1341
+ onMouseUp: handleMouseUp,
1342
+ readOnly: true,
1343
+ decorate: decorate,
1344
+ renderElement: renderElement,
1345
+ renderLeaf: renderLeafCb
1346
+ }))), active && !subjectRange && /*#__PURE__*/React.createElement(AddCommentHint, null), /*#__PURE__*/React.createElement(PopoversColumn, {
1347
+ highlights: highlights,
1348
+ anchors: anchors
1349
+ }));
1350
+ }
1351
+ function ClickableHighlight({
1352
+ subjectRange,
1353
+ children
1354
+ }) {
1355
+ const {
1356
+ contentElementPermaId
1357
+ } = useContentElementAttributes();
1358
+ const {
1359
+ deactivate
1360
+ } = useAddCommentMode();
1361
+ const {
1362
+ isSelected,
1363
+ revealOnly,
1364
+ select,
1365
+ highlightedThreadId
1366
+ } = useSelectedSubject('ContentElement', contentElementPermaId, subjectRange);
1367
+ function handleClick(event) {
1368
+ if (event.target.closest('a')) return;
1369
+ if (isSelected && !revealOnly) return;
1370
+ deactivate();
1371
+ select(revealOnly ? {
1372
+ highlightedThreadId
1373
+ } : undefined);
1374
+ }
1375
+ return /*#__PURE__*/React.createElement("span", {
1376
+ className: classNames(commentHighlightStyles.highlight, {
1377
+ [commentHighlightStyles.selected]: isSelected,
1378
+ [commentingStyles.clickable]: !isSelected || revealOnly
1379
+ }),
1380
+ "data-comment-highlight": true,
1381
+ onClick: handleClick
1382
+ }, children);
1383
+ }
1384
+ function useSelectTextOnMouseUp(active, editor, threads, deactivate, select) {
1385
+ return useCallback(event => {
1386
+ if (!active) return;
1387
+ const slateRange = slateSelection.inEditor(editor) || topLevelRangeFromEvent(editor, event);
1388
+ if (!slateRange) return;
1389
+ const matchingThread = findMatchingThread(threads, slateRange);
1390
+ deactivate();
1391
+ select({
1392
+ subjectRange: (matchingThread === null || matchingThread === void 0 ? void 0 : matchingThread.subjectRange) || slateRange,
1393
+ showNewForm: !matchingThread
1394
+ });
1395
+ }, [active, editor, threads, deactivate, select]);
1396
+ }
1397
+ function topLevelRangeFromEvent(editor, event) {
1398
+ if (event.target.closest('a')) return null;
1399
+ if (event.target.closest('[data-comment-highlight]')) return null;
1400
+ try {
1401
+ const node = ReactEditor.toSlateNode(editor, event.target);
1402
+ const path = ReactEditor.findPath(editor, node);
1403
+ if (!path.length) return null;
1404
+ return Editor.range(editor, [path[0]]);
1405
+ } catch (e) {
1406
+ return null;
1407
+ }
1408
+ }
1409
+ function usePreselection(editor, contentElementPermaId, threads, active, preselect, clearPreselection) {
1410
+ useEffect(() => {
1411
+ function handleSelectionChange() {
1412
+ if (active) return;
1413
+ const slateRange = slateSelection.inEditor(editor);
1414
+ if (slateRange) {
1415
+ const matchingThread = findMatchingThread(threads, slateRange);
1416
+ preselect({
1417
+ subjectType: 'ContentElement',
1418
+ subjectId: contentElementPermaId,
1419
+ subjectRange: (matchingThread === null || matchingThread === void 0 ? void 0 : matchingThread.subjectRange) || slateRange,
1420
+ showNewForm: !matchingThread
1421
+ });
1422
+ } else {
1423
+ clearPreselection(contentElementPermaId);
1424
+ }
1425
+ }
1426
+ document.addEventListener('selectionchange', handleSelectionChange);
1427
+ return () => document.removeEventListener('selectionchange', handleSelectionChange);
1428
+ }, [editor, contentElementPermaId, threads, active, preselect, clearPreselection]);
1429
+ }
1430
+ function findMatchingThread(threads, slateRange) {
1431
+ const key = JSON.stringify(slateRange);
1432
+ return threads.find(t => JSON.stringify(t.subjectRange) === key);
1433
+ }
1434
+ function withLinks(editor) {
1435
+ const {
1436
+ isInline
1437
+ } = editor;
1438
+ editor.isInline = element => {
1439
+ return element.type === 'link' ? true : isInline(element);
1440
+ };
1441
+ return editor;
1442
+ }
1443
+
1444
+ const extensions = {
1445
+ decorators: {
1446
+ Entry: EntryDecorator,
1447
+ Section: SectionDecorator,
1448
+ ContentElement: ContentElementDecorator
1449
+ },
1450
+ alternatives: {
1451
+ EditableText
1452
+ }
1453
+ };
1454
+
1455
+ export { extensions };