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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +342 -41
- data/README.md +3 -5
- data/admins/pageflow/accounts.rb +22 -20
- data/admins/pageflow/entry.rb +76 -26
- data/admins/pageflow/entry_templates.rb +10 -9
- data/admins/pageflow/folder.rb +1 -1
- data/admins/pageflow/membership.rb +15 -15
- data/admins/pageflow/revisions.rb +5 -5
- data/admins/pageflow/site_root_entry.rb +64 -0
- data/admins/pageflow/sites.rb +12 -3
- data/admins/pageflow/translations.rb +75 -0
- data/admins/pageflow/user.rb +21 -35
- data/app/assets/images/pageflow/admin/icons/comment.svg +1 -0
- data/app/assets/javascripts/pageflow/admin/entries.js +30 -5
- data/app/assets/javascripts/pageflow/dist/ui.js +4228 -900
- data/app/assets/javascripts/pageflow/editor/vendor.js +0 -1
- data/app/assets/javascripts/pageflow/ui.js +0 -1
- data/app/assets/stylesheets/pageflow/admin/entries/index_table.scss +2 -1
- data/app/assets/stylesheets/pageflow/admin/entry_comments_indicator.scss +45 -0
- data/app/assets/stylesheets/pageflow/admin/permalink_input.scss +8 -0
- data/app/assets/stylesheets/pageflow/admin.scss +1 -0
- data/app/assets/stylesheets/pageflow/animations/spin.scss +9 -0
- data/app/assets/stylesheets/pageflow/animations.scss +1 -0
- data/app/assets/stylesheets/pageflow/editor/background_positioning.scss +27 -5
- data/app/assets/stylesheets/pageflow/editor/base.scss +11 -1
- data/app/assets/stylesheets/pageflow/editor/drop_down_button.scss +20 -2
- data/app/assets/stylesheets/pageflow/editor/edit_configuration_view.scss +5 -0
- data/app/assets/stylesheets/pageflow/editor/file_folders.scss +127 -0
- data/app/assets/stylesheets/pageflow/editor/file_meta_data.scss +5 -2
- data/app/assets/stylesheets/pageflow/editor/file_meta_data_overlay.scss +45 -0
- data/app/assets/stylesheets/pageflow/editor/file_preview.scss +138 -0
- data/app/assets/stylesheets/pageflow/editor/file_references.scss +68 -0
- data/app/assets/stylesheets/pageflow/editor/file_settings_dialog.scss +1 -1
- data/app/assets/stylesheets/pageflow/editor/file_stage_icons.scss +17 -0
- data/app/assets/stylesheets/pageflow/editor/file_stages.scss +25 -32
- data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +31 -48
- data/app/assets/stylesheets/pageflow/editor/file_type_pills.scss +73 -0
- data/app/assets/stylesheets/pageflow/editor/files.scss +242 -50
- data/app/assets/stylesheets/pageflow/editor/filtered_files.scss +161 -9
- data/app/assets/stylesheets/pageflow/editor/folder_breadcrumb.scss +40 -0
- data/app/assets/stylesheets/pageflow/editor/info_box.scss +23 -3
- data/app/assets/stylesheets/pageflow/editor/inputs/edit_defaults_button.scss +15 -0
- data/app/assets/stylesheets/pageflow/editor/inputs.scss +1 -0
- data/app/assets/stylesheets/pageflow/editor/list.scss +89 -37
- data/app/assets/stylesheets/pageflow/editor/list_search_field.scss +52 -0
- data/app/assets/stylesheets/pageflow/editor/manage_files.scss +9 -0
- data/app/assets/stylesheets/pageflow/editor/menu.scss +14 -0
- data/app/assets/stylesheets/pageflow/editor/move_to_folder_dialog.scss +83 -0
- data/app/assets/stylesheets/pageflow/editor/outline.scss +0 -13
- data/app/assets/stylesheets/pageflow/editor/sortable.scss +12 -0
- data/app/assets/stylesheets/pageflow/mixins/buttons.scss +4 -4
- data/app/assets/stylesheets/pageflow/mixins/pageflow.scss +9 -5
- data/app/assets/stylesheets/pageflow/ui/color_picker.scss +230 -0
- data/app/assets/stylesheets/pageflow/ui/forms.scss +38 -4
- data/app/assets/stylesheets/pageflow/ui/functions.scss +12 -2
- data/app/assets/stylesheets/pageflow/ui/input/color_input.scss +9 -8
- data/app/assets/stylesheets/pageflow/ui/input/file_name_input.scss +37 -0
- data/app/assets/stylesheets/pageflow/ui/input/text_area_input.scss +15 -0
- data/app/assets/stylesheets/pageflow/ui/overrides.scss +8 -0
- data/app/assets/stylesheets/pageflow/ui/properties.scss +34 -0
- data/app/assets/stylesheets/pageflow/ui/tabs_view.scss +8 -3
- data/app/assets/stylesheets/pageflow/ui.scss +4 -1
- data/app/controllers/concerns/pageflow/controller_delegation.rb +1 -1
- data/app/controllers/concerns/pageflow/edit_locking.rb +17 -10
- data/app/controllers/concerns/pageflow/entry_password_protection.rb +1 -0
- data/app/controllers/concerns/pageflow/public_https_mode.rb +2 -1
- data/app/controllers/concerns/pageflow/quota_verification.rb +5 -4
- data/app/controllers/pageflow/admin/initial_passwords_controller.rb +1 -0
- data/app/controllers/pageflow/application_controller.rb +19 -19
- data/app/controllers/pageflow/chapters_controller.rb +3 -2
- data/app/controllers/pageflow/edit_locks_controller.rb +3 -2
- data/app/controllers/pageflow/editor/encoding_confirmations_controller.rb +1 -0
- data/app/controllers/pageflow/editor/entries_controller.rb +3 -1
- data/app/controllers/pageflow/editor/entry_publications_controller.rb +1 -0
- data/app/controllers/pageflow/editor/file_folders_controller.rb +80 -0
- data/app/controllers/pageflow/editor/file_import_controller.rb +4 -3
- data/app/controllers/pageflow/editor/files_controller.rb +20 -10
- data/app/controllers/pageflow/editor/oembeds_controller.rb +21 -0
- data/app/controllers/pageflow/editor/widgets_controller.rb +1 -0
- data/app/controllers/pageflow/entries_controller.rb +85 -21
- data/app/controllers/pageflow/feeds_controller.rb +1 -1
- data/app/controllers/pageflow/files_controller.rb +1 -0
- data/app/controllers/pageflow/pages_controller.rb +4 -2
- data/app/controllers/pageflow/review/comment_thread_reads_controller.rb +30 -0
- data/app/controllers/pageflow/review/comment_threads_controller.rb +60 -0
- data/app/controllers/pageflow/review/comments_controller.rb +53 -0
- data/app/controllers/pageflow/revisions_controller.rb +5 -1
- data/app/controllers/pageflow/sitemaps_controller.rb +1 -1
- data/app/controllers/pageflow/storylines_controller.rb +1 -0
- data/app/helpers/pageflow/admin/cutoff_modes_helper.rb +12 -0
- data/app/helpers/pageflow/admin/entries_helper.rb +41 -1
- data/app/helpers/pageflow/admin/entry_translations_helper.rb +18 -0
- data/app/helpers/pageflow/admin/features_helper.rb +1 -1
- data/app/helpers/pageflow/admin/form_helper.rb +3 -3
- data/app/helpers/pageflow/admin/locales_helper.rb +10 -2
- data/app/helpers/pageflow/admin/memberships_helper.rb +32 -32
- data/app/helpers/pageflow/admin/revisions_helper.rb +1 -1
- data/app/helpers/pageflow/admin/sites_helper.rb +22 -0
- data/app/helpers/pageflow/admin/users_helper.rb +7 -5
- data/app/helpers/pageflow/admin/widgets_helper.rb +5 -5
- data/app/helpers/pageflow/asset_urls_helper.rb +1 -1
- data/app/helpers/pageflow/audio_files_helper.rb +5 -2
- data/app/helpers/pageflow/background_image_helper.rb +7 -6
- data/app/helpers/pageflow/common_entry_seed_helper.rb +7 -7
- data/app/helpers/pageflow/editor/config_helper.rb +3 -1
- data/app/helpers/pageflow/editor/files_helper.rb +1 -1
- data/app/helpers/pageflow/embed_code_helper.rb +3 -3
- data/app/helpers/pageflow/entries_helper.rb +52 -46
- data/app/helpers/pageflow/entry_json_seed_helper.rb +7 -6
- data/app/helpers/pageflow/feeds_helper.rb +2 -2
- data/app/helpers/pageflow/file_background_images_helper.rb +2 -2
- data/app/helpers/pageflow/file_thumbnails_helper.rb +4 -3
- data/app/helpers/pageflow/files_helper.rb +5 -4
- data/app/helpers/pageflow/folders_helper.rb +8 -5
- data/app/helpers/pageflow/help_entries_helper.rb +2 -2
- data/app/helpers/pageflow/hreflang_links_helper.rb +37 -0
- data/app/helpers/pageflow/info_box_helper.rb +7 -11
- data/app/helpers/pageflow/media_query_helper.rb +3 -3
- data/app/helpers/pageflow/navigation_bar_helper.rb +1 -1
- data/app/helpers/pageflow/overview_helper.rb +1 -1
- data/app/helpers/pageflow/page_types_helper.rb +5 -5
- data/app/helpers/pageflow/pages_helper.rb +29 -15
- data/app/helpers/pageflow/public_i18n_helper.rb +10 -9
- data/app/helpers/pageflow/quota_helper.rb +4 -4
- data/app/helpers/pageflow/render_json_helper.rb +6 -3
- data/app/helpers/pageflow/revision_file_helper.rb +2 -1
- data/app/helpers/pageflow/sites_helper.rb +3 -3
- data/app/helpers/pageflow/social_share_helper.rb +24 -10
- data/app/helpers/pageflow/social_share_links_helper.rb +12 -9
- data/app/helpers/pageflow/structured_data_helper.rb +5 -2
- data/app/helpers/pageflow/stub_page_configuration.rb +7 -3
- data/app/helpers/pageflow/text_direction_helper.rb +1 -1
- data/app/helpers/pageflow/themes_helper.rb +2 -4
- data/app/helpers/pageflow/video_files_helper.rb +29 -13
- data/app/helpers/pageflow/widgets_helper.rb +8 -6
- data/app/inputs/pageflow_permalink_input.rb +8 -3
- data/app/jobs/pageflow/application_job.rb +1 -0
- data/app/jobs/pageflow/entry_export_import/upload_and_publish_file_job.rb +1 -1
- data/app/jobs/pageflow/poll_meta_data_from_zencoder_job.rb +1 -0
- data/app/jobs/pageflow/poll_zencoder_job.rb +3 -2
- data/app/jobs/pageflow/process_image_or_text_track_job.rb +1 -0
- data/app/jobs/pageflow/prune_auto_snapshots_job.rb +1 -0
- data/app/jobs/pageflow/request_meta_data_from_zencoder_job.rb +1 -0
- data/app/jobs/pageflow/submit_file_to_zencoder_job.rb +1 -0
- data/app/mailers/pageflow/user_mailer.rb +1 -0
- data/app/models/concerns/pageflow/auto_generated_perma_id.rb +20 -1
- data/app/models/concerns/pageflow/entry_publication_states.rb +7 -3
- data/app/models/concerns/pageflow/feature_target.rb +8 -4
- data/app/models/concerns/pageflow/output_source.rb +3 -3
- data/app/models/concerns/pageflow/permalinkable.rb +2 -1
- data/app/models/concerns/pageflow/reusable_file.rb +24 -24
- data/app/models/concerns/pageflow/serialization_blacklist.rb +3 -5
- data/app/models/concerns/pageflow/suspendable.rb +5 -3
- data/app/models/concerns/pageflow/theme_referencer.rb +1 -1
- data/app/models/concerns/pageflow/translatable.rb +62 -0
- data/app/models/concerns/pageflow/translated_attributes.rb +101 -0
- data/app/models/concerns/pageflow/uploadable_file.rb +6 -6
- data/app/models/pageflow/account.rb +6 -5
- data/app/models/pageflow/account_member_query.rb +1 -1
- data/app/models/pageflow/account_role_query.rb +1 -1
- data/app/models/pageflow/application_query.rb +1 -1
- data/app/models/pageflow/application_record.rb +1 -1
- data/app/models/pageflow/audio_file.rb +4 -4
- data/app/models/pageflow/audio_file_url_templates.rb +1 -1
- data/app/models/pageflow/authentication_token.rb +2 -2
- data/app/models/pageflow/chapter.rb +6 -1
- data/app/models/pageflow/chapter_scaffold.rb +2 -4
- data/app/models/pageflow/cname_site_request_scope.rb +1 -1
- data/app/models/pageflow/comment.rb +30 -0
- data/app/models/pageflow/comment_thread.rb +65 -0
- data/app/models/pageflow/comment_thread_read.rb +22 -0
- data/app/models/pageflow/customized_theme.rb +9 -8
- data/app/models/pageflow/draft_entry.rb +49 -9
- data/app/models/pageflow/edit_lock.rb +19 -21
- data/app/models/pageflow/encoding_confirmation.rb +2 -2
- data/app/models/pageflow/entries_feed.rb +2 -2
- data/app/models/pageflow/entry.rb +46 -30
- data/app/models/pageflow/entry_at_revision.rb +14 -2
- data/app/models/pageflow/entry_comment_summary.rb +114 -0
- data/app/models/pageflow/entry_duplicate.rb +8 -5
- data/app/models/pageflow/entry_publication.rb +2 -2
- data/app/models/pageflow/entry_role_query.rb +4 -4
- data/app/models/pageflow/entry_template.rb +4 -4
- data/app/models/pageflow/entry_title_or_account_name_query.rb +2 -2
- data/app/models/pageflow/entry_translation_group.rb +42 -0
- data/app/models/pageflow/file_folder.rb +74 -0
- data/app/models/pageflow/file_reuse.rb +5 -4
- data/app/models/pageflow/file_usage.rb +18 -3
- data/app/models/pageflow/folder.rb +2 -2
- data/app/models/pageflow/home_button.rb +7 -7
- data/app/models/pageflow/image_file.rb +44 -25
- data/app/models/pageflow/image_file_url_templates.rb +4 -4
- data/app/models/pageflow/invitation_form.rb +2 -1
- data/app/models/pageflow/legal_info.rb +38 -0
- data/app/models/pageflow/managed_user_query.rb +1 -1
- data/app/models/pageflow/membership.rb +5 -5
- data/app/models/pageflow/nested_revision_component_copy.rb +263 -0
- data/app/models/pageflow/null_user.rb +1 -1
- data/app/models/pageflow/overview_button.rb +1 -1
- data/app/models/pageflow/page.rb +7 -3
- data/app/models/pageflow/permalink.rb +24 -2
- data/app/models/pageflow/permalink_directory.rb +7 -0
- data/app/models/pageflow/permalink_redirect.rb +7 -0
- data/app/models/pageflow/positioned_file.rb +5 -5
- data/app/models/pageflow/potential_entry_translations.rb +55 -0
- data/app/models/pageflow/potential_memberships.rb +5 -4
- data/app/models/pageflow/published_entry.rb +62 -11
- data/app/models/pageflow/revision.rb +29 -16
- data/app/models/pageflow/roles.rb +14 -18
- data/app/models/pageflow/site.rb +46 -3
- data/app/models/pageflow/site_root_entry_form.rb +27 -0
- data/app/models/pageflow/sitemaps.rb +10 -1
- data/app/models/pageflow/storyline.rb +5 -2
- data/app/models/pageflow/storyline_scaffold.rb +1 -1
- data/app/models/pageflow/text_track_file.rb +1 -1
- data/app/models/pageflow/text_track_file_url_templates.rb +1 -1
- data/app/models/pageflow/theme_customization_file.rb +3 -2
- data/app/models/pageflow/thumbnail_file_resolver.rb +1 -1
- data/app/models/pageflow/url_template.rb +1 -1
- data/app/models/pageflow/used_file.rb +13 -3
- data/app/models/pageflow/user_name_query.rb +2 -2
- data/app/models/pageflow/video_file.rb +22 -15
- data/app/models/pageflow/video_file_url_templates.rb +6 -4
- data/app/models/pageflow/widget.rb +5 -4
- data/app/models/pageflow/with_file_usage_extension.rb +1 -1
- data/app/models/pageflow/zencoder_attachment.rb +8 -8
- data/app/policies/pageflow/account_policy.rb +3 -1
- data/app/policies/pageflow/admin/admin_only_tab_policy.rb +1 -0
- data/app/policies/pageflow/admin/entry_tab_policy.rb +1 -0
- data/app/policies/pageflow/application_policy.rb +2 -0
- data/app/policies/pageflow/entry_policy.rb +7 -1
- data/app/policies/pageflow/entry_template_policy.rb +2 -1
- data/app/policies/pageflow/file_policy.rb +4 -7
- data/app/policies/pageflow/folder_policy.rb +18 -8
- data/app/policies/pageflow/membership_policy.rb +6 -4
- data/app/policies/pageflow/site_policy.rb +10 -3
- data/app/policies/pageflow/user_policy.rb +6 -4
- data/app/state_machines/pageflow/image_and_text_track_processing_state_machine.rb +3 -2
- data/app/state_machines/pageflow/media_encoding_state_machine.rb +5 -4
- data/app/views/admin/accounts/_entry_template_details.html.arb +2 -2
- data/app/views/admin/entries/_attributes_table.html.arb +6 -5
- data/app/views/admin/entries/_form.html.erb +2 -1
- data/app/views/admin/entries/_permalink_inputs.html.erb +9 -2
- data/app/views/admin/entry_templates/_form.html.erb +1 -3
- data/app/views/admin/site_root_entry/choose.html.erb +19 -0
- data/app/views/admin/sites/_fields.html.erb +14 -1
- data/app/views/admin/translations/_form.html.erb +31 -0
- data/app/views/admin/users/_attributes_table.html.arb +13 -0
- data/app/views/components/pageflow/admin/add_membership_button.rb +13 -12
- data/app/views/components/pageflow/admin/custom_scopes_renderer.rb +1 -0
- data/app/views/components/pageflow/admin/embed_code_field.rb +1 -0
- data/app/views/components/pageflow/admin/embedded_index_table.rb +9 -10
- data/app/views/components/pageflow/admin/entries_tab.rb +1 -0
- data/app/views/components/pageflow/admin/entry_publication_state_indicator.rb +6 -5
- data/app/views/components/pageflow/admin/entry_templates_tab.rb +2 -1
- data/app/views/components/pageflow/admin/entry_translations_tab.rb +102 -0
- data/app/views/components/pageflow/admin/entry_user_badge_list.rb +1 -0
- data/app/views/components/pageflow/admin/extensible_attributes_table.rb +9 -8
- data/app/views/components/pageflow/admin/features_tab.rb +1 -0
- data/app/views/components/pageflow/admin/grouped_folder_list.rb +1 -0
- data/app/views/components/pageflow/admin/icon_link_to.rb +1 -0
- data/app/views/components/pageflow/admin/members_tab.rb +4 -3
- data/app/views/components/pageflow/admin/membership_role_with_tooltip.rb +3 -2
- data/app/views/components/pageflow/admin/revisions_tab.rb +14 -10
- data/app/views/components/pageflow/admin/sites_tab.rb +1 -0
- data/app/views/components/pageflow/admin/tabs_view.rb +1 -0
- data/app/views/components/pageflow/admin/timestamp.rb +6 -5
- data/app/views/components/pageflow/admin/user_account_badge_list.rb +2 -3
- data/app/views/components/pageflow/admin/user_accounts_tab.rb +1 -0
- data/app/views/components/pageflow/admin/user_entries_tab.rb +1 -0
- data/app/views/components/pageflow/admin/users_tab.rb +1 -0
- data/app/views/pageflow/audio_files/_audio_file.json.jbuilder +0 -1
- data/app/views/pageflow/editor/config/_seeds.json.jbuilder +5 -3
- data/app/views/pageflow/editor/entries/_entry.json.jbuilder +2 -1
- data/app/views/pageflow/editor/entries/index.json.jbuilder +1 -1
- data/app/views/pageflow/editor/entries/seed.json.erb +1 -0
- data/app/views/pageflow/editor/entries/show.json.jbuilder +1 -1
- data/app/views/pageflow/editor/entry_publications/check.json.jbuilder +2 -2
- data/app/views/pageflow/editor/file_folders/_file_folder.json.jbuilder +5 -0
- data/app/views/pageflow/editor/file_folders/create.json.jbuilder +1 -0
- data/app/views/pageflow/editor/file_folders/index.json.jbuilder +3 -0
- data/app/views/pageflow/editor/files/_file.json.jbuilder +7 -14
- data/app/views/pageflow/editor/files/create.json.jbuilder +1 -1
- data/app/views/pageflow/editor/files/index.json.jbuilder +1 -1
- data/app/views/pageflow/editor/image_files/_image_file.json.jbuilder +3 -0
- data/app/views/pageflow/editor/sites/_site.json.jbuilder +1 -0
- data/app/views/pageflow/editor/video_files/_video_file.json.jbuilder +4 -3
- data/app/views/pageflow/entries/share_menu/_bluesky_link.html.erb +8 -0
- data/app/views/pageflow/entries/share_menu/_threads_link.html.erb +8 -0
- data/app/views/pageflow/files/_file.json.jbuilder +5 -3
- data/app/views/pageflow/image_files/_image_file.json.jbuilder +0 -1
- data/app/views/pageflow/review/comment_threads/_comment_thread.json.jbuilder +20 -0
- data/app/views/pageflow/review/comment_threads/create.json.jbuilder +2 -0
- data/app/views/pageflow/review/comment_threads/index.json.jbuilder +13 -0
- data/app/views/pageflow/review/comments/_comment.json.jbuilder +13 -0
- data/app/views/pageflow/review/comments/create.json.jbuilder +1 -0
- data/app/views/pageflow/sitemaps/index.xml.builder +9 -1
- data/app/views/pageflow/social_share/_entry_meta_tags.html.erb +1 -1
- data/app/views/pageflow/social_share/_page_meta_tags.html.erb +1 -1
- data/app/views/pageflow/structured_data/_entry.json.jbuilder +2 -3
- data/app/views/pageflow/video_files/_video_file.json.jbuilder +0 -1
- data/config/initializers/active_admin_patches.rb +3 -6
- data/config/initializers/admin_resource_tabs.rb +3 -0
- data/config/initializers/paperclip.rb +1 -0
- data/config/initializers/symmetric_encryption.rb +1 -1
- data/config/initializers/zencoder.rb +24 -13
- data/config/locales/de.yml +256 -12
- data/config/locales/en.yml +253 -15
- data/config/routes.rb +29 -13
- data/config/spring.rb +2 -1
- data/db/migrate/20140418225525_setup_schema.rb +2 -2
- data/db/migrate/20190306161431_copy_file_attributes_of_failed_uploads.rb +2 -2
- data/db/migrate/20190820152900_drop_accounts_themes.rb +2 -1
- data/db/migrate/20191202145757_create_pageflow_scrolled_sections.rb +11 -11
- data/db/migrate/20191202150657_create_pageflow_scrolled_chapters.rb +1 -1
- data/db/migrate/20191202154723_create_pageflow_scrolled_content_elements.rb +9 -9
- data/db/migrate/20191219143450_add_position_to_content_elements.rb +2 -1
- data/db/migrate/20200117133200_change_revision_appearance_option_default_and_null.rb +2 -1
- data/db/migrate/20200122115400_create_pageflow_entry_templates.rb +25 -25
- data/db/migrate/20200206134400_convert_legacy_scrolled_content_element_types.rb +3 -3
- data/db/migrate/20221215120856_associate_entry_templates_with_sites.rb +2 -2
- data/db/migrate/20230120092923_create_other_files.rb +2 -1
- data/db/migrate/20230419083307_create_pageflow_entry_translation_group.rb +9 -0
- data/db/migrate/20240612110434_add_cutoff_mode_name_to_sites.rb +5 -0
- data/db/migrate/20240918084059_create_pageflow_permalink_redirects.rb +14 -0
- data/db/migrate/20250508172234_ensure_scrolled_entries_have_main_storyline.rb +14 -0
- data/db/migrate/20250617090048_add_custom404_entry_to_sites.rb +5 -0
- data/db/migrate/20250617100000_add_perma_id_counter_to_entries.rb +28 -0
- data/db/migrate/20250722174123_add_perma_id_to_chapters.rb +10 -0
- data/db/migrate/20250725080603_add_perma_id_indexes_to_revision_components.rb +13 -0
- data/db/migrate/20250726000000_add_display_name_to_file_usages.rb +5 -0
- data/db/migrate/20251015000000_add_structured_data_type_name_to_revisions.rb +5 -0
- data/db/migrate/20251029142849_convert_legacy_social_embeds_to_unified_social_embed.rb +38 -0
- data/db/migrate/20251119083347_fix_main_storyline_positions.rb +16 -0
- data/db/migrate/20251119083348_ensure_scrolled_entries_have_excursion_storyline.rb +15 -0
- data/db/migrate/20260303000000_add_layout_version_to_revisions.rb +6 -0
- data/db/migrate/20260323000000_create_comment_threads_and_comments.rb +30 -0
- data/db/migrate/20260414000000_add_subject_range_to_comment_threads.rb +5 -0
- data/db/migrate/20260415000000_add_section_perma_id_to_comment_threads.rb +5 -0
- data/db/migrate/20260727000000_add_quote_to_comments.rb +5 -0
- data/db/migrate/20260728000000_create_file_folders.rb +17 -0
- data/db/migrate/20260805000000_add_attribute_translations_to_sites.rb +5 -0
- data/db/migrate/20260806000000_add_edited_at_to_comments.rb +5 -0
- data/db/migrate/20260810000000_create_pageflow_scrolled_lottie_files.rb +24 -0
- data/db/migrate/20260817000000_create_comment_thread_reads.rb +16 -0
- data/db/migrate/20260819000000_add_unread_comments_since_at_to_users.rb +18 -0
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/editor.js +12599 -5398
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/frontend.js +1275 -4560
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-client.js +20204 -22
- data/entry_types/paged/app/assets/javascripts/pageflow_paged/dist/react-server.js +18657 -19
- data/entry_types/paged/app/controllers/pageflow_paged/entries_controller.rb +1 -0
- data/entry_types/paged/app/helpers/pageflow_paged/page_background_asset_helper.rb +1 -1
- data/entry_types/paged/app/helpers/pageflow_paged/third_party_embed_consent_helper.rb +7 -7
- data/entry_types/paged/app/views/pageflow_paged/editor/entries/_seed.json.jbuilder +1 -0
- data/entry_types/paged/app/views/pageflow_paged/entries/show.html.erb +1 -0
- data/entry_types/paged/lib/pageflow_paged/plugin.rb +4 -0
- data/entry_types/paged/lib/pageflow_paged/react/page_type.rb +1 -1
- data/entry_types/paged/lib/pageflow_paged/react/widget_type.rb +3 -3
- data/entry_types/paged/lib/pageflow_paged.rb +1 -1
- data/entry_types/scrolled/app/assets/stylesheets/pageflow_scrolled/ui.scss +2 -0
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/chapters_controller.rb +5 -3
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/content_elements_controller.rb +35 -5
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/editor/sections_controller.rb +4 -5
- data/entry_types/scrolled/app/controllers/pageflow_scrolled/entries_controller.rb +23 -2
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/cache_helper.rb +3 -3
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb +8 -5
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/editor/seed_html_helper.rb +7 -3
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/entry_json_seed_helper.rb +72 -10
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/i18n_helper.rb +28 -13
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/packs_helper.rb +41 -12
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/react_server_side_rendering_helper.rb +23 -25
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/sprockets_helper.rb +16 -0
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/themes_helper.rb +189 -3
- data/entry_types/scrolled/app/models/pageflow_scrolled/chapter.rb +15 -14
- data/entry_types/scrolled/app/models/pageflow_scrolled/content_element.rb +61 -7
- data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file.rb +6 -0
- data/entry_types/scrolled/app/models/pageflow_scrolled/lottie_file_url_templates.rb +16 -0
- data/entry_types/scrolled/app/models/pageflow_scrolled/section.rb +12 -1
- data/entry_types/scrolled/app/models/pageflow_scrolled/storyline.rb +20 -1
- data/entry_types/scrolled/app/views/pageflow_scrolled/editor/entries/_head.html.erb +1 -0
- data/entry_types/scrolled/app/views/pageflow_scrolled/editor/sections/_section_with_content_elements.json.jbuilder +2 -2
- data/entry_types/scrolled/app/views/pageflow_scrolled/entries/show.html.erb +15 -12
- data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry.json.jbuilder +45 -17
- data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_entry_translations.json.jbuilder +14 -0
- data/entry_types/scrolled/app/views/pageflow_scrolled/entry_json_seed/_theme.json.jbuilder +34 -5
- data/entry_types/scrolled/app/views/pageflow_scrolled/favicons/_entry.html.erb +1 -1
- data/entry_types/scrolled/app/views/pageflow_scrolled/storylines/_storyline.json.jbuilder +7 -0
- data/entry_types/scrolled/config/configuration_schemas/pageflow-scrolled.json +414 -0
- data/entry_types/scrolled/config/locales/de.yml +1094 -78
- data/entry_types/scrolled/config/locales/en.yml +1083 -78
- data/entry_types/scrolled/config/routes.rb +18 -8
- data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/install_generator.rb +11 -11
- data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDarkVariantDesktop.svg +56 -0
- data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/theme/logoDarkVariantMobile.svg +22 -0
- data/entry_types/scrolled/lib/generators/pageflow_scrolled/install/templates/themes_plugin.rb.tt +26 -11
- data/entry_types/scrolled/lib/pageflow_scrolled/additional_packs.rb +27 -8
- data/entry_types/scrolled/lib/pageflow_scrolled/additional_seed_data.rb +2 -2
- data/entry_types/scrolled/lib/pageflow_scrolled/additional_theme_assets.rb +27 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/configuration.rb +67 -10
- data/entry_types/scrolled/lib/pageflow_scrolled/configuration_schemas.rb +91 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/content_element_consent_vendors.rb +1 -1
- data/entry_types/scrolled/lib/pageflow_scrolled/engine.rb +2 -1
- data/entry_types/scrolled/lib/pageflow_scrolled/entry_file_reference_locations.rb +71 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/entry_structured_data_types/faq_page.rb +58 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/file_reference_locations.rb +69 -0
- data/entry_types/scrolled/lib/pageflow_scrolled/plugin.rb +222 -19
- data/entry_types/scrolled/lib/pageflow_scrolled/react_widget_type.rb +2 -4
- data/entry_types/scrolled/lib/pageflow_scrolled/seeds.rb +76 -54
- data/entry_types/scrolled/lib/pageflow_scrolled/theme_options_default_scale.rb +35 -0
- data/entry_types/scrolled/lib/pageflow_scrolled.rb +14 -1
- data/entry_types/scrolled/lib/tasks/pageflow_scrolled/storybook.rake +24 -5
- data/entry_types/scrolled/package/config/configurationSchemas.js +70 -0
- data/entry_types/scrolled/package/config/rollup/configurationSchemas.js +19 -0
- data/entry_types/scrolled/package/config/webpack.js +94 -0
- data/entry_types/scrolled/package/contentElements/hotspots-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/hotspots-frontend.js +1795 -0
- data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/inlineBeforeAfter-frontend.js +219 -0
- data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/lottieAnimation-frontend.js +244 -0
- data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/socialEmbed-frontend.js +823 -0
- data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/tikTokEmbed-frontend.js +109 -0
- data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/twitterEmbed-frontend.js +277 -0
- data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.css +1 -0
- data/entry_types/scrolled/package/contentElements/videoEmbed-frontend.js +244 -0
- data/entry_types/scrolled/package/contentElements-editor.js +3155 -583
- data/entry_types/scrolled/package/contentElements-frontend.css +1 -1
- data/entry_types/scrolled/package/contentElements-frontend.js +3375 -1585
- data/entry_types/scrolled/package/editor.css +1 -0
- data/entry_types/scrolled/package/editor.js +8452 -2867
- data/entry_types/scrolled/package/entryState.js +1600 -0
- data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-20c600de.js +1979 -0
- data/entry_types/scrolled/package/frontend/FloatingPortalRootProvider-58189220.js +2538 -0
- data/entry_types/scrolled/package/frontend/{PhonePlatformContext-4ec6b2de.js → PhonePlatformContext-035a99fa.js} +9 -15
- data/entry_types/scrolled/package/frontend/PhonePlatformContext-9da43797.js +33 -0
- data/entry_types/scrolled/package/frontend/Placeholder.module-bf0966b4.js +5267 -0
- data/entry_types/scrolled/package/frontend/Placeholder.module-d22a9335.js +4180 -0
- data/entry_types/scrolled/package/frontend/ThemeIcon-ab834849.js +754 -0
- data/entry_types/scrolled/package/frontend/ThemeIcon-f6cb3a8f.js +773 -0
- data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-30fd1124.js +39 -0
- data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-61c25224.js +72 -0
- data/entry_types/scrolled/package/frontend/Viewer-1074fd59.js +147 -0
- data/entry_types/scrolled/package/frontend/Viewer-1482ca34.js +480 -0
- data/entry_types/scrolled/package/frontend/Viewer-70504231.js +210 -0
- data/entry_types/scrolled/package/frontend/{Viewer-1bb5597c.js → Viewer-cc8d4072.js} +100 -135
- data/entry_types/scrolled/package/frontend/Wavesurfer-656e3c36.js +302 -0
- data/entry_types/scrolled/package/frontend/Wavesurfer-b753b838.js +385 -0
- data/entry_types/scrolled/package/frontend/commenting.css +1 -0
- data/entry_types/scrolled/package/frontend/extensions-167ae143.js +1455 -0
- data/entry_types/scrolled/package/frontend/extensions-2318f92b.js +5918 -0
- data/entry_types/scrolled/package/frontend/extensions-a461fd13.js +4890 -0
- data/entry_types/scrolled/package/frontend/extensions-c98269fd.js +1982 -0
- data/entry_types/scrolled/package/frontend/i18n-493cd2a6.js +93 -0
- data/entry_types/scrolled/package/frontend/i18n-e06cac14.js +100 -0
- data/entry_types/scrolled/package/frontend/{index-11f32f10.js → index-2e5546f7.js} +39 -54
- data/entry_types/scrolled/package/frontend/index-de2b418d.js +130 -0
- data/entry_types/scrolled/package/frontend/index.css +1 -1
- data/entry_types/scrolled/package/frontend/index.js +1976 -1367
- data/entry_types/scrolled/package/frontend/inlineEditing.css +1 -0
- data/entry_types/scrolled/package/frontend/useContentElementEditorState-a084912e.js +25 -0
- data/entry_types/scrolled/package/frontend/useDelayedBoolean-a387d85b.js +24 -0
- data/entry_types/scrolled/package/frontend/usePhonePlatform-4ecb96d4.js +8 -0
- data/entry_types/scrolled/package/frontend/usePhonePlatform-ce9ff08d.js +8 -0
- data/entry_types/scrolled/package/frontend-server.js +20 -210
- data/entry_types/scrolled/package/package.json +22 -12
- data/entry_types/scrolled/package/review.css +1 -0
- data/entry_types/scrolled/package/review.js +3306 -0
- data/entry_types/scrolled/package/testHelpers.js +952 -239
- data/entry_types/scrolled/package/values/widgets.module.css +18 -0
- data/entry_types/scrolled/package/widgets/consentBar.css +1 -1
- data/entry_types/scrolled/package/widgets/consentBar.js +275 -315
- data/entry_types/scrolled/package/widgets/defaultNavigation.css +2 -2
- data/entry_types/scrolled/package/widgets/defaultNavigation.js +961 -432
- data/entry_types/scrolled/package/widgets/excursionSheet.css +1 -0
- data/entry_types/scrolled/package/widgets/excursionSheet.js +225 -0
- data/entry_types/scrolled/package/widgets/iconInlineFileRights.css +1 -1
- data/entry_types/scrolled/package/widgets/iconInlineFileRights.js +62 -32
- data/entry_types/scrolled/package/widgets/iconScrollIndicator.css +1 -0
- data/entry_types/scrolled/package/widgets/iconScrollIndicator.js +67 -0
- data/entry_types/scrolled/package/widgets/mainStorylineSheet.css +1 -0
- data/entry_types/scrolled/package/widgets/mainStorylineSheet.js +100 -0
- data/entry_types/scrolled/package/widgets/textInlineFileRights.css +1 -1
- data/entry_types/scrolled/package/widgets/textInlineFileRights.js +48 -26
- data/entry_types/scrolled/package/widgets-server.js +2 -0
- data/entry_types/scrolled/spec/factories/chapters.rb +14 -1
- data/entry_types/scrolled/spec/factories/content_elements.rb +1 -1
- data/entry_types/scrolled/spec/factories/lottie_files.rb +29 -0
- data/entry_types/scrolled/spec/fixtures/animation.lottie +0 -0
- data/entry_types/scrolled/spec/fixtures/font.woff +0 -0
- data/entry_types/scrolled/spec/fixtures/font.woff2 +0 -0
- data/lib/generators/pageflow/active_admin_initializer/active_admin_initializer_generator.rb +5 -3
- data/lib/generators/pageflow/assets/assets_generator.rb +7 -5
- data/lib/generators/pageflow/cancan/cancan_generator.rb +2 -1
- data/lib/generators/pageflow/cancan/templates/ability.rb +1 -1
- data/lib/generators/pageflow/error_pages/error_pages_generator.rb +2 -1
- data/lib/generators/pageflow/initializer/initializer_generator.rb +3 -2
- data/lib/generators/pageflow/install/install_generator.rb +2 -2
- data/lib/generators/pageflow/procfile/procfile_generator.rb +2 -1
- data/lib/generators/pageflow/resque/resque_generator.rb +4 -4
- data/lib/generators/pageflow/resque/templates/resque.rake +1 -1
- data/lib/generators/pageflow/routes/routes_generator.rb +4 -2
- data/lib/generators/pageflow/seeds/seeds_generator.rb +3 -2
- data/lib/generators/pageflow/seeds/templates/seeds.rb +6 -6
- data/lib/generators/pageflow/theme/theme_generator.rb +2 -1
- data/lib/generators/pageflow/user/user_generator.rb +2 -1
- data/lib/pageflow/ability_mixin.rb +25 -15
- data/lib/pageflow/active_admin_patches/views/attributes_table.rb +1 -0
- data/lib/pageflow/active_admin_patches/views/pages/base.rb +3 -2
- data/lib/pageflow/active_admin_patches/views/table_for.rb +1 -0
- data/lib/pageflow/additional_headers.rb +27 -0
- data/lib/pageflow/admin/attributes_table_rows.rb +3 -3
- data/lib/pageflow/admin/tabs.rb +1 -1
- data/lib/pageflow/built_in_file_type.rb +1 -1
- data/lib/pageflow/built_in_page_types_plugin.rb +1 -1
- data/lib/pageflow/built_in_widget_type.rb +2 -2
- data/lib/pageflow/built_in_widget_types_plugin.rb +2 -1
- data/lib/pageflow/configuration.rb +183 -18
- data/lib/pageflow/cutoff_modes.rb +39 -0
- data/lib/pageflow/deprecation.rb +19 -0
- data/lib/pageflow/editor_controller.rb +6 -10
- data/lib/pageflow/engine.rb +5 -6
- data/lib/pageflow/entries_controller_env_helper.rb +32 -2
- data/lib/pageflow/entry_export_import/attachment_files.rb +1 -1
- data/lib/pageflow/entry_export_import/entry_serialization.rb +9 -8
- data/lib/pageflow/entry_export_import/file_mappings.rb +1 -0
- data/lib/pageflow/entry_export_import/page_type_versions.rb +2 -2
- data/lib/pageflow/entry_export_import/revision_serialization/import.rb +11 -1
- data/lib/pageflow/entry_export_import/revision_serialization.rb +3 -0
- data/lib/pageflow/entry_export_import.rb +3 -3
- data/lib/pageflow/entry_structured_data_types.rb +43 -0
- data/lib/pageflow/entry_type_configuration.rb +1 -0
- data/lib/pageflow/entry_types.rb +2 -2
- data/lib/pageflow/feature.rb +1 -1
- data/lib/pageflow/features.rb +4 -6
- data/lib/pageflow/file_importers.rb +4 -4
- data/lib/pageflow/file_type.rb +5 -5
- data/lib/pageflow/file_types.rb +4 -4
- data/lib/pageflow/global_config_api.rb +5 -6
- data/lib/pageflow/help_entries.rb +7 -7
- data/lib/pageflow/help_entry.rb +1 -1
- data/lib/pageflow/hooks.rb +1 -1
- data/lib/pageflow/nested_revision_component.rb +9 -27
- data/lib/pageflow/news_item_api.rb +1 -1
- data/lib/pageflow/oembed_providers.rb +42 -0
- data/lib/pageflow/page_type.rb +2 -3
- data/lib/pageflow/page_types.rb +3 -3
- data/lib/pageflow/paperclip_interpolations/support.rb +1 -1
- data/lib/pageflow/paperclip_processors/vtt.rb +1 -0
- data/lib/pageflow/paperclip_processors/webp.rb +2 -2
- data/lib/pageflow/partial_editor_fragment_renderer.rb +2 -2
- data/lib/pageflow/plugin.rb +1 -2
- data/lib/pageflow/primary_domain_entry_redirect.rb +6 -0
- data/lib/pageflow/quota.rb +9 -5
- data/lib/pageflow/quotas.rb +1 -1
- data/lib/pageflow/rails_version.rb +14 -2
- data/lib/pageflow/react.rb +1 -1
- data/lib/pageflow/revision_component.rb +8 -40
- data/lib/pageflow/revision_components.rb +16 -6
- data/lib/pageflow/seeds.rb +12 -16
- data/lib/pageflow/theme.rb +1 -1
- data/lib/pageflow/theme_customizations.rb +10 -10
- data/lib/pageflow/themes.rb +44 -3
- data/lib/pageflow/user_mixin.rb +18 -6
- data/lib/pageflow/version.rb +1 -1
- data/lib/pageflow/widget_type.rb +4 -4
- data/lib/pageflow/widget_types.rb +9 -9
- data/lib/pageflow/zencoder_api.rb +32 -42
- data/lib/pageflow/zencoder_audio_output_definition.rb +14 -13
- data/lib/pageflow/zencoder_meta_data_output_definition.rb +3 -2
- data/lib/pageflow/zencoder_output_definition.rb +16 -14
- data/lib/pageflow/zencoder_video_output_definition.rb +140 -88
- data/lib/pageflow.rb +8 -2
- data/lib/tasks/pageflow_tasks.rake +1 -1
- data/package/config/eslint-rules/documented-in-toc.js +125 -0
- data/package/config/jest/index.js +0 -1
- data/package/config/webpack.js +0 -1
- data/package/config/webpack5.js +0 -1
- data/package/editor.js +4880 -2313
- data/package/frontend.js +710 -1223
- data/package/package.json +3 -1
- data/package/review.js +384 -0
- data/package/testHelpers.js +257 -243
- data/package/ui.js +1487 -813
- data/package/vendor/stubs/wysihtml5.js +2 -0
- data/spec/factories/accounts.rb +37 -22
- data/spec/factories/audio_files.rb +2 -2
- data/spec/factories/authentication_tokens.rb +4 -4
- data/spec/factories/chapters.rb +4 -4
- data/spec/factories/comment_thread_reads.rb +10 -0
- data/spec/factories/comment_threads.rb +10 -0
- data/spec/factories/comments.rb +9 -0
- data/spec/factories/draft_entries.rb +14 -6
- data/spec/factories/edit_locks.rb +1 -1
- data/spec/factories/entries.rb +28 -19
- data/spec/factories/entry_translation_groups.rb +6 -0
- data/spec/factories/file_folders.rb +8 -0
- data/spec/factories/file_usages.rb +2 -1
- data/spec/factories/folders.rb +1 -1
- data/spec/factories/image_files.rb +2 -2
- data/spec/factories/pages.rb +3 -3
- data/spec/factories/published_entries.rb +28 -8
- data/spec/factories/revisions.rb +1 -1
- data/spec/factories/sites.rb +6 -0
- data/spec/factories/test_multi_attachment_files.rb +1 -1
- data/spec/factories/text_track_files.rb +1 -1
- data/spec/factories/uploadable_files.rb +1 -1
- data/spec/factories/users.rb +6 -6
- data/spec/factories/video_files.rb +2 -2
- data/spec/factories/widgets.rb +1 -1
- data/spec/fixtures/7x15_rotated.jpg +0 -0
- data/vendor/assets/javascripts/wysihtml-toolbar.js +19288 -0
- metadata +266 -92
- data/app/assets/stylesheets/pageflow/editor/select_button.scss +0 -51
- data/config/initializers/revision_components.rb +0 -5
- data/config/locales/twitter_to_x.de.yml +0 -6
- data/config/locales/twitter_to_x.en.yml +0 -6
- data/entry_types/scrolled/app/helpers/pageflow_scrolled/generated_media_queries_helper.rb +0 -55
- data/entry_types/scrolled/config/locales/twitter_to_x.de.yml +0 -12
- data/entry_types/scrolled/config/locales/twitter_to_x.en.yml +0 -12
- data/entry_types/scrolled/config/locales/vr_image_projection.de.yml +0 -24
- data/entry_types/scrolled/config/locales/vr_image_projection.en.yml +0 -24
- data/entry_types/scrolled/package/frontend/EditableInlineText.module-ebd22921.js +0 -5497
- data/entry_types/scrolled/package/frontend/ToggleFullscreenCornerButton-b79159cc.js +0 -107
- data/entry_types/scrolled/package/frontend/Viewer-1ecf3375.js +0 -154
- data/entry_types/scrolled/package/frontend/Wavesurfer-7d9cf1b7.js +0 -333
- data/entry_types/scrolled/package/frontend/arrowRight-62998af9.js +0 -77
- data/entry_types/scrolled/package/frontend/components-024a9893.js +0 -2853
- data/entry_types/scrolled/package/frontend/createSuper-d0f30da3.js +0 -115
- data/entry_types/scrolled/package/frontend/i18n-ce13a8bf.js +0 -1129
- data/entry_types/scrolled/package/frontend/useContentElementEditorState-4f4c3cf6.js +0 -52
- data/lib/generators/pageflow/resque/templates/resque_enqueue_after_commit_patch.rb +0 -25
- data/package/vendor/jquery.minicolors.js +0 -1108
|
@@ -0,0 +1,4890 @@
|
|
|
1
|
+
import { features } from 'pageflow/frontend';
|
|
2
|
+
import React, { useMemo, useState, useCallback, useContext, useEffect, useRef, forwardRef, createContext, memo } from 'react';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import { P as scrollToElement, g as useContentElementAttributes, n as useStorylineActivity, w as widths, d as api, o as useFloatingPortalRoot, u as useScrollToTarget, Q as LayoutWithoutInlineEditing, f as useDarkBackground, R as renderElement, N as renderLeaf$1, T as Text$1 } from './FloatingPortalRootProvider-20c600de.js';
|
|
5
|
+
import './useDelayedBoolean-a387d85b.js';
|
|
6
|
+
import { v as ContentElementEditorCommandEmitterContext, a as usePostMessageListener, a4 as MotifAreaVisibilityProvider, a5 as ForcePaddingContext, a6 as ContentElementConfigurationUpdateContext, a7 as WidgetConfigurationUpdateContext, N as getAppearanceSectionScopeName, a3 as SectionThumbnail, t as useContentElementEditorCommandSubscription, l as frontendStyles, a8 as createRenderElement, a9 as usePhoneLayout, aa as tableStyles, s as styles$j } from './Placeholder.module-d22a9335.js';
|
|
7
|
+
import BackboneEvents from 'backbone-events-standalone';
|
|
8
|
+
import { useEntryStateDispatch, useTheme, updateContentElementConfiguration, updateWidgetConfiguration, useChapter, useMainStoryline, useDownloadableFile } from 'pageflow-scrolled/entryState';
|
|
9
|
+
import 'i18n-js';
|
|
10
|
+
import { u as useI18n } from './i18n-493cd2a6.js';
|
|
11
|
+
import 'striptags';
|
|
12
|
+
import 'react-measure';
|
|
13
|
+
import { P as PhonePlatformContext } from './PhonePlatformContext-035a99fa.js';
|
|
14
|
+
import { u as useContentElementEditorState, C as ContentElementEditorStateContext } from './useContentElementEditorState-a084912e.js';
|
|
15
|
+
import './ThemeIcon-ab834849.js';
|
|
16
|
+
import { ReviewStateProvider, LocatedCommentThreadsProvider, CommentDisplayFilterProvider, useCommentThreads, useCommentDisplayFilter, useLocatedCommentThreadsForSubject, ThreadsBadge, useAnchoredFloating, useUnreadActivityCount, Badge, alignToContainerEdge, useRangeAnchors, useCommentHighlights, decorateCommentHighlights, RangeAnchor, commentHighlightStyles } from 'pageflow-scrolled/review';
|
|
17
|
+
import { DndProvider, useDrop, useDrag } from 'react-dnd';
|
|
18
|
+
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
19
|
+
import { useFloating, hide, shift, autoUpdate, FloatingPortal, offset, arrow, inline, FloatingArrow } from '@floating-ui/react';
|
|
20
|
+
import { Range, Transforms, Editor, Node as Node$1, Element as Element$1, Path, Text, createEditor } from 'slate';
|
|
21
|
+
import { ReactEditor, useSlate, withReact, Slate, Editable } from 'slate-react';
|
|
22
|
+
import { withHistory } from 'slate-history';
|
|
23
|
+
import debounce from 'debounce';
|
|
24
|
+
|
|
25
|
+
const Context = React.createContext({});
|
|
26
|
+
function EditorStateProvider(props) {
|
|
27
|
+
const [selection, setSelectionState] = useState(null);
|
|
28
|
+
const setSelection = useCallback(selection => {
|
|
29
|
+
if (window.parent !== window) {
|
|
30
|
+
window.parent.postMessage({
|
|
31
|
+
type: 'SELECTED',
|
|
32
|
+
payload: selection || {}
|
|
33
|
+
}, window.location.origin);
|
|
34
|
+
}
|
|
35
|
+
setSelectionState(selection);
|
|
36
|
+
}, []);
|
|
37
|
+
const value = useMemo(() => ({
|
|
38
|
+
selection,
|
|
39
|
+
setSelection
|
|
40
|
+
}), [setSelection, selection]);
|
|
41
|
+
return /*#__PURE__*/React.createElement(Context.Provider, {
|
|
42
|
+
value: value
|
|
43
|
+
}, props.children);
|
|
44
|
+
}
|
|
45
|
+
function useEditorSelection(options) {
|
|
46
|
+
const {
|
|
47
|
+
selection,
|
|
48
|
+
setSelection
|
|
49
|
+
} = useContext(Context);
|
|
50
|
+
const resetSelection = useCallback(() => {
|
|
51
|
+
setSelection(null);
|
|
52
|
+
}, [setSelection]);
|
|
53
|
+
const select = useCallback(selection => {
|
|
54
|
+
setSelection(selection || options);
|
|
55
|
+
}, [setSelection, options]);
|
|
56
|
+
return useMemo(() => {
|
|
57
|
+
if (!setSelection) return {};
|
|
58
|
+
const isSelected = !!(selection && options && selection.id === options.id && selection.type === options.type && selection.subjectType === options.subjectType && selection.subjectId === options.subjectId);
|
|
59
|
+
return {
|
|
60
|
+
range: selection === null || selection === void 0 ? void 0 : selection.range,
|
|
61
|
+
isSelected,
|
|
62
|
+
selection: isSelected ? selection : null,
|
|
63
|
+
select,
|
|
64
|
+
resetSelection
|
|
65
|
+
};
|
|
66
|
+
}, [options, selection, setSelection, select, resetSelection]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function useContentElementEditorCommandEmitter() {
|
|
70
|
+
return useMemo(() => Object.assign({}, BackboneEvents), []);
|
|
71
|
+
}
|
|
72
|
+
function ContentElementEditorCommandSubscriptionProvider({
|
|
73
|
+
emitter,
|
|
74
|
+
children
|
|
75
|
+
}) {
|
|
76
|
+
return /*#__PURE__*/React.createElement(ContentElementEditorCommandEmitterContext.Provider, {
|
|
77
|
+
value: emitter
|
|
78
|
+
}, children);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function EntryDecorator({
|
|
82
|
+
commentingInitialState,
|
|
83
|
+
children
|
|
84
|
+
}) {
|
|
85
|
+
const contentElementEditorCommandEmitter = useContentElementEditorCommandEmitter();
|
|
86
|
+
return /*#__PURE__*/React.createElement(EditorStateProvider, null, /*#__PURE__*/React.createElement(ReviewStateProvider, {
|
|
87
|
+
initialState: commentingInitialState
|
|
88
|
+
}, /*#__PURE__*/React.createElement(MessageHandler, {
|
|
89
|
+
contentElementEditorCommandEmitter: contentElementEditorCommandEmitter
|
|
90
|
+
}), /*#__PURE__*/React.createElement(LocatedCommentThreadsProvider, null, /*#__PURE__*/React.createElement(CommentDisplayFilterFromEditor, null, /*#__PURE__*/React.createElement(ContentElementEditorCommandSubscriptionProvider, {
|
|
91
|
+
emitter: contentElementEditorCommandEmitter
|
|
92
|
+
}, children)))));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// The reviewer picks which resolutions to see in the editor's sidebar
|
|
96
|
+
// menu, so the preview only follows what the editor tells it.
|
|
97
|
+
function CommentDisplayFilterFromEditor({
|
|
98
|
+
children
|
|
99
|
+
}) {
|
|
100
|
+
const [filter, setFilter] = useState({
|
|
101
|
+
resolution: 'unresolved',
|
|
102
|
+
alwaysShowComments: true
|
|
103
|
+
});
|
|
104
|
+
usePostMessageListener(useCallback(data => {
|
|
105
|
+
if (data.type === 'CHANGE_COMMENT_DISPLAY_FILTER') {
|
|
106
|
+
setFilter(data.payload);
|
|
107
|
+
}
|
|
108
|
+
}, []));
|
|
109
|
+
return /*#__PURE__*/React.createElement(CommentDisplayFilterProvider, {
|
|
110
|
+
resolution: filter.resolution,
|
|
111
|
+
alwaysShowComments: filter.alwaysShowComments
|
|
112
|
+
}, children);
|
|
113
|
+
}
|
|
114
|
+
function MessageHandler({
|
|
115
|
+
contentElementEditorCommandEmitter
|
|
116
|
+
}) {
|
|
117
|
+
const {
|
|
118
|
+
select
|
|
119
|
+
} = useEditorSelection();
|
|
120
|
+
const dispatch = useEntryStateDispatch();
|
|
121
|
+
const receiveMessage = useCallback(data => {
|
|
122
|
+
if (data.type === 'ACTION') {
|
|
123
|
+
dispatch(data.payload);
|
|
124
|
+
} else if (data.type === 'SELECT') {
|
|
125
|
+
select(data.payload);
|
|
126
|
+
} else if (data.type === 'CONTENT_ELEMENT_EDITOR_COMMAND') {
|
|
127
|
+
contentElementEditorCommandEmitter.trigger(`command:${data.payload.contentElementId}`, data.payload.command);
|
|
128
|
+
}
|
|
129
|
+
}, [dispatch, select, contentElementEditorCommandEmitter]);
|
|
130
|
+
usePostMessageListener(receiveMessage);
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (window.parent !== window) {
|
|
133
|
+
window.parent.postMessage({
|
|
134
|
+
type: 'READY'
|
|
135
|
+
}, window.location.origin);
|
|
136
|
+
}
|
|
137
|
+
}, []);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Scroll points are used to preserve scroll position when toggling
|
|
142
|
+
// the editor phone preview. Each ContentElementDecorator renders a
|
|
143
|
+
// `data-scrollpoint` attribute with a unique value on its wrapper
|
|
144
|
+
// div. Before toggling the phone preview mode, the `EntryPreviewView`
|
|
145
|
+
// sends a `SAVE_SCROLL_POINT` message. `getCurrentScrollPoint` looks
|
|
146
|
+
// through all DOM elements with `data-scrollpoint` attributes and
|
|
147
|
+
// stores the unique id of the element with the smallest non-negative
|
|
148
|
+
// y coordinate in the viewport (i.e. the first content element inside
|
|
149
|
+
// the viewport). `ScrollPointMessageHandler` responds with a
|
|
150
|
+
// `SAVED_SCROLL_POINT` message which makes `EntryPreviewView` toggle
|
|
151
|
+
// the preview mode. Once the preview has been resized,
|
|
152
|
+
// `EntryPreviewView` sends a `RESTORE_SCROLL_POINT`
|
|
153
|
+
// message. `restoreScrollPoint` looks up the new position of the
|
|
154
|
+
// element with the saved scroll point and scrolls it into view.
|
|
155
|
+
//
|
|
156
|
+
// When a content element is selected, we want to keep that element
|
|
157
|
+
// in the viewport instead. The `SelectionRect` therefore renders a
|
|
158
|
+
// `data-scrollpoint=selection` attribute. If an element with such an
|
|
159
|
+
// attribute is present, `getCurrentScrollPoint` prefers it over all
|
|
160
|
+
// other scroll points. Since text block elements render a selection
|
|
161
|
+
// rect around the current paragraph, scroll position is also
|
|
162
|
+
// preserved correctly inside long text blocks.
|
|
163
|
+
|
|
164
|
+
function ScrollPointMessageHandler() {
|
|
165
|
+
const scrollPoint = useRef();
|
|
166
|
+
const receiveMessage = useCallback(data => {
|
|
167
|
+
if (data.type === 'SAVE_SCROLL_POINT') {
|
|
168
|
+
scrollPoint.current = getCurrentScrollPoint();
|
|
169
|
+
window.parent.postMessage({
|
|
170
|
+
type: 'SAVED_SCROLL_POINT'
|
|
171
|
+
}, window.location.origin);
|
|
172
|
+
} else if (data.type === 'RESTORE_SCROLL_POINT') {
|
|
173
|
+
if (scrollPoint.current) {
|
|
174
|
+
restoreScrollPoint(scrollPoint.current);
|
|
175
|
+
}
|
|
176
|
+
} else if (data.type === 'SCROLL_TO_CONTENT_ELEMENT') {
|
|
177
|
+
scrollToContentElement(data.payload);
|
|
178
|
+
}
|
|
179
|
+
}, []);
|
|
180
|
+
usePostMessageListener(receiveMessage);
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
function scrollToContentElement({
|
|
184
|
+
id,
|
|
185
|
+
...options
|
|
186
|
+
}) {
|
|
187
|
+
const element = document.querySelector(`[data-scrollpoint="${id}"]`);
|
|
188
|
+
if (element) {
|
|
189
|
+
scrollToElement(element, options);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function getCurrentScrollPoint() {
|
|
193
|
+
let scrollPointElement = getSelectionScrollPointElement() || getScrollPointElementWithMinimumTopPositionInViewport();
|
|
194
|
+
return scrollPointElement === null || scrollPointElement === void 0 ? void 0 : scrollPointElement.getAttribute('data-scrollpoint');
|
|
195
|
+
}
|
|
196
|
+
function getSelectionScrollPointElement() {
|
|
197
|
+
return document.querySelector('[data-scrollpoint=selection]');
|
|
198
|
+
}
|
|
199
|
+
function getScrollPointElementWithMinimumTopPositionInViewport() {
|
|
200
|
+
let minTop = Infinity;
|
|
201
|
+
let scrollPointElement;
|
|
202
|
+
const scrollPoints = document.querySelectorAll('[data-scrollpoint]');
|
|
203
|
+
for (let i = 0; i < scrollPoints.length; i++) {
|
|
204
|
+
const rect = scrollPoints[i].getBoundingClientRect();
|
|
205
|
+
if (rect.top > 0 && rect.top < minTop) {
|
|
206
|
+
minTop = rect.top;
|
|
207
|
+
scrollPointElement = scrollPoints[i];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return scrollPointElement;
|
|
211
|
+
}
|
|
212
|
+
function restoreScrollPoint(name) {
|
|
213
|
+
let element = document.querySelector(`[data-scrollpoint="${name}"]`);
|
|
214
|
+
if (element) {
|
|
215
|
+
window.scrollTo({
|
|
216
|
+
top: element.getBoundingClientRect().top + window.scrollY - 100,
|
|
217
|
+
behavior: 'smooth'
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function ContentDecorator(props) {
|
|
223
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ScrollPointMessageHandler, null), /*#__PURE__*/React.createElement(DndProvider, {
|
|
224
|
+
backend: HTML5Backend
|
|
225
|
+
}, props.children));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var styles = {"wrapper":"SectionDecorator-module_wrapper__3sTk3","highlighted":"SectionDecorator-module_highlighted__18FyB","lineAbove":"SectionDecorator-module_lineAbove__BZqEr","lineBelow":"SectionDecorator-module_lineBelow__1RbG-","selected":"SectionDecorator-module_selected__1gcmF","transitionSelected":"SectionDecorator-module_transitionSelected__Wklk6","controls":"SectionDecorator-module_controls__LVEJG","transitionToolbar-after":"SectionDecorator-module_transitionToolbar-after__2_DVO SectionDecorator-module_toolbar__2Va1D","toolbar":"SectionDecorator-module_toolbar__2Va1D","commentBadge":"SectionDecorator-module_commentBadge__dSkqW","sticky":"SectionDecorator-module_sticky__3ALcJ","clipBadgeCorner":"SectionDecorator-module_clipBadgeCorner__3n3iG","commenting":"SectionDecorator-module_commenting__2IONO","transitionToolbar-before":"SectionDecorator-module_transitionToolbar-before__KipOO SectionDecorator-module_toolbar__2Va1D"};
|
|
229
|
+
|
|
230
|
+
var styles$1 = {"wrapper":"BackdropDecorator-module_wrapper__X-h1o","visible":"BackdropDecorator-module_visible__3VqiR","inner":"BackdropDecorator-module_inner__14JfF"};
|
|
231
|
+
|
|
232
|
+
var styles$2 = {"wrapper":"ContentElementDecorator-module_wrapper__NQgFN"};
|
|
233
|
+
|
|
234
|
+
var styles$3 = {"wrapper":"WidgetSelectionRect-module_wrapper__1ktq9","selected":"WidgetSelectionRect-module_selected__2nm_L"};
|
|
235
|
+
|
|
236
|
+
var styles$4 = {"indicator":"PaddingIndicator-module_indicator__1XR6g","selected":"PaddingIndicator-module_selected__2nryl","indicator-top":"PaddingIndicator-module_indicator-top__3CQ9Y PaddingIndicator-module_indicator__1XR6g","indicator-bottom":"PaddingIndicator-module_indicator-bottom__31WQe PaddingIndicator-module_indicator__1XR6g","none":"PaddingIndicator-module_none__3QJ9B","motif":"PaddingIndicator-module_motif__1s4Z2","tooltip":"PaddingIndicator-module_tooltip__3lItX"};
|
|
237
|
+
|
|
238
|
+
var styles$5 = {"Toolbar":"Toolbar-module_Toolbar__1INSj","button":"Toolbar-module_button__de5BW","activeButton":"Toolbar-module_activeButton__2sOLP","collapsible":"Toolbar-module_collapsible__3sivb"};
|
|
239
|
+
|
|
240
|
+
function Toolbar({
|
|
241
|
+
buttons,
|
|
242
|
+
onButtonClick,
|
|
243
|
+
iconSize,
|
|
244
|
+
collapsible
|
|
245
|
+
}) {
|
|
246
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
247
|
+
className: classNames(styles$5.Toolbar, {
|
|
248
|
+
[styles$5.collapsible]: collapsible
|
|
249
|
+
}),
|
|
250
|
+
contentEditable: false
|
|
251
|
+
}, buttons.map(button => {
|
|
252
|
+
const Icon = button.icon;
|
|
253
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
254
|
+
key: button.name,
|
|
255
|
+
title: button.text,
|
|
256
|
+
className: classNames(styles$5.button, {
|
|
257
|
+
[styles$5.activeButton]: button.active
|
|
258
|
+
}),
|
|
259
|
+
onMouseDown: event => {
|
|
260
|
+
event.preventDefault();
|
|
261
|
+
event.stopPropagation();
|
|
262
|
+
onButtonClick(button.name);
|
|
263
|
+
}
|
|
264
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
265
|
+
width: iconSize,
|
|
266
|
+
height: iconSize
|
|
267
|
+
}));
|
|
268
|
+
}));
|
|
269
|
+
}
|
|
270
|
+
Toolbar.defaultProps = {
|
|
271
|
+
iconSize: 15
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// Bundles an element's two comment-related editor selections - the
|
|
275
|
+
// highlighted comment thread and the pending new thread - which are
|
|
276
|
+
// mutually exclusive since the editor has a single selection at a time.
|
|
277
|
+
// Returns the active state plus actions to select the comments, a
|
|
278
|
+
// specific thread or a new thread. `type` is the comments selection type
|
|
279
|
+
// ('contentElementComments' or 'sectionComments'); `subjectType` and
|
|
280
|
+
// `subjectId` identify the new-thread subject.
|
|
281
|
+
function useCommentSelection({
|
|
282
|
+
type,
|
|
283
|
+
id,
|
|
284
|
+
subjectType,
|
|
285
|
+
subjectId
|
|
286
|
+
}) {
|
|
287
|
+
const {
|
|
288
|
+
isSelected: commentsSelected,
|
|
289
|
+
selection: commentsSelection,
|
|
290
|
+
select: selectComments
|
|
291
|
+
} = useEditorSelection(useMemo(() => ({
|
|
292
|
+
type,
|
|
293
|
+
id
|
|
294
|
+
}), [type, id]));
|
|
295
|
+
const {
|
|
296
|
+
isSelected: newThreadActive,
|
|
297
|
+
range: newThreadRange,
|
|
298
|
+
select: selectNewThreadSelection
|
|
299
|
+
} = useEditorSelection(useMemo(() => ({
|
|
300
|
+
type: 'newThread',
|
|
301
|
+
subjectType,
|
|
302
|
+
subjectId
|
|
303
|
+
}), [subjectType, subjectId]));
|
|
304
|
+
const selectThread = useCallback((threadId, options) => selectComments({
|
|
305
|
+
type,
|
|
306
|
+
id,
|
|
307
|
+
highlightedThreadId: threadId,
|
|
308
|
+
...options
|
|
309
|
+
}), [selectComments, type, id]);
|
|
310
|
+
const selectNewThread = useCallback(range => range ? selectNewThreadSelection({
|
|
311
|
+
type: 'newThread',
|
|
312
|
+
subjectType,
|
|
313
|
+
subjectId,
|
|
314
|
+
range
|
|
315
|
+
}) : selectNewThreadSelection(), [selectNewThreadSelection, subjectType, subjectId]);
|
|
316
|
+
return {
|
|
317
|
+
selected: commentsSelected ? 'comments' : newThreadActive ? 'newThread' : null,
|
|
318
|
+
highlightedThreadId: commentsSelection === null || commentsSelection === void 0 ? void 0 : commentsSelection.highlightedThreadId,
|
|
319
|
+
newThreadRange: newThreadActive ? newThreadRange : undefined,
|
|
320
|
+
selectComments,
|
|
321
|
+
selectThread,
|
|
322
|
+
selectNewThread
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function useContentElementCommentSelection() {
|
|
326
|
+
const {
|
|
327
|
+
contentElementId,
|
|
328
|
+
contentElementPermaId
|
|
329
|
+
} = useContentElementAttributes();
|
|
330
|
+
return useCommentSelection({
|
|
331
|
+
type: 'contentElementComments',
|
|
332
|
+
id: contentElementId,
|
|
333
|
+
subjectType: 'ContentElement',
|
|
334
|
+
subjectId: contentElementPermaId
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Handles the SELECT_COMMENT_THREAD message the editor posts when a
|
|
339
|
+
// thread is clicked in the comments sidebar. Fetches the subject's
|
|
340
|
+
// threads itself - including resolved ones, so a resolved thread can be
|
|
341
|
+
// revealed when clicked - ignores threads of other subjects, scrolls
|
|
342
|
+
// the relevant element into view and calls `selectThread` to make the
|
|
343
|
+
// matching editor selection. `beforeSelect` runs right before that, for
|
|
344
|
+
// callers that need to prepare for it (e.g. move the editor cursor into
|
|
345
|
+
// the thread's block). Shared by the content element and section
|
|
346
|
+
// decorators and the EditableText editor so the handling lives in one
|
|
347
|
+
// place instead of inside each badge. The selection names the editor as
|
|
348
|
+
// its source, which tells the editor it is looking at its own request
|
|
349
|
+
// coming back rather than at the reviewer picking a subject in the
|
|
350
|
+
// preview.
|
|
351
|
+
function useSelectCommentThreadHandler({
|
|
352
|
+
subjectType,
|
|
353
|
+
subjectId,
|
|
354
|
+
getScrollTarget,
|
|
355
|
+
beforeSelect,
|
|
356
|
+
selectThread
|
|
357
|
+
}) {
|
|
358
|
+
const threads = useCommentThreads({
|
|
359
|
+
subjectType,
|
|
360
|
+
subjectId
|
|
361
|
+
});
|
|
362
|
+
usePostMessageListener(useCallback(data => {
|
|
363
|
+
if (data.type !== 'SELECT_COMMENT_THREAD') return;
|
|
364
|
+
const {
|
|
365
|
+
threadId
|
|
366
|
+
} = data.payload;
|
|
367
|
+
if (!threads.some(thread => thread.id === threadId)) return;
|
|
368
|
+
const scrollTarget = getScrollTarget && getScrollTarget(threadId);
|
|
369
|
+
if (scrollTarget) {
|
|
370
|
+
scrollTarget.scrollIntoView({
|
|
371
|
+
block: 'nearest',
|
|
372
|
+
behavior: 'smooth'
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
if (beforeSelect) beforeSelect(threadId);
|
|
376
|
+
selectThread(threadId, {
|
|
377
|
+
source: 'editor'
|
|
378
|
+
});
|
|
379
|
+
}, [threads, getScrollTarget, beforeSelect, selectThread]));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function _extends() {
|
|
383
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
384
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
385
|
+
var source = arguments[i];
|
|
386
|
+
for (var key in source) {
|
|
387
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
388
|
+
target[key] = source[key];
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return target;
|
|
393
|
+
};
|
|
394
|
+
return _extends.apply(this, arguments);
|
|
395
|
+
}
|
|
396
|
+
var transitionIcon = (({
|
|
397
|
+
styles = {},
|
|
398
|
+
...props
|
|
399
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends({
|
|
400
|
+
"aria-hidden": "true",
|
|
401
|
+
"data-prefix": "fas",
|
|
402
|
+
"data-icon": "random",
|
|
403
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-random"] || "fa-random") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
404
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
405
|
+
viewBox: "0 0 512 512"
|
|
406
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
407
|
+
fill: "currentColor",
|
|
408
|
+
d: "M504.971 359.029c9.373 9.373 9.373 24.569 0 33.941l-80 79.984c-15.01 15.01-40.971 4.49-40.971-16.971V416h-58.785a12.004 12.004 0 01-8.773-3.812l-70.556-75.596 53.333-57.143L352 336h32v-39.981c0-21.438 25.943-31.998 40.971-16.971l80 79.981zM12 176h84l52.781 56.551 53.333-57.143-70.556-75.596A11.999 11.999 0 00122.785 96H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12zm372 0v39.984c0 21.46 25.961 31.98 40.971 16.971l80-79.984c9.373-9.373 9.373-24.569 0-33.941l-80-79.981C409.943 24.021 384 34.582 384 56.019V96h-58.785a12.004 12.004 0 00-8.773 3.812L96 336H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h110.785c3.326 0 6.503-1.381 8.773-3.812L352 176h32z"
|
|
409
|
+
})));
|
|
410
|
+
|
|
411
|
+
function SectionDecorator({
|
|
412
|
+
backdrop,
|
|
413
|
+
section,
|
|
414
|
+
contentElements,
|
|
415
|
+
transitions,
|
|
416
|
+
children
|
|
417
|
+
}) {
|
|
418
|
+
var _backdrop$contentElem;
|
|
419
|
+
const {
|
|
420
|
+
t
|
|
421
|
+
} = useI18n({
|
|
422
|
+
locale: 'ui'
|
|
423
|
+
});
|
|
424
|
+
const commentingEnabled = features.isEnabled('commenting');
|
|
425
|
+
const {
|
|
426
|
+
isSelected: isSectionSelected,
|
|
427
|
+
select,
|
|
428
|
+
resetSelection
|
|
429
|
+
} = useEditorSelection({
|
|
430
|
+
id: section.id,
|
|
431
|
+
type: 'sectionSettings'
|
|
432
|
+
});
|
|
433
|
+
const {
|
|
434
|
+
isSelected: isPaddingSelected
|
|
435
|
+
} = useEditorSelection({
|
|
436
|
+
id: section.id,
|
|
437
|
+
type: 'sectionPaddings'
|
|
438
|
+
});
|
|
439
|
+
const {
|
|
440
|
+
selected: commentSelectionState,
|
|
441
|
+
selectComments,
|
|
442
|
+
selectThread,
|
|
443
|
+
selectNewThread
|
|
444
|
+
} = useCommentSelection({
|
|
445
|
+
type: 'sectionComments',
|
|
446
|
+
id: section.id,
|
|
447
|
+
subjectType: 'Section',
|
|
448
|
+
subjectId: section.permaId
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// Viewing a section's comments or composing a new thread on it.
|
|
452
|
+
const commentsSelected = commentSelectionState !== null;
|
|
453
|
+
|
|
454
|
+
// The section reads as selected while its comments are open, so the
|
|
455
|
+
// section and the sidebar comment panel stay visually in sync.
|
|
456
|
+
const isSelected = isSectionSelected || isPaddingSelected || commentsSelected;
|
|
457
|
+
const {
|
|
458
|
+
resolution,
|
|
459
|
+
alwaysShowComments
|
|
460
|
+
} = useCommentDisplayFilter();
|
|
461
|
+
const threads = useLocatedCommentThreadsForSubject({
|
|
462
|
+
subjectType: 'Section',
|
|
463
|
+
subjectId: section.permaId,
|
|
464
|
+
resolution
|
|
465
|
+
});
|
|
466
|
+
const hasThreads = threads.length > 0;
|
|
467
|
+
const wrapperRef = useRef();
|
|
468
|
+
useSelectCommentThreadHandler({
|
|
469
|
+
subjectType: 'Section',
|
|
470
|
+
subjectId: section.permaId,
|
|
471
|
+
getScrollTarget: useCallback(() => wrapperRef.current, []),
|
|
472
|
+
selectThread
|
|
473
|
+
});
|
|
474
|
+
const clipBadgeCorner = commentingEnabled && (isSectionSelected || isPaddingSelected) && !hasThreads;
|
|
475
|
+
const {
|
|
476
|
+
isSelected: isBackdropElementSelected
|
|
477
|
+
} = useEditorSelection({
|
|
478
|
+
id: (_backdrop$contentElem = backdrop.contentElement) === null || _backdrop$contentElem === void 0 ? void 0 : _backdrop$contentElem.id,
|
|
479
|
+
type: 'contentElement'
|
|
480
|
+
});
|
|
481
|
+
const {
|
|
482
|
+
isSelected: isHighlighted
|
|
483
|
+
} = useEditorSelection({
|
|
484
|
+
id: section.id,
|
|
485
|
+
type: 'section'
|
|
486
|
+
});
|
|
487
|
+
const transitionSelection = useEditorSelection({
|
|
488
|
+
id: section.id,
|
|
489
|
+
type: 'sectionTransition'
|
|
490
|
+
});
|
|
491
|
+
const nextTransitionSelection = useEditorSelection({
|
|
492
|
+
id: section.nextSection && section.nextSection.id,
|
|
493
|
+
type: 'sectionTransition'
|
|
494
|
+
});
|
|
495
|
+
const lastContentElement = contentElements[contentElements.length - 1];
|
|
496
|
+
const {
|
|
497
|
+
isSelected: isLastContentElementSelected
|
|
498
|
+
} = useEditorSelection({
|
|
499
|
+
id: lastContentElement && lastContentElement.id,
|
|
500
|
+
type: 'contentElement'
|
|
501
|
+
});
|
|
502
|
+
function selectIfOutsideContentItem(event) {
|
|
503
|
+
if (!event.target.closest(`.${styles$2.wrapper}`) && !event.target.closest(`.${styles$1.wrapper}`) && !event.target.closest(`.${styles$3.wrapper}`) && !event.target.closest(`.${styles$4.indicator}`) && !event.target.closest(`.${styles.commentBadge}`) && !event.target.closest('#fullscreenRoot') && !event.target.closest('[data-floating-ui-portal]')) {
|
|
504
|
+
isSectionSelected ? resetSelection() : select();
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
508
|
+
ref: wrapperRef,
|
|
509
|
+
"aria-label": t('pageflow_scrolled.inline_editing.select_section'),
|
|
510
|
+
"aria-selected": isSelected,
|
|
511
|
+
className: className(isSelected, transitionSelection, isHighlighted, isBackdropElementSelected, transitions, clipBadgeCorner, commentingEnabled),
|
|
512
|
+
onMouseDown: selectIfOutsideContentItem
|
|
513
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
514
|
+
className: styles.controls
|
|
515
|
+
}, renderEditTransitionButton({
|
|
516
|
+
id: section.previousSection && section.id,
|
|
517
|
+
selection: transitionSelection,
|
|
518
|
+
position: 'before'
|
|
519
|
+
}), renderEditTransitionButton({
|
|
520
|
+
id: section.nextSection && section.nextSection.id,
|
|
521
|
+
selection: nextTransitionSelection,
|
|
522
|
+
position: 'after'
|
|
523
|
+
})), /*#__PURE__*/React.createElement(MotifAreaVisibilityProvider, {
|
|
524
|
+
visible: isSelected
|
|
525
|
+
}, /*#__PURE__*/React.createElement(ForcePaddingContext.Provider, {
|
|
526
|
+
value: isLastContentElementSelected || isSectionSelected || isHighlighted || commentsSelected
|
|
527
|
+
}, children)), commentingEnabled && /*#__PURE__*/React.createElement("div", {
|
|
528
|
+
className: classNames(styles.commentBadge, {
|
|
529
|
+
[styles.sticky]: hasThreads || commentsSelected
|
|
530
|
+
})
|
|
531
|
+
}, /*#__PURE__*/React.createElement(ThreadsBadge, {
|
|
532
|
+
subjectType: "Section",
|
|
533
|
+
subjectId: section.permaId,
|
|
534
|
+
resolution: resolution,
|
|
535
|
+
mode: commentsSelected ? 'active' : isSelected ? 'icon' : alwaysShowComments ? 'dot' : 'none',
|
|
536
|
+
onClick: () => hasThreads ? selectComments() : selectNewThread()
|
|
537
|
+
})));
|
|
538
|
+
}
|
|
539
|
+
function className(isSelected, transitionSelection, isHighlighted, isBackdropElementSelected, transitions, clipBadgeCorner, commenting) {
|
|
540
|
+
return classNames(styles.wrapper, {
|
|
541
|
+
[styles.selected]: isSelected,
|
|
542
|
+
[styles.highlighted]: isHighlighted,
|
|
543
|
+
[styles.lineAbove]: isBackdropElementSelected && transitions[0].startsWith('fade'),
|
|
544
|
+
[styles.lineBelow]: isBackdropElementSelected && transitions[1].startsWith('fade'),
|
|
545
|
+
[styles.transitionSelected]: transitionSelection.isSelected,
|
|
546
|
+
[styles.clipBadgeCorner]: clipBadgeCorner,
|
|
547
|
+
[styles.commenting]: commenting
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
function renderEditTransitionButton({
|
|
551
|
+
id,
|
|
552
|
+
position,
|
|
553
|
+
selection
|
|
554
|
+
}) {
|
|
555
|
+
if (!id) {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
559
|
+
className: styles[`transitionToolbar-${position}`]
|
|
560
|
+
}, /*#__PURE__*/React.createElement(EditTransitionButton, {
|
|
561
|
+
id: id,
|
|
562
|
+
selection: selection,
|
|
563
|
+
position: position
|
|
564
|
+
}));
|
|
565
|
+
}
|
|
566
|
+
function EditTransitionButton({
|
|
567
|
+
id,
|
|
568
|
+
position,
|
|
569
|
+
selection
|
|
570
|
+
}) {
|
|
571
|
+
const {
|
|
572
|
+
t
|
|
573
|
+
} = useI18n({
|
|
574
|
+
locale: 'ui'
|
|
575
|
+
});
|
|
576
|
+
return /*#__PURE__*/React.createElement(EditSectionButton, {
|
|
577
|
+
id: id,
|
|
578
|
+
selection: selection,
|
|
579
|
+
text: t(`pageflow_scrolled.inline_editing.edit_section_transition_${position}`),
|
|
580
|
+
icon: transitionIcon
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
function EditSectionButton({
|
|
584
|
+
id,
|
|
585
|
+
selection,
|
|
586
|
+
icon,
|
|
587
|
+
text
|
|
588
|
+
}) {
|
|
589
|
+
return /*#__PURE__*/React.createElement(Toolbar, {
|
|
590
|
+
buttons: [{
|
|
591
|
+
name: 'button',
|
|
592
|
+
active: selection.isSelected,
|
|
593
|
+
icon,
|
|
594
|
+
text
|
|
595
|
+
}],
|
|
596
|
+
iconSize: 20,
|
|
597
|
+
onButtonClick: () => selection.select()
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
var styles$6 = {"selectionWidth":"1px","selectionPadding":"-0.5em","main":"SelectionRect-module_main__3AOhG","draggable":"SelectionRect-module_draggable__3Qp53","tug":"SelectionRect-module_tug__DmW1G","openSides":"SelectionRect-module_openSides__bf5fO","inset":"SelectionRect-module_inset__3den3","selected":"SelectionRect-module_selected__1PhM6","toolbar":"SelectionRect-module_toolbar__3nPrd","insert":"SelectionRect-module_insert__w0Tl0","insertHovered":"SelectionRect-module_insertHovered__VTsDD","start":"SelectionRect-module_start__3_nAf","insert-before":"SelectionRect-module_insert-before__2Tyq5 SelectionRect-module_insert__w0Tl0","end":"SelectionRect-module_end__3qOoK","insert-after":"SelectionRect-module_insert-after__3FJ4R SelectionRect-module_insert__w0Tl0","hasCommentBadge":"SelectionRect-module_hasCommentBadge__RuLsP","insertButton":"SelectionRect-module_insertButton__1g-ZG","dragHandle":"SelectionRect-module_dragHandle__2vVhP","commentBadge":"SelectionRect-module_commentBadge__3e0x_","commentBadgeInset":"SelectionRect-module_commentBadgeInset__3YISH"};
|
|
602
|
+
|
|
603
|
+
function _extends$1() {
|
|
604
|
+
_extends$1 = Object.assign ? Object.assign.bind() : function (target) {
|
|
605
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
606
|
+
var source = arguments[i];
|
|
607
|
+
for (var key in source) {
|
|
608
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
609
|
+
target[key] = source[key];
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return target;
|
|
614
|
+
};
|
|
615
|
+
return _extends$1.apply(this, arguments);
|
|
616
|
+
}
|
|
617
|
+
var PlusIcon = (({
|
|
618
|
+
styles = {},
|
|
619
|
+
...props
|
|
620
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$1({
|
|
621
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
622
|
+
viewBox: "0 0 512 512"
|
|
623
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
624
|
+
d: "M256 0C114.844 0 0 114.839 0 256s114.844 256 256 256 256-114.839 256-256S397.156 0 256 0zm133.594 272.699H272.699v116.895c0 9.225-7.48 16.699-16.699 16.699-9.219 0-16.699-7.475-16.699-16.699V272.699H122.406c-9.219 0-16.699-7.475-16.699-16.699 0-9.225 7.48-16.699 16.699-16.699h116.895V122.406c0-9.225 7.48-16.699 16.699-16.699 9.219 0 16.699 7.475 16.699 16.699v116.895h116.895c9.219 0 16.699 7.475 16.699 16.699.001 9.225-7.48 16.699-16.699 16.699z"
|
|
625
|
+
})));
|
|
626
|
+
|
|
627
|
+
function _extends$2() {
|
|
628
|
+
_extends$2 = Object.assign ? Object.assign.bind() : function (target) {
|
|
629
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
630
|
+
var source = arguments[i];
|
|
631
|
+
for (var key in source) {
|
|
632
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
633
|
+
target[key] = source[key];
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return target;
|
|
638
|
+
};
|
|
639
|
+
return _extends$2.apply(this, arguments);
|
|
640
|
+
}
|
|
641
|
+
var MoveIcon = (({
|
|
642
|
+
styles = {},
|
|
643
|
+
...props
|
|
644
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$2({
|
|
645
|
+
"aria-hidden": "true",
|
|
646
|
+
"data-prefix": "fas",
|
|
647
|
+
"data-icon": "arrows-alt",
|
|
648
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-arrows-alt"] || "fa-arrows-alt") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
649
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
650
|
+
viewBox: "0 0 512 512"
|
|
651
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
652
|
+
fill: "currentColor",
|
|
653
|
+
d: "M352.201 425.775l-79.196 79.196c-9.373 9.373-24.568 9.373-33.941 0l-79.196-79.196c-15.119-15.119-4.411-40.971 16.971-40.97h51.162L228 284H127.196v51.162c0 21.382-25.851 32.09-40.971 16.971L7.029 272.937c-9.373-9.373-9.373-24.569 0-33.941L86.225 159.8c15.119-15.119 40.971-4.411 40.971 16.971V228H228V127.196h-51.23c-21.382 0-32.09-25.851-16.971-40.971l79.196-79.196c9.373-9.373 24.568-9.373 33.941 0l79.196 79.196c15.119 15.119 4.411 40.971-16.971 40.971h-51.162V228h100.804v-51.162c0-21.382 25.851-32.09 40.97-16.971l79.196 79.196c9.373 9.373 9.373 24.569 0 33.941L425.773 352.2c-15.119 15.119-40.971 4.411-40.97-16.971V284H284v100.804h51.23c21.382 0 32.09 25.851 16.971 40.971z"
|
|
654
|
+
})));
|
|
655
|
+
|
|
656
|
+
const SelectionRect = forwardRef(function SelectionRect(props, ref) {
|
|
657
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
658
|
+
ref: ref,
|
|
659
|
+
className: classNames(styles$6.main, {
|
|
660
|
+
[styles$6.openSides]: props.full && !props.inset,
|
|
661
|
+
[styles$6.tug]: props.full || props.customMargin,
|
|
662
|
+
[styles$6.inset]: props.inset,
|
|
663
|
+
[styles$6.selected]: props.selected,
|
|
664
|
+
[styles$6.draggable]: props.drag,
|
|
665
|
+
[styles$6.hasCommentBadge]: props.commentBadge && !props.commentBadgeInset,
|
|
666
|
+
[styles$6.start]: props.selected && props.start,
|
|
667
|
+
[styles$6.end]: props.selected && props.end
|
|
668
|
+
}),
|
|
669
|
+
"aria-label": props.ariaLabel,
|
|
670
|
+
"aria-selected": props.selected,
|
|
671
|
+
"data-scrollpoint": props.scrollPoint ? 'selection' : undefined,
|
|
672
|
+
onClick: props.onClick
|
|
673
|
+
}, renderDragHandle(props), renderCommentBadge(props), renderToolbar(props), /*#__PURE__*/React.createElement(InsertButton, Object.assign({}, props, {
|
|
674
|
+
at: "before"
|
|
675
|
+
})), props.children, /*#__PURE__*/React.createElement(InsertButton, Object.assign({}, props, {
|
|
676
|
+
at: "after"
|
|
677
|
+
})));
|
|
678
|
+
});
|
|
679
|
+
function InsertButton(props) {
|
|
680
|
+
const [insertHovered, setInsertHovered] = useState(false);
|
|
681
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
682
|
+
className: classNames(styles$6[`insert-${props.at}`], {
|
|
683
|
+
[styles$6.insertHovered]: insertHovered
|
|
684
|
+
}),
|
|
685
|
+
contentEditable: false
|
|
686
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
687
|
+
className: styles$6.insertButton,
|
|
688
|
+
title: props.insertButtonTitles && props.insertButtonTitles[props.at],
|
|
689
|
+
onMouseDown: event => event.preventDefault(),
|
|
690
|
+
onClick: () => props.onInsertButtonClick(props.at),
|
|
691
|
+
onMouseEnter: () => setInsertHovered(true),
|
|
692
|
+
onMouseLeave: () => setInsertHovered(false)
|
|
693
|
+
}, /*#__PURE__*/React.createElement(PlusIcon, {
|
|
694
|
+
width: 15,
|
|
695
|
+
height: 15,
|
|
696
|
+
fill: "currentColor"
|
|
697
|
+
})));
|
|
698
|
+
}
|
|
699
|
+
function renderDragHandle({
|
|
700
|
+
drag,
|
|
701
|
+
dragHandleTitle
|
|
702
|
+
}) {
|
|
703
|
+
if (!drag) {
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
707
|
+
ref: drag,
|
|
708
|
+
className: styles$6.dragHandle,
|
|
709
|
+
title: dragHandleTitle
|
|
710
|
+
}, /*#__PURE__*/React.createElement(MoveIcon, null));
|
|
711
|
+
}
|
|
712
|
+
function renderCommentBadge({
|
|
713
|
+
commentBadge,
|
|
714
|
+
commentBadgeInset
|
|
715
|
+
}) {
|
|
716
|
+
if (!commentBadge) {
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
719
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
720
|
+
className: classNames(styles$6.commentBadge, {
|
|
721
|
+
[styles$6.commentBadgeInset]: commentBadgeInset
|
|
722
|
+
}),
|
|
723
|
+
onClick: e => e.stopPropagation()
|
|
724
|
+
}, commentBadge);
|
|
725
|
+
}
|
|
726
|
+
function renderToolbar({
|
|
727
|
+
toolbarButtons,
|
|
728
|
+
onToolbarButtonClick,
|
|
729
|
+
start
|
|
730
|
+
}) {
|
|
731
|
+
if (toolbarButtons && start) {
|
|
732
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
733
|
+
className: styles$6.toolbar
|
|
734
|
+
}, /*#__PURE__*/React.createElement(Toolbar, {
|
|
735
|
+
buttons: toolbarButtons,
|
|
736
|
+
collapsible: true,
|
|
737
|
+
onButtonClick: onToolbarButtonClick
|
|
738
|
+
}));
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
SelectionRect.defaultProps = {
|
|
742
|
+
start: true,
|
|
743
|
+
end: true
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
var styles$7 = {"target":"DropTargets-module_target__Z2N2d","isOver":"DropTargets-module_isOver__3ksFy","before":"DropTargets-module_before__cAXo1 DropTargets-module_target__Z2N2d","after":"DropTargets-module_after__2Q8QU DropTargets-module_target__Z2N2d"};
|
|
747
|
+
|
|
748
|
+
function DropTargets({
|
|
749
|
+
accept,
|
|
750
|
+
canDrop,
|
|
751
|
+
onDrop
|
|
752
|
+
}) {
|
|
753
|
+
const [{
|
|
754
|
+
canDropBefore,
|
|
755
|
+
isBefore
|
|
756
|
+
}, dropBefore] = useDrop({
|
|
757
|
+
accept,
|
|
758
|
+
canDrop: item => canDrop({
|
|
759
|
+
at: 'before',
|
|
760
|
+
id: item.id
|
|
761
|
+
}),
|
|
762
|
+
collect: monitor => ({
|
|
763
|
+
canDropBefore: monitor.canDrop(),
|
|
764
|
+
isBefore: monitor.isOver() && monitor.canDrop()
|
|
765
|
+
}),
|
|
766
|
+
drop: item => onDrop({
|
|
767
|
+
at: 'before',
|
|
768
|
+
id: item.id,
|
|
769
|
+
range: item.range
|
|
770
|
+
})
|
|
771
|
+
});
|
|
772
|
+
const [{
|
|
773
|
+
canDropAfter,
|
|
774
|
+
isAfter
|
|
775
|
+
}, dropAfter] = useDrop({
|
|
776
|
+
accept,
|
|
777
|
+
canDrop: item => canDrop({
|
|
778
|
+
at: 'after',
|
|
779
|
+
id: item.id
|
|
780
|
+
}),
|
|
781
|
+
collect: monitor => ({
|
|
782
|
+
canDropAfter: monitor.canDrop(),
|
|
783
|
+
isAfter: monitor.isOver() && monitor.canDrop()
|
|
784
|
+
}),
|
|
785
|
+
drop: item => onDrop({
|
|
786
|
+
at: 'after',
|
|
787
|
+
id: item.id,
|
|
788
|
+
range: item.range
|
|
789
|
+
})
|
|
790
|
+
});
|
|
791
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, canDropBefore && /*#__PURE__*/React.createElement("div", {
|
|
792
|
+
ref: dropBefore,
|
|
793
|
+
"data-testid": "drop-before",
|
|
794
|
+
className: classNames(styles$7.before, {
|
|
795
|
+
[styles$7.isOver]: isBefore
|
|
796
|
+
})
|
|
797
|
+
}), canDropAfter && /*#__PURE__*/React.createElement("div", {
|
|
798
|
+
ref: dropAfter,
|
|
799
|
+
"data-testid": "drop-after",
|
|
800
|
+
title: "bar",
|
|
801
|
+
className: classNames(styles$7.after, {
|
|
802
|
+
[styles$7.isOver]: isAfter
|
|
803
|
+
})
|
|
804
|
+
}));
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function Scale({
|
|
808
|
+
scaleName,
|
|
809
|
+
themeProperties,
|
|
810
|
+
scaleTranslations,
|
|
811
|
+
defaultValuePropertyName,
|
|
812
|
+
scope
|
|
813
|
+
}) {
|
|
814
|
+
const root = themeProperties.root || {};
|
|
815
|
+
const scaleProperties = Object.keys(root).filter(name => name.indexOf(`${scaleName}-`) === 0);
|
|
816
|
+
const values = scaleProperties.map(name => name.split('-').pop());
|
|
817
|
+
const texts = values.map(value => {
|
|
818
|
+
var _scaleTranslations$sc;
|
|
819
|
+
return (_scaleTranslations$sc = scaleTranslations[scaleName]) === null || _scaleTranslations$sc === void 0 ? void 0 : _scaleTranslations$sc[value];
|
|
820
|
+
});
|
|
821
|
+
const cssValues = scaleProperties.map(propertyName => root[propertyName]);
|
|
822
|
+
return {
|
|
823
|
+
values,
|
|
824
|
+
texts,
|
|
825
|
+
defaultValue: getDefaultValue()
|
|
826
|
+
};
|
|
827
|
+
function getDefaultValue() {
|
|
828
|
+
var _themeProperties$scop, _themeProperties$scop2, _themeProperties$root;
|
|
829
|
+
if (!defaultValuePropertyName) {
|
|
830
|
+
return undefined;
|
|
831
|
+
}
|
|
832
|
+
const defaultCssValue = (_themeProperties$scop = (_themeProperties$scop2 = themeProperties[scope]) === null || _themeProperties$scop2 === void 0 ? void 0 : _themeProperties$scop2[defaultValuePropertyName]) !== null && _themeProperties$scop !== void 0 ? _themeProperties$scop : (_themeProperties$root = themeProperties.root) === null || _themeProperties$root === void 0 ? void 0 : _themeProperties$root[defaultValuePropertyName];
|
|
833
|
+
if (!defaultCssValue) {
|
|
834
|
+
return undefined;
|
|
835
|
+
}
|
|
836
|
+
const index = cssValues.indexOf(defaultCssValue);
|
|
837
|
+
return index >= 0 ? values[index] : undefined;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
var styles$8 = {"indicator":"MarginIndicator-module_indicator__eise1","indicator-top":"MarginIndicator-module_indicator-top__2igv4 MarginIndicator-module_indicator__eise1","indicator-bottom":"MarginIndicator-module_indicator-bottom__2-qSB MarginIndicator-module_indicator__eise1","tooltip":"MarginIndicator-module_tooltip__1cC4b","inset":"MarginIndicator-module_inset__xg51Q"};
|
|
842
|
+
|
|
843
|
+
function MarginIndicator({
|
|
844
|
+
marginValue,
|
|
845
|
+
position,
|
|
846
|
+
tooltipInset
|
|
847
|
+
}) {
|
|
848
|
+
var _theme$options, _theme$translations;
|
|
849
|
+
const {
|
|
850
|
+
isSelected
|
|
851
|
+
} = useContentElementEditorState();
|
|
852
|
+
const theme = useTheme();
|
|
853
|
+
const {
|
|
854
|
+
t
|
|
855
|
+
} = useI18n({
|
|
856
|
+
locale: 'ui'
|
|
857
|
+
});
|
|
858
|
+
const scale = Scale({
|
|
859
|
+
scaleName: 'contentElementMargin',
|
|
860
|
+
themeProperties: ((_theme$options = theme.options) === null || _theme$options === void 0 ? void 0 : _theme$options.properties) || {},
|
|
861
|
+
scaleTranslations: ((_theme$translations = theme.translations) === null || _theme$translations === void 0 ? void 0 : _theme$translations.scales) || {},
|
|
862
|
+
defaultValuePropertyName: 'contentElementMarginStyleDefault'
|
|
863
|
+
});
|
|
864
|
+
const index = scale.values.indexOf(marginValue);
|
|
865
|
+
if (!isSelected || !marginValue || index < 0) {
|
|
866
|
+
return null;
|
|
867
|
+
}
|
|
868
|
+
const label = t(`pageflow_scrolled.inline_editing.content_element_margin_${position}`);
|
|
869
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
870
|
+
"aria-label": label,
|
|
871
|
+
className: styles$8[`indicator-${position}`],
|
|
872
|
+
style: {
|
|
873
|
+
'--indicator-height': `var(--theme-content-element-margin-${marginValue})`
|
|
874
|
+
}
|
|
875
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
876
|
+
className: classNames(styles$8.tooltip, {
|
|
877
|
+
[styles$8.inset]: tooltipInset
|
|
878
|
+
}),
|
|
879
|
+
title: label
|
|
880
|
+
}, scale.texts[index]));
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
function postInsertContentElementMessage({
|
|
884
|
+
id,
|
|
885
|
+
at,
|
|
886
|
+
splitPoint
|
|
887
|
+
}) {
|
|
888
|
+
window.parent.postMessage({
|
|
889
|
+
type: 'INSERT_CONTENT_ELEMENT',
|
|
890
|
+
payload: {
|
|
891
|
+
id,
|
|
892
|
+
at,
|
|
893
|
+
splitPoint
|
|
894
|
+
}
|
|
895
|
+
}, window.location.origin);
|
|
896
|
+
}
|
|
897
|
+
function postMoveContentElementMessage({
|
|
898
|
+
id,
|
|
899
|
+
range,
|
|
900
|
+
to
|
|
901
|
+
}) {
|
|
902
|
+
window.parent.postMessage({
|
|
903
|
+
type: 'MOVE_CONTENT_ELEMENT',
|
|
904
|
+
payload: {
|
|
905
|
+
id,
|
|
906
|
+
range,
|
|
907
|
+
to
|
|
908
|
+
}
|
|
909
|
+
}, window.location.origin);
|
|
910
|
+
}
|
|
911
|
+
function postUpdateContentElementMessage({
|
|
912
|
+
id,
|
|
913
|
+
configuration,
|
|
914
|
+
commentThreadSubjectRanges
|
|
915
|
+
}) {
|
|
916
|
+
window.parent.postMessage({
|
|
917
|
+
type: 'UPDATE_CONTENT_ELEMENT',
|
|
918
|
+
payload: {
|
|
919
|
+
id,
|
|
920
|
+
configuration,
|
|
921
|
+
commentThreadSubjectRanges
|
|
922
|
+
}
|
|
923
|
+
}, window.location.origin);
|
|
924
|
+
}
|
|
925
|
+
function postUpdateWidgetMessage({
|
|
926
|
+
role,
|
|
927
|
+
configuration
|
|
928
|
+
}) {
|
|
929
|
+
window.parent.postMessage({
|
|
930
|
+
type: 'UPDATE_WIDGET',
|
|
931
|
+
payload: {
|
|
932
|
+
role,
|
|
933
|
+
configuration
|
|
934
|
+
}
|
|
935
|
+
}, window.location.origin);
|
|
936
|
+
}
|
|
937
|
+
function postUpdateTransientContentElementStateMessage({
|
|
938
|
+
id,
|
|
939
|
+
state
|
|
940
|
+
}) {
|
|
941
|
+
window.parent.postMessage({
|
|
942
|
+
type: 'UPDATE_TRANSIENT_CONTENT_ELEMENT_STATE',
|
|
943
|
+
payload: {
|
|
944
|
+
id,
|
|
945
|
+
state
|
|
946
|
+
}
|
|
947
|
+
}, window.location.origin);
|
|
948
|
+
}
|
|
949
|
+
function postSelectLinkDestinationMessage() {
|
|
950
|
+
window.parent.postMessage({
|
|
951
|
+
type: 'SELECT_LINK_DESTINATION'
|
|
952
|
+
}, window.location.origin);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
function ContentElementConfigurationUpdateProvider({
|
|
956
|
+
id,
|
|
957
|
+
permaId,
|
|
958
|
+
children
|
|
959
|
+
}) {
|
|
960
|
+
const dispatch = useEntryStateDispatch();
|
|
961
|
+
const update = useCallback((configuration, {
|
|
962
|
+
commentThreadSubjectRanges
|
|
963
|
+
} = {}) => {
|
|
964
|
+
postUpdateContentElementMessage({
|
|
965
|
+
id,
|
|
966
|
+
configuration,
|
|
967
|
+
commentThreadSubjectRanges
|
|
968
|
+
});
|
|
969
|
+
updateContentElementConfiguration({
|
|
970
|
+
dispatch,
|
|
971
|
+
permaId,
|
|
972
|
+
configuration
|
|
973
|
+
});
|
|
974
|
+
}, [dispatch, permaId, id]);
|
|
975
|
+
return /*#__PURE__*/React.createElement(ContentElementConfigurationUpdateContext.Provider, {
|
|
976
|
+
value: update
|
|
977
|
+
}, children);
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
function ContentElementEditorStateProvider({
|
|
981
|
+
id,
|
|
982
|
+
permaId,
|
|
983
|
+
children
|
|
984
|
+
}) {
|
|
985
|
+
const {
|
|
986
|
+
isSelected,
|
|
987
|
+
select,
|
|
988
|
+
range
|
|
989
|
+
} = useEditorSelection(useMemo(() => ({
|
|
990
|
+
id,
|
|
991
|
+
type: 'contentElement'
|
|
992
|
+
}), [id]));
|
|
993
|
+
const {
|
|
994
|
+
isSelected: commentsSelected,
|
|
995
|
+
select: selectComments
|
|
996
|
+
} = useEditorSelection(useMemo(() => ({
|
|
997
|
+
id,
|
|
998
|
+
type: 'contentElementComments'
|
|
999
|
+
}), [id]));
|
|
1000
|
+
const {
|
|
1001
|
+
isSelected: newThreadSelected,
|
|
1002
|
+
select: selectNewThread
|
|
1003
|
+
} = useEditorSelection(useMemo(() => ({
|
|
1004
|
+
type: 'newThread',
|
|
1005
|
+
subjectType: 'ContentElement',
|
|
1006
|
+
subjectId: permaId
|
|
1007
|
+
}), [permaId]));
|
|
1008
|
+
const storylineMode = useStorylineActivity();
|
|
1009
|
+
const inForeground = storylineMode === 'active';
|
|
1010
|
+
const type = inForeground ? isSelected ? 'contentElement' : commentsSelected ? 'contentElementComments' : newThreadSelected ? 'newThread' : null : null;
|
|
1011
|
+
const previousTransientState = useRef({});
|
|
1012
|
+
const setTransientState = useCallback(state => {
|
|
1013
|
+
if (!shallowEqual(state, previousTransientState.current)) {
|
|
1014
|
+
postUpdateTransientContentElementStateMessage({
|
|
1015
|
+
id,
|
|
1016
|
+
state
|
|
1017
|
+
});
|
|
1018
|
+
previousTransientState.current = state;
|
|
1019
|
+
}
|
|
1020
|
+
}, [id]);
|
|
1021
|
+
const value = useMemo(() => ({
|
|
1022
|
+
isEditable: true,
|
|
1023
|
+
select,
|
|
1024
|
+
selectComments,
|
|
1025
|
+
selectNewThread,
|
|
1026
|
+
isSelected: !!type,
|
|
1027
|
+
type,
|
|
1028
|
+
range,
|
|
1029
|
+
setTransientState
|
|
1030
|
+
}), [select, selectComments, selectNewThread, type, range, setTransientState]);
|
|
1031
|
+
return /*#__PURE__*/React.createElement(ContentElementEditorStateContext.Provider, {
|
|
1032
|
+
value: value
|
|
1033
|
+
}, children);
|
|
1034
|
+
}
|
|
1035
|
+
function shallowEqual(obj1, obj2) {
|
|
1036
|
+
return Object.keys(obj1).length === Object.keys(obj2).length && Object.keys(obj1).every(key => Object.prototype.hasOwnProperty.call(obj2, key) && obj1[key] === obj2[key]);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
function ContentElementDecorator(props) {
|
|
1040
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1041
|
+
className: styles$2.wrapper,
|
|
1042
|
+
"data-scrollpoint": props.id
|
|
1043
|
+
}, /*#__PURE__*/React.createElement(ContentElementEditorStateProvider, {
|
|
1044
|
+
id: props.id,
|
|
1045
|
+
permaId: props.permaId
|
|
1046
|
+
}, /*#__PURE__*/React.createElement(OptionalSelectionRect, props, /*#__PURE__*/React.createElement(ContentElementConfigurationUpdateProvider, {
|
|
1047
|
+
id: props.id,
|
|
1048
|
+
permaId: props.permaId
|
|
1049
|
+
}, renderMarginIndicators(props), props.children))));
|
|
1050
|
+
}
|
|
1051
|
+
function OptionalSelectionRect(props) {
|
|
1052
|
+
const {
|
|
1053
|
+
customSelectionRect
|
|
1054
|
+
} = api.contentElementTypes.getOptions(props.type) || {};
|
|
1055
|
+
if (customSelectionRect) {
|
|
1056
|
+
return props.children;
|
|
1057
|
+
} else {
|
|
1058
|
+
return /*#__PURE__*/React.createElement(DefaultSelectionRect, props, props.children);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
function DefaultSelectionRect(props) {
|
|
1062
|
+
const {
|
|
1063
|
+
isSelected,
|
|
1064
|
+
type,
|
|
1065
|
+
select,
|
|
1066
|
+
selectComments,
|
|
1067
|
+
selectNewThread
|
|
1068
|
+
} = useContentElementEditorState();
|
|
1069
|
+
const commentsSelected = type === 'contentElementComments' || type === 'newThread';
|
|
1070
|
+
const {
|
|
1071
|
+
resolution,
|
|
1072
|
+
alwaysShowComments
|
|
1073
|
+
} = useCommentDisplayFilter();
|
|
1074
|
+
const {
|
|
1075
|
+
t
|
|
1076
|
+
} = useI18n({
|
|
1077
|
+
locale: 'ui'
|
|
1078
|
+
});
|
|
1079
|
+
const selectionRectRef = useRef();
|
|
1080
|
+
useSelectCommentThreadHandler({
|
|
1081
|
+
subjectType: 'ContentElement',
|
|
1082
|
+
subjectId: props.permaId,
|
|
1083
|
+
getScrollTarget: useCallback(() => selectionRectRef.current, []),
|
|
1084
|
+
selectThread: useCallback((threadId, options) => selectComments({
|
|
1085
|
+
type: 'contentElementComments',
|
|
1086
|
+
id: props.id,
|
|
1087
|
+
highlightedThreadId: threadId,
|
|
1088
|
+
...options
|
|
1089
|
+
}), [selectComments, props.id])
|
|
1090
|
+
});
|
|
1091
|
+
const [, drag, preview] = useDrag({
|
|
1092
|
+
item: {
|
|
1093
|
+
type: 'contentElement',
|
|
1094
|
+
id: props.id
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
return /*#__PURE__*/React.createElement(SelectionRect, {
|
|
1098
|
+
ref: selectionRectRef,
|
|
1099
|
+
selected: isSelected,
|
|
1100
|
+
scrollPoint: isSelected,
|
|
1101
|
+
drag: drag,
|
|
1102
|
+
dragHandleTitle: t('pageflow_scrolled.inline_editing.drag_content_element'),
|
|
1103
|
+
full: props.width === widths.full,
|
|
1104
|
+
customMargin: props.customMargin,
|
|
1105
|
+
inset: props.position === 'backdrop',
|
|
1106
|
+
commentBadge: features.isEnabled('commenting') && /*#__PURE__*/React.createElement(ThreadsBadge, {
|
|
1107
|
+
subjectType: "ContentElement",
|
|
1108
|
+
subjectId: props.permaId,
|
|
1109
|
+
resolution: resolution,
|
|
1110
|
+
mode: commentsSelected ? 'active' : isSelected ? 'icon' : alwaysShowComments ? 'dot' : 'none',
|
|
1111
|
+
onClick: threads => threads.length === 0 ? selectNewThread() : selectComments()
|
|
1112
|
+
}),
|
|
1113
|
+
commentBadgeInset: !isSelected,
|
|
1114
|
+
ariaLabel: t('pageflow_scrolled.inline_editing.select_content_element'),
|
|
1115
|
+
insertButtonTitles: t('pageflow_scrolled.inline_editing.insert_content_element'),
|
|
1116
|
+
onClick: () => select(),
|
|
1117
|
+
onInsertButtonClick: at => postInsertContentElementMessage({
|
|
1118
|
+
id: props.id,
|
|
1119
|
+
at
|
|
1120
|
+
})
|
|
1121
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1122
|
+
ref: preview
|
|
1123
|
+
}, props.children), /*#__PURE__*/React.createElement(DropTargets, {
|
|
1124
|
+
accept: "contentElement",
|
|
1125
|
+
canDrop: ({
|
|
1126
|
+
id
|
|
1127
|
+
}) => id !== props.id,
|
|
1128
|
+
onDrop: ({
|
|
1129
|
+
id,
|
|
1130
|
+
range,
|
|
1131
|
+
at
|
|
1132
|
+
}) => postMoveContentElementMessage({
|
|
1133
|
+
id,
|
|
1134
|
+
range,
|
|
1135
|
+
to: {
|
|
1136
|
+
id: props.id,
|
|
1137
|
+
at
|
|
1138
|
+
}
|
|
1139
|
+
})
|
|
1140
|
+
}));
|
|
1141
|
+
}
|
|
1142
|
+
function renderMarginIndicators(props) {
|
|
1143
|
+
var _props$itemProps, _props$itemProps2;
|
|
1144
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MarginIndicator, {
|
|
1145
|
+
marginValue: (_props$itemProps = props.itemProps) === null || _props$itemProps === void 0 ? void 0 : _props$itemProps.marginTop,
|
|
1146
|
+
position: "top",
|
|
1147
|
+
tooltipInset: props.width === widths.full || props.customMargin
|
|
1148
|
+
}), /*#__PURE__*/React.createElement(MarginIndicator, {
|
|
1149
|
+
marginValue: (_props$itemProps2 = props.itemProps) === null || _props$itemProps2 === void 0 ? void 0 : _props$itemProps2.marginBottom,
|
|
1150
|
+
position: "bottom",
|
|
1151
|
+
tooltipInset: props.width === widths.full || props.customMargin
|
|
1152
|
+
}));
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
const WidgetEditorStateContext = createContext({});
|
|
1156
|
+
function useWidgetEditorState() {
|
|
1157
|
+
return useContext(WidgetEditorStateContext);
|
|
1158
|
+
}
|
|
1159
|
+
function SelectableWidgetDecorator({
|
|
1160
|
+
role,
|
|
1161
|
+
props,
|
|
1162
|
+
children
|
|
1163
|
+
}) {
|
|
1164
|
+
const {
|
|
1165
|
+
isSelected,
|
|
1166
|
+
select
|
|
1167
|
+
} = useEditorSelection(useMemo(() => ({
|
|
1168
|
+
id: role,
|
|
1169
|
+
type: 'widget'
|
|
1170
|
+
}), [role]));
|
|
1171
|
+
const value = useMemo(() => ({
|
|
1172
|
+
isSelected,
|
|
1173
|
+
select
|
|
1174
|
+
}), [isSelected, select]);
|
|
1175
|
+
return /*#__PURE__*/React.createElement(WidgetEditorStateContext.Provider, {
|
|
1176
|
+
value: value
|
|
1177
|
+
}, children);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
function WidgetConfigurationUpdateProvider({
|
|
1181
|
+
role,
|
|
1182
|
+
children
|
|
1183
|
+
}) {
|
|
1184
|
+
const dispatch = useEntryStateDispatch();
|
|
1185
|
+
const update = useCallback(configuration => {
|
|
1186
|
+
postUpdateWidgetMessage({
|
|
1187
|
+
role,
|
|
1188
|
+
configuration
|
|
1189
|
+
});
|
|
1190
|
+
updateWidgetConfiguration({
|
|
1191
|
+
dispatch,
|
|
1192
|
+
role,
|
|
1193
|
+
configuration
|
|
1194
|
+
});
|
|
1195
|
+
}, [dispatch, role]);
|
|
1196
|
+
return /*#__PURE__*/React.createElement(WidgetConfigurationUpdateContext.Provider, {
|
|
1197
|
+
value: update
|
|
1198
|
+
}, children);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
function WidgetDecorator(props) {
|
|
1202
|
+
return /*#__PURE__*/React.createElement(WidgetConfigurationUpdateProvider, {
|
|
1203
|
+
role: props.role
|
|
1204
|
+
}, props.children);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
var styles$9 = {"reference":"ActionButtons-module_reference__27uyP","buttons":"ActionButtons-module_buttons__1Hz2Z","button":"ActionButtons-module_button__1wzIk","iconOnly":"ActionButtons-module_iconOnly__1VEGK","floating":"ActionButtons-module_floating__18Epj","escaped":"ActionButtons-module_escaped__2M1PU","size-lg":"ActionButtons-module_size-lg__2b0Dw","position-outside":"ActionButtons-module_position-outside__1rpXW","position-outsideLeft":"ActionButtons-module_position-outsideLeft__3bo3f","position-outsideIndented":"ActionButtons-module_position-outsideIndented__2LZds","position-inside":"ActionButtons-module_position-inside__IDFN8","position-center":"ActionButtons-module_position-center__1ff85","position-topRight":"ActionButtons-module_position-topRight__3HrcE"};
|
|
1208
|
+
|
|
1209
|
+
function _extends$3() {
|
|
1210
|
+
_extends$3 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1211
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1212
|
+
var source = arguments[i];
|
|
1213
|
+
for (var key in source) {
|
|
1214
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1215
|
+
target[key] = source[key];
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
return target;
|
|
1220
|
+
};
|
|
1221
|
+
return _extends$3.apply(this, arguments);
|
|
1222
|
+
}
|
|
1223
|
+
var background = (({
|
|
1224
|
+
styles = {},
|
|
1225
|
+
...props
|
|
1226
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$3({
|
|
1227
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1228
|
+
viewBox: "0 0 448 512"
|
|
1229
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1230
|
+
d: "M64 32C28.7 32 0 60.7 0 96v200c0 35.3 28.7 64 64 64h208c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64z"
|
|
1231
|
+
}), /*#__PURE__*/React.createElement("path", {
|
|
1232
|
+
d: "M363.494 144v48H384c8.8 0 16 7.2 16 16v200c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16v-21.16h-48V408c0 35.3 28.7 64 64 64h208c35.3 0 64-28.7 64-64V208c0-35.3-28.7-64-64-64z"
|
|
1233
|
+
})));
|
|
1234
|
+
|
|
1235
|
+
function _extends$4() {
|
|
1236
|
+
_extends$4 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1237
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1238
|
+
var source = arguments[i];
|
|
1239
|
+
for (var key in source) {
|
|
1240
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1241
|
+
target[key] = source[key];
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return target;
|
|
1246
|
+
};
|
|
1247
|
+
return _extends$4.apply(this, arguments);
|
|
1248
|
+
}
|
|
1249
|
+
var foreground = (({
|
|
1250
|
+
styles = {},
|
|
1251
|
+
...props
|
|
1252
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$4({
|
|
1253
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1254
|
+
viewBox: "0 0 448 512"
|
|
1255
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1256
|
+
d: "M363.494 148v168.365c0 41.077-33.397 74.475-74.474 74.475H112V412c0 35.3 28.7 64 64 64h208c35.3 0 64-28.7 64-64V212c0-35.3-28.7-64-64-64z"
|
|
1257
|
+
}), /*#__PURE__*/React.createElement("path", {
|
|
1258
|
+
d: "M272 84c8.8 0 16 7.2 16 16v200c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16V100c0-8.8 7.2-16 16-16zM64 36C28.7 36 0 64.7 0 100v200c0 35.3 28.7 64 64 64h208c35.3 0 64-28.7 64-64V100c0-35.3-28.7-64-64-64z"
|
|
1259
|
+
})));
|
|
1260
|
+
|
|
1261
|
+
function _extends$5() {
|
|
1262
|
+
_extends$5 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1263
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1264
|
+
var source = arguments[i];
|
|
1265
|
+
for (var key in source) {
|
|
1266
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1267
|
+
target[key] = source[key];
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return target;
|
|
1272
|
+
};
|
|
1273
|
+
return _extends$5.apply(this, arguments);
|
|
1274
|
+
}
|
|
1275
|
+
var pencil = (({
|
|
1276
|
+
styles = {},
|
|
1277
|
+
...props
|
|
1278
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$5({
|
|
1279
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1280
|
+
viewBox: "0 0 512 512"
|
|
1281
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1282
|
+
d: "M410.3 231l11.3-11.3-33.9-33.9-62.1-62.1-33.9-33.9-11.3 11.3-22.6 22.6L58.6 322.9c-10.4 10.4-18 23.3-22.2 37.4L1 480.7c-2.5 8.4-.2 17.5 6.1 23.7s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2l199.2-199.2 22.6-22.7zM160 399.4l-9.1 22.7c-4 3.1-8.5 5.4-13.3 6.9l-78.2 23 23-78.1c1.4-4.9 3.8-9.4 6.9-13.3l22.7-9.1v32c0 8.8 7.2 16 16 16h32zM362.7 18.7l-14.4 14.5-22.6 22.6-11.4 11.3 33.9 33.9 62.1 62.1 33.9 33.9 11.3-11.3 22.6-22.6 14.5-14.5c25-25 25-65.5 0-90.5l-39.3-39.4c-25-25-65.5-25-90.5 0zm-47.4 168l-144 144c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6l144-144c6.2-6.2 16.4-6.2 22.6 0s6.2 16.4 0 22.6z"
|
|
1283
|
+
})));
|
|
1284
|
+
|
|
1285
|
+
function _extends$6() {
|
|
1286
|
+
_extends$6 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1287
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1288
|
+
var source = arguments[i];
|
|
1289
|
+
for (var key in source) {
|
|
1290
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1291
|
+
target[key] = source[key];
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
return target;
|
|
1296
|
+
};
|
|
1297
|
+
return _extends$6.apply(this, arguments);
|
|
1298
|
+
}
|
|
1299
|
+
var LinkIcon = (({
|
|
1300
|
+
styles = {},
|
|
1301
|
+
...props
|
|
1302
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$6({
|
|
1303
|
+
"aria-hidden": "true",
|
|
1304
|
+
"data-prefix": "fas",
|
|
1305
|
+
"data-icon": "link",
|
|
1306
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-link"] || "fa-link") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
1307
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1308
|
+
viewBox: "0 0 512 512"
|
|
1309
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1310
|
+
fill: "currentColor",
|
|
1311
|
+
d: "M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 01-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0120.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0020.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 00-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"
|
|
1312
|
+
})));
|
|
1313
|
+
|
|
1314
|
+
function _extends$7() {
|
|
1315
|
+
_extends$7 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1316
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1317
|
+
var source = arguments[i];
|
|
1318
|
+
for (var key in source) {
|
|
1319
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1320
|
+
target[key] = source[key];
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
return target;
|
|
1325
|
+
};
|
|
1326
|
+
return _extends$7.apply(this, arguments);
|
|
1327
|
+
}
|
|
1328
|
+
var unlink = (({
|
|
1329
|
+
styles = {},
|
|
1330
|
+
...props
|
|
1331
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$7({
|
|
1332
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1333
|
+
viewBox: "0 0 512 512",
|
|
1334
|
+
"aria-hidden": "true"
|
|
1335
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1336
|
+
d: "M360 0c-39-.001-78 14.8-107 44.4L185 112l-1 1 57 56s1 0 1-1l67-67c28-28.2 74-28.1 102 1 28 28 27 73-1 101l-13 14c-4 4-6 10-4 16 6 17 9 35 10 53 1 14 18 20 27 11l38-38c59-59 59-155 0-214.6C438 14.8 399 .001 360 0zm-63 165c-4 0-8 2-11 5l-22 21v1l107 107c2-41-13-82-44-114a152 152 0 00-21-17c-3-2-6-3-9-3zM93.3 211c-4.1 0-8.4 1-11.7 4l-37.1 38c-59.3 59-59.3 155 0 215C104 527 200 527 259 468l68-68v-1l-56-56s-1 0-1 1l-67 67c-28 28-74 28-102-1-28.2-28-27.4-73 1-101l13-14c4-4 6-10 4-16-6-17-10-35-10-53 0-9-8-15-15.7-15zm47.7 2c-2 41 13 82 44 114a152 152 0 0021 17c6 4 15 4 20-2l22-21v-1L141 213z"
|
|
1337
|
+
}), /*#__PURE__*/React.createElement("path", {
|
|
1338
|
+
stroke: "#000",
|
|
1339
|
+
strokeWidth: "68.787",
|
|
1340
|
+
strokeLinecap: "round",
|
|
1341
|
+
d: "M64 64l384 384"
|
|
1342
|
+
})));
|
|
1343
|
+
|
|
1344
|
+
const icons = {
|
|
1345
|
+
background,
|
|
1346
|
+
foreground,
|
|
1347
|
+
link: LinkIcon,
|
|
1348
|
+
pencil,
|
|
1349
|
+
unlink
|
|
1350
|
+
};
|
|
1351
|
+
function ActionButtons({
|
|
1352
|
+
buttons,
|
|
1353
|
+
position,
|
|
1354
|
+
portal,
|
|
1355
|
+
floatingStrategy,
|
|
1356
|
+
size = 'md'
|
|
1357
|
+
}) {
|
|
1358
|
+
var _middlewareData$hide;
|
|
1359
|
+
const iconSize = size === 'md' ? 15 : 20;
|
|
1360
|
+
const {
|
|
1361
|
+
refs,
|
|
1362
|
+
floatingStyles,
|
|
1363
|
+
middlewareData
|
|
1364
|
+
} = useFloating({
|
|
1365
|
+
strategy: floatingStrategy,
|
|
1366
|
+
placement: position === 'center' ? 'bottom' : position === 'inside' ? 'top-end' : position === 'outsideLeft' ? 'bottom-start' : position === 'topRight' ? 'top-end' : 'bottom-end',
|
|
1367
|
+
middleware: portal && [hide({
|
|
1368
|
+
strategy: 'escaped'
|
|
1369
|
+
}), shift({
|
|
1370
|
+
elementContext: 'reference'
|
|
1371
|
+
})],
|
|
1372
|
+
whileElementsMounted: autoUpdate
|
|
1373
|
+
});
|
|
1374
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
1375
|
+
className: classNames(styles$9.reference, styles$9[`position-${position}`]),
|
|
1376
|
+
ref: refs.setReference
|
|
1377
|
+
}, /*#__PURE__*/React.createElement(Portal, {
|
|
1378
|
+
enabled: !!portal,
|
|
1379
|
+
aboveNavigationWidgets: portal === 'aboveNavigationWidgets'
|
|
1380
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1381
|
+
ref: refs.setFloating,
|
|
1382
|
+
className: classNames(styles$9.floating, {
|
|
1383
|
+
[styles$9.escaped]: (_middlewareData$hide = middlewareData.hide) === null || _middlewareData$hide === void 0 ? void 0 : _middlewareData$hide.escaped
|
|
1384
|
+
}),
|
|
1385
|
+
style: floatingStyles
|
|
1386
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1387
|
+
className: styles$9.buttons
|
|
1388
|
+
}, buttons.map(({
|
|
1389
|
+
icon,
|
|
1390
|
+
text,
|
|
1391
|
+
onClick,
|
|
1392
|
+
iconOnly
|
|
1393
|
+
}, index) => {
|
|
1394
|
+
const Icon = icons[icon];
|
|
1395
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
1396
|
+
key: index,
|
|
1397
|
+
className: classNames(styles$9.button, styles$9[`size-${size}`], {
|
|
1398
|
+
[styles$9.iconOnly]: iconOnly
|
|
1399
|
+
}),
|
|
1400
|
+
onClick: onClick,
|
|
1401
|
+
title: iconOnly ? text : undefined,
|
|
1402
|
+
"aria-label": iconOnly ? text : undefined
|
|
1403
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
1404
|
+
width: iconSize,
|
|
1405
|
+
height: iconSize
|
|
1406
|
+
}), !iconOnly && text);
|
|
1407
|
+
})))));
|
|
1408
|
+
}
|
|
1409
|
+
function Portal({
|
|
1410
|
+
enabled,
|
|
1411
|
+
aboveNavigationWidgets,
|
|
1412
|
+
children
|
|
1413
|
+
}) {
|
|
1414
|
+
const floatingPortalRoot = useFloatingPortalRoot();
|
|
1415
|
+
if (enabled) {
|
|
1416
|
+
return /*#__PURE__*/React.createElement(FloatingPortal, {
|
|
1417
|
+
id: aboveNavigationWidgets ? 'floating-ui-above-navigation-widgets' : undefined,
|
|
1418
|
+
root: floatingPortalRoot
|
|
1419
|
+
}, children);
|
|
1420
|
+
} else {
|
|
1421
|
+
return children;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
function ActionButton({
|
|
1426
|
+
icon,
|
|
1427
|
+
text,
|
|
1428
|
+
onClick,
|
|
1429
|
+
iconOnly,
|
|
1430
|
+
...rest
|
|
1431
|
+
}) {
|
|
1432
|
+
return /*#__PURE__*/React.createElement(ActionButtons, Object.assign({}, rest, {
|
|
1433
|
+
buttons: [{
|
|
1434
|
+
icon,
|
|
1435
|
+
text,
|
|
1436
|
+
onClick,
|
|
1437
|
+
iconOnly
|
|
1438
|
+
}]
|
|
1439
|
+
}));
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
function BackdropDecorator({
|
|
1443
|
+
backdrop,
|
|
1444
|
+
motifAreaState,
|
|
1445
|
+
children
|
|
1446
|
+
}) {
|
|
1447
|
+
var _backdrop$contentElem, _backdrop$contentElem2;
|
|
1448
|
+
const {
|
|
1449
|
+
t
|
|
1450
|
+
} = useI18n({
|
|
1451
|
+
locale: 'ui'
|
|
1452
|
+
});
|
|
1453
|
+
const {
|
|
1454
|
+
isSelected: isSectionSelected,
|
|
1455
|
+
select: selectSection
|
|
1456
|
+
} = useEditorSelection({
|
|
1457
|
+
id: (_backdrop$contentElem = backdrop.contentElement) === null || _backdrop$contentElem === void 0 ? void 0 : _backdrop$contentElem.sectionId,
|
|
1458
|
+
type: 'sectionSettings'
|
|
1459
|
+
});
|
|
1460
|
+
const {
|
|
1461
|
+
isSelected: isBackdropElementSelected,
|
|
1462
|
+
select: selectBackdropElement
|
|
1463
|
+
} = useEditorSelection({
|
|
1464
|
+
id: (_backdrop$contentElem2 = backdrop.contentElement) === null || _backdrop$contentElem2 === void 0 ? void 0 : _backdrop$contentElem2.id,
|
|
1465
|
+
type: 'contentElement'
|
|
1466
|
+
});
|
|
1467
|
+
const scrollToTarget = useScrollToTarget();
|
|
1468
|
+
let text, icon, handleClick;
|
|
1469
|
+
if (isBackdropElementSelected) {
|
|
1470
|
+
text = t('pageflow_scrolled.inline_editing.back_to_section');
|
|
1471
|
+
icon = 'foreground';
|
|
1472
|
+
handleClick = () => selectSection();
|
|
1473
|
+
} else if (backdrop.contentElement) {
|
|
1474
|
+
text = t('pageflow_scrolled.inline_editing.select_backdrop_content_element');
|
|
1475
|
+
icon = 'background';
|
|
1476
|
+
handleClick = () => {
|
|
1477
|
+
scrollToTarget({
|
|
1478
|
+
id: backdrop.contentElement.sectionId,
|
|
1479
|
+
align: 'start'
|
|
1480
|
+
});
|
|
1481
|
+
selectBackdropElement();
|
|
1482
|
+
};
|
|
1483
|
+
} else {
|
|
1484
|
+
return children;
|
|
1485
|
+
}
|
|
1486
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
1487
|
+
className: classNames(styles$1.wrapper, {
|
|
1488
|
+
[styles$1.visible]: isBackdropElementSelected || isSectionSelected
|
|
1489
|
+
}),
|
|
1490
|
+
style: {
|
|
1491
|
+
height: motifAreaState.paddingTop
|
|
1492
|
+
}
|
|
1493
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1494
|
+
className: styles$1.inner
|
|
1495
|
+
}, /*#__PURE__*/React.createElement(ActionButton, {
|
|
1496
|
+
size: "lg",
|
|
1497
|
+
position: "center",
|
|
1498
|
+
icon: icon,
|
|
1499
|
+
text: text,
|
|
1500
|
+
onClick: handleClick
|
|
1501
|
+
}))), children);
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
function BackgroundContentElementDecorator({
|
|
1505
|
+
contentElement,
|
|
1506
|
+
children
|
|
1507
|
+
}) {
|
|
1508
|
+
const {
|
|
1509
|
+
isSelected
|
|
1510
|
+
} = useEditorSelection({
|
|
1511
|
+
id: contentElement === null || contentElement === void 0 ? void 0 : contentElement.id,
|
|
1512
|
+
type: 'contentElement'
|
|
1513
|
+
});
|
|
1514
|
+
const {
|
|
1515
|
+
isSelected: isSectionSelected
|
|
1516
|
+
} = useEditorSelection({
|
|
1517
|
+
id: contentElement === null || contentElement === void 0 ? void 0 : contentElement.sectionId,
|
|
1518
|
+
type: 'sectionSettings'
|
|
1519
|
+
});
|
|
1520
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1521
|
+
style: {
|
|
1522
|
+
pointerEvents: isSelected || isSectionSelected ? 'auto' : 'none'
|
|
1523
|
+
}
|
|
1524
|
+
}, children);
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
function _extends$8() {
|
|
1528
|
+
_extends$8 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1529
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1530
|
+
var source = arguments[i];
|
|
1531
|
+
for (var key in source) {
|
|
1532
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1533
|
+
target[key] = source[key];
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
return target;
|
|
1538
|
+
};
|
|
1539
|
+
return _extends$8.apply(this, arguments);
|
|
1540
|
+
}
|
|
1541
|
+
var paddingTopIcon = (({
|
|
1542
|
+
styles = {},
|
|
1543
|
+
...props
|
|
1544
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$8({
|
|
1545
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1546
|
+
width: "18",
|
|
1547
|
+
height: "18",
|
|
1548
|
+
viewBox: "0 3 24 27",
|
|
1549
|
+
fill: "none",
|
|
1550
|
+
stroke: "currentColor",
|
|
1551
|
+
strokeWidth: "2",
|
|
1552
|
+
strokeLinecap: "round",
|
|
1553
|
+
strokeLinejoin: "round",
|
|
1554
|
+
className: (styles["lucide"] || "lucide") + " " + (styles["lucide-unfold-vertical-icon"] || "lucide-unfold-vertical-icon") + " " + (styles["lucide-unfold-vertical"] || "lucide-unfold-vertical")
|
|
1555
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1556
|
+
d: "M12 22v-6m-8-4H2m8 0H8m8 0h-2m8 0h-2m-5 7l-3 3-3-3"
|
|
1557
|
+
})));
|
|
1558
|
+
|
|
1559
|
+
function _extends$9() {
|
|
1560
|
+
_extends$9 = Object.assign ? Object.assign.bind() : function (target) {
|
|
1561
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
1562
|
+
var source = arguments[i];
|
|
1563
|
+
for (var key in source) {
|
|
1564
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1565
|
+
target[key] = source[key];
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
return target;
|
|
1570
|
+
};
|
|
1571
|
+
return _extends$9.apply(this, arguments);
|
|
1572
|
+
}
|
|
1573
|
+
var paddingBottomIcon = (({
|
|
1574
|
+
styles = {},
|
|
1575
|
+
...props
|
|
1576
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$9({
|
|
1577
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1578
|
+
width: "18",
|
|
1579
|
+
height: "18",
|
|
1580
|
+
viewBox: "0 -3 24 21",
|
|
1581
|
+
fill: "none",
|
|
1582
|
+
stroke: "currentColor",
|
|
1583
|
+
strokeWidth: "2",
|
|
1584
|
+
strokeLinecap: "round",
|
|
1585
|
+
strokeLinejoin: "round",
|
|
1586
|
+
className: (styles["lucide"] || "lucide") + " " + (styles["lucide-unfold-vertical-icon"] || "lucide-unfold-vertical-icon") + " " + (styles["lucide-unfold-vertical"] || "lucide-unfold-vertical")
|
|
1587
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
1588
|
+
d: "M12 8V2M4 12H2m8 0H8m8 0h-2m8 0h-2m-5-7l-3-3-3 3"
|
|
1589
|
+
})));
|
|
1590
|
+
|
|
1591
|
+
const paddingIcons = {
|
|
1592
|
+
top: paddingTopIcon,
|
|
1593
|
+
bottom: paddingBottomIcon
|
|
1594
|
+
};
|
|
1595
|
+
const scaleNames = {
|
|
1596
|
+
top: 'sectionPaddingTop',
|
|
1597
|
+
bottom: 'sectionPaddingBottom'
|
|
1598
|
+
};
|
|
1599
|
+
const scaleDefaultPropertyNames = {
|
|
1600
|
+
sectionPaddingTop: 'sectionDefaultPaddingTop',
|
|
1601
|
+
sectionPaddingBottom: 'sectionDefaultPaddingBottom'
|
|
1602
|
+
};
|
|
1603
|
+
function PaddingIndicator({
|
|
1604
|
+
section,
|
|
1605
|
+
motifAreaState,
|
|
1606
|
+
paddingValue,
|
|
1607
|
+
position,
|
|
1608
|
+
suppressed
|
|
1609
|
+
}) {
|
|
1610
|
+
const Icon = paddingIcons[position];
|
|
1611
|
+
const theme = useTheme();
|
|
1612
|
+
const {
|
|
1613
|
+
t
|
|
1614
|
+
} = useI18n({
|
|
1615
|
+
locale: 'ui'
|
|
1616
|
+
});
|
|
1617
|
+
const {
|
|
1618
|
+
isSelected: isSectionSelected
|
|
1619
|
+
} = useEditorSelection({
|
|
1620
|
+
id: section.id,
|
|
1621
|
+
type: 'sectionSettings'
|
|
1622
|
+
});
|
|
1623
|
+
const {
|
|
1624
|
+
isSelected: isPaddingSelected,
|
|
1625
|
+
select
|
|
1626
|
+
} = useEditorSelection({
|
|
1627
|
+
id: section.id,
|
|
1628
|
+
type: 'sectionPaddings',
|
|
1629
|
+
position
|
|
1630
|
+
});
|
|
1631
|
+
const motifPadding = (motifAreaState === null || motifAreaState === void 0 ? void 0 : motifAreaState.paddingTop) > 0;
|
|
1632
|
+
if (isSectionSelected || isPaddingSelected) {
|
|
1633
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1634
|
+
"aria-label": t(`pageflow_scrolled.inline_editing.edit_section_padding_${position}`),
|
|
1635
|
+
className: classNames(styles$4[`indicator-${position}`], {
|
|
1636
|
+
[styles$4.selected]: isPaddingSelected,
|
|
1637
|
+
[styles$4.motif]: motifPadding,
|
|
1638
|
+
[styles$4.none]: !motifPadding && (paddingValue === 'none' || suppressed)
|
|
1639
|
+
}),
|
|
1640
|
+
onClick: () => select()
|
|
1641
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1642
|
+
className: styles$4.tooltip
|
|
1643
|
+
}, /*#__PURE__*/React.createElement(Icon, null), getPaddingText()));
|
|
1644
|
+
} else {
|
|
1645
|
+
return null;
|
|
1646
|
+
}
|
|
1647
|
+
function getPaddingText() {
|
|
1648
|
+
var _theme$options, _theme$translations;
|
|
1649
|
+
if (motifPadding) {
|
|
1650
|
+
return t('pageflow_scrolled.inline_editing.expose_motif_area');
|
|
1651
|
+
}
|
|
1652
|
+
if (suppressed) {
|
|
1653
|
+
const key = position === 'top' ? 'pageflow_scrolled.inline_editing.padding_suppressed_before_full_width' : 'pageflow_scrolled.inline_editing.padding_suppressed_after_full_width';
|
|
1654
|
+
return t(key);
|
|
1655
|
+
}
|
|
1656
|
+
const scaleName = scaleNames[position];
|
|
1657
|
+
const scope = getAppearanceSectionScopeName(section.appearance);
|
|
1658
|
+
const scale = Scale({
|
|
1659
|
+
scaleName,
|
|
1660
|
+
themeProperties: ((_theme$options = theme.options) === null || _theme$options === void 0 ? void 0 : _theme$options.properties) || {},
|
|
1661
|
+
scaleTranslations: ((_theme$translations = theme.translations) === null || _theme$translations === void 0 ? void 0 : _theme$translations.scales) || {},
|
|
1662
|
+
defaultValuePropertyName: scaleDefaultPropertyNames[scaleName],
|
|
1663
|
+
scope
|
|
1664
|
+
});
|
|
1665
|
+
const value = paddingValue || scale.defaultValue;
|
|
1666
|
+
const index = scale.values.indexOf(value);
|
|
1667
|
+
return scale.texts[index];
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
function ForegroundDecorator({
|
|
1672
|
+
section,
|
|
1673
|
+
motifAreaState,
|
|
1674
|
+
sectionPadding,
|
|
1675
|
+
suppressedPaddings,
|
|
1676
|
+
children
|
|
1677
|
+
}) {
|
|
1678
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(PaddingIndicator, {
|
|
1679
|
+
section: section,
|
|
1680
|
+
motifAreaState: motifAreaState,
|
|
1681
|
+
paddingValue: sectionPadding === null || sectionPadding === void 0 ? void 0 : sectionPadding.paddingTop,
|
|
1682
|
+
suppressed: suppressedPaddings === null || suppressedPaddings === void 0 ? void 0 : suppressedPaddings.top,
|
|
1683
|
+
position: "top"
|
|
1684
|
+
}), children, /*#__PURE__*/React.createElement(PaddingIndicator, {
|
|
1685
|
+
section: section,
|
|
1686
|
+
paddingValue: sectionPadding === null || sectionPadding === void 0 ? void 0 : sectionPadding.paddingBottom,
|
|
1687
|
+
suppressed: suppressedPaddings === null || suppressedPaddings === void 0 ? void 0 : suppressedPaddings.bottom,
|
|
1688
|
+
position: "bottom"
|
|
1689
|
+
}));
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
var styles$a = {"container":"ContentElementInsertButton-module_container__3dvUS","hovered":"ContentElementInsertButton-module_hovered__3Pggi","button":"ContentElementInsertButton-module_button__2-eE2"};
|
|
1693
|
+
|
|
1694
|
+
function ContentElementInsertButton({
|
|
1695
|
+
onClick
|
|
1696
|
+
}) {
|
|
1697
|
+
const [hovered, setHovered] = useState();
|
|
1698
|
+
const {
|
|
1699
|
+
t
|
|
1700
|
+
} = useI18n({
|
|
1701
|
+
locale: 'ui'
|
|
1702
|
+
});
|
|
1703
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1704
|
+
className: classNames(styles$a.container, {
|
|
1705
|
+
[styles$a.hovered]: hovered
|
|
1706
|
+
})
|
|
1707
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
1708
|
+
className: styles$a.button,
|
|
1709
|
+
title: t('pageflow_scrolled.inline_editing.add_content_element'),
|
|
1710
|
+
onClick: onClick,
|
|
1711
|
+
onMouseDown: event => event.stopPropagation(),
|
|
1712
|
+
onMouseEnter: () => setHovered(true),
|
|
1713
|
+
onMouseLeave: () => setHovered(false)
|
|
1714
|
+
}, /*#__PURE__*/React.createElement(PlusIcon, {
|
|
1715
|
+
width: 15,
|
|
1716
|
+
height: 15,
|
|
1717
|
+
fill: "currentColor"
|
|
1718
|
+
})));
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
function LayoutWithPlaceholder(props) {
|
|
1722
|
+
const {
|
|
1723
|
+
isSelected
|
|
1724
|
+
} = useEditorSelection({
|
|
1725
|
+
id: props.sectionId,
|
|
1726
|
+
type: 'section'
|
|
1727
|
+
});
|
|
1728
|
+
const {
|
|
1729
|
+
isSelected: settingsSelected
|
|
1730
|
+
} = useEditorSelection({
|
|
1731
|
+
id: props.sectionId,
|
|
1732
|
+
type: 'sectionSettings'
|
|
1733
|
+
});
|
|
1734
|
+
const placeholder = isSelected || settingsSelected ? /*#__PURE__*/React.createElement(ContentElementInsertButton, {
|
|
1735
|
+
onClick: () => postInsertContentElementMessage({
|
|
1736
|
+
at: 'endOfSection',
|
|
1737
|
+
id: props.sectionId
|
|
1738
|
+
})
|
|
1739
|
+
}) : null;
|
|
1740
|
+
return /*#__PURE__*/React.createElement(LayoutWithoutInlineEditing, Object.assign({}, props, {
|
|
1741
|
+
placeholder: placeholder
|
|
1742
|
+
}));
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
const originalToSlateRange = ReactEditor.toSlateRange;
|
|
1746
|
+
ReactEditor.toSlateRange = function (editor, domRange) {
|
|
1747
|
+
try {
|
|
1748
|
+
return originalToSlateRange.apply(this, arguments);
|
|
1749
|
+
} catch (e) {
|
|
1750
|
+
if (e.message.startsWith('Cannot resolve a Slate point from DOM point') && domRange === window.getSelection() && editor.selection) {
|
|
1751
|
+
console.warn('Ignored "Cannot resolve a Slate point from DOM point" - selection outside editor');
|
|
1752
|
+
return editor.selection;
|
|
1753
|
+
}
|
|
1754
|
+
throw e;
|
|
1755
|
+
}
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
function useCachedValue(value, {
|
|
1759
|
+
defaultValue,
|
|
1760
|
+
onReset,
|
|
1761
|
+
onDebouncedChange,
|
|
1762
|
+
delay = 2000
|
|
1763
|
+
} = {}) {
|
|
1764
|
+
const [cachedValue, setCachedValue] = useState(value || defaultValue);
|
|
1765
|
+
const previousValue = useRef(value);
|
|
1766
|
+
useEffect(() => {
|
|
1767
|
+
if (previousValue.current !== value && value !== cachedValue) {
|
|
1768
|
+
onReset && onReset(value);
|
|
1769
|
+
setCachedValue(value);
|
|
1770
|
+
}
|
|
1771
|
+
}, [onReset, value, cachedValue]);
|
|
1772
|
+
useEffect(() => {
|
|
1773
|
+
previousValue.current = value;
|
|
1774
|
+
});
|
|
1775
|
+
const debouncedHandler = useDebouncedCallback(onDebouncedChange, delay);
|
|
1776
|
+
const setValue = useCallback(value => {
|
|
1777
|
+
setCachedValue(previousValue => {
|
|
1778
|
+
if (previousValue !== value) {
|
|
1779
|
+
debouncedHandler(value);
|
|
1780
|
+
}
|
|
1781
|
+
return value;
|
|
1782
|
+
});
|
|
1783
|
+
}, [debouncedHandler]);
|
|
1784
|
+
return [cachedValue, setValue];
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// Debounce callback even if the callback function changes across renders.
|
|
1788
|
+
function useDebouncedCallback(callback, delay) {
|
|
1789
|
+
const mostRecentCallback = useRef(null);
|
|
1790
|
+
const debouncedHandler = useRef(null);
|
|
1791
|
+
useEffect(() => {
|
|
1792
|
+
mostRecentCallback.current = callback;
|
|
1793
|
+
}, [callback]);
|
|
1794
|
+
useEffect(() => {
|
|
1795
|
+
debouncedHandler.current = debounce(value => {
|
|
1796
|
+
if (mostRecentCallback.current) {
|
|
1797
|
+
mostRecentCallback.current(value);
|
|
1798
|
+
}
|
|
1799
|
+
}, delay);
|
|
1800
|
+
return () => {
|
|
1801
|
+
debouncedHandler.current.flush();
|
|
1802
|
+
};
|
|
1803
|
+
}, [delay]);
|
|
1804
|
+
return useCallback((...args) => debouncedHandler.current(...args), []);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
var styles$b = {"placeholder":"TextPlaceholder-module_placeholder__sgVwx"};
|
|
1808
|
+
|
|
1809
|
+
function TextPlaceholder({
|
|
1810
|
+
text,
|
|
1811
|
+
visible,
|
|
1812
|
+
className
|
|
1813
|
+
}) {
|
|
1814
|
+
if (!text || !visible) {
|
|
1815
|
+
return null;
|
|
1816
|
+
}
|
|
1817
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1818
|
+
className: styles$b.placeholder
|
|
1819
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1820
|
+
className: className
|
|
1821
|
+
}, text));
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
function rangeOverlapsSelection(range, selection) {
|
|
1825
|
+
if (!range || !selection) return false;
|
|
1826
|
+
const selStart = Range.start(selection);
|
|
1827
|
+
const selEnd = Range.end(selection);
|
|
1828
|
+
const selStartBlock = selStart.path[0];
|
|
1829
|
+
let selEndBlock = selEnd.path[0];
|
|
1830
|
+
if (selEndBlock !== selStartBlock && selEnd.offset === 0) {
|
|
1831
|
+
selEndBlock -= 1;
|
|
1832
|
+
}
|
|
1833
|
+
const startBlock = Range.start(range).path[0];
|
|
1834
|
+
return selStartBlock <= startBlock && startBlock <= selEndBlock;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
// The cursor that comment marks are measured against, so that the badge
|
|
1838
|
+
// column and the highlight overlay agree on which of them the reviewer
|
|
1839
|
+
// has selected.
|
|
1840
|
+
//
|
|
1841
|
+
// Treats `editor.selection` as a live cursor only while the editor is
|
|
1842
|
+
// focused. After the user clicks away, slate-react's throttled
|
|
1843
|
+
// `selectionchange` listener can sync a clamped DOM cursor back into
|
|
1844
|
+
// `editor.selection`, which would otherwise pass as a selection without
|
|
1845
|
+
// there being one.
|
|
1846
|
+
//
|
|
1847
|
+
// Falls back to the start point of the highlighted thread's range, so
|
|
1848
|
+
// that its block keeps counting as selected once focus has drifted away
|
|
1849
|
+
// from the slate editor — following a comment from the sidebar leaves it
|
|
1850
|
+
// outside. Just the start point, not the full range, to stay consistent
|
|
1851
|
+
// with rangeOverlapsSelection, which anchors to range starts.
|
|
1852
|
+
function useOverlapSelection(highlightedRange) {
|
|
1853
|
+
const editor = useSlate();
|
|
1854
|
+
const editorSelection = ReactEditor.isFocused(editor) ? editor.selection : null;
|
|
1855
|
+
const fallbackPoint = highlightedRange && Range.start(highlightedRange);
|
|
1856
|
+
return editorSelection || fallbackPoint && {
|
|
1857
|
+
anchor: fallbackPoint,
|
|
1858
|
+
focus: fallbackPoint
|
|
1859
|
+
};
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
var styles$c = {"darkContentTextColor":"var(--theme-dark-content-text-color, #222)","lightContentTextColor":"var(--theme-light-content-text-color, #fff)","box":"BadgeColumn-module_box___7PO_","onDark":"BadgeColumn-module_onDark__3xkyl","onLight":"BadgeColumn-module_onLight__1xTpi"};
|
|
1863
|
+
|
|
1864
|
+
const noThreads = [];
|
|
1865
|
+
function BadgeColumn({
|
|
1866
|
+
highlights,
|
|
1867
|
+
highlightedRange,
|
|
1868
|
+
anchors
|
|
1869
|
+
}) {
|
|
1870
|
+
const editor = useSlate();
|
|
1871
|
+
|
|
1872
|
+
// The same for every badge, so resolved once here rather than per badge.
|
|
1873
|
+
const overlapSelection = useOverlapSelection(highlightedRange);
|
|
1874
|
+
return highlights.map(highlight => /*#__PURE__*/React.createElement(PositionedBadge, {
|
|
1875
|
+
key: highlight.key,
|
|
1876
|
+
editor: editor,
|
|
1877
|
+
highlight: highlight,
|
|
1878
|
+
overlapSelection: overlapSelection,
|
|
1879
|
+
anchors: anchors
|
|
1880
|
+
}));
|
|
1881
|
+
}
|
|
1882
|
+
function PositionedBadge({
|
|
1883
|
+
editor,
|
|
1884
|
+
highlight,
|
|
1885
|
+
overlapSelection,
|
|
1886
|
+
anchors
|
|
1887
|
+
}) {
|
|
1888
|
+
var _highlight$thread2;
|
|
1889
|
+
const {
|
|
1890
|
+
selected,
|
|
1891
|
+
highlightedThreadId,
|
|
1892
|
+
selectComments,
|
|
1893
|
+
selectThread
|
|
1894
|
+
} = useContentElementCommentSelection();
|
|
1895
|
+
const {
|
|
1896
|
+
alwaysShowComments
|
|
1897
|
+
} = useCommentDisplayFilter();
|
|
1898
|
+
const {
|
|
1899
|
+
refs,
|
|
1900
|
+
floatingStyles,
|
|
1901
|
+
hasAnchor
|
|
1902
|
+
} = useAnchoredFloating(highlight.key, anchors, {
|
|
1903
|
+
placement: 'left-start'
|
|
1904
|
+
});
|
|
1905
|
+
const threads = useMemo(() => highlight.thread ? [highlight.thread] : noThreads, [highlight.thread]);
|
|
1906
|
+
const unreadCount = useUnreadActivityCount(threads);
|
|
1907
|
+
const handleClick = useCallback(() => {
|
|
1908
|
+
var _highlight$thread;
|
|
1909
|
+
if (highlight.key === 'selection') {
|
|
1910
|
+
selectComments();
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
// Don't try to also clear the DOM selection here: calling
|
|
1915
|
+
// removeAllRanges fires a selectionchange that slate-react's
|
|
1916
|
+
// listener picks up and uses to overwrite editor.selection back
|
|
1917
|
+
// to null — undoing this Transforms.select and dropping the
|
|
1918
|
+
// selection rect. The visible text selection therefore lingers
|
|
1919
|
+
// on screen until the user's next interaction with the editor;
|
|
1920
|
+
// slate's internal state (which downstream consumers depend on)
|
|
1921
|
+
// stays correct.
|
|
1922
|
+
Transforms.select(editor, Range.start(highlight.range));
|
|
1923
|
+
selectThread((_highlight$thread = highlight.thread) === null || _highlight$thread === void 0 ? void 0 : _highlight$thread.id);
|
|
1924
|
+
}, [editor, highlight, selectComments, selectThread]);
|
|
1925
|
+
if (!hasAnchor) return null;
|
|
1926
|
+
const isHighlightedThread = !!highlight.thread && highlightedThreadId === highlight.thread.id;
|
|
1927
|
+
const isActive = isHighlightedThread || highlight.key === 'selection' && selected === 'newThread';
|
|
1928
|
+
const mode = isActive ? 'active' : rangeOverlapsSelection(highlight.range, overlapSelection) ? undefined : alwaysShowComments ? 'dot' : 'none';
|
|
1929
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1930
|
+
ref: refs.setFloating,
|
|
1931
|
+
className: styles$c.box,
|
|
1932
|
+
style: floatingStyles
|
|
1933
|
+
}, /*#__PURE__*/React.createElement(Badge, {
|
|
1934
|
+
counter: 1,
|
|
1935
|
+
mode: mode,
|
|
1936
|
+
resolved: !!((_highlight$thread2 = highlight.thread) === null || _highlight$thread2 === void 0 ? void 0 : _highlight$thread2.resolvedAt),
|
|
1937
|
+
unreadCount: unreadCount,
|
|
1938
|
+
onClick: handleClick
|
|
1939
|
+
}));
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
function useEffectiveSelection(editor, onChange) {
|
|
1943
|
+
const isDragging = useEditorDragging(editor);
|
|
1944
|
+
useEffect(() => {
|
|
1945
|
+
const {
|
|
1946
|
+
selection
|
|
1947
|
+
} = editor;
|
|
1948
|
+
if (isDragging || !selection || !ReactEditor.isFocused(editor) || Range.isCollapsed(selection) || Editor.string(editor, selection) === '') {
|
|
1949
|
+
onChange(null);
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
onChange(selection);
|
|
1953
|
+
}, [editor, editor.selection, isDragging, onChange]);
|
|
1954
|
+
}
|
|
1955
|
+
function useEditorDragging(editor) {
|
|
1956
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
1957
|
+
useEffect(() => {
|
|
1958
|
+
const editorEl = ReactEditor.toDOMNode(editor, editor);
|
|
1959
|
+
function handleMouseDown() {
|
|
1960
|
+
setIsDragging(true);
|
|
1961
|
+
function handleMouseUp() {
|
|
1962
|
+
// Selection sometimes only resets after mouseup has fired
|
|
1963
|
+
// when clicking inside an existing selection.
|
|
1964
|
+
setTimeout(() => setIsDragging(false), 10);
|
|
1965
|
+
}
|
|
1966
|
+
document.addEventListener('mouseup', handleMouseUp, {
|
|
1967
|
+
once: true
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
editorEl.addEventListener('mousedown', handleMouseDown);
|
|
1971
|
+
return () => editorEl.removeEventListener('mousedown', handleMouseDown);
|
|
1972
|
+
}, [editor]);
|
|
1973
|
+
return isDragging;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
function useStartNewThread(editor) {
|
|
1977
|
+
const {
|
|
1978
|
+
inlineComments
|
|
1979
|
+
} = useContentElementAttributes();
|
|
1980
|
+
const commentingEnabled = features.isEnabled('commenting') && inlineComments;
|
|
1981
|
+
const {
|
|
1982
|
+
selectNewThread
|
|
1983
|
+
} = useContentElementCommentSelection();
|
|
1984
|
+
if (!commentingEnabled) return null;
|
|
1985
|
+
return () => selectNewThread(editor.selection);
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
function PendingSelectionBadge({
|
|
1989
|
+
containerRef
|
|
1990
|
+
}) {
|
|
1991
|
+
const editor = useSlate();
|
|
1992
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
1993
|
+
const darkBackground = useDarkBackground();
|
|
1994
|
+
const startNewThread = useStartNewThread(editor);
|
|
1995
|
+
const {
|
|
1996
|
+
refs,
|
|
1997
|
+
floatingStyles
|
|
1998
|
+
} = useFloating({
|
|
1999
|
+
placement: 'left-start',
|
|
2000
|
+
middleware: [alignToContainerEdge(containerRef, {
|
|
2001
|
+
mainAxisOffset: 32
|
|
2002
|
+
})]
|
|
2003
|
+
});
|
|
2004
|
+
useEffectiveSelection(editor, useCallback(selection => {
|
|
2005
|
+
if (!selection) {
|
|
2006
|
+
setIsVisible(false);
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
const domRange = ReactEditor.toDOMRange(editor, selection);
|
|
2010
|
+
refs.setPositionReference({
|
|
2011
|
+
getBoundingClientRect: () => domRange.getBoundingClientRect(),
|
|
2012
|
+
getClientRects: () => domRange.getClientRects()
|
|
2013
|
+
});
|
|
2014
|
+
setIsVisible(true);
|
|
2015
|
+
}, [editor, refs]));
|
|
2016
|
+
if (!isVisible) return null;
|
|
2017
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
2018
|
+
ref: refs.setFloating,
|
|
2019
|
+
className: classNames(styles$c.box, darkBackground ? styles$c.onDark : styles$c.onLight),
|
|
2020
|
+
style: floatingStyles
|
|
2021
|
+
}, /*#__PURE__*/React.createElement(Badge, {
|
|
2022
|
+
counter: 0,
|
|
2023
|
+
mode: "icon",
|
|
2024
|
+
onClick: startNewThread
|
|
2025
|
+
}));
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
// Keeps a Slate `rangeRef` per comment thread alive so that ongoing
|
|
2029
|
+
// text edits stay reflected in the thread's effective subject range
|
|
2030
|
+
// without round-tripping through the server. When the upstream value
|
|
2031
|
+
// is replaced (e.g. after a structural shift applied by the editor),
|
|
2032
|
+
// `EditableText` calls `resetRangeRefs` from `useCachedValue`'s
|
|
2033
|
+
// `onReset`, which fires from an effect *before* `setCachedValue`
|
|
2034
|
+
// triggers the re-render in which Slate's `<Slate>` useMemo replaces
|
|
2035
|
+
// `editor.children` with the new value. So `resetRangeRefs` only
|
|
2036
|
+
// drops the stale refs and arms `pendingResyncRef`; the second effect
|
|
2037
|
+
// below consumes that flag on the next render — by which point
|
|
2038
|
+
// `editor.children` has flipped — and rebuilds against the new
|
|
2039
|
+
// content. Rebuilding inside `resetRangeRefs` would sync against the
|
|
2040
|
+
// still-old content and skip migrated threads whose new path doesn't
|
|
2041
|
+
// yet exist there.
|
|
2042
|
+
function useCommentRangeRefs(editor, threads) {
|
|
2043
|
+
const rangeRefsMap = useRef(new Map());
|
|
2044
|
+
const pendingResyncRef = useRef(false);
|
|
2045
|
+
const syncRangeRefs = useCallback(threads => {
|
|
2046
|
+
const map = rangeRefsMap.current;
|
|
2047
|
+
const currentIds = new Set(threads.map(t => t.id));
|
|
2048
|
+
for (const [id, rangeRef] of map) {
|
|
2049
|
+
if (!currentIds.has(id)) {
|
|
2050
|
+
rangeRef.unref();
|
|
2051
|
+
map.delete(id);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
for (const thread of threads) {
|
|
2055
|
+
if (!map.has(thread.id) && isValidRange(editor, thread.subjectRange)) {
|
|
2056
|
+
map.set(thread.id, Editor.rangeRef(editor, thread.subjectRange, {
|
|
2057
|
+
affinity: 'inward'
|
|
2058
|
+
}));
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
}, [editor]);
|
|
2062
|
+
useEffect(() => {
|
|
2063
|
+
syncRangeRefs(threads);
|
|
2064
|
+
}, [threads, syncRangeRefs]);
|
|
2065
|
+
useEffect(() => {
|
|
2066
|
+
const map = rangeRefsMap.current;
|
|
2067
|
+
return () => {
|
|
2068
|
+
for (const rangeRef of map.values()) {
|
|
2069
|
+
rangeRef.unref();
|
|
2070
|
+
}
|
|
2071
|
+
map.clear();
|
|
2072
|
+
};
|
|
2073
|
+
}, [editor]);
|
|
2074
|
+
useEffect(() => {
|
|
2075
|
+
if (pendingResyncRef.current) {
|
|
2076
|
+
pendingResyncRef.current = false;
|
|
2077
|
+
syncRangeRefs(threads);
|
|
2078
|
+
}
|
|
2079
|
+
});
|
|
2080
|
+
const resetRangeRefs = useCallback(() => {
|
|
2081
|
+
for (const rangeRef of rangeRefsMap.current.values()) {
|
|
2082
|
+
rangeRef.unref();
|
|
2083
|
+
}
|
|
2084
|
+
rangeRefsMap.current.clear();
|
|
2085
|
+
pendingResyncRef.current = true;
|
|
2086
|
+
}, []);
|
|
2087
|
+
const trackedThreads = threads.map(t => {
|
|
2088
|
+
const rangeRef = rangeRefsMap.current.get(t.id);
|
|
2089
|
+
return (rangeRef === null || rangeRef === void 0 ? void 0 : rangeRef.current) ? {
|
|
2090
|
+
...t,
|
|
2091
|
+
subjectRange: rangeRef.current
|
|
2092
|
+
} : t;
|
|
2093
|
+
});
|
|
2094
|
+
const getTrackedSubjectRanges = useCallback(() => {
|
|
2095
|
+
const ranges = {};
|
|
2096
|
+
threads.forEach(t => {
|
|
2097
|
+
const rangeRef = rangeRefsMap.current.get(t.id);
|
|
2098
|
+
if (rangeRef === null || rangeRef === void 0 ? void 0 : rangeRef.current) {
|
|
2099
|
+
ranges[t.id] = rangeRef.current;
|
|
2100
|
+
}
|
|
2101
|
+
});
|
|
2102
|
+
return ranges;
|
|
2103
|
+
}, [threads]);
|
|
2104
|
+
return {
|
|
2105
|
+
trackedThreads,
|
|
2106
|
+
resetRangeRefs,
|
|
2107
|
+
getTrackedSubjectRanges
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
function isValidRange(editor, range) {
|
|
2111
|
+
return range && Node$1.has(editor, range.anchor.path) && Node$1.has(editor, range.focus.path);
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
const noThreads$1 = [];
|
|
2115
|
+
|
|
2116
|
+
// Bundles all commenting-related state and render helpers for the
|
|
2117
|
+
// EditableText editor. Returns `enabled: false` when commenting is
|
|
2118
|
+
// disabled for the current content element; consumers can then skip
|
|
2119
|
+
// the commenting-specific decorate/BadgeColumn paths.
|
|
2120
|
+
function useCommenting(editor) {
|
|
2121
|
+
const {
|
|
2122
|
+
contentElementPermaId,
|
|
2123
|
+
inlineComments
|
|
2124
|
+
} = useContentElementAttributes();
|
|
2125
|
+
const enabled = features.isEnabled('commenting') && inlineComments;
|
|
2126
|
+
|
|
2127
|
+
// Track ranges for resolved threads too, so their subject ranges keep
|
|
2128
|
+
// following live edits and stay correct once a thread is reopened.
|
|
2129
|
+
// Resolved threads are merely hidden from the highlight overlay until
|
|
2130
|
+
// they become the highlighted thread (see `visibleThreads`).
|
|
2131
|
+
const elementThreads = useCommentThreads({
|
|
2132
|
+
subjectType: 'ContentElement',
|
|
2133
|
+
subjectId: contentElementPermaId
|
|
2134
|
+
});
|
|
2135
|
+
const threads = enabled ? elementThreads : noThreads$1;
|
|
2136
|
+
const {
|
|
2137
|
+
trackedThreads,
|
|
2138
|
+
resetRangeRefs,
|
|
2139
|
+
getTrackedSubjectRanges
|
|
2140
|
+
} = useCommentRangeRefs(editor, threads);
|
|
2141
|
+
const {
|
|
2142
|
+
anchors,
|
|
2143
|
+
registerAnchor
|
|
2144
|
+
} = useRangeAnchors();
|
|
2145
|
+
const {
|
|
2146
|
+
resolution
|
|
2147
|
+
} = useCommentDisplayFilter();
|
|
2148
|
+
const {
|
|
2149
|
+
highlightedThreadId,
|
|
2150
|
+
newThreadRange,
|
|
2151
|
+
selectThread
|
|
2152
|
+
} = useContentElementCommentSelection();
|
|
2153
|
+
|
|
2154
|
+
// Move the cursor into the thread's block before the handler selects
|
|
2155
|
+
// it, so `Selection`'s `cursorLeftHighlightedThreadBlock` does not
|
|
2156
|
+
// treat a pre-existing cursor as having left the comment and re-select
|
|
2157
|
+
// the content element, which would hide the highlight again. Routing
|
|
2158
|
+
// through the handler also reveals a resolved thread (via
|
|
2159
|
+
// `visibleThreads`) when it is selected.
|
|
2160
|
+
useSelectCommentThreadHandler({
|
|
2161
|
+
subjectType: 'ContentElement',
|
|
2162
|
+
subjectId: contentElementPermaId,
|
|
2163
|
+
getScrollTarget: useCallback(threadId => {
|
|
2164
|
+
const range = getTrackedSubjectRanges()[threadId];
|
|
2165
|
+
return range ? domElementAtRangeStart(editor, range) : null;
|
|
2166
|
+
}, [editor, getTrackedSubjectRanges]),
|
|
2167
|
+
beforeSelect: useCallback(threadId => {
|
|
2168
|
+
const range = getTrackedSubjectRanges()[threadId];
|
|
2169
|
+
if (range) {
|
|
2170
|
+
Transforms.select(editor, Range.start(range));
|
|
2171
|
+
}
|
|
2172
|
+
}, [editor, getTrackedSubjectRanges]),
|
|
2173
|
+
selectThread
|
|
2174
|
+
});
|
|
2175
|
+
|
|
2176
|
+
// Build highlights for all tracked threads, resolved ones included, so
|
|
2177
|
+
// the thread ids at the cursor (which scope the comments sidebar) cover
|
|
2178
|
+
// them too. Only `visibleHighlights` get a text overlay and a badge.
|
|
2179
|
+
const highlights = useCommentHighlights(trackedThreads, newThreadRange);
|
|
2180
|
+
const visibleHighlights = useMemo(() => highlights.filter(highlight => isVisible(highlight, {
|
|
2181
|
+
resolution,
|
|
2182
|
+
highlightedThreadId
|
|
2183
|
+
})), [highlights, resolution, highlightedThreadId]);
|
|
2184
|
+
|
|
2185
|
+
// Stands in for the cursor once focus has left the editor, for the
|
|
2186
|
+
// badges as much as for the overlay.
|
|
2187
|
+
const highlightedRange = useMemo(() => {
|
|
2188
|
+
var _visibleHighlights$fi;
|
|
2189
|
+
return (_visibleHighlights$fi = visibleHighlights.find(highlight => {
|
|
2190
|
+
var _highlight$thread;
|
|
2191
|
+
return ((_highlight$thread = highlight.thread) === null || _highlight$thread === void 0 ? void 0 : _highlight$thread.id) === highlightedThreadId;
|
|
2192
|
+
})) === null || _visibleHighlights$fi === void 0 ? void 0 : _visibleHighlights$fi.range;
|
|
2193
|
+
}, [visibleHighlights, highlightedThreadId]);
|
|
2194
|
+
const decorate = useMemo(() => enabled ? decorateCommentHighlights(editor, visibleHighlights) : null, [editor, visibleHighlights, enabled]);
|
|
2195
|
+
const withCommentHighlightDecoration = useCallback(({
|
|
2196
|
+
attributes,
|
|
2197
|
+
children,
|
|
2198
|
+
leaf
|
|
2199
|
+
}) => {
|
|
2200
|
+
if (leaf.commentHighlight) {
|
|
2201
|
+
children = /*#__PURE__*/React.createElement(HighlightSpan, {
|
|
2202
|
+
rangeKey: leaf.rangeKey,
|
|
2203
|
+
subjectRange: leaf.subjectRange,
|
|
2204
|
+
highlightedRange: highlightedRange,
|
|
2205
|
+
resolved: leaf.resolved
|
|
2206
|
+
}, children);
|
|
2207
|
+
}
|
|
2208
|
+
if (leaf.firstInRange) {
|
|
2209
|
+
children = /*#__PURE__*/React.createElement(RangeAnchor, {
|
|
2210
|
+
rangeKey: leaf.rangeKey,
|
|
2211
|
+
onRegister: registerAnchor
|
|
2212
|
+
}, children);
|
|
2213
|
+
}
|
|
2214
|
+
return {
|
|
2215
|
+
attributes,
|
|
2216
|
+
children,
|
|
2217
|
+
leaf
|
|
2218
|
+
};
|
|
2219
|
+
// `threads` and `newThreadRange` are included to invalidate this
|
|
2220
|
+
// callback (and the `renderLeaf` that wraps it) when decorations
|
|
2221
|
+
// change. Without that, slate-react's `MemoizedText` would skip
|
|
2222
|
+
// re-rendering leaves whose decorations changed because its memo
|
|
2223
|
+
// equality function does not compare `decorations`.
|
|
2224
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2225
|
+
}, [registerAnchor, contentElementPermaId, threads, newThreadRange, highlightedThreadId, highlightedRange, resolution]);
|
|
2226
|
+
return {
|
|
2227
|
+
enabled,
|
|
2228
|
+
highlights,
|
|
2229
|
+
visibleHighlights,
|
|
2230
|
+
highlightedRange,
|
|
2231
|
+
anchors,
|
|
2232
|
+
decorate,
|
|
2233
|
+
withCommentHighlightDecoration,
|
|
2234
|
+
resetRangeRefs,
|
|
2235
|
+
getTrackedSubjectRanges
|
|
2236
|
+
};
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
// The range of a thread being composed and the thread the reviewer picked
|
|
2240
|
+
// show even where the resolution filter would hide them.
|
|
2241
|
+
function isVisible({
|
|
2242
|
+
thread
|
|
2243
|
+
}, {
|
|
2244
|
+
resolution,
|
|
2245
|
+
highlightedThreadId
|
|
2246
|
+
}) {
|
|
2247
|
+
return !thread || thread.id === highlightedThreadId || resolution === 'all' || !thread.resolvedAt;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
// A resolved thread has no badge yet to scroll itself into view, so the
|
|
2251
|
+
// commented text is scrolled directly. The leaf DOM already exists, so
|
|
2252
|
+
// this resolves even before the highlight re-renders.
|
|
2253
|
+
function domElementAtRangeStart(editor, range) {
|
|
2254
|
+
try {
|
|
2255
|
+
const start = Range.start(range);
|
|
2256
|
+
const domRange = ReactEditor.toDOMRange(editor, {
|
|
2257
|
+
anchor: start,
|
|
2258
|
+
focus: start
|
|
2259
|
+
});
|
|
2260
|
+
const {
|
|
2261
|
+
startContainer
|
|
2262
|
+
} = domRange;
|
|
2263
|
+
return startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentElement;
|
|
2264
|
+
} catch (e) {
|
|
2265
|
+
// toDOMRange throws when the range is not currently rendered.
|
|
2266
|
+
return null;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
function HighlightSpan({
|
|
2270
|
+
rangeKey,
|
|
2271
|
+
subjectRange,
|
|
2272
|
+
highlightedRange,
|
|
2273
|
+
resolved,
|
|
2274
|
+
children
|
|
2275
|
+
}) {
|
|
2276
|
+
const threadId = parseInt(rangeKey, 10);
|
|
2277
|
+
const {
|
|
2278
|
+
selected,
|
|
2279
|
+
highlightedThreadId
|
|
2280
|
+
} = useContentElementCommentSelection();
|
|
2281
|
+
const {
|
|
2282
|
+
alwaysShowComments
|
|
2283
|
+
} = useCommentDisplayFilter();
|
|
2284
|
+
|
|
2285
|
+
// Comes through the slate context, which reaches this span on every
|
|
2286
|
+
// selection change even though the memoized leaf around it does not
|
|
2287
|
+
// re-render for one.
|
|
2288
|
+
const overlapSelection = useOverlapSelection(highlightedRange);
|
|
2289
|
+
const isSelected = selected === 'comments' && highlightedThreadId === threadId || rangeKey === 'selection' && selected === 'newThread';
|
|
2290
|
+
|
|
2291
|
+
// The question the badge column asks as well: what the reviewer has not
|
|
2292
|
+
// selected is what an uncluttered view leaves out.
|
|
2293
|
+
if (!alwaysShowComments && !isSelected && !rangeOverlapsSelection(subjectRange, overlapSelection)) {
|
|
2294
|
+
return children;
|
|
2295
|
+
}
|
|
2296
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
2297
|
+
className: classNames(commentHighlightStyles.highlight, {
|
|
2298
|
+
[commentHighlightStyles.resolved]: resolved,
|
|
2299
|
+
[commentHighlightStyles.selected]: isSelected && !resolved
|
|
2300
|
+
})
|
|
2301
|
+
}, children);
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
function withCustomInsertBreak(editor) {
|
|
2305
|
+
const {
|
|
2306
|
+
insertBreak
|
|
2307
|
+
} = editor;
|
|
2308
|
+
editor.insertBreak = function () {
|
|
2309
|
+
const {
|
|
2310
|
+
selection
|
|
2311
|
+
} = editor;
|
|
2312
|
+
if (selection && Range.isCollapsed(selection)) {
|
|
2313
|
+
const match = Editor.above(editor, {
|
|
2314
|
+
match: n => Editor.isBlock(editor, n)
|
|
2315
|
+
});
|
|
2316
|
+
if (match) {
|
|
2317
|
+
const [block, path] = match;
|
|
2318
|
+
if (Editor.isEnd(editor, selection.anchor, path) && block.type === 'heading') {
|
|
2319
|
+
Transforms.insertNodes(editor, {
|
|
2320
|
+
type: 'paragraph',
|
|
2321
|
+
children: [{
|
|
2322
|
+
text: ''
|
|
2323
|
+
}]
|
|
2324
|
+
});
|
|
2325
|
+
return;
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
insertBreak();
|
|
2330
|
+
};
|
|
2331
|
+
return editor;
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
var styles$d = {"linkTooltip":"LinkTooltip-module_linkTooltip__esBv0","thumbnail":"LinkTooltip-module_thumbnail__3Vzce","thumbnailClickMask":"LinkTooltip-module_thumbnailClickMask__3iSZw","newTab":"LinkTooltip-module_newTab__3uW7O","chapterNumber":"LinkTooltip-module_chapterNumber__YUvjI"};
|
|
2335
|
+
|
|
2336
|
+
function _extends$a() {
|
|
2337
|
+
_extends$a = Object.assign ? Object.assign.bind() : function (target) {
|
|
2338
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2339
|
+
var source = arguments[i];
|
|
2340
|
+
for (var key in source) {
|
|
2341
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2342
|
+
target[key] = source[key];
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
return target;
|
|
2347
|
+
};
|
|
2348
|
+
return _extends$a.apply(this, arguments);
|
|
2349
|
+
}
|
|
2350
|
+
var ExternalLinkIcon = (({
|
|
2351
|
+
styles = {},
|
|
2352
|
+
...props
|
|
2353
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$a({
|
|
2354
|
+
"aria-hidden": "true",
|
|
2355
|
+
"data-prefix": "fas",
|
|
2356
|
+
"data-icon": "external-link-alt",
|
|
2357
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-external-link-alt"] || "fa-external-link-alt") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
2358
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2359
|
+
viewBox: "0 0 512 512"
|
|
2360
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2361
|
+
fill: "currentColor",
|
|
2362
|
+
d: "M432 320h-32a16 16 0 00-16 16v112H64V128h144a16 16 0 0016-16V80a16 16 0 00-16-16H48a48 48 0 00-48 48v352a48 48 0 0048 48h352a48 48 0 0048-48V336a16 16 0 00-16-16zM488 0H360c-21.37 0-32.05 25.91-17 41l35.73 35.73L135 320.37a24 24 0 000 34L157.67 377a24 24 0 0034 0l243.61-243.68L471 169c15 15 41 4.5 41-17V24a24 24 0 00-24-24z"
|
|
2363
|
+
})));
|
|
2364
|
+
|
|
2365
|
+
const UpdateContext = createContext();
|
|
2366
|
+
function LinkTooltipProvider(props) {
|
|
2367
|
+
const update = useContext(UpdateContext);
|
|
2368
|
+
if (update) {
|
|
2369
|
+
return props.children;
|
|
2370
|
+
} else {
|
|
2371
|
+
return /*#__PURE__*/React.createElement(LinkTooltipProviderInner, props);
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
function LinkTooltipProviderInner({
|
|
2375
|
+
disabled,
|
|
2376
|
+
position,
|
|
2377
|
+
floatingStrategy,
|
|
2378
|
+
onClick,
|
|
2379
|
+
children,
|
|
2380
|
+
align = 'left',
|
|
2381
|
+
gap = 10
|
|
2382
|
+
}) {
|
|
2383
|
+
const storylineMode = useStorylineActivity();
|
|
2384
|
+
const [state, setState] = useState();
|
|
2385
|
+
const arrowRef = useRef();
|
|
2386
|
+
const {
|
|
2387
|
+
refs,
|
|
2388
|
+
floatingStyles,
|
|
2389
|
+
context: floatingContext
|
|
2390
|
+
} = useFloating({
|
|
2391
|
+
strategy: floatingStrategy,
|
|
2392
|
+
placement: `${position === 'below' ? 'bottom' : 'top'}${align === 'left' ? '-start' : ''}`,
|
|
2393
|
+
middleware: [offset(gap), shift(), arrow({
|
|
2394
|
+
element: arrowRef,
|
|
2395
|
+
padding: 10
|
|
2396
|
+
}), inline()],
|
|
2397
|
+
whileElementsMounted: autoUpdate
|
|
2398
|
+
});
|
|
2399
|
+
const update = useMemo(() => {
|
|
2400
|
+
let timeout;
|
|
2401
|
+
return {
|
|
2402
|
+
activate(href, openInNewTab, linkRef) {
|
|
2403
|
+
clearTimeout(timeout);
|
|
2404
|
+
timeout = null;
|
|
2405
|
+
refs.setReference(linkRef.current);
|
|
2406
|
+
setState({
|
|
2407
|
+
href,
|
|
2408
|
+
openInNewTab
|
|
2409
|
+
});
|
|
2410
|
+
},
|
|
2411
|
+
keep() {
|
|
2412
|
+
clearTimeout(timeout);
|
|
2413
|
+
timeout = null;
|
|
2414
|
+
},
|
|
2415
|
+
deactivate({
|
|
2416
|
+
delay = 200
|
|
2417
|
+
} = {}) {
|
|
2418
|
+
if (!timeout) {
|
|
2419
|
+
timeout = setTimeout(() => {
|
|
2420
|
+
timeout = null;
|
|
2421
|
+
setState(null);
|
|
2422
|
+
}, delay);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
};
|
|
2426
|
+
}, [refs]);
|
|
2427
|
+
useEffect(() => {
|
|
2428
|
+
if (storylineMode !== 'active') {
|
|
2429
|
+
update.deactivate({
|
|
2430
|
+
delay: 0
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
}, [storylineMode, update]);
|
|
2434
|
+
return /*#__PURE__*/React.createElement(UpdateContext.Provider, {
|
|
2435
|
+
value: update
|
|
2436
|
+
}, /*#__PURE__*/React.createElement(FloatingPortal, {
|
|
2437
|
+
root: useFloatingPortalRoot()
|
|
2438
|
+
}, /*#__PURE__*/React.createElement(LinkTooltip, {
|
|
2439
|
+
state: state,
|
|
2440
|
+
setFloating: refs.setFloating,
|
|
2441
|
+
floatingStyles: floatingStyles,
|
|
2442
|
+
floatingContext: floatingContext,
|
|
2443
|
+
arrowRef: arrowRef,
|
|
2444
|
+
onClick: onClick,
|
|
2445
|
+
disabled: disabled
|
|
2446
|
+
})), children);
|
|
2447
|
+
}
|
|
2448
|
+
function LinkPreview({
|
|
2449
|
+
disabled,
|
|
2450
|
+
href,
|
|
2451
|
+
openInNewTab,
|
|
2452
|
+
children,
|
|
2453
|
+
className
|
|
2454
|
+
}) {
|
|
2455
|
+
const {
|
|
2456
|
+
activate,
|
|
2457
|
+
deactivate
|
|
2458
|
+
} = useContext(UpdateContext);
|
|
2459
|
+
const ref = useRef();
|
|
2460
|
+
useEffect(() => {
|
|
2461
|
+
if (disabled) {
|
|
2462
|
+
deactivate({
|
|
2463
|
+
delay: 0
|
|
2464
|
+
});
|
|
2465
|
+
}
|
|
2466
|
+
}, [disabled, deactivate]);
|
|
2467
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
2468
|
+
ref: ref,
|
|
2469
|
+
className: className,
|
|
2470
|
+
onMouseEnter: () => !disabled && activate(href, openInNewTab, ref),
|
|
2471
|
+
onMouseLeave: () => !disabled && deactivate()
|
|
2472
|
+
}, children);
|
|
2473
|
+
}
|
|
2474
|
+
function LinkTooltip({
|
|
2475
|
+
disabled,
|
|
2476
|
+
setFloating,
|
|
2477
|
+
floatingStyles,
|
|
2478
|
+
floatingContext,
|
|
2479
|
+
arrowRef,
|
|
2480
|
+
onClick,
|
|
2481
|
+
state
|
|
2482
|
+
}) {
|
|
2483
|
+
const {
|
|
2484
|
+
keep,
|
|
2485
|
+
deactivate
|
|
2486
|
+
} = useContext(UpdateContext);
|
|
2487
|
+
if (disabled || !state || !state.href) {
|
|
2488
|
+
return null;
|
|
2489
|
+
}
|
|
2490
|
+
function handleClick(event) {
|
|
2491
|
+
event.stopPropagation();
|
|
2492
|
+
if (onClick) {
|
|
2493
|
+
onClick(event);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
2497
|
+
ref: setFloating,
|
|
2498
|
+
className: classNames(styles$d.linkTooltip),
|
|
2499
|
+
onClick: handleClick,
|
|
2500
|
+
onMouseEnter: keep,
|
|
2501
|
+
onMouseLeave: deactivate,
|
|
2502
|
+
style: floatingStyles
|
|
2503
|
+
}, /*#__PURE__*/React.createElement(FloatingArrow, {
|
|
2504
|
+
ref: arrowRef,
|
|
2505
|
+
context: floatingContext
|
|
2506
|
+
}), /*#__PURE__*/React.createElement(LinkDestination, {
|
|
2507
|
+
href: state.href,
|
|
2508
|
+
openInNewTab: state.openInNewTab
|
|
2509
|
+
}));
|
|
2510
|
+
}
|
|
2511
|
+
function LinkDestination({
|
|
2512
|
+
href,
|
|
2513
|
+
openInNewTab
|
|
2514
|
+
}) {
|
|
2515
|
+
if (href === null || href === void 0 ? void 0 : href.chapter) {
|
|
2516
|
+
return /*#__PURE__*/React.createElement(ChapterLinkDestination, {
|
|
2517
|
+
permaId: href.chapter
|
|
2518
|
+
});
|
|
2519
|
+
} else if (href === null || href === void 0 ? void 0 : href.section) {
|
|
2520
|
+
return /*#__PURE__*/React.createElement(SectionLinkDestination, {
|
|
2521
|
+
permaId: href.section
|
|
2522
|
+
});
|
|
2523
|
+
} else if (href === null || href === void 0 ? void 0 : href.file) {
|
|
2524
|
+
return /*#__PURE__*/React.createElement(FileLinkDestination, {
|
|
2525
|
+
fileOptions: href.file
|
|
2526
|
+
});
|
|
2527
|
+
} else {
|
|
2528
|
+
return /*#__PURE__*/React.createElement(ExternalLinkDestination, {
|
|
2529
|
+
href: href,
|
|
2530
|
+
openInNewTab: openInNewTab
|
|
2531
|
+
});
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
function ChapterLinkDestination({
|
|
2535
|
+
permaId
|
|
2536
|
+
}) {
|
|
2537
|
+
const chapter = useChapter({
|
|
2538
|
+
permaId
|
|
2539
|
+
});
|
|
2540
|
+
const mainStoryline = useMainStoryline();
|
|
2541
|
+
const {
|
|
2542
|
+
t
|
|
2543
|
+
} = useI18n({
|
|
2544
|
+
locale: 'ui'
|
|
2545
|
+
});
|
|
2546
|
+
if (!chapter) {
|
|
2547
|
+
return /*#__PURE__*/React.createElement("span", null, t('pageflow_scrolled.inline_editing.link_tooltip.deleted_chapter'));
|
|
2548
|
+
}
|
|
2549
|
+
const isExcursion = mainStoryline && chapter.storylineId !== mainStoryline.id;
|
|
2550
|
+
if (isExcursion) {
|
|
2551
|
+
return /*#__PURE__*/React.createElement("a", {
|
|
2552
|
+
href: `#${chapter.chapterSlug}`,
|
|
2553
|
+
title: t('pageflow_scrolled.inline_editing.link_tooltip.visit_excursion')
|
|
2554
|
+
}, chapter.title ? t('pageflow_scrolled.inline_editing.link_tooltip.excursion_with_title', {
|
|
2555
|
+
title: chapter.title
|
|
2556
|
+
}) : t('pageflow_scrolled.inline_editing.link_tooltip.untitled_excursion'));
|
|
2557
|
+
}
|
|
2558
|
+
return /*#__PURE__*/React.createElement("a", {
|
|
2559
|
+
href: `#${chapter.chapterSlug}`,
|
|
2560
|
+
title: t('pageflow_scrolled.inline_editing.link_tooltip.visit_chapter')
|
|
2561
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
2562
|
+
className: styles$d.chapterNumber
|
|
2563
|
+
}, t('pageflow_scrolled.inline_editing.link_tooltip.chapter_number', {
|
|
2564
|
+
number: chapter.index + 1
|
|
2565
|
+
})), " ", chapter.title);
|
|
2566
|
+
}
|
|
2567
|
+
function SectionLinkDestination({
|
|
2568
|
+
permaId
|
|
2569
|
+
}) {
|
|
2570
|
+
const {
|
|
2571
|
+
t
|
|
2572
|
+
} = useI18n({
|
|
2573
|
+
locale: 'ui'
|
|
2574
|
+
});
|
|
2575
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
2576
|
+
className: styles$d.thumbnail
|
|
2577
|
+
}, /*#__PURE__*/React.createElement(SectionThumbnail, {
|
|
2578
|
+
sectionPermaId: permaId
|
|
2579
|
+
}), /*#__PURE__*/React.createElement("a", {
|
|
2580
|
+
href: `#section-${permaId}`,
|
|
2581
|
+
className: styles$d.thumbnailClickMask,
|
|
2582
|
+
title: t('pageflow_scrolled.inline_editing.link_tooltip.visit_section')
|
|
2583
|
+
}));
|
|
2584
|
+
}
|
|
2585
|
+
function ExternalLinkDestination({
|
|
2586
|
+
href,
|
|
2587
|
+
openInNewTab
|
|
2588
|
+
}) {
|
|
2589
|
+
const {
|
|
2590
|
+
t
|
|
2591
|
+
} = useI18n({
|
|
2592
|
+
locale: 'ui'
|
|
2593
|
+
});
|
|
2594
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("a", {
|
|
2595
|
+
href: href,
|
|
2596
|
+
target: "_blank",
|
|
2597
|
+
rel: "noopener noreferrer"
|
|
2598
|
+
}, href, /*#__PURE__*/React.createElement(ExternalLinkIcon, {
|
|
2599
|
+
width: 10,
|
|
2600
|
+
height: 10
|
|
2601
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
2602
|
+
className: styles$d.newTab
|
|
2603
|
+
}, openInNewTab ? t('pageflow_scrolled.inline_editing.link_tooltip.opens_in_new_tab') : t('pageflow_scrolled.inline_editing.link_tooltip.opens_in_same_tab')));
|
|
2604
|
+
}
|
|
2605
|
+
function FileLinkDestination({
|
|
2606
|
+
fileOptions
|
|
2607
|
+
}) {
|
|
2608
|
+
const file = useDownloadableFile(fileOptions);
|
|
2609
|
+
const {
|
|
2610
|
+
t
|
|
2611
|
+
} = useI18n({
|
|
2612
|
+
locale: 'ui'
|
|
2613
|
+
});
|
|
2614
|
+
if (!file) {
|
|
2615
|
+
return /*#__PURE__*/React.createElement("span", null, t('pageflow_scrolled.inline_editing.link_tooltip.deleted_file'));
|
|
2616
|
+
}
|
|
2617
|
+
return /*#__PURE__*/React.createElement("a", {
|
|
2618
|
+
href: file.urls.download,
|
|
2619
|
+
target: "_blank",
|
|
2620
|
+
rel: "noopener noreferrer"
|
|
2621
|
+
}, file.displayName, /*#__PURE__*/React.createElement(ExternalLinkIcon, {
|
|
2622
|
+
width: 10,
|
|
2623
|
+
height: 10
|
|
2624
|
+
}));
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
function withLinks(editor) {
|
|
2628
|
+
const {
|
|
2629
|
+
isInline
|
|
2630
|
+
} = editor;
|
|
2631
|
+
editor.isInline = element => {
|
|
2632
|
+
return element.type === 'link' ? true : isInline(element);
|
|
2633
|
+
};
|
|
2634
|
+
return editor;
|
|
2635
|
+
}
|
|
2636
|
+
const renderElementWithLinkPreview = wrapRenderElementWithLinkPreview(renderElement);
|
|
2637
|
+
function wrapRenderElementWithLinkPreview(renderElement) {
|
|
2638
|
+
return function (options) {
|
|
2639
|
+
if (options.element.type === 'link') {
|
|
2640
|
+
return /*#__PURE__*/React.createElement(LinkPreview, {
|
|
2641
|
+
href: options.element.href,
|
|
2642
|
+
openInNewTab: options.element.openInNewTab
|
|
2643
|
+
}, renderElement(options));
|
|
2644
|
+
} else {
|
|
2645
|
+
return renderElement(options);
|
|
2646
|
+
}
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
// Used to render drop targets between paragraphs only when a content
|
|
2651
|
+
// element is currently being dragged over the element. `react-dnd`
|
|
2652
|
+
// causes "Update on unmounted component warning" when dropping an
|
|
2653
|
+
// element removes a drop target [1]. As a workaround, couple
|
|
2654
|
+
// rendering of drop targets to asynchronously updated state. That way
|
|
2655
|
+
// the drop target is only removed after element has been dropped.
|
|
2656
|
+
//
|
|
2657
|
+
// [1] https://github.com/react-dnd/react-dnd/issues/1573
|
|
2658
|
+
function useDropTargetsActive() {
|
|
2659
|
+
const [dropTargetsActive, setDropTargetsActive] = useState(false);
|
|
2660
|
+
const [{
|
|
2661
|
+
canDrop
|
|
2662
|
+
}, drop] = useDrop({
|
|
2663
|
+
accept: 'contentElement',
|
|
2664
|
+
collect: monitor => ({
|
|
2665
|
+
canDrop: monitor.canDrop() && monitor.isOver()
|
|
2666
|
+
})
|
|
2667
|
+
});
|
|
2668
|
+
useEffect(() => {
|
|
2669
|
+
if (canDrop) {
|
|
2670
|
+
setDropTargetsActive(true);
|
|
2671
|
+
} else {
|
|
2672
|
+
const timeout = setTimeout(() => {
|
|
2673
|
+
setDropTargetsActive(false);
|
|
2674
|
+
}, 10);
|
|
2675
|
+
return () => {
|
|
2676
|
+
clearTimeout(timeout);
|
|
2677
|
+
};
|
|
2678
|
+
}
|
|
2679
|
+
}, [canDrop]);
|
|
2680
|
+
return [dropTargetsActive, drop];
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
let abortPreviousCall;
|
|
2684
|
+
function useSelectLinkDestination() {
|
|
2685
|
+
return () => {
|
|
2686
|
+
return new Promise((resolve, reject) => {
|
|
2687
|
+
if (abortPreviousCall) {
|
|
2688
|
+
abortPreviousCall();
|
|
2689
|
+
}
|
|
2690
|
+
abortPreviousCall = () => {
|
|
2691
|
+
window.removeEventListener('message', receive);
|
|
2692
|
+
reject();
|
|
2693
|
+
};
|
|
2694
|
+
postSelectLinkDestinationMessage();
|
|
2695
|
+
window.addEventListener('message', receive);
|
|
2696
|
+
function receive(message) {
|
|
2697
|
+
if (window.location.href.indexOf(message.origin) === 0) {
|
|
2698
|
+
if (message.data.type === 'LINK_DESTINATION_SELECTED') {
|
|
2699
|
+
abortPreviousCall = null;
|
|
2700
|
+
window.removeEventListener('message', receive);
|
|
2701
|
+
resolve(message.data.payload);
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
});
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
const mutuallyExclusive = {
|
|
2710
|
+
sup: 'sub',
|
|
2711
|
+
sub: 'sup'
|
|
2712
|
+
};
|
|
2713
|
+
function toggleMark(editor, format) {
|
|
2714
|
+
const isActive = isMarkActive(editor, format);
|
|
2715
|
+
if (isActive) {
|
|
2716
|
+
Editor.removeMark(editor, format);
|
|
2717
|
+
} else {
|
|
2718
|
+
if (mutuallyExclusive[format] && isMarkActive(editor, mutuallyExclusive[format])) {
|
|
2719
|
+
Editor.removeMark(editor, mutuallyExclusive[format]);
|
|
2720
|
+
}
|
|
2721
|
+
Editor.addMark(editor, format, true);
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
function isMarkActive(editor, format) {
|
|
2725
|
+
const marks = Editor.marks(editor);
|
|
2726
|
+
return marks ? marks[format] === true : false;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
function _extends$b() {
|
|
2730
|
+
_extends$b = Object.assign ? Object.assign.bind() : function (target) {
|
|
2731
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2732
|
+
var source = arguments[i];
|
|
2733
|
+
for (var key in source) {
|
|
2734
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2735
|
+
target[key] = source[key];
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
return target;
|
|
2740
|
+
};
|
|
2741
|
+
return _extends$b.apply(this, arguments);
|
|
2742
|
+
}
|
|
2743
|
+
var BoldIcon = (({
|
|
2744
|
+
styles = {},
|
|
2745
|
+
...props
|
|
2746
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$b({
|
|
2747
|
+
"aria-hidden": "true",
|
|
2748
|
+
"data-prefix": "fas",
|
|
2749
|
+
"data-icon": "bold",
|
|
2750
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-bold"] || "fa-bold") + " " + (styles["fa-w-12"] || "fa-w-12"),
|
|
2751
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2752
|
+
viewBox: "0 0 384 512"
|
|
2753
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2754
|
+
fill: "currentColor",
|
|
2755
|
+
d: "M333.49 238a122 122 0 0027-65.21C367.87 96.49 308 32 233.42 32H34a16 16 0 00-16 16v48a16 16 0 0016 16h31.87v288H34a16 16 0 00-16 16v48a16 16 0 0016 16h209.32c70.8 0 134.14-51.75 141-122.4 4.74-48.45-16.39-92.06-50.83-119.6zM145.66 112h87.76a48 48 0 010 96h-87.76zm87.76 288h-87.76V288h87.76a56 56 0 010 112z"
|
|
2756
|
+
})));
|
|
2757
|
+
|
|
2758
|
+
function _extends$c() {
|
|
2759
|
+
_extends$c = Object.assign ? Object.assign.bind() : function (target) {
|
|
2760
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2761
|
+
var source = arguments[i];
|
|
2762
|
+
for (var key in source) {
|
|
2763
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2764
|
+
target[key] = source[key];
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
return target;
|
|
2769
|
+
};
|
|
2770
|
+
return _extends$c.apply(this, arguments);
|
|
2771
|
+
}
|
|
2772
|
+
var UnderlineIcon = (({
|
|
2773
|
+
styles = {},
|
|
2774
|
+
...props
|
|
2775
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$c({
|
|
2776
|
+
"aria-hidden": "true",
|
|
2777
|
+
"data-prefix": "fas",
|
|
2778
|
+
"data-icon": "underline",
|
|
2779
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-underline"] || "fa-underline") + " " + (styles["fa-w-14"] || "fa-w-14"),
|
|
2780
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2781
|
+
viewBox: "0 0 448 512"
|
|
2782
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2783
|
+
fill: "currentColor",
|
|
2784
|
+
d: "M32 64h32v160c0 88.22 71.78 160 160 160s160-71.78 160-160V64h32a16 16 0 0016-16V16a16 16 0 00-16-16H272a16 16 0 00-16 16v32a16 16 0 0016 16h32v160a80 80 0 01-160 0V64h32a16 16 0 0016-16V16a16 16 0 00-16-16H32a16 16 0 00-16 16v32a16 16 0 0016 16zm400 384H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16z"
|
|
2785
|
+
})));
|
|
2786
|
+
|
|
2787
|
+
function _extends$d() {
|
|
2788
|
+
_extends$d = Object.assign ? Object.assign.bind() : function (target) {
|
|
2789
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2790
|
+
var source = arguments[i];
|
|
2791
|
+
for (var key in source) {
|
|
2792
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2793
|
+
target[key] = source[key];
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
return target;
|
|
2798
|
+
};
|
|
2799
|
+
return _extends$d.apply(this, arguments);
|
|
2800
|
+
}
|
|
2801
|
+
var ItalicIcon = (({
|
|
2802
|
+
styles = {},
|
|
2803
|
+
...props
|
|
2804
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$d({
|
|
2805
|
+
"aria-hidden": "true",
|
|
2806
|
+
"data-prefix": "fas",
|
|
2807
|
+
"data-icon": "italic",
|
|
2808
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-italic"] || "fa-italic") + " " + (styles["fa-w-10"] || "fa-w-10"),
|
|
2809
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2810
|
+
viewBox: "0 0 320 512"
|
|
2811
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2812
|
+
fill: "currentColor",
|
|
2813
|
+
d: "M320 48v32a16 16 0 01-16 16h-62.76l-80 320H208a16 16 0 0116 16v32a16 16 0 01-16 16H16a16 16 0 01-16-16v-32a16 16 0 0116-16h62.76l80-320H112a16 16 0 01-16-16V48a16 16 0 0116-16h192a16 16 0 0116 16z"
|
|
2814
|
+
})));
|
|
2815
|
+
|
|
2816
|
+
function _extends$e() {
|
|
2817
|
+
_extends$e = Object.assign ? Object.assign.bind() : function (target) {
|
|
2818
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2819
|
+
var source = arguments[i];
|
|
2820
|
+
for (var key in source) {
|
|
2821
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2822
|
+
target[key] = source[key];
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
return target;
|
|
2827
|
+
};
|
|
2828
|
+
return _extends$e.apply(this, arguments);
|
|
2829
|
+
}
|
|
2830
|
+
var StrikethroughIcon = (({
|
|
2831
|
+
styles = {},
|
|
2832
|
+
...props
|
|
2833
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$e({
|
|
2834
|
+
"aria-hidden": "true",
|
|
2835
|
+
"data-prefix": "fas",
|
|
2836
|
+
"data-icon": "strikethrough",
|
|
2837
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-strikethrough"] || "fa-strikethrough") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
2838
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2839
|
+
viewBox: "0 0 512 512"
|
|
2840
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2841
|
+
fill: "currentColor",
|
|
2842
|
+
d: "M496 224H293.9l-87.17-26.83A43.55 43.55 0 01219.55 112h66.79A49.89 49.89 0 01331 139.58a16 16 0 0021.46 7.15l42.94-21.47a16 16 0 007.16-21.46l-.53-1A128 128 0 00287.51 32h-68a123.68 123.68 0 00-123 135.64c2 20.89 10.1 39.83 21.78 56.36H16a16 16 0 00-16 16v32a16 16 0 0016 16h480a16 16 0 0016-16v-32a16 16 0 00-16-16zm-180.24 96A43 43 0 01336 356.45 43.59 43.59 0 01292.45 400h-66.79A49.89 49.89 0 01181 372.42a16 16 0 00-21.46-7.15l-42.94 21.47a16 16 0 00-7.16 21.46l.53 1A128 128 0 00224.49 480h68a123.68 123.68 0 00123-135.64 114.25 114.25 0 00-5.34-24.36z"
|
|
2843
|
+
})));
|
|
2844
|
+
|
|
2845
|
+
function _extends$f() {
|
|
2846
|
+
_extends$f = Object.assign ? Object.assign.bind() : function (target) {
|
|
2847
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2848
|
+
var source = arguments[i];
|
|
2849
|
+
for (var key in source) {
|
|
2850
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2851
|
+
target[key] = source[key];
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
return target;
|
|
2856
|
+
};
|
|
2857
|
+
return _extends$f.apply(this, arguments);
|
|
2858
|
+
}
|
|
2859
|
+
var SubIcon = (({
|
|
2860
|
+
styles = {},
|
|
2861
|
+
...props
|
|
2862
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$f({
|
|
2863
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2864
|
+
viewBox: "0 0 512 512"
|
|
2865
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2866
|
+
d: "M32 64C14.3 64 0 78.3 0 96s14.3 32 32 32h15.3l89.6 128-89.6 128H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h32c10.4 0 20.2-5.1 26.2-13.6L176 311.8l85.8 122.6c6 8.6 15.8 13.6 26.2 13.6h32c17.7 0 32-14.3 32-32s-14.3-32-32-32h-15.3l-89.6-128 89.6-128H320c17.7 0 32-14.3 32-32s-14.3-32-32-32h-32c-10.4 0-20.2 5.1-26.2 13.6L176 200.2 90.2 77.6C84.2 69.1 74.4 64 64 64H32zm448 256c0-11.1-5.7-21.4-15.2-27.2s-21.2-6.4-31.1-1.4l-32 16c-15.8 7.9-22.2 27.1-14.3 42.9C393 361.5 404.3 368 416 368v80c-17.7 0-32 14.3-32 32s14.3 32 32 32h64c17.7 0 32-14.3 32-32s-14.3-32-32-32V320z"
|
|
2867
|
+
})));
|
|
2868
|
+
|
|
2869
|
+
function _extends$g() {
|
|
2870
|
+
_extends$g = Object.assign ? Object.assign.bind() : function (target) {
|
|
2871
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
2872
|
+
var source = arguments[i];
|
|
2873
|
+
for (var key in source) {
|
|
2874
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2875
|
+
target[key] = source[key];
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
return target;
|
|
2880
|
+
};
|
|
2881
|
+
return _extends$g.apply(this, arguments);
|
|
2882
|
+
}
|
|
2883
|
+
var SupIcon = (({
|
|
2884
|
+
styles = {},
|
|
2885
|
+
...props
|
|
2886
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$g({
|
|
2887
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2888
|
+
viewBox: "0 0 512 512"
|
|
2889
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
2890
|
+
d: "M480 32c0-11.1-5.7-21.4-15.2-27.2s-21.2-6.4-31.1-1.4l-32 16c-15.8 7.9-22.2 27.1-14.3 42.9C393 73.5 404.3 80 416 80v80c-17.7 0-32 14.3-32 32s14.3 32 32 32h64c17.7 0 32-14.3 32-32s-14.3-32-32-32V32zM32 64C14.3 64 0 78.3 0 96s14.3 32 32 32h15.3l89.6 128-89.6 128H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h32c10.4 0 20.2-5.1 26.2-13.6L176 311.8l85.8 122.6c6 8.6 15.8 13.6 26.2 13.6h32c17.7 0 32-14.3 32-32s-14.3-32-32-32h-15.3l-89.6-128 89.6-128H320c17.7 0 32-14.3 32-32s-14.3-32-32-32h-32c-10.4 0-20.2 5.1-26.2 13.6L176 200.2 90.2 77.6C84.2 69.1 74.4 64 64 64H32z"
|
|
2891
|
+
})));
|
|
2892
|
+
|
|
2893
|
+
function HoveringToolbar({
|
|
2894
|
+
children
|
|
2895
|
+
}) {
|
|
2896
|
+
const editor = useSlate();
|
|
2897
|
+
const {
|
|
2898
|
+
t
|
|
2899
|
+
} = useI18n({
|
|
2900
|
+
locale: 'ui'
|
|
2901
|
+
});
|
|
2902
|
+
const selectLinkDestination = useSelectLinkDestination();
|
|
2903
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
2904
|
+
const {
|
|
2905
|
+
refs,
|
|
2906
|
+
floatingStyles
|
|
2907
|
+
} = useFloating({
|
|
2908
|
+
placement: 'bottom-start',
|
|
2909
|
+
middleware: [offset(5), shift({
|
|
2910
|
+
crossAxis: true,
|
|
2911
|
+
padding: {
|
|
2912
|
+
left: 10,
|
|
2913
|
+
right: 10
|
|
2914
|
+
}
|
|
2915
|
+
})]
|
|
2916
|
+
});
|
|
2917
|
+
useEffectiveSelection(editor, useCallback(selection => {
|
|
2918
|
+
if (!selection) {
|
|
2919
|
+
setIsOpen(false);
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
const domRange = ReactEditor.toDOMRange(editor, selection);
|
|
2923
|
+
refs.setPositionReference({
|
|
2924
|
+
getBoundingClientRect: () => domRange.getBoundingClientRect(),
|
|
2925
|
+
getClientRects: () => domRange.getClientRects()
|
|
2926
|
+
});
|
|
2927
|
+
setIsOpen(true);
|
|
2928
|
+
}, [editor, refs]));
|
|
2929
|
+
const floatingPortalRoot = useFloatingPortalRoot();
|
|
2930
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, isOpen && /*#__PURE__*/React.createElement(FloatingPortal, {
|
|
2931
|
+
root: floatingPortalRoot
|
|
2932
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
2933
|
+
ref: refs.setFloating,
|
|
2934
|
+
style: floatingStyles
|
|
2935
|
+
}, renderToolbar$1(editor, t, selectLinkDestination))), children);
|
|
2936
|
+
}
|
|
2937
|
+
function renderToolbar$1(editor, t, selectLinkDestination) {
|
|
2938
|
+
const buttons = [{
|
|
2939
|
+
name: 'bold',
|
|
2940
|
+
text: t('pageflow_scrolled.inline_editing.formats.bold'),
|
|
2941
|
+
icon: BoldIcon
|
|
2942
|
+
}, {
|
|
2943
|
+
name: 'italic',
|
|
2944
|
+
text: t('pageflow_scrolled.inline_editing.formats.italic'),
|
|
2945
|
+
icon: ItalicIcon
|
|
2946
|
+
}, {
|
|
2947
|
+
name: 'underline',
|
|
2948
|
+
text: t('pageflow_scrolled.inline_editing.formats.underline'),
|
|
2949
|
+
icon: UnderlineIcon
|
|
2950
|
+
}, {
|
|
2951
|
+
name: 'strikethrough',
|
|
2952
|
+
text: t('pageflow_scrolled.inline_editing.formats.strikethrough'),
|
|
2953
|
+
icon: StrikethroughIcon
|
|
2954
|
+
}, {
|
|
2955
|
+
name: 'sub',
|
|
2956
|
+
text: t('pageflow_scrolled.inline_editing.formats.sub'),
|
|
2957
|
+
icon: SubIcon
|
|
2958
|
+
}, {
|
|
2959
|
+
name: 'sup',
|
|
2960
|
+
text: t('pageflow_scrolled.inline_editing.formats.sup'),
|
|
2961
|
+
icon: SupIcon
|
|
2962
|
+
}, {
|
|
2963
|
+
name: 'link',
|
|
2964
|
+
text: isButtonActive(editor, 'link') ? t('pageflow_scrolled.inline_editing.remove_link') : t('pageflow_scrolled.inline_editing.insert_link'),
|
|
2965
|
+
icon: LinkIcon
|
|
2966
|
+
}].map(button => ({
|
|
2967
|
+
...button,
|
|
2968
|
+
active: isButtonActive(editor, button.name)
|
|
2969
|
+
}));
|
|
2970
|
+
return /*#__PURE__*/React.createElement(Toolbar, {
|
|
2971
|
+
buttons: buttons,
|
|
2972
|
+
onButtonClick: name => handleButtonClick(editor, name, selectLinkDestination)
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
function handleButtonClick(editor, format, selectLinkDestination) {
|
|
2976
|
+
if (format === 'link') {
|
|
2977
|
+
if (isLinkActive(editor)) {
|
|
2978
|
+
unwrapLink(editor);
|
|
2979
|
+
} else {
|
|
2980
|
+
selectLinkDestination().then(({
|
|
2981
|
+
href,
|
|
2982
|
+
openInNewTab
|
|
2983
|
+
}) => {
|
|
2984
|
+
wrapLink(editor, href, openInNewTab);
|
|
2985
|
+
}, () => {});
|
|
2986
|
+
}
|
|
2987
|
+
} else {
|
|
2988
|
+
toggleMark(editor, format);
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
function isButtonActive(editor, format) {
|
|
2992
|
+
if (format === 'link') {
|
|
2993
|
+
return isLinkActive(editor);
|
|
2994
|
+
} else {
|
|
2995
|
+
return isMarkActive(editor, format);
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
function unwrapLink(editor) {
|
|
2999
|
+
Transforms.unwrapNodes(editor, {
|
|
3000
|
+
match: n => n.type === 'link'
|
|
3001
|
+
});
|
|
3002
|
+
}
|
|
3003
|
+
function wrapLink(editor, href, openInNewTab) {
|
|
3004
|
+
const link = {
|
|
3005
|
+
type: 'link',
|
|
3006
|
+
href,
|
|
3007
|
+
openInNewTab,
|
|
3008
|
+
children: []
|
|
3009
|
+
};
|
|
3010
|
+
Transforms.wrapNodes(editor, link, {
|
|
3011
|
+
split: true
|
|
3012
|
+
});
|
|
3013
|
+
Transforms.collapse(editor, {
|
|
3014
|
+
edge: 'end'
|
|
3015
|
+
});
|
|
3016
|
+
}
|
|
3017
|
+
function isLinkActive(editor) {
|
|
3018
|
+
const [link] = Editor.nodes(editor, {
|
|
3019
|
+
match: n => n.type === 'link'
|
|
3020
|
+
});
|
|
3021
|
+
return !!link;
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
var styles$e = {"container":"index-module_container__3dD9z","shy":"index-module_shy__KgWjc","selected":"index-module_selected__mE58y","selection":"index-module_selection__3dUiD"};
|
|
3025
|
+
|
|
3026
|
+
// True when the cursor's top-level block differs from the highlighted
|
|
3027
|
+
// thread's start block. Editing in the same block as the highlighted
|
|
3028
|
+
// thread should keep the highlight in place (so the comment can be
|
|
3029
|
+
// referenced while editing); only block changes mean the user moved
|
|
3030
|
+
// past the comment's anchor.
|
|
3031
|
+
function cursorLeftHighlightedThreadBlock({
|
|
3032
|
+
editor,
|
|
3033
|
+
highlightedThreadId,
|
|
3034
|
+
highlights
|
|
3035
|
+
}) {
|
|
3036
|
+
var _highlights$find;
|
|
3037
|
+
if (!highlightedThreadId || !highlights) {
|
|
3038
|
+
return false;
|
|
3039
|
+
}
|
|
3040
|
+
const highlightedRange = (_highlights$find = highlights.find(h => {
|
|
3041
|
+
var _h$thread;
|
|
3042
|
+
return ((_h$thread = h.thread) === null || _h$thread === void 0 ? void 0 : _h$thread.id) === highlightedThreadId;
|
|
3043
|
+
})) === null || _highlights$find === void 0 ? void 0 : _highlights$find.range;
|
|
3044
|
+
if (!highlightedRange) return false;
|
|
3045
|
+
return editor.selection.anchor.path[0] !== highlightedRange.anchor.path[0];
|
|
3046
|
+
}
|
|
3047
|
+
|
|
3048
|
+
// True when the cursor sits at a different range than the pending
|
|
3049
|
+
// new-thread range AND the editor is focused. The focus guard is
|
|
3050
|
+
// important: clicking the pending badge itself moves focus to the
|
|
3051
|
+
// portaled badge button and can drift editor.selection — but that
|
|
3052
|
+
// drift is not the user moving away from the new thread.
|
|
3053
|
+
function cursorMovedFromPendingNewThreadRange({
|
|
3054
|
+
editor,
|
|
3055
|
+
newThreadRange
|
|
3056
|
+
}) {
|
|
3057
|
+
if (!ReactEditor.isFocused(editor)) return false;
|
|
3058
|
+
return !Range.equals(editor.selection, newThreadRange);
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
function getUniformSelectedNode(editor, propertyName) {
|
|
3062
|
+
const currentNodeEntries = [...Editor.nodes(editor, {
|
|
3063
|
+
match: n => !!n.type,
|
|
3064
|
+
mode: 'highest'
|
|
3065
|
+
})];
|
|
3066
|
+
const values = [...new Set(currentNodeEntries.map(([node, path]) => node[propertyName]))];
|
|
3067
|
+
return values.length === 1 ? currentNodeEntries[0][0] : null;
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
function isBlockActive(editor, format) {
|
|
3071
|
+
const [match] = Editor.nodes(editor, {
|
|
3072
|
+
match: n => n.type === format
|
|
3073
|
+
});
|
|
3074
|
+
return !!match;
|
|
3075
|
+
}
|
|
3076
|
+
const listTypes = ['numbered-list', 'bulleted-list'];
|
|
3077
|
+
function toggleBlock(editor, format) {
|
|
3078
|
+
const isActive = isBlockActive(editor, format);
|
|
3079
|
+
const isList = listTypes.includes(format);
|
|
3080
|
+
Transforms.unwrapNodes(editor, {
|
|
3081
|
+
match: n => listTypes.includes(n.type),
|
|
3082
|
+
split: true
|
|
3083
|
+
});
|
|
3084
|
+
Transforms.setNodes(editor, {
|
|
3085
|
+
type: isActive ? 'paragraph' : isList ? 'list-item' : format
|
|
3086
|
+
});
|
|
3087
|
+
if (!isActive && isList) {
|
|
3088
|
+
const block = {
|
|
3089
|
+
type: format,
|
|
3090
|
+
children: [],
|
|
3091
|
+
...preserveColorAndTypographyVariant(editor)
|
|
3092
|
+
};
|
|
3093
|
+
Transforms.wrapNodes(editor, block);
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3096
|
+
function applyTypographyVariant(editor, variant) {
|
|
3097
|
+
applyProperties(editor, {
|
|
3098
|
+
variant
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
function applyTypographySize(editor, size) {
|
|
3102
|
+
applyProperties(editor, {
|
|
3103
|
+
size
|
|
3104
|
+
});
|
|
3105
|
+
}
|
|
3106
|
+
function applyColor(editor, color) {
|
|
3107
|
+
applyProperties(editor, {
|
|
3108
|
+
color
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
3111
|
+
function applyTextAlign(editor, textAlign) {
|
|
3112
|
+
applyProperties(editor, {
|
|
3113
|
+
textAlign: textAlign === 'justify' ? 'justify' : undefined
|
|
3114
|
+
});
|
|
3115
|
+
}
|
|
3116
|
+
function applyProperties(editor, properties) {
|
|
3117
|
+
Transforms.setNodes(editor, properties, {
|
|
3118
|
+
mode: 'highest'
|
|
3119
|
+
});
|
|
3120
|
+
applyPropertiesToListItems(editor, properties);
|
|
3121
|
+
}
|
|
3122
|
+
function applyPropertiesToListItems(editor, properties) {
|
|
3123
|
+
const lists = Editor.nodes(editor, {
|
|
3124
|
+
match: n => listTypes.includes(n.type)
|
|
3125
|
+
});
|
|
3126
|
+
for (const [, listPath] of lists) {
|
|
3127
|
+
const items = Editor.nodes(editor, {
|
|
3128
|
+
at: listPath,
|
|
3129
|
+
match: n => n.type === 'list-item'
|
|
3130
|
+
});
|
|
3131
|
+
for (const [, itemPath] of items) {
|
|
3132
|
+
Transforms.setNodes(editor, properties, {
|
|
3133
|
+
at: itemPath
|
|
3134
|
+
});
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
function preserveColorAndTypographyVariant(editor) {
|
|
3139
|
+
const nodeEntry = Editor.above(editor, {
|
|
3140
|
+
at: Range.start(editor.selection),
|
|
3141
|
+
match: n => !!n.type
|
|
3142
|
+
});
|
|
3143
|
+
const result = {};
|
|
3144
|
+
if (nodeEntry && nodeEntry[0].variant) {
|
|
3145
|
+
result.variant = nodeEntry[0].variant;
|
|
3146
|
+
}
|
|
3147
|
+
if (nodeEntry && nodeEntry[0].color) {
|
|
3148
|
+
result.color = nodeEntry[0].color;
|
|
3149
|
+
}
|
|
3150
|
+
return result;
|
|
3151
|
+
}
|
|
3152
|
+
function withBlockNormalization({
|
|
3153
|
+
onlyParagraphs
|
|
3154
|
+
}, editor) {
|
|
3155
|
+
if (!onlyParagraphs) {
|
|
3156
|
+
return editor;
|
|
3157
|
+
}
|
|
3158
|
+
const {
|
|
3159
|
+
normalizeNode
|
|
3160
|
+
} = editor;
|
|
3161
|
+
editor.normalizeNode = ([node, path]) => {
|
|
3162
|
+
if (path.length === 0) {
|
|
3163
|
+
for (const [child, childPath] of Node$1.children(editor, path)) {
|
|
3164
|
+
if (Element$1.isElement(child) && child.type !== 'paragraph') {
|
|
3165
|
+
Transforms.unwrapNodes(editor, {
|
|
3166
|
+
match: n => listTypes.includes(n.type),
|
|
3167
|
+
split: true,
|
|
3168
|
+
at: childPath
|
|
3169
|
+
});
|
|
3170
|
+
Transforms.setNodes(editor, {
|
|
3171
|
+
type: 'paragraph'
|
|
3172
|
+
}, {
|
|
3173
|
+
at: childPath
|
|
3174
|
+
});
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
return normalizeNode([node, path]);
|
|
3179
|
+
};
|
|
3180
|
+
return editor;
|
|
3181
|
+
}
|
|
3182
|
+
|
|
3183
|
+
function commentThreadIdsAtSelection(highlights, selection) {
|
|
3184
|
+
if (!selection) return [];
|
|
3185
|
+
return highlights.filter(h => h.thread && rangeOverlapsSelection(h.range, selection)).map(h => h.thread.id);
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3188
|
+
function computeBounds(editor) {
|
|
3189
|
+
if (!editor.selection) {
|
|
3190
|
+
return [0, 0];
|
|
3191
|
+
}
|
|
3192
|
+
const startPoint = Range.start(editor.selection);
|
|
3193
|
+
const endPoint = Range.end(editor.selection);
|
|
3194
|
+
const startPath = startPoint.path.slice(0, 1);
|
|
3195
|
+
let endPath = endPoint.path.slice(0, 1);
|
|
3196
|
+
if (!Path.equals(startPath, endPath) && endPoint.offset === 0) {
|
|
3197
|
+
endPath = Path.previous(endPath);
|
|
3198
|
+
}
|
|
3199
|
+
return [startPath[0], endPath[0]];
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
// Range to seed a new comment thread on the current slate selection.
|
|
3203
|
+
// When the selection is collapsed (just a cursor), expand to the full
|
|
3204
|
+
// surrounding top-level block so the new thread anchors to the whole
|
|
3205
|
+
// paragraph rather than a zero-width point.
|
|
3206
|
+
function newCommentThreadSubjectRange(editor) {
|
|
3207
|
+
if (!editor.selection) return undefined;
|
|
3208
|
+
if (Range.isCollapsed(editor.selection)) {
|
|
3209
|
+
const blockIdx = editor.selection.anchor.path[0];
|
|
3210
|
+
return {
|
|
3211
|
+
anchor: Editor.point(editor, [blockIdx], {
|
|
3212
|
+
edge: 'start'
|
|
3213
|
+
}),
|
|
3214
|
+
focus: Editor.point(editor, [blockIdx], {
|
|
3215
|
+
edge: 'end'
|
|
3216
|
+
})
|
|
3217
|
+
};
|
|
3218
|
+
}
|
|
3219
|
+
return editor.selection;
|
|
3220
|
+
}
|
|
3221
|
+
|
|
3222
|
+
function _extends$h() {
|
|
3223
|
+
_extends$h = Object.assign ? Object.assign.bind() : function (target) {
|
|
3224
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
3225
|
+
var source = arguments[i];
|
|
3226
|
+
for (var key in source) {
|
|
3227
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
3228
|
+
target[key] = source[key];
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
return target;
|
|
3233
|
+
};
|
|
3234
|
+
return _extends$h.apply(this, arguments);
|
|
3235
|
+
}
|
|
3236
|
+
var TextIcon = (({
|
|
3237
|
+
styles = {},
|
|
3238
|
+
...props
|
|
3239
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$h({
|
|
3240
|
+
"aria-hidden": "true",
|
|
3241
|
+
"data-prefix": "fas",
|
|
3242
|
+
"data-icon": "align-justify",
|
|
3243
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-align-justify"] || "fa-align-justify") + " " + (styles["fa-w-14"] || "fa-w-14"),
|
|
3244
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3245
|
+
viewBox: "0 0 448 512"
|
|
3246
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
3247
|
+
fill: "currentColor",
|
|
3248
|
+
d: "M432 416H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0-128H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0-128H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0-128H16A16 16 0 000 48v32a16 16 0 0016 16h416a16 16 0 0016-16V48a16 16 0 00-16-16z"
|
|
3249
|
+
})));
|
|
3250
|
+
|
|
3251
|
+
function _extends$i() {
|
|
3252
|
+
_extends$i = Object.assign ? Object.assign.bind() : function (target) {
|
|
3253
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
3254
|
+
var source = arguments[i];
|
|
3255
|
+
for (var key in source) {
|
|
3256
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
3257
|
+
target[key] = source[key];
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
return target;
|
|
3262
|
+
};
|
|
3263
|
+
return _extends$i.apply(this, arguments);
|
|
3264
|
+
}
|
|
3265
|
+
var HeadingIcon = (({
|
|
3266
|
+
styles = {},
|
|
3267
|
+
...props
|
|
3268
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$i({
|
|
3269
|
+
"aria-hidden": "true",
|
|
3270
|
+
"data-prefix": "fas",
|
|
3271
|
+
"data-icon": "heading",
|
|
3272
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-heading"] || "fa-heading") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
3273
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3274
|
+
viewBox: "0 0 512 512"
|
|
3275
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
3276
|
+
fill: "currentColor",
|
|
3277
|
+
d: "M448 96v320h32a16 16 0 0116 16v32a16 16 0 01-16 16H320a16 16 0 01-16-16v-32a16 16 0 0116-16h32V288H160v128h32a16 16 0 0116 16v32a16 16 0 01-16 16H32a16 16 0 01-16-16v-32a16 16 0 0116-16h32V96H32a16 16 0 01-16-16V48a16 16 0 0116-16h160a16 16 0 0116 16v32a16 16 0 01-16 16h-32v128h192V96h-32a16 16 0 01-16-16V48a16 16 0 0116-16h160a16 16 0 0116 16v32a16 16 0 01-16 16z"
|
|
3278
|
+
})));
|
|
3279
|
+
|
|
3280
|
+
function _extends$j() {
|
|
3281
|
+
_extends$j = Object.assign ? Object.assign.bind() : function (target) {
|
|
3282
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
3283
|
+
var source = arguments[i];
|
|
3284
|
+
for (var key in source) {
|
|
3285
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
3286
|
+
target[key] = source[key];
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
return target;
|
|
3291
|
+
};
|
|
3292
|
+
return _extends$j.apply(this, arguments);
|
|
3293
|
+
}
|
|
3294
|
+
var OlIcon = (({
|
|
3295
|
+
styles = {},
|
|
3296
|
+
...props
|
|
3297
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$j({
|
|
3298
|
+
"aria-hidden": "true",
|
|
3299
|
+
"data-prefix": "fas",
|
|
3300
|
+
"data-icon": "list-ol",
|
|
3301
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-list-ol"] || "fa-list-ol") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
3302
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3303
|
+
viewBox: "0 0 512 512"
|
|
3304
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
3305
|
+
fill: "currentColor",
|
|
3306
|
+
d: "M61.77 401l17.5-20.15a19.92 19.92 0 005.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 00-8 8v16a8 8 0 008 8h22.83a157.41 157.41 0 00-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 01-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 00-16 16v32a16 16 0 0016 16h320a16 16 0 0016-16v-32a16 16 0 00-16-16zm0-160H176a16 16 0 00-16 16v32a16 16 0 0016 16h320a16 16 0 0016-16V80a16 16 0 00-16-16zm0 320H176a16 16 0 00-16 16v32a16 16 0 0016 16h320a16 16 0 0016-16v-32a16 16 0 00-16-16zM16 160h64a8 8 0 008-8v-16a8 8 0 00-8-8H64V40a8 8 0 00-8-8H32a8 8 0 00-7.14 4.42l-8 16A8 8 0 0024 64h8v64H16a8 8 0 00-8 8v16a8 8 0 008 8zm-3.91 160H80a8 8 0 008-8v-16a8 8 0 00-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 019.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"
|
|
3307
|
+
})));
|
|
3308
|
+
|
|
3309
|
+
function _extends$k() {
|
|
3310
|
+
_extends$k = Object.assign ? Object.assign.bind() : function (target) {
|
|
3311
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
3312
|
+
var source = arguments[i];
|
|
3313
|
+
for (var key in source) {
|
|
3314
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
3315
|
+
target[key] = source[key];
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
return target;
|
|
3320
|
+
};
|
|
3321
|
+
return _extends$k.apply(this, arguments);
|
|
3322
|
+
}
|
|
3323
|
+
var UlIcon = (({
|
|
3324
|
+
styles = {},
|
|
3325
|
+
...props
|
|
3326
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$k({
|
|
3327
|
+
"aria-hidden": "true",
|
|
3328
|
+
"data-prefix": "fas",
|
|
3329
|
+
"data-icon": "list-ul",
|
|
3330
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-list-ul"] || "fa-list-ul") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
3331
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3332
|
+
viewBox: "0 0 512 512"
|
|
3333
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
3334
|
+
fill: "currentColor",
|
|
3335
|
+
d: "M48 48a48 48 0 1048 48 48 48 0 00-48-48zm0 160a48 48 0 1048 48 48 48 0 00-48-48zm0 160a48 48 0 1048 48 48 48 0 00-48-48zm448 16H176a16 16 0 00-16 16v32a16 16 0 0016 16h320a16 16 0 0016-16v-32a16 16 0 00-16-16zm0-320H176a16 16 0 00-16 16v32a16 16 0 0016 16h320a16 16 0 0016-16V80a16 16 0 00-16-16zm0 160H176a16 16 0 00-16 16v32a16 16 0 0016 16h320a16 16 0 0016-16v-32a16 16 0 00-16-16z"
|
|
3336
|
+
})));
|
|
3337
|
+
|
|
3338
|
+
function _extends$l() {
|
|
3339
|
+
_extends$l = Object.assign ? Object.assign.bind() : function (target) {
|
|
3340
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
3341
|
+
var source = arguments[i];
|
|
3342
|
+
for (var key in source) {
|
|
3343
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
3344
|
+
target[key] = source[key];
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
}
|
|
3348
|
+
return target;
|
|
3349
|
+
};
|
|
3350
|
+
return _extends$l.apply(this, arguments);
|
|
3351
|
+
}
|
|
3352
|
+
var QuoteIcon = (({
|
|
3353
|
+
styles = {},
|
|
3354
|
+
...props
|
|
3355
|
+
}) => /*#__PURE__*/React.createElement("svg", _extends$l({
|
|
3356
|
+
"aria-hidden": "true",
|
|
3357
|
+
"data-prefix": "fas",
|
|
3358
|
+
"data-icon": "quote-right",
|
|
3359
|
+
className: (styles["svg-inline--fa"] || "svg-inline--fa") + " " + (styles["fa-quote-right"] || "fa-quote-right") + " " + (styles["fa-w-16"] || "fa-w-16"),
|
|
3360
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3361
|
+
viewBox: "0 0 512 512"
|
|
3362
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
3363
|
+
fill: "currentColor",
|
|
3364
|
+
d: "M464 32H336c-26.5 0-48 21.5-48 48v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48zm-288 0H48C21.5 32 0 53.5 0 80v128c0 26.5 21.5 48 48 48h80v64c0 35.3-28.7 64-64 64h-8c-13.3 0-24 10.7-24 24v48c0 13.3 10.7 24 24 24h8c88.4 0 160-71.6 160-160V80c0-26.5-21.5-48-48-48z"
|
|
3365
|
+
})));
|
|
3366
|
+
|
|
3367
|
+
function Selection(props) {
|
|
3368
|
+
const editor = useSlate();
|
|
3369
|
+
const {
|
|
3370
|
+
t
|
|
3371
|
+
} = useI18n({
|
|
3372
|
+
locale: 'ui'
|
|
3373
|
+
});
|
|
3374
|
+
const ref = useRef();
|
|
3375
|
+
const outerRef = useRef();
|
|
3376
|
+
const innerRef = useRef();
|
|
3377
|
+
const boundsRef = useRef();
|
|
3378
|
+
const lastRangeRef = useRef();
|
|
3379
|
+
const {
|
|
3380
|
+
setTransientState,
|
|
3381
|
+
select,
|
|
3382
|
+
isSelected: isContentElementSelected,
|
|
3383
|
+
type,
|
|
3384
|
+
range
|
|
3385
|
+
} = useContentElementEditorState();
|
|
3386
|
+
const {
|
|
3387
|
+
selected,
|
|
3388
|
+
highlightedThreadId,
|
|
3389
|
+
newThreadRange
|
|
3390
|
+
} = useContentElementCommentSelection();
|
|
3391
|
+
const newThreadActive = selected === 'newThread';
|
|
3392
|
+
useEffect(() => {
|
|
3393
|
+
var _getUniformSelectedNo, _getUniformSelectedNo2, _getUniformSelectedNo3, _getUniformSelectedNo4;
|
|
3394
|
+
const {
|
|
3395
|
+
selection
|
|
3396
|
+
} = editor;
|
|
3397
|
+
if (!ref.current) {
|
|
3398
|
+
return;
|
|
3399
|
+
}
|
|
3400
|
+
if (type === 'contentElement' && range && lastRangeRef.current !== range) {
|
|
3401
|
+
lastRangeRef.current = range;
|
|
3402
|
+
if (range[1] === range[0] + 1) {
|
|
3403
|
+
Transforms.select(editor, Editor.point(editor, [range[0]], {
|
|
3404
|
+
edge: 'start'
|
|
3405
|
+
}));
|
|
3406
|
+
} else {
|
|
3407
|
+
Transforms.select(editor, {
|
|
3408
|
+
anchor: Editor.point(editor, [range[0]], {
|
|
3409
|
+
edge: 'start'
|
|
3410
|
+
}),
|
|
3411
|
+
focus: Editor.point(editor, [range[1] - 1], {
|
|
3412
|
+
edge: 'end'
|
|
3413
|
+
})
|
|
3414
|
+
});
|
|
3415
|
+
}
|
|
3416
|
+
ReactEditor.focus(editor);
|
|
3417
|
+
}
|
|
3418
|
+
if (!selection) {
|
|
3419
|
+
if (boundsRef.current) {
|
|
3420
|
+
hideRect(ref.current);
|
|
3421
|
+
boundsRef.current = null;
|
|
3422
|
+
}
|
|
3423
|
+
return;
|
|
3424
|
+
}
|
|
3425
|
+
if (!isContentElementSelected && boundsRef.current) {
|
|
3426
|
+
hideRect(ref.current);
|
|
3427
|
+
boundsRef.current = null;
|
|
3428
|
+
Transforms.deselect(editor);
|
|
3429
|
+
return;
|
|
3430
|
+
}
|
|
3431
|
+
if (!isContentElementSelected && !boundsRef.current) {
|
|
3432
|
+
// Only treat the selection as user-initiated when the editor is
|
|
3433
|
+
// actually focused. After an external value replacement, the
|
|
3434
|
+
// browser may clamp its DOM cursor to the start of the
|
|
3435
|
+
// shrunken contenteditable; slate-react's throttled
|
|
3436
|
+
// `selectionchange` listener then re-syncs that cursor into
|
|
3437
|
+
// `editor.selection`. Without this guard, that synthetic
|
|
3438
|
+
// selection would re-select the content element here.
|
|
3439
|
+
if (!ReactEditor.isFocused(editor)) {
|
|
3440
|
+
return;
|
|
3441
|
+
}
|
|
3442
|
+
select();
|
|
3443
|
+
}
|
|
3444
|
+
const [start, end] = computeBounds(editor);
|
|
3445
|
+
if (type === 'contentElementComments' && cursorLeftHighlightedThreadBlock({
|
|
3446
|
+
editor,
|
|
3447
|
+
highlightedThreadId,
|
|
3448
|
+
highlights: props.highlights
|
|
3449
|
+
})) {
|
|
3450
|
+
select();
|
|
3451
|
+
return;
|
|
3452
|
+
}
|
|
3453
|
+
if (newThreadActive && newThreadRange && cursorMovedFromPendingNewThreadRange({
|
|
3454
|
+
editor,
|
|
3455
|
+
newThreadRange
|
|
3456
|
+
})) {
|
|
3457
|
+
select();
|
|
3458
|
+
return;
|
|
3459
|
+
}
|
|
3460
|
+
setTransientState({
|
|
3461
|
+
editableTextIsSingleBlock: editor.children.length <= 1,
|
|
3462
|
+
exampleNode: getUniformSelectedNode(editor, 'type'),
|
|
3463
|
+
typographyVariant: (_getUniformSelectedNo = getUniformSelectedNode(editor, 'variant')) === null || _getUniformSelectedNo === void 0 ? void 0 : _getUniformSelectedNo.variant,
|
|
3464
|
+
typographySize: (_getUniformSelectedNo2 = getUniformSelectedNode(editor, 'size')) === null || _getUniformSelectedNo2 === void 0 ? void 0 : _getUniformSelectedNo2.size,
|
|
3465
|
+
color: (_getUniformSelectedNo3 = getUniformSelectedNode(editor, 'color')) === null || _getUniformSelectedNo3 === void 0 ? void 0 : _getUniformSelectedNo3.color,
|
|
3466
|
+
textAlign: (_getUniformSelectedNo4 = getUniformSelectedNode(editor, 'textAlign')) === null || _getUniformSelectedNo4 === void 0 ? void 0 : _getUniformSelectedNo4.textAlign,
|
|
3467
|
+
commentThreadIdsAtSelection: commentThreadIdsAtSelection(props.highlights || [], editor.selection),
|
|
3468
|
+
newCommentThreadSubjectRange: newCommentThreadSubjectRange(editor)
|
|
3469
|
+
});
|
|
3470
|
+
boundsRef.current = {
|
|
3471
|
+
start,
|
|
3472
|
+
end
|
|
3473
|
+
};
|
|
3474
|
+
updateRect(editor, start, end, outerRef.current, ref.current, innerRef.current);
|
|
3475
|
+
});
|
|
3476
|
+
useEffect(() => {
|
|
3477
|
+
if (!isContentElementSelected) return;
|
|
3478
|
+
function handleResize() {
|
|
3479
|
+
if (boundsRef.current) {
|
|
3480
|
+
updateRect(editor, boundsRef.current.start, boundsRef.current.end, outerRef.current, ref.current, innerRef.current);
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
window.addEventListener('resize', handleResize);
|
|
3484
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
3485
|
+
}, [isContentElementSelected, editor]);
|
|
3486
|
+
const [, drag] = useDrag({
|
|
3487
|
+
item: {
|
|
3488
|
+
type: 'contentElement',
|
|
3489
|
+
id: props.contentElementId
|
|
3490
|
+
},
|
|
3491
|
+
begin: () => ({
|
|
3492
|
+
type: 'contentElement',
|
|
3493
|
+
id: props.contentElementId,
|
|
3494
|
+
range: [boundsRef.current.start, boundsRef.current.end + 1]
|
|
3495
|
+
})
|
|
3496
|
+
});
|
|
3497
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
3498
|
+
ref: outerRef
|
|
3499
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
3500
|
+
ref: ref,
|
|
3501
|
+
className: styles$e.selection
|
|
3502
|
+
}, /*#__PURE__*/React.createElement(SelectionRect, {
|
|
3503
|
+
selected: true,
|
|
3504
|
+
drag: drag,
|
|
3505
|
+
scrollPoint: isContentElementSelected,
|
|
3506
|
+
insertButtonTitles: t('pageflow_scrolled.inline_editing.insert_content_element'),
|
|
3507
|
+
onInsertButtonClick: at => {
|
|
3508
|
+
if (at === 'before' && boundsRef.current.start === 0 || at === 'after' && !Node$1.has(editor, [boundsRef.current.end + 1])) {
|
|
3509
|
+
postInsertContentElementMessage({
|
|
3510
|
+
id: props.contentElementId,
|
|
3511
|
+
at
|
|
3512
|
+
});
|
|
3513
|
+
} else {
|
|
3514
|
+
postInsertContentElementMessage({
|
|
3515
|
+
id: props.contentElementId,
|
|
3516
|
+
at: 'split',
|
|
3517
|
+
splitPoint: at === 'before' ? boundsRef.current.start : boundsRef.current.end + 1
|
|
3518
|
+
});
|
|
3519
|
+
}
|
|
3520
|
+
},
|
|
3521
|
+
toolbarButtons: toolbarButtons(t).map(button => ({
|
|
3522
|
+
...button,
|
|
3523
|
+
active: isBlockActive(editor, button.name)
|
|
3524
|
+
})),
|
|
3525
|
+
onToolbarButtonClick: name => toggleBlock(editor, name)
|
|
3526
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
3527
|
+
ref: innerRef
|
|
3528
|
+
}))));
|
|
3529
|
+
}
|
|
3530
|
+
function hideRect(el) {
|
|
3531
|
+
el.removeAttribute('style');
|
|
3532
|
+
}
|
|
3533
|
+
function updateRect(editor, startIndex, endIndex, outer, el, inner) {
|
|
3534
|
+
const [startDOMNode, endDOMNode] = getDOMNodes(editor, startIndex, endIndex);
|
|
3535
|
+
if (startDOMNode && endDOMNode) {
|
|
3536
|
+
const startRect = startDOMNode.getBoundingClientRect();
|
|
3537
|
+
const endRect = endDOMNode.getBoundingClientRect();
|
|
3538
|
+
const outerRect = outer.getBoundingClientRect();
|
|
3539
|
+
el.style.display = 'block';
|
|
3540
|
+
el.style.top = `${startRect.top - outerRect.top}px`;
|
|
3541
|
+
inner.style.height = `${endRect.bottom - startRect.top}px`;
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
function getDOMNodes(editor, startIndex, endIndex) {
|
|
3545
|
+
const startNode = Node$1.get(editor, [startIndex]);
|
|
3546
|
+
const endNode = Node$1.get(editor, [endIndex]);
|
|
3547
|
+
try {
|
|
3548
|
+
const startDOMNode = ReactEditor.toDOMNode(editor, startNode);
|
|
3549
|
+
const endDOMNode = ReactEditor.toDOMNode(editor, endNode);
|
|
3550
|
+
return [startDOMNode, endDOMNode];
|
|
3551
|
+
} catch (e) {
|
|
3552
|
+
return [];
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
function toolbarButtons(t) {
|
|
3556
|
+
return [{
|
|
3557
|
+
name: 'paragraph',
|
|
3558
|
+
text: t('pageflow_scrolled.inline_editing.formats.paragraph'),
|
|
3559
|
+
icon: TextIcon
|
|
3560
|
+
}, {
|
|
3561
|
+
name: 'heading',
|
|
3562
|
+
text: t('pageflow_scrolled.inline_editing.formats.heading'),
|
|
3563
|
+
icon: HeadingIcon
|
|
3564
|
+
}, {
|
|
3565
|
+
name: 'numbered-list',
|
|
3566
|
+
text: t('pageflow_scrolled.inline_editing.formats.ordered_list'),
|
|
3567
|
+
icon: OlIcon
|
|
3568
|
+
}, {
|
|
3569
|
+
name: 'bulleted-list',
|
|
3570
|
+
text: t('pageflow_scrolled.inline_editing.formats.bulleted_list'),
|
|
3571
|
+
icon: UlIcon
|
|
3572
|
+
}, {
|
|
3573
|
+
name: 'block-quote',
|
|
3574
|
+
text: t('pageflow_scrolled.inline_editing.formats.block_quote'),
|
|
3575
|
+
icon: QuoteIcon
|
|
3576
|
+
}];
|
|
3577
|
+
}
|
|
3578
|
+
|
|
3579
|
+
var styles$f = {"container":"DropTargets-module_container__3vudG","dropTarget":"DropTargets-module_dropTarget__3mmox","dropIndicator":"DropTargets-module_dropIndicator__2zu4d","isOver":"DropTargets-module_isOver__2usWn"};
|
|
3580
|
+
|
|
3581
|
+
function DropTargets$1({
|
|
3582
|
+
contentElementId
|
|
3583
|
+
}) {
|
|
3584
|
+
const editor = useSlate();
|
|
3585
|
+
const [targets, setTargets] = useState();
|
|
3586
|
+
const containerRef = useRef();
|
|
3587
|
+
useEffect(() => {
|
|
3588
|
+
if (!targets) {
|
|
3589
|
+
setTargets(measureHeights(editor, containerRef.current));
|
|
3590
|
+
}
|
|
3591
|
+
}, [targets, editor]);
|
|
3592
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
3593
|
+
ref: containerRef,
|
|
3594
|
+
className: styles$f.container
|
|
3595
|
+
}, renderDropTargets(targets || [], contentElementId));
|
|
3596
|
+
}
|
|
3597
|
+
function renderDropTargets(targets, contentElementId) {
|
|
3598
|
+
function handleDrop(item, index) {
|
|
3599
|
+
if (index === 0) {
|
|
3600
|
+
postMoveContentElementMessage({
|
|
3601
|
+
id: item.id,
|
|
3602
|
+
range: item.range,
|
|
3603
|
+
to: {
|
|
3604
|
+
at: 'before',
|
|
3605
|
+
id: contentElementId
|
|
3606
|
+
}
|
|
3607
|
+
});
|
|
3608
|
+
} else if (index === targets.length - 1) {
|
|
3609
|
+
postMoveContentElementMessage({
|
|
3610
|
+
id: item.id,
|
|
3611
|
+
range: item.range,
|
|
3612
|
+
to: {
|
|
3613
|
+
at: 'after',
|
|
3614
|
+
id: contentElementId
|
|
3615
|
+
}
|
|
3616
|
+
});
|
|
3617
|
+
} else {
|
|
3618
|
+
postMoveContentElementMessage({
|
|
3619
|
+
id: item.id,
|
|
3620
|
+
range: item.range,
|
|
3621
|
+
to: {
|
|
3622
|
+
at: 'split',
|
|
3623
|
+
id: contentElementId,
|
|
3624
|
+
splitPoint: index
|
|
3625
|
+
}
|
|
3626
|
+
});
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
return targets.map((target, index) => /*#__PURE__*/React.createElement(DropTarget, Object.assign({}, target, {
|
|
3630
|
+
key: index,
|
|
3631
|
+
onDrop: item => handleDrop(item, index)
|
|
3632
|
+
})));
|
|
3633
|
+
}
|
|
3634
|
+
function DropTarget({
|
|
3635
|
+
display,
|
|
3636
|
+
top,
|
|
3637
|
+
height,
|
|
3638
|
+
indicatorTop,
|
|
3639
|
+
onDrop
|
|
3640
|
+
}) {
|
|
3641
|
+
const [{
|
|
3642
|
+
isOver
|
|
3643
|
+
}, drop] = useDrop({
|
|
3644
|
+
accept: 'contentElement',
|
|
3645
|
+
collect: monitor => ({
|
|
3646
|
+
isOver: monitor.isOver()
|
|
3647
|
+
}),
|
|
3648
|
+
drop: item => onDrop(item)
|
|
3649
|
+
});
|
|
3650
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
3651
|
+
ref: drop,
|
|
3652
|
+
className: classNames(styles$f.dropTarget, {
|
|
3653
|
+
[styles$f.isOver]: isOver
|
|
3654
|
+
}),
|
|
3655
|
+
style: {
|
|
3656
|
+
display,
|
|
3657
|
+
top,
|
|
3658
|
+
height
|
|
3659
|
+
}
|
|
3660
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
3661
|
+
className: styles$f.dropIndicator,
|
|
3662
|
+
style: {
|
|
3663
|
+
top: indicatorTop
|
|
3664
|
+
}
|
|
3665
|
+
}));
|
|
3666
|
+
}
|
|
3667
|
+
function measureHeights(editor, container) {
|
|
3668
|
+
const containerRect = container.getBoundingClientRect();
|
|
3669
|
+
let lastTargetDimensions = {
|
|
3670
|
+
top: 0,
|
|
3671
|
+
height: 0
|
|
3672
|
+
};
|
|
3673
|
+
let lastRectBottom = 0;
|
|
3674
|
+
const targetDimensions = editor.children.map((child, index) => {
|
|
3675
|
+
const node = Node$1.get(editor, [index]);
|
|
3676
|
+
const domNode = ReactEditor.toDOMNode(editor, node);
|
|
3677
|
+
const rect = domNode.getBoundingClientRect();
|
|
3678
|
+
const top = lastTargetDimensions.top + lastTargetDimensions.height;
|
|
3679
|
+
const bottom = rect.top + rect.height / 2 - containerRect.top;
|
|
3680
|
+
const targetDimensions = {
|
|
3681
|
+
top,
|
|
3682
|
+
height: bottom - top,
|
|
3683
|
+
display: editor.selection && Range.includes(editor.selection, [index]) ? 'none' : undefined,
|
|
3684
|
+
indicatorTop: index > 0 ? lastRectBottom + (rect.top - lastRectBottom) / 2 - containerRect.top - top : 0
|
|
3685
|
+
};
|
|
3686
|
+
lastRectBottom = rect.bottom;
|
|
3687
|
+
lastTargetDimensions = targetDimensions;
|
|
3688
|
+
return targetDimensions;
|
|
3689
|
+
});
|
|
3690
|
+
return [...targetDimensions, {
|
|
3691
|
+
top: lastTargetDimensions.top + lastTargetDimensions.height,
|
|
3692
|
+
height: containerRect.height - (lastTargetDimensions.top + lastTargetDimensions.height),
|
|
3693
|
+
indicatorTop: containerRect.height - (lastTargetDimensions.top + lastTargetDimensions.height)
|
|
3694
|
+
}];
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
const shy = '\u00AD';
|
|
3698
|
+
function decorateCharacter([node, path], character, attributes, {
|
|
3699
|
+
length
|
|
3700
|
+
}) {
|
|
3701
|
+
if (Text.isText(node)) {
|
|
3702
|
+
const parts = node.text.split(character);
|
|
3703
|
+
parts.pop();
|
|
3704
|
+
let i = 0;
|
|
3705
|
+
return parts.map(part => {
|
|
3706
|
+
i += part.length + 1;
|
|
3707
|
+
return {
|
|
3708
|
+
anchor: {
|
|
3709
|
+
path,
|
|
3710
|
+
offset: i - 1
|
|
3711
|
+
},
|
|
3712
|
+
focus: {
|
|
3713
|
+
path,
|
|
3714
|
+
offset: i - 1 + length
|
|
3715
|
+
},
|
|
3716
|
+
...attributes
|
|
3717
|
+
};
|
|
3718
|
+
});
|
|
3719
|
+
}
|
|
3720
|
+
return [];
|
|
3721
|
+
}
|
|
3722
|
+
function deleteCharacter(editor, node, path, regExp, offset = 0) {
|
|
3723
|
+
const match = regExp.exec(node.text);
|
|
3724
|
+
if (match) {
|
|
3725
|
+
Transforms.delete(editor, {
|
|
3726
|
+
at: {
|
|
3727
|
+
path,
|
|
3728
|
+
offset: match.index + offset
|
|
3729
|
+
},
|
|
3730
|
+
distance: 1,
|
|
3731
|
+
unit: 'character'
|
|
3732
|
+
});
|
|
3733
|
+
return true;
|
|
3734
|
+
}
|
|
3735
|
+
return false;
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3738
|
+
function useLineBreakHandler(editor) {
|
|
3739
|
+
return useCallback(event => {
|
|
3740
|
+
if (event.key !== 'Enter') {
|
|
3741
|
+
return;
|
|
3742
|
+
}
|
|
3743
|
+
if (event.altKey === true) {
|
|
3744
|
+
editor.insertText(shy);
|
|
3745
|
+
event.preventDefault();
|
|
3746
|
+
} else if (event.shiftKey === true) {
|
|
3747
|
+
editor.insertText('\n');
|
|
3748
|
+
event.preventDefault();
|
|
3749
|
+
}
|
|
3750
|
+
}, [editor]);
|
|
3751
|
+
}
|
|
3752
|
+
function decorateLineBreaks(nodeEntry) {
|
|
3753
|
+
return decorateCharacter(nodeEntry, shy, {
|
|
3754
|
+
shy: true
|
|
3755
|
+
}, {
|
|
3756
|
+
length: 1
|
|
3757
|
+
});
|
|
3758
|
+
}
|
|
3759
|
+
function renderLeafWithLineBreakDecoration({
|
|
3760
|
+
leaf,
|
|
3761
|
+
children,
|
|
3762
|
+
attributes
|
|
3763
|
+
}) {
|
|
3764
|
+
if (leaf.shy) {
|
|
3765
|
+
children = /*#__PURE__*/React.createElement("span", {
|
|
3766
|
+
className: styles$e.shy
|
|
3767
|
+
}, children);
|
|
3768
|
+
}
|
|
3769
|
+
return renderLeaf$1({
|
|
3770
|
+
leaf,
|
|
3771
|
+
children,
|
|
3772
|
+
attributes
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
3775
|
+
function withLineBreakNormalization(editor) {
|
|
3776
|
+
const {
|
|
3777
|
+
normalizeNode
|
|
3778
|
+
} = editor;
|
|
3779
|
+
editor.normalizeNode = ([node, path]) => {
|
|
3780
|
+
if (node.text) {
|
|
3781
|
+
if (deleteCharacter(editor, node, path, new RegExp(`${shy}\\s`)) || deleteCharacter(editor, node, path, new RegExp(`^${shy}`)) || deleteCharacter(editor, node, path, new RegExp(`\\s${shy}`), 1) || deleteCharacter(editor, node, path, new RegExp(`${shy}${shy}`))) {
|
|
3782
|
+
return;
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
return normalizeNode([node, path]);
|
|
3786
|
+
};
|
|
3787
|
+
return editor;
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
function useShortcutHandler(editor) {
|
|
3791
|
+
return useCallback(event => {
|
|
3792
|
+
if (!event.ctrlKey) {
|
|
3793
|
+
return;
|
|
3794
|
+
}
|
|
3795
|
+
if (event.key === 'z') {
|
|
3796
|
+
event.preventDefault();
|
|
3797
|
+
editor.undo();
|
|
3798
|
+
} else if (event.key === 'y') {
|
|
3799
|
+
event.preventDefault();
|
|
3800
|
+
editor.redo();
|
|
3801
|
+
} else if (event.key === 'b') {
|
|
3802
|
+
event.preventDefault();
|
|
3803
|
+
toggleMark(editor, 'bold');
|
|
3804
|
+
} else if (event.key === 'i') {
|
|
3805
|
+
event.preventDefault();
|
|
3806
|
+
toggleMark(editor, 'italic');
|
|
3807
|
+
} else if (event.key === 'u') {
|
|
3808
|
+
event.preventDefault();
|
|
3809
|
+
toggleMark(editor, 'underline');
|
|
3810
|
+
} else if (event.key === 'S') {
|
|
3811
|
+
event.preventDefault();
|
|
3812
|
+
toggleMark(editor, 'strikethrough');
|
|
3813
|
+
} else if (event.key === ',') {
|
|
3814
|
+
event.preventDefault();
|
|
3815
|
+
toggleMark(editor, 'sup');
|
|
3816
|
+
} else if (event.key === ';') {
|
|
3817
|
+
event.preventDefault();
|
|
3818
|
+
toggleMark(editor, 'sub');
|
|
3819
|
+
}
|
|
3820
|
+
}, [editor]);
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
function duplicateNodes(editor) {
|
|
3824
|
+
if (!editor.selection) {
|
|
3825
|
+
return;
|
|
3826
|
+
}
|
|
3827
|
+
const selectedEntries = Array.from(Editor.nodes(editor, {
|
|
3828
|
+
at: editor.selection,
|
|
3829
|
+
mode: 'highest',
|
|
3830
|
+
match: n => Element$1.isElement(n)
|
|
3831
|
+
}));
|
|
3832
|
+
if (selectedEntries.length === 0) {
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
const clonedNodes = selectedEntries.map(([node]) => JSON.parse(JSON.stringify(node)));
|
|
3836
|
+
const lastPath = selectedEntries[selectedEntries.length - 1][1];
|
|
3837
|
+
const insertAt = lastPath[0] + 1;
|
|
3838
|
+
Transforms.insertNodes(editor, clonedNodes, {
|
|
3839
|
+
at: [insertAt]
|
|
3840
|
+
});
|
|
3841
|
+
Transforms.select(editor, {
|
|
3842
|
+
anchor: Editor.start(editor, [insertAt]),
|
|
3843
|
+
focus: Editor.end(editor, [insertAt + clonedNodes.length - 1])
|
|
3844
|
+
});
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
const selectedClassName = styles$e.selected;
|
|
3848
|
+
const EditableText = React.memo(function EditableText({
|
|
3849
|
+
value,
|
|
3850
|
+
contentElementId,
|
|
3851
|
+
placeholder,
|
|
3852
|
+
onChange,
|
|
3853
|
+
selectionRect,
|
|
3854
|
+
className,
|
|
3855
|
+
placeholderClassName,
|
|
3856
|
+
scaleCategory = 'body',
|
|
3857
|
+
typographyVariant,
|
|
3858
|
+
typographySize,
|
|
3859
|
+
autoFocus,
|
|
3860
|
+
floatingControlsPosition = 'above'
|
|
3861
|
+
}) {
|
|
3862
|
+
const editor = useMemo(() => withLinks(withCustomInsertBreak(withBlockNormalization({
|
|
3863
|
+
onlyParagraphs: !selectionRect
|
|
3864
|
+
}, withLineBreakNormalization(withReact(withHistory(createEditor())))))), [selectionRect]);
|
|
3865
|
+
const handleLineBreaks = useLineBreakHandler(editor);
|
|
3866
|
+
const handleShortcuts = useShortcutHandler(editor);
|
|
3867
|
+
const handleKeyDown = useCallback(event => {
|
|
3868
|
+
handleLineBreaks(event);
|
|
3869
|
+
handleShortcuts(event);
|
|
3870
|
+
}, [handleLineBreaks, handleShortcuts]);
|
|
3871
|
+
useEffect(() => {
|
|
3872
|
+
if (autoFocus) {
|
|
3873
|
+
ReactEditor.focus(editor);
|
|
3874
|
+
}
|
|
3875
|
+
}, [autoFocus, editor]);
|
|
3876
|
+
const {
|
|
3877
|
+
enabled: commentingEnabled,
|
|
3878
|
+
anchors,
|
|
3879
|
+
highlights,
|
|
3880
|
+
visibleHighlights,
|
|
3881
|
+
highlightedRange,
|
|
3882
|
+
decorate: decorateComments,
|
|
3883
|
+
withCommentHighlightDecoration,
|
|
3884
|
+
resetRangeRefs,
|
|
3885
|
+
getTrackedSubjectRanges
|
|
3886
|
+
} = useCommenting(editor);
|
|
3887
|
+
const [cachedValue, setCachedValue] = useCachedValue(value, {
|
|
3888
|
+
defaultValue: [{
|
|
3889
|
+
type: 'paragraph',
|
|
3890
|
+
children: [{
|
|
3891
|
+
text: ''
|
|
3892
|
+
}]
|
|
3893
|
+
}],
|
|
3894
|
+
onDebouncedChange: nextValue => {
|
|
3895
|
+
if (onChange) {
|
|
3896
|
+
onChange(nextValue, {
|
|
3897
|
+
commentThreadSubjectRanges: getTrackedSubjectRanges()
|
|
3898
|
+
});
|
|
3899
|
+
}
|
|
3900
|
+
},
|
|
3901
|
+
onReset: nextValue => {
|
|
3902
|
+
resetSelectionIfOutsideNextValue(editor, nextValue);
|
|
3903
|
+
resetHistory(editor);
|
|
3904
|
+
resetRangeRefs();
|
|
3905
|
+
}
|
|
3906
|
+
});
|
|
3907
|
+
const {
|
|
3908
|
+
isSelected
|
|
3909
|
+
} = useContentElementEditorState();
|
|
3910
|
+
useContentElementEditorCommandSubscription(command => {
|
|
3911
|
+
if (command.type === 'REMOVE') {
|
|
3912
|
+
Transforms.removeNodes(editor, {
|
|
3913
|
+
mode: 'highest'
|
|
3914
|
+
});
|
|
3915
|
+
} else if (command.type === 'DUPLICATE') {
|
|
3916
|
+
duplicateNodes(editor);
|
|
3917
|
+
ReactEditor.focus(editor);
|
|
3918
|
+
} else if (command.type === 'MOVE_TO') {
|
|
3919
|
+
const {
|
|
3920
|
+
to
|
|
3921
|
+
} = command.payload;
|
|
3922
|
+
const [start, end] = computeBounds(editor);
|
|
3923
|
+
postMoveContentElementMessage({
|
|
3924
|
+
id: contentElementId,
|
|
3925
|
+
range: [start, end + 1],
|
|
3926
|
+
to
|
|
3927
|
+
});
|
|
3928
|
+
} else if (command.type === 'TRANSIENT_STATE_UPDATE') {
|
|
3929
|
+
if ('typographyVariant' in command.payload) {
|
|
3930
|
+
applyTypographyVariant(editor, command.payload.typographyVariant);
|
|
3931
|
+
}
|
|
3932
|
+
if ('typographySize' in command.payload) {
|
|
3933
|
+
applyTypographySize(editor, command.payload.typographySize);
|
|
3934
|
+
}
|
|
3935
|
+
if ('color' in command.payload) {
|
|
3936
|
+
applyColor(editor, command.payload.color);
|
|
3937
|
+
}
|
|
3938
|
+
if ('textAlign' in command.payload) {
|
|
3939
|
+
applyTextAlign(editor, command.payload.textAlign);
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
});
|
|
3943
|
+
const [dropTargetsActive, dropTargetsRef] = useDropTargetsActive();
|
|
3944
|
+
const decorate = useMemo(() => {
|
|
3945
|
+
if (!commentingEnabled) {
|
|
3946
|
+
return decorateLineBreaks;
|
|
3947
|
+
}
|
|
3948
|
+
return entry => [...decorateLineBreaks(entry), ...decorateComments(entry)];
|
|
3949
|
+
}, [decorateComments, commentingEnabled]);
|
|
3950
|
+
const renderLeaf = useCallback(props => renderLeafWithLineBreakDecoration(withCommentHighlightDecoration(props)), [withCommentHighlightDecoration]);
|
|
3951
|
+
return /*#__PURE__*/React.createElement(Text$1, {
|
|
3952
|
+
scaleCategory: scaleCategory,
|
|
3953
|
+
typographyVariant: typographyVariant,
|
|
3954
|
+
typographySize: typographySize
|
|
3955
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
3956
|
+
className: classNames(styles$e.container, {
|
|
3957
|
+
[styles$e.selected]: isSelected
|
|
3958
|
+
}),
|
|
3959
|
+
ref: el => {
|
|
3960
|
+
dropTargetsRef(el);
|
|
3961
|
+
anchors.containerRef.current = el;
|
|
3962
|
+
}
|
|
3963
|
+
}, /*#__PURE__*/React.createElement(Slate, {
|
|
3964
|
+
editor: editor,
|
|
3965
|
+
value: cachedValue,
|
|
3966
|
+
onChange: setCachedValue
|
|
3967
|
+
}, /*#__PURE__*/React.createElement(LinkTooltipProvider, {
|
|
3968
|
+
disabled: editor.selection && !Range.isCollapsed(editor.selection),
|
|
3969
|
+
position: floatingControlsPosition
|
|
3970
|
+
}, selectionRect && /*#__PURE__*/React.createElement(Selection, {
|
|
3971
|
+
contentElementId: contentElementId,
|
|
3972
|
+
highlights: highlights
|
|
3973
|
+
}), dropTargetsActive && /*#__PURE__*/React.createElement(DropTargets$1, {
|
|
3974
|
+
contentElementId: contentElementId
|
|
3975
|
+
}), /*#__PURE__*/React.createElement(HoveringToolbar, null, /*#__PURE__*/React.createElement(Editable, {
|
|
3976
|
+
className: className,
|
|
3977
|
+
decorate: decorate,
|
|
3978
|
+
onKeyDown: handleKeyDown,
|
|
3979
|
+
renderElement: renderElementWithLinkPreview,
|
|
3980
|
+
renderLeaf: renderLeaf
|
|
3981
|
+
}))), commentingEnabled && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(BadgeColumn, {
|
|
3982
|
+
highlights: visibleHighlights,
|
|
3983
|
+
highlightedRange: highlightedRange,
|
|
3984
|
+
anchors: anchors
|
|
3985
|
+
}), /*#__PURE__*/React.createElement(PendingSelectionBadge, {
|
|
3986
|
+
containerRef: anchors.containerRef
|
|
3987
|
+
}))), /*#__PURE__*/React.createElement(TextPlaceholder, {
|
|
3988
|
+
text: placeholder,
|
|
3989
|
+
className: placeholderClassName,
|
|
3990
|
+
visible: isBlank(cachedValue)
|
|
3991
|
+
})));
|
|
3992
|
+
});
|
|
3993
|
+
function isBlank(value) {
|
|
3994
|
+
var _value$, _value$2, _value$2$children$;
|
|
3995
|
+
return value.length <= 1 && ((_value$ = value[0]) === null || _value$ === void 0 ? void 0 : _value$.children.length) <= 1 && value[0].type === 'paragraph' && !((_value$2 = value[0]) === null || _value$2 === void 0 ? void 0 : (_value$2$children$ = _value$2.children[0]) === null || _value$2$children$ === void 0 ? void 0 : _value$2$children$.text);
|
|
3996
|
+
}
|
|
3997
|
+
function resetSelectionIfOutsideNextValue(editor, nextValue) {
|
|
3998
|
+
const nextEditor = {
|
|
3999
|
+
children: nextValue
|
|
4000
|
+
};
|
|
4001
|
+
if (editor.selection && (!hasTextAtPoint(nextEditor, editor.selection.anchor) || !hasTextAtPoint(nextEditor, editor.selection.focus))) {
|
|
4002
|
+
Transforms.deselect(editor);
|
|
4003
|
+
// Also drop the browser's DOM cursor when it sits inside this
|
|
4004
|
+
// editor's contenteditable. Otherwise slate-react's throttled
|
|
4005
|
+
// `selectionchange` listener would later re-sync that stale
|
|
4006
|
+
// cursor — clamped to the start of the now-shrunken content —
|
|
4007
|
+
// back into `editor.selection`, and `Selection`'s auto-select
|
|
4008
|
+
// would treat it as a user click and re-select this content
|
|
4009
|
+
// element (overriding whatever the calling op selected, e.g. a
|
|
4010
|
+
// freshly inserted image).
|
|
4011
|
+
const domSelection = window.getSelection();
|
|
4012
|
+
const editorEl = ReactEditor.toDOMNode(editor, editor);
|
|
4013
|
+
if (domSelection && editorEl.contains(domSelection.anchorNode)) {
|
|
4014
|
+
domSelection.removeAllRanges();
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
function hasTextAtPoint(editor, point) {
|
|
4019
|
+
if (!Node$1.has(editor, point.path)) {
|
|
4020
|
+
return false;
|
|
4021
|
+
}
|
|
4022
|
+
const node = Node$1.get(editor, point.path);
|
|
4023
|
+
return Text.isText(node) && point.offset <= node.text.length;
|
|
4024
|
+
}
|
|
4025
|
+
function resetHistory(editor) {
|
|
4026
|
+
editor.history.undos = [];
|
|
4027
|
+
editor.history.redos = [];
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
function useLineBreakHandler$1(editor) {
|
|
4031
|
+
return useCallback(event => {
|
|
4032
|
+
if (event.key !== 'Enter') {
|
|
4033
|
+
return true;
|
|
4034
|
+
}
|
|
4035
|
+
|
|
4036
|
+
// Soft hyphens used to be inserted with Shift + Enter.
|
|
4037
|
+
// Since Shift + Enter is now used for soft breaks in text blocks,
|
|
4038
|
+
// we switched to Alt + Enter. Since all line breaks in
|
|
4039
|
+
// EdtiableInlineText are soft, we also keep the old short cut
|
|
4040
|
+
if (event.shiftKey === true || event.altKey === true) {
|
|
4041
|
+
editor.insertText(shy);
|
|
4042
|
+
} else {
|
|
4043
|
+
editor.insertText('\n');
|
|
4044
|
+
}
|
|
4045
|
+
return false;
|
|
4046
|
+
}, [editor]);
|
|
4047
|
+
}
|
|
4048
|
+
function decorateLineBreaks$1(nodeEntry) {
|
|
4049
|
+
return [...decorateCharacter(nodeEntry, shy, {
|
|
4050
|
+
shy: true
|
|
4051
|
+
}, {
|
|
4052
|
+
length: 1
|
|
4053
|
+
}), ...decorateCharacter(nodeEntry, "\n", {
|
|
4054
|
+
newLine: true
|
|
4055
|
+
}, {
|
|
4056
|
+
length: 0
|
|
4057
|
+
})];
|
|
4058
|
+
}
|
|
4059
|
+
function withLineBreakNormalization$1(editor) {
|
|
4060
|
+
const {
|
|
4061
|
+
normalizeNode
|
|
4062
|
+
} = editor;
|
|
4063
|
+
editor.normalizeNode = ([node, path]) => {
|
|
4064
|
+
if (path.length === 0 && editor.children.length > 1) {
|
|
4065
|
+
Transforms.mergeNodes(editor);
|
|
4066
|
+
return;
|
|
4067
|
+
} else if (node.text) {
|
|
4068
|
+
if (deleteCharacter(editor, node, path, /\n\n/) || deleteCharacter(editor, node, path, new RegExp(`^\n`)) || deleteCharacter(editor, node, path, new RegExp(`${shy}\\s`)) || deleteCharacter(editor, node, path, new RegExp(`^${shy}`)) || deleteCharacter(editor, node, path, new RegExp(`\\s${shy}`), 1) || deleteCharacter(editor, node, path, new RegExp(`${shy}${shy}`))) {
|
|
4069
|
+
return;
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
return normalizeNode([node, path]);
|
|
4073
|
+
};
|
|
4074
|
+
return editor;
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
function useShortcutHandler$1(editor) {
|
|
4078
|
+
return useCallback(event => {
|
|
4079
|
+
if (!event.ctrlKey) {
|
|
4080
|
+
return;
|
|
4081
|
+
}
|
|
4082
|
+
if (event.key === 'z') {
|
|
4083
|
+
event.preventDefault();
|
|
4084
|
+
editor.undo();
|
|
4085
|
+
} else if (event.key === 'y') {
|
|
4086
|
+
event.preventDefault();
|
|
4087
|
+
editor.redo();
|
|
4088
|
+
}
|
|
4089
|
+
}, [editor]);
|
|
4090
|
+
}
|
|
4091
|
+
|
|
4092
|
+
var styles$g = {"shy":"index-module_shy__1E2-J","newLine":"index-module_newLine__1QnIs","selected":"index-module_selected__1U9ro","manualHyphens":"index-module_manualHyphens__16b2t"};
|
|
4093
|
+
|
|
4094
|
+
const EditableInlineText = memo(function EditableInlineText({
|
|
4095
|
+
value,
|
|
4096
|
+
defaultValue = '',
|
|
4097
|
+
hyphens,
|
|
4098
|
+
placeholder,
|
|
4099
|
+
onChange
|
|
4100
|
+
}) {
|
|
4101
|
+
var _cachedValue$, _cachedValue$$childre;
|
|
4102
|
+
const editor = useMemo(() => withLineBreakNormalization$1(withReact(withHistory(createEditor()))), []);
|
|
4103
|
+
const handleLineBreaks = useLineBreakHandler$1(editor);
|
|
4104
|
+
const handleShortcuts = useShortcutHandler$1(editor);
|
|
4105
|
+
const handleKeyDown = useCallback(event => {
|
|
4106
|
+
handleLineBreaks(event);
|
|
4107
|
+
handleShortcuts(event);
|
|
4108
|
+
}, [handleLineBreaks, handleShortcuts]);
|
|
4109
|
+
const [cachedValue, setCachedValue] = useCachedValue(value, {
|
|
4110
|
+
defaultValue: [{
|
|
4111
|
+
type: 'heading',
|
|
4112
|
+
children: [{
|
|
4113
|
+
text: defaultValue
|
|
4114
|
+
}]
|
|
4115
|
+
}],
|
|
4116
|
+
onDebouncedChange: onChange
|
|
4117
|
+
});
|
|
4118
|
+
const {
|
|
4119
|
+
isSelected
|
|
4120
|
+
} = useContentElementEditorState();
|
|
4121
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
4122
|
+
className: classNames(frontendStyles.root, frontendStyles[`hyphens-${hyphens}`], {
|
|
4123
|
+
[styles$g.manualHyphens]: hyphens === 'manual'
|
|
4124
|
+
}, {
|
|
4125
|
+
[styles$g.selected]: isSelected
|
|
4126
|
+
}),
|
|
4127
|
+
spellCheck: "false"
|
|
4128
|
+
}, /*#__PURE__*/React.createElement(Slate, {
|
|
4129
|
+
editor: editor,
|
|
4130
|
+
value: cachedValue,
|
|
4131
|
+
onChange: setCachedValue
|
|
4132
|
+
}, /*#__PURE__*/React.createElement(Editable, {
|
|
4133
|
+
decorate: decorateLineBreaks$1,
|
|
4134
|
+
onKeyDown: handleKeyDown,
|
|
4135
|
+
renderElement: props => /*#__PURE__*/React.createElement(Element, props),
|
|
4136
|
+
renderLeaf: renderLeaf
|
|
4137
|
+
})), /*#__PURE__*/React.createElement(TextPlaceholder, {
|
|
4138
|
+
text: placeholder,
|
|
4139
|
+
visible: !((_cachedValue$ = cachedValue[0]) === null || _cachedValue$ === void 0 ? void 0 : (_cachedValue$$childre = _cachedValue$.children[0]) === null || _cachedValue$$childre === void 0 ? void 0 : _cachedValue$$childre.text)
|
|
4140
|
+
}));
|
|
4141
|
+
});
|
|
4142
|
+
function Element({
|
|
4143
|
+
attributes,
|
|
4144
|
+
children,
|
|
4145
|
+
element
|
|
4146
|
+
}) {
|
|
4147
|
+
return /*#__PURE__*/React.createElement("div", Object.assign({}, attributes, {
|
|
4148
|
+
style: {
|
|
4149
|
+
position: 'relative'
|
|
4150
|
+
}
|
|
4151
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
4152
|
+
className: frontendStyles.textEffects
|
|
4153
|
+
}, children));
|
|
4154
|
+
}
|
|
4155
|
+
function renderLeaf({
|
|
4156
|
+
attributes,
|
|
4157
|
+
children,
|
|
4158
|
+
leaf
|
|
4159
|
+
}) {
|
|
4160
|
+
if (leaf.shy) {
|
|
4161
|
+
children = /*#__PURE__*/React.createElement("span", {
|
|
4162
|
+
className: styles$g.shy
|
|
4163
|
+
}, children);
|
|
4164
|
+
}
|
|
4165
|
+
if (leaf.newLine) {
|
|
4166
|
+
children = /*#__PURE__*/React.createElement("span", {
|
|
4167
|
+
className: styles$g.newLine
|
|
4168
|
+
}, children);
|
|
4169
|
+
}
|
|
4170
|
+
return /*#__PURE__*/React.createElement("span", attributes, children);
|
|
4171
|
+
}
|
|
4172
|
+
|
|
4173
|
+
const Row = {
|
|
4174
|
+
match(editor) {
|
|
4175
|
+
const [rowMatch] = Editor.nodes(editor, {
|
|
4176
|
+
match: n => n.type === 'row'
|
|
4177
|
+
});
|
|
4178
|
+
return rowMatch;
|
|
4179
|
+
}
|
|
4180
|
+
};
|
|
4181
|
+
const Cell = {
|
|
4182
|
+
splitChildren(editor, {
|
|
4183
|
+
cellNode,
|
|
4184
|
+
point
|
|
4185
|
+
}) {
|
|
4186
|
+
const [leafNode, leafPath] = Editor.leaf(editor, point.path);
|
|
4187
|
+
const cursorOffset = point.offset;
|
|
4188
|
+
const text = leafNode.text || '';
|
|
4189
|
+
const beforeText = text.slice(0, cursorOffset);
|
|
4190
|
+
const afterText = text.slice(cursorOffset);
|
|
4191
|
+
const splitIndex = leafPath[leafPath.length - 1];
|
|
4192
|
+
const beforeNodes = [];
|
|
4193
|
+
const afterNodes = [];
|
|
4194
|
+
cellNode.children.forEach((node, index) => {
|
|
4195
|
+
if (index < splitIndex) {
|
|
4196
|
+
beforeNodes.push(node);
|
|
4197
|
+
} else if (index === splitIndex) {
|
|
4198
|
+
if (beforeText) {
|
|
4199
|
+
beforeNodes.push({
|
|
4200
|
+
...node,
|
|
4201
|
+
text: beforeText
|
|
4202
|
+
});
|
|
4203
|
+
}
|
|
4204
|
+
if (afterText) {
|
|
4205
|
+
afterNodes.push({
|
|
4206
|
+
...node,
|
|
4207
|
+
text: afterText
|
|
4208
|
+
});
|
|
4209
|
+
}
|
|
4210
|
+
} else {
|
|
4211
|
+
afterNodes.push(node);
|
|
4212
|
+
}
|
|
4213
|
+
});
|
|
4214
|
+
return [beforeNodes, afterNodes];
|
|
4215
|
+
},
|
|
4216
|
+
match(editor, {
|
|
4217
|
+
at
|
|
4218
|
+
} = {}) {
|
|
4219
|
+
const [cellMatch] = Editor.nodes(editor, {
|
|
4220
|
+
match: n => n.type === 'label' || n.type === 'value',
|
|
4221
|
+
at
|
|
4222
|
+
});
|
|
4223
|
+
return cellMatch;
|
|
4224
|
+
},
|
|
4225
|
+
inFirstLine(editor, point) {
|
|
4226
|
+
const [node] = Editor.node(editor, point.path);
|
|
4227
|
+
const text = Node$1.string(node);
|
|
4228
|
+
const firstLineBreak = text.indexOf('\n');
|
|
4229
|
+
return firstLineBreak === -1 || point.offset <= firstLineBreak;
|
|
4230
|
+
},
|
|
4231
|
+
inLastLine(editor, point) {
|
|
4232
|
+
const [node] = Editor.node(editor, point.path);
|
|
4233
|
+
const text = Node$1.string(node);
|
|
4234
|
+
const lastLineBreak = text.lastIndexOf('\n');
|
|
4235
|
+
return lastLineBreak === -1 || point.offset > lastLineBreak;
|
|
4236
|
+
},
|
|
4237
|
+
getPointAtStartOfLastLine(editor, cellPath) {
|
|
4238
|
+
const [node] = Editor.node(editor, cellPath);
|
|
4239
|
+
const text = Node$1.string(node);
|
|
4240
|
+
const lastLineBreak = text.lastIndexOf('\n');
|
|
4241
|
+
const offset = lastLineBreak === -1 ? 0 : lastLineBreak + 1;
|
|
4242
|
+
return {
|
|
4243
|
+
path: cellPath,
|
|
4244
|
+
offset
|
|
4245
|
+
};
|
|
4246
|
+
}
|
|
4247
|
+
};
|
|
4248
|
+
const CellPath = {
|
|
4249
|
+
columnIndex(path) {
|
|
4250
|
+
return path[path.length - 1];
|
|
4251
|
+
},
|
|
4252
|
+
rowIndex(path) {
|
|
4253
|
+
return path[path.length - 2];
|
|
4254
|
+
}
|
|
4255
|
+
};
|
|
4256
|
+
|
|
4257
|
+
const CellTransforms = {
|
|
4258
|
+
replaceContent(editor, nodes, {
|
|
4259
|
+
cellPath
|
|
4260
|
+
}) {
|
|
4261
|
+
Transforms.insertText(editor, '', {
|
|
4262
|
+
at: cellPath
|
|
4263
|
+
});
|
|
4264
|
+
if (nodes.length > 0) {
|
|
4265
|
+
Transforms.insertNodes(editor, nodes, {
|
|
4266
|
+
at: [...cellPath, 0]
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
4269
|
+
},
|
|
4270
|
+
deleteContentUntil(editor, {
|
|
4271
|
+
cellPath,
|
|
4272
|
+
point
|
|
4273
|
+
}) {
|
|
4274
|
+
if (!Editor.isStart(editor, point, cellPath)) {
|
|
4275
|
+
Transforms.delete(editor, {
|
|
4276
|
+
at: {
|
|
4277
|
+
anchor: Editor.start(editor, cellPath),
|
|
4278
|
+
focus: point
|
|
4279
|
+
}
|
|
4280
|
+
});
|
|
4281
|
+
}
|
|
4282
|
+
},
|
|
4283
|
+
deleteContentFrom(editor, {
|
|
4284
|
+
cellPath,
|
|
4285
|
+
point
|
|
4286
|
+
}) {
|
|
4287
|
+
if (!Editor.isEnd(editor, point, cellPath)) {
|
|
4288
|
+
Transforms.delete(editor, {
|
|
4289
|
+
at: {
|
|
4290
|
+
anchor: point,
|
|
4291
|
+
focus: Editor.end(editor, cellPath)
|
|
4292
|
+
}
|
|
4293
|
+
});
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
};
|
|
4297
|
+
|
|
4298
|
+
const TableTransforms = {
|
|
4299
|
+
deleteRange(editor, [startPoint, endPoint]) {
|
|
4300
|
+
const startCellMatch = Cell.match(editor, {
|
|
4301
|
+
at: startPoint.path
|
|
4302
|
+
});
|
|
4303
|
+
const endCellMatch = Cell.match(editor, {
|
|
4304
|
+
at: endPoint.path
|
|
4305
|
+
});
|
|
4306
|
+
if (startCellMatch && endCellMatch) {
|
|
4307
|
+
const [startCellNode, startCellPath] = startCellMatch;
|
|
4308
|
+
const [endCellNode, endCellPath] = endCellMatch;
|
|
4309
|
+
if (!Path.equals(startCellPath, endCellPath)) {
|
|
4310
|
+
const rewrittenCellPath = getRewrittenCellPath(editor, startCellPath, endCellPath);
|
|
4311
|
+
const rows = Array.from(Editor.nodes(editor, {
|
|
4312
|
+
match: n => n.type === 'row',
|
|
4313
|
+
at: {
|
|
4314
|
+
anchor: startPoint,
|
|
4315
|
+
focus: endPoint
|
|
4316
|
+
}
|
|
4317
|
+
}));
|
|
4318
|
+
CellTransforms.deleteContentFrom(editor, {
|
|
4319
|
+
cellPath: startCellPath,
|
|
4320
|
+
point: startPoint
|
|
4321
|
+
});
|
|
4322
|
+
if (rewrittenCellPath) {
|
|
4323
|
+
var _beforeNodes;
|
|
4324
|
+
const beforeNodes = CellPath.columnIndex(startCellPath) === CellPath.columnIndex(endCellPath) ? Cell.splitChildren(editor, {
|
|
4325
|
+
cellNode: startCellNode,
|
|
4326
|
+
point: startPoint
|
|
4327
|
+
})[0] : [];
|
|
4328
|
+
const [, afterNodes] = Cell.splitChildren(editor, {
|
|
4329
|
+
cellNode: endCellNode,
|
|
4330
|
+
point: endPoint
|
|
4331
|
+
});
|
|
4332
|
+
CellTransforms.replaceContent(editor, beforeNodes.concat(afterNodes), {
|
|
4333
|
+
cellPath: rewrittenCellPath
|
|
4334
|
+
});
|
|
4335
|
+
Transforms.select(editor, {
|
|
4336
|
+
path: [...rewrittenCellPath, beforeNodes.length ? beforeNodes.length - 1 : 0],
|
|
4337
|
+
offset: ((_beforeNodes = beforeNodes[beforeNodes.length - 1]) === null || _beforeNodes === void 0 ? void 0 : _beforeNodes.text.length) || 0
|
|
4338
|
+
});
|
|
4339
|
+
rows.reverse().forEach(([_, rowPath]) => {
|
|
4340
|
+
if (rowPath[rowPath.length - 1] !== CellPath.rowIndex(rewrittenCellPath)) {
|
|
4341
|
+
Transforms.removeNodes(editor, {
|
|
4342
|
+
at: rowPath
|
|
4343
|
+
});
|
|
4344
|
+
}
|
|
4345
|
+
});
|
|
4346
|
+
} else {
|
|
4347
|
+
CellTransforms.deleteContentUntil(editor, {
|
|
4348
|
+
cellPath: endCellPath,
|
|
4349
|
+
point: endPoint
|
|
4350
|
+
});
|
|
4351
|
+
rows.slice(1, -1).reverse().forEach(([_, rowPath]) => {
|
|
4352
|
+
Transforms.removeNodes(editor, {
|
|
4353
|
+
at: rowPath
|
|
4354
|
+
});
|
|
4355
|
+
});
|
|
4356
|
+
Transforms.select(editor, startPoint);
|
|
4357
|
+
}
|
|
4358
|
+
return;
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
};
|
|
4363
|
+
function getRewrittenCellPath(editor, startCellPath, endCellPath) {
|
|
4364
|
+
if (CellPath.columnIndex(startCellPath) < CellPath.columnIndex(endCellPath)) {
|
|
4365
|
+
const [, rewrittenCellPath] = Editor.next(editor, {
|
|
4366
|
+
at: startCellPath
|
|
4367
|
+
});
|
|
4368
|
+
return rewrittenCellPath;
|
|
4369
|
+
} else if (CellPath.columnIndex(startCellPath) > CellPath.columnIndex(endCellPath)) {
|
|
4370
|
+
return null;
|
|
4371
|
+
} else if (CellPath.columnIndex(startCellPath) === 0) {
|
|
4372
|
+
return endCellPath;
|
|
4373
|
+
} else {
|
|
4374
|
+
return startCellPath;
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
4377
|
+
|
|
4378
|
+
function withFixedColumns(editor) {
|
|
4379
|
+
const {
|
|
4380
|
+
deleteBackward,
|
|
4381
|
+
deleteForward,
|
|
4382
|
+
deleteFragment
|
|
4383
|
+
} = editor;
|
|
4384
|
+
editor.insertBreak = () => {
|
|
4385
|
+
const cellMatch = Cell.match(editor);
|
|
4386
|
+
if (!cellMatch) {
|
|
4387
|
+
return;
|
|
4388
|
+
}
|
|
4389
|
+
const [cellNode, cellPath] = cellMatch;
|
|
4390
|
+
const rowPath = Path.parent(cellPath);
|
|
4391
|
+
const columnIndex = CellPath.columnIndex(cellPath);
|
|
4392
|
+
const newRowPath = Path.next(rowPath);
|
|
4393
|
+
const [beforeNodes, afterNodes] = Cell.splitChildren(editor, {
|
|
4394
|
+
cellNode,
|
|
4395
|
+
point: editor.selection.anchor
|
|
4396
|
+
});
|
|
4397
|
+
if (columnIndex === 0) {
|
|
4398
|
+
CellTransforms.replaceContent(editor, afterNodes, {
|
|
4399
|
+
cellPath
|
|
4400
|
+
});
|
|
4401
|
+
const newRow = {
|
|
4402
|
+
type: 'row',
|
|
4403
|
+
children: [{
|
|
4404
|
+
type: 'label',
|
|
4405
|
+
children: beforeNodes
|
|
4406
|
+
}, {
|
|
4407
|
+
type: 'value',
|
|
4408
|
+
children: [{
|
|
4409
|
+
text: ''
|
|
4410
|
+
}]
|
|
4411
|
+
}]
|
|
4412
|
+
};
|
|
4413
|
+
Transforms.insertNodes(editor, newRow, {
|
|
4414
|
+
at: rowPath
|
|
4415
|
+
});
|
|
4416
|
+
} else {
|
|
4417
|
+
CellTransforms.replaceContent(editor, beforeNodes, {
|
|
4418
|
+
cellPath
|
|
4419
|
+
});
|
|
4420
|
+
const newRow = {
|
|
4421
|
+
type: 'row',
|
|
4422
|
+
children: [{
|
|
4423
|
+
type: 'label',
|
|
4424
|
+
children: [{
|
|
4425
|
+
text: ''
|
|
4426
|
+
}]
|
|
4427
|
+
}, {
|
|
4428
|
+
type: 'value',
|
|
4429
|
+
children: afterNodes
|
|
4430
|
+
}]
|
|
4431
|
+
};
|
|
4432
|
+
Transforms.insertNodes(editor, newRow, {
|
|
4433
|
+
at: newRowPath
|
|
4434
|
+
});
|
|
4435
|
+
}
|
|
4436
|
+
Transforms.select(editor, {
|
|
4437
|
+
path: [...newRowPath, afterNodes.length ? columnIndex : 0, 0],
|
|
4438
|
+
offset: 0
|
|
4439
|
+
});
|
|
4440
|
+
};
|
|
4441
|
+
editor.deleteBackward = function () {
|
|
4442
|
+
if (!editor.selection || !Range.isCollapsed(editor.selection)) {
|
|
4443
|
+
return;
|
|
4444
|
+
}
|
|
4445
|
+
const cellMatch = Cell.match(editor);
|
|
4446
|
+
if (!cellMatch) {
|
|
4447
|
+
return;
|
|
4448
|
+
}
|
|
4449
|
+
const [, cellPath] = cellMatch;
|
|
4450
|
+
if (!Editor.isStart(editor, editor.selection.anchor, cellPath)) {
|
|
4451
|
+
deleteBackward.apply(this, arguments);
|
|
4452
|
+
return;
|
|
4453
|
+
}
|
|
4454
|
+
const [row, rowPath] = Editor.parent(editor, cellPath);
|
|
4455
|
+
const previousRowMatch = Editor.previous(editor, {
|
|
4456
|
+
at: rowPath
|
|
4457
|
+
});
|
|
4458
|
+
if (CellPath.columnIndex(cellPath) === 0) {
|
|
4459
|
+
if (previousRowMatch) {
|
|
4460
|
+
const [previousRow, previousRowPath] = previousRowMatch;
|
|
4461
|
+
if (Node$1.string(previousRow) === '') {
|
|
4462
|
+
Transforms.delete(editor, {
|
|
4463
|
+
at: previousRowPath
|
|
4464
|
+
});
|
|
4465
|
+
} else if (Node$1.string(row) === '') {
|
|
4466
|
+
Transforms.delete(editor, {
|
|
4467
|
+
at: rowPath
|
|
4468
|
+
});
|
|
4469
|
+
} else if (Node$1.string(Node$1.child(previousRow, 1)) === '') {
|
|
4470
|
+
TableTransforms.deleteRange(editor, [Editor.end(editor, [...previousRowPath, 0]), editor.selection.anchor]);
|
|
4471
|
+
} else {
|
|
4472
|
+
Transforms.select(editor, Editor.end(editor, previousRowPath));
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
} else {
|
|
4476
|
+
if (previousRowMatch) {
|
|
4477
|
+
const [, previousRowPath] = previousRowMatch;
|
|
4478
|
+
if (Node$1.string(Node$1.child(row, 0)) === '') {
|
|
4479
|
+
TableTransforms.deleteRange(editor, [Editor.end(editor, previousRowPath), editor.selection.anchor]);
|
|
4480
|
+
return;
|
|
4481
|
+
}
|
|
4482
|
+
}
|
|
4483
|
+
Transforms.select(editor, Editor.end(editor, Path.previous(cellPath)));
|
|
4484
|
+
}
|
|
4485
|
+
};
|
|
4486
|
+
editor.deleteForward = () => {
|
|
4487
|
+
if (!editor.selection || !Range.isCollapsed(editor.selection)) {
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
const cellMatch = Cell.match(editor);
|
|
4491
|
+
if (!cellMatch) {
|
|
4492
|
+
return;
|
|
4493
|
+
}
|
|
4494
|
+
const [, cellPath] = cellMatch;
|
|
4495
|
+
if (!Editor.isEnd(editor, editor.selection.anchor, cellPath)) {
|
|
4496
|
+
deleteForward();
|
|
4497
|
+
return;
|
|
4498
|
+
}
|
|
4499
|
+
const columnIndex = cellPath[cellPath.length - 1];
|
|
4500
|
+
const [row, rowPath] = Editor.parent(editor, cellPath);
|
|
4501
|
+
const nextRowMatch = Editor.next(editor, {
|
|
4502
|
+
at: rowPath
|
|
4503
|
+
});
|
|
4504
|
+
if (columnIndex === 0) {
|
|
4505
|
+
if (Node$1.string(row) === '') {
|
|
4506
|
+
const previousRowMatch = Editor.previous(editor, {
|
|
4507
|
+
at: rowPath
|
|
4508
|
+
});
|
|
4509
|
+
if (previousRowMatch || nextRowMatch) {
|
|
4510
|
+
Transforms.delete(editor, {
|
|
4511
|
+
at: rowPath
|
|
4512
|
+
});
|
|
4513
|
+
if (Node$1.has(editor, rowPath)) {
|
|
4514
|
+
Transforms.select(editor, Editor.start(editor, rowPath));
|
|
4515
|
+
} else {
|
|
4516
|
+
const [, previousRowPath] = previousRowMatch;
|
|
4517
|
+
Transforms.select(editor, Editor.start(editor, previousRowPath));
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
} else {
|
|
4521
|
+
if (nextRowMatch) {
|
|
4522
|
+
const [, nextRowPath] = nextRowMatch;
|
|
4523
|
+
if (Node$1.string(Node$1.child(row, 1)) === '') {
|
|
4524
|
+
TableTransforms.deleteRange(editor, [editor.selection.anchor, Editor.start(editor, nextRowPath)]);
|
|
4525
|
+
return;
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
Transforms.select(editor, Editor.start(editor, Path.next(cellPath)));
|
|
4529
|
+
}
|
|
4530
|
+
} else {
|
|
4531
|
+
if (nextRowMatch) {
|
|
4532
|
+
const [nextRow, nextRowPath] = nextRowMatch;
|
|
4533
|
+
if (Node$1.string(nextRow) === '') {
|
|
4534
|
+
Transforms.delete(editor, {
|
|
4535
|
+
at: nextRowPath
|
|
4536
|
+
});
|
|
4537
|
+
} else if (Node$1.string(Node$1.child(nextRow, 0)) === '') {
|
|
4538
|
+
TableTransforms.deleteRange(editor, [editor.selection.anchor, Editor.start(editor, [...nextRowPath, 1])]);
|
|
4539
|
+
} else {
|
|
4540
|
+
Transforms.select(editor, Editor.start(editor, nextRowPath));
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4543
|
+
}
|
|
4544
|
+
};
|
|
4545
|
+
editor.deleteFragment = () => {
|
|
4546
|
+
if (editor.selection && Range.isExpanded(editor.selection)) {
|
|
4547
|
+
if (TableTransforms.deleteRange(editor, Range.edges(editor.selection))) {
|
|
4548
|
+
return;
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
deleteFragment();
|
|
4552
|
+
};
|
|
4553
|
+
editor.insertData = function (data) {
|
|
4554
|
+
const fragment = data.getData('application/x-slate-fragment');
|
|
4555
|
+
if (fragment) {
|
|
4556
|
+
const decoded = decodeURIComponent(window.atob(fragment));
|
|
4557
|
+
const parsed = JSON.parse(decoded);
|
|
4558
|
+
if (parsed.every(element => element['type'] === 'row')) {
|
|
4559
|
+
editor.insertFragment(parsed);
|
|
4560
|
+
return;
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
const text = data.getData('text/plain');
|
|
4564
|
+
if (text) {
|
|
4565
|
+
editor.insertText(text);
|
|
4566
|
+
}
|
|
4567
|
+
};
|
|
4568
|
+
editor.insertFragment = function (fragment) {
|
|
4569
|
+
if (fragment.length === 1 && fragment[0].children.length === 1) {
|
|
4570
|
+
Transforms.insertFragment(editor, fragment[0].children[0].children);
|
|
4571
|
+
} else {
|
|
4572
|
+
const rowMatch = Row.match(editor);
|
|
4573
|
+
if (rowMatch) {
|
|
4574
|
+
ensureLabelAndValueCells(fragment);
|
|
4575
|
+
const [, rowPath] = rowMatch;
|
|
4576
|
+
const nextRowPath = Path.next(rowPath);
|
|
4577
|
+
const pathRef = Editor.pathRef(editor, nextRowPath);
|
|
4578
|
+
Transforms.insertNodes(editor, fragment, {
|
|
4579
|
+
at: nextRowPath
|
|
4580
|
+
});
|
|
4581
|
+
Transforms.select(editor, Editor.end(editor, Path.previous(pathRef.unref())));
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4584
|
+
function ensureLabelAndValueCells(fragment) {
|
|
4585
|
+
if (fragment[0].children.length === 1) {
|
|
4586
|
+
fragment[0].children.unshift({
|
|
4587
|
+
type: 'label',
|
|
4588
|
+
children: [{
|
|
4589
|
+
text: ''
|
|
4590
|
+
}]
|
|
4591
|
+
});
|
|
4592
|
+
}
|
|
4593
|
+
if (fragment[fragment.length - 1].children.length === 1) {
|
|
4594
|
+
fragment[fragment.length - 1].children.push({
|
|
4595
|
+
type: 'value',
|
|
4596
|
+
children: [{
|
|
4597
|
+
text: ''
|
|
4598
|
+
}]
|
|
4599
|
+
});
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
};
|
|
4603
|
+
return editor;
|
|
4604
|
+
}
|
|
4605
|
+
|
|
4606
|
+
function handleTableNavigation(editor, event, stacked) {
|
|
4607
|
+
if (stacked) {
|
|
4608
|
+
return;
|
|
4609
|
+
}
|
|
4610
|
+
const {
|
|
4611
|
+
selection
|
|
4612
|
+
} = editor;
|
|
4613
|
+
if (selection && Range.isCollapsed(selection)) {
|
|
4614
|
+
const cellMatch = Cell.match(editor);
|
|
4615
|
+
if (cellMatch) {
|
|
4616
|
+
const [, cellPath] = cellMatch;
|
|
4617
|
+
const rowPath = cellPath.slice(0, -1);
|
|
4618
|
+
if (event.key === 'ArrowUp' && Cell.inFirstLine(editor, selection.anchor)) {
|
|
4619
|
+
event.preventDefault();
|
|
4620
|
+
if (rowPath[rowPath.length - 1] > 0) {
|
|
4621
|
+
const previousRowPath = Path.previous(rowPath);
|
|
4622
|
+
const targetPath = [...previousRowPath, cellPath[cellPath.length - 1]];
|
|
4623
|
+
Transforms.select(editor, Cell.getPointAtStartOfLastLine(editor, Editor.start(editor, targetPath).path));
|
|
4624
|
+
}
|
|
4625
|
+
} else if (event.key === 'ArrowDown' && Cell.inLastLine(editor, selection.anchor)) {
|
|
4626
|
+
event.preventDefault();
|
|
4627
|
+
const nextRowPath = Path.next(rowPath);
|
|
4628
|
+
const targetPath = [...nextRowPath, cellPath[cellPath.length - 1]];
|
|
4629
|
+
if (Node$1.has(editor, targetPath)) {
|
|
4630
|
+
Transforms.select(editor, Editor.start(editor, targetPath));
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
}
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
|
|
4637
|
+
var styles$h = {"placeholder":"placeholders-module_placeholder__2j2eo"};
|
|
4638
|
+
|
|
4639
|
+
function createRenderElementWithPlaceholder(options) {
|
|
4640
|
+
const renderElement = createRenderElement(options);
|
|
4641
|
+
return function ({
|
|
4642
|
+
attributes,
|
|
4643
|
+
children,
|
|
4644
|
+
element
|
|
4645
|
+
}) {
|
|
4646
|
+
if ((element.type === 'label' || element.type === 'value') && options.showPlaceholders && Node$1.string(element) === '') {
|
|
4647
|
+
children = /*#__PURE__*/React.createElement(React.Fragment, null, children, /*#__PURE__*/React.createElement("span", {
|
|
4648
|
+
contentEditable: false,
|
|
4649
|
+
className: styles$h.placeholder,
|
|
4650
|
+
"data-text": element.type === 'label' ? options.labelPlaceholder : options.valuePlaceholder
|
|
4651
|
+
}));
|
|
4652
|
+
}
|
|
4653
|
+
return renderElement({
|
|
4654
|
+
attributes,
|
|
4655
|
+
children,
|
|
4656
|
+
element
|
|
4657
|
+
});
|
|
4658
|
+
};
|
|
4659
|
+
}
|
|
4660
|
+
|
|
4661
|
+
const EditableTable = React.memo(function EditableTable({
|
|
4662
|
+
value,
|
|
4663
|
+
onChange,
|
|
4664
|
+
className,
|
|
4665
|
+
labelScaleCategory = 'body',
|
|
4666
|
+
valueScaleCategory = 'body',
|
|
4667
|
+
labelPlaceholder,
|
|
4668
|
+
valuePlaceholder,
|
|
4669
|
+
floatingControlsPosition = 'below',
|
|
4670
|
+
stackedInPhoneLayout = false
|
|
4671
|
+
}) {
|
|
4672
|
+
const editor = useMemo(() => withFixedColumns(withLinks(withLineBreakNormalization(withReact(withHistory(createEditor()))))), []);
|
|
4673
|
+
const {
|
|
4674
|
+
isSelected
|
|
4675
|
+
} = useContentElementEditorState();
|
|
4676
|
+
const phoneLayout = usePhoneLayout();
|
|
4677
|
+
const stacked = stackedInPhoneLayout && phoneLayout;
|
|
4678
|
+
const handleLineBreaks = useLineBreakHandler(editor);
|
|
4679
|
+
const handleShortcuts = useShortcutHandler(editor);
|
|
4680
|
+
const handleKeyDown = useCallback(event => {
|
|
4681
|
+
handleLineBreaks(event);
|
|
4682
|
+
handleShortcuts(event);
|
|
4683
|
+
handleTableNavigation(editor, event, stacked);
|
|
4684
|
+
}, [editor, handleLineBreaks, handleShortcuts, stacked]);
|
|
4685
|
+
const [cachedValue, setCachedValue] = useCachedValue(value, {
|
|
4686
|
+
defaultValue: [{
|
|
4687
|
+
type: 'row',
|
|
4688
|
+
children: [{
|
|
4689
|
+
type: 'label',
|
|
4690
|
+
children: [{
|
|
4691
|
+
text: ''
|
|
4692
|
+
}]
|
|
4693
|
+
}, {
|
|
4694
|
+
type: 'value',
|
|
4695
|
+
children: [{
|
|
4696
|
+
text: ''
|
|
4697
|
+
}]
|
|
4698
|
+
}]
|
|
4699
|
+
}],
|
|
4700
|
+
onDebouncedChange: onChange
|
|
4701
|
+
});
|
|
4702
|
+
const showPlaceholders = cachedValue.length === 1;
|
|
4703
|
+
const renderElement = useMemo(() => wrapRenderElementWithLinkPreview(createRenderElementWithPlaceholder({
|
|
4704
|
+
labelScaleCategory,
|
|
4705
|
+
valueScaleCategory,
|
|
4706
|
+
labelPlaceholder,
|
|
4707
|
+
valuePlaceholder,
|
|
4708
|
+
showPlaceholders
|
|
4709
|
+
})), [labelScaleCategory, valueScaleCategory, labelPlaceholder, valuePlaceholder, showPlaceholders]);
|
|
4710
|
+
return /*#__PURE__*/React.createElement(Slate, {
|
|
4711
|
+
editor: editor,
|
|
4712
|
+
value: cachedValue,
|
|
4713
|
+
onChange: setCachedValue
|
|
4714
|
+
}, /*#__PURE__*/React.createElement(LinkTooltipProvider, {
|
|
4715
|
+
disabled: editor.selection && !Range.isCollapsed(editor.selection),
|
|
4716
|
+
position: floatingControlsPosition
|
|
4717
|
+
}, /*#__PURE__*/React.createElement(HoveringToolbar, {
|
|
4718
|
+
position: floatingControlsPosition
|
|
4719
|
+
}), /*#__PURE__*/React.createElement("table", {
|
|
4720
|
+
className: classNames(className, tableStyles.table, {
|
|
4721
|
+
[selectedClassName]: isSelected
|
|
4722
|
+
}),
|
|
4723
|
+
"data-stacked": stacked ? '' : undefined
|
|
4724
|
+
}, /*#__PURE__*/React.createElement(Editable, {
|
|
4725
|
+
as: "tbody",
|
|
4726
|
+
decorate: decorateLineBreaks,
|
|
4727
|
+
onKeyDown: handleKeyDown,
|
|
4728
|
+
renderElement: renderElement,
|
|
4729
|
+
renderLeaf: renderLeafWithLineBreakDecoration
|
|
4730
|
+
}))));
|
|
4731
|
+
});
|
|
4732
|
+
|
|
4733
|
+
var styles$i = {"wrapper":"EditableLink-module_wrapper__2sbJy"};
|
|
4734
|
+
|
|
4735
|
+
function EditableLink({
|
|
4736
|
+
className,
|
|
4737
|
+
href,
|
|
4738
|
+
openInNewTab,
|
|
4739
|
+
children,
|
|
4740
|
+
onChange,
|
|
4741
|
+
onClick,
|
|
4742
|
+
linkPreviewDisabled,
|
|
4743
|
+
linkPreviewPosition = 'below',
|
|
4744
|
+
linkPreviewAlign = 'center',
|
|
4745
|
+
floatingStrategy,
|
|
4746
|
+
actionButtonPosition = 'outside',
|
|
4747
|
+
actionButtonVisible = 'whenSelected',
|
|
4748
|
+
actionButtonPortal,
|
|
4749
|
+
allowRemove = false
|
|
4750
|
+
}) {
|
|
4751
|
+
const selectLinkDestination = useSelectLinkDestination();
|
|
4752
|
+
const {
|
|
4753
|
+
t
|
|
4754
|
+
} = useI18n({
|
|
4755
|
+
locale: 'ui'
|
|
4756
|
+
});
|
|
4757
|
+
const {
|
|
4758
|
+
isSelected: inSelectedContentElement
|
|
4759
|
+
} = useContentElementEditorState();
|
|
4760
|
+
const {
|
|
4761
|
+
isSelected: inSelectedWidget
|
|
4762
|
+
} = useWidgetEditorState();
|
|
4763
|
+
if (actionButtonVisible === 'whenSelected') {
|
|
4764
|
+
actionButtonVisible = inSelectedContentElement || inSelectedWidget;
|
|
4765
|
+
}
|
|
4766
|
+
function handleSelectLinkDestination() {
|
|
4767
|
+
selectLinkDestination().then(onChange, () => {});
|
|
4768
|
+
}
|
|
4769
|
+
function handleRemoveLink() {
|
|
4770
|
+
onChange(null);
|
|
4771
|
+
}
|
|
4772
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
4773
|
+
className: styles$i.wrapper
|
|
4774
|
+
}, /*#__PURE__*/React.createElement(LinkTooltipProvider, {
|
|
4775
|
+
position: linkPreviewPosition,
|
|
4776
|
+
floatingStrategy: floatingStrategy,
|
|
4777
|
+
align: linkPreviewAlign,
|
|
4778
|
+
onClick: onClick,
|
|
4779
|
+
gap: 5
|
|
4780
|
+
}, /*#__PURE__*/React.createElement(LinkPreview, {
|
|
4781
|
+
disabled: linkPreviewDisabled,
|
|
4782
|
+
href: href,
|
|
4783
|
+
openInNewTab: openInNewTab,
|
|
4784
|
+
className: className
|
|
4785
|
+
}, children)), actionButtonVisible && /*#__PURE__*/React.createElement(ActionButtons, {
|
|
4786
|
+
buttons: [{
|
|
4787
|
+
icon: 'link',
|
|
4788
|
+
text: href ? t('pageflow_scrolled.inline_editing.change_link_destination') : t('pageflow_scrolled.inline_editing.select_link_destination'),
|
|
4789
|
+
onClick: handleSelectLinkDestination
|
|
4790
|
+
}, ...(allowRemove && href ? [{
|
|
4791
|
+
icon: 'unlink',
|
|
4792
|
+
iconOnly: true,
|
|
4793
|
+
text: t('pageflow_scrolled.inline_editing.remove_link'),
|
|
4794
|
+
onClick: handleRemoveLink
|
|
4795
|
+
}] : [])],
|
|
4796
|
+
position: actionButtonPosition,
|
|
4797
|
+
portal: actionButtonPortal,
|
|
4798
|
+
floatingStrategy: floatingStrategy
|
|
4799
|
+
}));
|
|
4800
|
+
}
|
|
4801
|
+
|
|
4802
|
+
function WidgetSelectionRect({
|
|
4803
|
+
children
|
|
4804
|
+
}) {
|
|
4805
|
+
const {
|
|
4806
|
+
select,
|
|
4807
|
+
isSelected
|
|
4808
|
+
} = useWidgetEditorState();
|
|
4809
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
4810
|
+
className: classNames(styles$3.wrapper, {
|
|
4811
|
+
[styles$3.selected]: isSelected
|
|
4812
|
+
}),
|
|
4813
|
+
onClick: () => select()
|
|
4814
|
+
}, children);
|
|
4815
|
+
}
|
|
4816
|
+
|
|
4817
|
+
function PhonePlatformProvider({
|
|
4818
|
+
children
|
|
4819
|
+
}) {
|
|
4820
|
+
const [phoneEmulationMode, setPhoneEmulationMode] = useState(false);
|
|
4821
|
+
useEffect(() => {
|
|
4822
|
+
window.addEventListener('message', receive);
|
|
4823
|
+
function receive(event) {
|
|
4824
|
+
if (event.data.type === 'CHANGE_EMULATION_MODE') {
|
|
4825
|
+
if (event.data['payload'] === 'phone') {
|
|
4826
|
+
setPhoneEmulationMode(true);
|
|
4827
|
+
} else {
|
|
4828
|
+
setPhoneEmulationMode(false);
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
return () => window.removeEventListener('message', receive);
|
|
4833
|
+
});
|
|
4834
|
+
return /*#__PURE__*/React.createElement(PhonePlatformContext.Provider, {
|
|
4835
|
+
value: phoneEmulationMode
|
|
4836
|
+
}, children);
|
|
4837
|
+
}
|
|
4838
|
+
|
|
4839
|
+
function Placeholder() {
|
|
4840
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
4841
|
+
className: styles$j.placeholder
|
|
4842
|
+
}, /*#__PURE__*/React.createElement("svg", {
|
|
4843
|
+
width: "100%",
|
|
4844
|
+
height: "100%",
|
|
4845
|
+
preserveAspectRatio: "none"
|
|
4846
|
+
}, /*#__PURE__*/React.createElement("line", {
|
|
4847
|
+
x1: "0",
|
|
4848
|
+
y1: "0",
|
|
4849
|
+
x2: "100%",
|
|
4850
|
+
y2: "100%",
|
|
4851
|
+
stroke: "rgba(255,255,255,0.2)",
|
|
4852
|
+
strokeWidth: "1"
|
|
4853
|
+
}), /*#__PURE__*/React.createElement("line", {
|
|
4854
|
+
x1: "100%",
|
|
4855
|
+
y1: "0",
|
|
4856
|
+
x2: "0",
|
|
4857
|
+
y2: "100%",
|
|
4858
|
+
stroke: "rgba(255,255,255,0.2)",
|
|
4859
|
+
strokeWidth: "1"
|
|
4860
|
+
})));
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
const extensions = {
|
|
4864
|
+
decorators: {
|
|
4865
|
+
Entry: EntryDecorator,
|
|
4866
|
+
Content: ContentDecorator,
|
|
4867
|
+
Section: SectionDecorator,
|
|
4868
|
+
ContentElement: ContentElementDecorator,
|
|
4869
|
+
SelectableWidget: SelectableWidgetDecorator,
|
|
4870
|
+
Widget: WidgetDecorator,
|
|
4871
|
+
Backdrop: BackdropDecorator,
|
|
4872
|
+
BackgroundContentElement: BackgroundContentElementDecorator,
|
|
4873
|
+
Foreground: ForegroundDecorator
|
|
4874
|
+
},
|
|
4875
|
+
alternatives: {
|
|
4876
|
+
LayoutWithPlaceholder,
|
|
4877
|
+
EditableText,
|
|
4878
|
+
EditableInlineText,
|
|
4879
|
+
EditableTable,
|
|
4880
|
+
EditableLink,
|
|
4881
|
+
LinkTooltipProvider,
|
|
4882
|
+
WidgetSelectionRect,
|
|
4883
|
+
ActionButton,
|
|
4884
|
+
ActionButtons,
|
|
4885
|
+
PhonePlatformProvider,
|
|
4886
|
+
Placeholder
|
|
4887
|
+
}
|
|
4888
|
+
};
|
|
4889
|
+
|
|
4890
|
+
export { extensions };
|