 css/entity_embed.media_library.dialog.css  | 10 ++++++
 entity_embed.libraries.yml                 |  6 ++++
 entity_embed.module                        | 52 ++++++++++++++++++++++++++++++
 js/plugins/drupalentity/plugin.js          | 29 +++++++++++++++--
 src/Plugin/CKEditorPlugin/DrupalEntity.php | 41 +++++++++++++++++++++--
 5 files changed, 134 insertions(+), 4 deletions(-)

diff --git a/css/entity_embed.media_library.dialog.css b/css/entity_embed.media_library.dialog.css
new file mode 100644
index 0000000..35307a3
--- /dev/null
+++ b/css/entity_embed.media_library.dialog.css
@@ -0,0 +1,10 @@
+/**
+ * @file
+ * Styles for Media Library's modal windows.
+ */
+
+/* Work around dialogOptions imposed by Drupal.ckeditor.openDialog(). */
+.ui-dialog--narrow.media-library-widget-modal {
+  width: 75% !important;
+  max-width: none;
+}
diff --git a/entity_embed.libraries.yml b/entity_embed.libraries.yml
index d56978d..d428a4a 100644
--- a/entity_embed.libraries.yml
+++ b/entity_embed.libraries.yml
@@ -16,3 +16,9 @@ caption:
       css/entity_embed.filter.caption.css: {}
   dependencies:
     - filter/caption
+
+media_library.dialog:
+  version: VERSION
+  css:
+    theme:
+      css/entity_embed.media_library.dialog.css: {}
diff --git a/entity_embed.module b/entity_embed.module
index bfe2f8f..861d6ae 100644
--- a/entity_embed.module
+++ b/entity_embed.module
@@ -292,3 +292,55 @@ function entity_embed_ckeditor_css_alter(array &$css) {
   $css[] = drupal_get_path('module', 'system') . '/css/components/hidden.module.css';
   $css[] = drupal_get_path('module', 'entity_embed') . '/css/entity_embed.editor.css';
 }
+
+/**
+ * Implements hook_form_views_form_media_library_widget_alter().
+ *
+ * @see media_library.module
+ */
+function entity_embed_form_views_form_media_library_widget_alter(&$form, FormStateInterface $form_state, $context) {
+  // When the Media Library is triggered from the text editor, override the
+  // submit handler.
+  if (\Drupal::request()->query->get('media_library_opener_id')) {
+    $form['#attached']['library'][] = 'editor/drupal.editor.dialog';
+    $form['actions']['submit']['#ajax']['callback'] = 'entity_embed_form_views_form_media_library_widget_ajax_update';
+  }
+}
+
+/**
+ * Submit handler for the media library select form.
+ *
+ * Modified version of MediaLibrarySelectForm::updateWidget() until
+ * https://www.drupal.org/project/drupal/issues/3044649 is available.
+ *
+ * @param array $form
+ *   An associative array containing the structure of the form.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ *   The current state of the form.
+ *
+ * @return \Drupal\Core\Ajax\AjaxResponse
+ *   A command to send the selection to the text editor.
+ *
+ * @see \Drupal\media_library\Plugin\views\field\MediaLibrarySelectForm::updateWidget
+ * @see https://www.drupal.org/project/drupal/issues/3044649
+ */
+function entity_embed_form_views_form_media_library_widget_ajax_update(array &$form, FormStateInterface $form_state) {
+  $field_id = $form_state->getTriggeringElement()['#field_id'];
+  $selected_media_id = $form_state->getValue($field_id, []);
+  $selected_media = \Drupal\media\Entity\Media::load($selected_media_id);
+
+  $response = new \Drupal\Core\Ajax\AjaxResponse();
+  $values = [
+    'attributes' => [
+      'data-entity-type' => 'media',
+      'data-entity-uuid' => $selected_media->uuid(),
+      'data-entity-embed-display' => 'entity_reference:entity_reference_entity_view',
+      'data-entity-embed-display-settings' => '{"view_mode":"embed"}',
+      'data-embed-button' => 'media',
+    ],
+  ];
+  $response->addCommand(new \Drupal\editor\Ajax\EditorDialogSave($values));
+  $response->addCommand(new \Drupal\Core\Ajax\CloseDialogCommand());
+
+  return $response;
+}
diff --git a/js/plugins/drupalentity/plugin.js b/js/plugins/drupalentity/plugin.js
index 895a75b..2c3665a 100644
--- a/js/plugins/drupalentity/plugin.js
+++ b/js/plugins/drupalentity/plugin.js
@@ -101,6 +101,12 @@
           var existingElement = getSelectedEmbeddedEntity(editor);
           var existingWidget = (existingElement) ? editor.widgets.getByElement(existingElement, true) : null;
 
+          // Until https://www.drupal.org/project/drupal/issues/3023809 lands, the current selection cannot be shown, so
+          // avoid opening the media library dialog again for existing embedded media.
+          if (existingWidget && existingWidget.data.attributes['data-embed-button'] === 'media') {
+            return;
+          }
+
           var existingValues = {};
 
           // Host entity's langcode added in entity_embed_field_widget_form_alter().
@@ -144,8 +150,21 @@
             editor.fire('saveSnapshot');
           };
 
-          // Open the entity embed dialog for corresponding EmbedButton.
-          Drupal.ckeditor.openDialog(editor, Drupal.url('entity-embed/dialog/' + editor.config.drupal.format + '/' + embed_button_id), existingValues, saveCallback, dialogSettings);
+          // Open the entity embed dialog for corresponding EmbedButton, unless it's for the Media entity type and the
+          // Media Library module is installed: then open the Media Library dialog.
+          if (embed_button_id === 'media' && editor.config.DrupalEntity_mediaLibraryUrl !== undefined) {
+            // @see \Drupal\media_library\MediaLibraryUiBuilder::dialogOptions()
+            Drupal.ckeditor.openDialog(
+              editor,
+              editor.config.DrupalEntity_mediaLibraryUrl,
+              existingValues,
+              saveCallback,
+              editor.config.DrupalEntity_mediaLibraryDialogOptions
+            );
+          }
+          else {
+            Drupal.ckeditor.openDialog(editor, Drupal.url('entity-embed/dialog/' + editor.config.drupal.format + '/' + embed_button_id), existingValues, saveCallback, dialogSettings);
+          }
         }
       });
 
@@ -342,6 +361,12 @@
         for (var key in editor.config.DrupalEntity_buttons) {
           var button = editor.config.DrupalEntity_buttons[key];
 
+          // Until https://www.drupal.org/project/drupal/issues/3023809 lands, the current selection cannot be shown, so
+          // avoid opening the media library dialog again for existing embedded media.
+          if (button.id === 'media') {
+            continue;
+          }
+
           var label = Drupal.t('Edit @buttonLabel', { '@buttonLabel': button.label });
 
           editor.addMenuItem('drupalentity_' + button.id, {
diff --git a/src/Plugin/CKEditorPlugin/DrupalEntity.php b/src/Plugin/CKEditorPlugin/DrupalEntity.php
index 3628cbf..04ea724 100644
--- a/src/Plugin/CKEditorPlugin/DrupalEntity.php
+++ b/src/Plugin/CKEditorPlugin/DrupalEntity.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\entity_embed\Plugin\CKEditorPlugin;
 
+use Drupal\Core\Url;
 use Drupal\editor\Entity\Editor;
 use Drupal\embed\EmbedButtonInterface;
 use Drupal\embed\EmbedCKEditorPluginBase;
+use Drupal\embed\Entity\EmbedButton;
+use Drupal\media\Entity\MediaType;
 
 /**
  * Defines the "drupalentity" plugin.
@@ -33,15 +36,49 @@ class DrupalEntity extends EmbedCKEditorPluginBase {
     return drupal_get_path('module', 'entity_embed') . '/js/plugins/drupalentity/plugin.js';
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLibraries(Editor $editor) {
+    $libraries = parent::getLibraries($editor);
+    $libraries[] = 'entity_embed/media_library.dialog';
+    return $libraries;
+  }
+
   /**
    * {@inheritdoc}
    */
   public function getConfig(Editor $editor) {
-    return [
+    $buttons = $this->getButtons();
+    $config = [
       'DrupalEntity_dialogTitleAdd' => t('Insert entity'),
       'DrupalEntity_dialogTitleEdit' => t('Edit entity'),
-      'DrupalEntity_buttons' => $this->getButtons(),
+      'DrupalEntity_buttons' => $buttons,
     ];
+    if (\Drupal::moduleHandler()->moduleExists('media_library') && class_exists(\Drupal\media_library\MediaLibraryUiBuilder::class) && array_key_exists('media', $buttons)) {
+      $media_button = EmbedButton::load('media');
+      assert($media_button instanceof EmbedButtonInterface);
+
+      $valid_media_type_ids = array_keys(MediaType::loadMultiple());
+      $embed_button_enabled_bundles = $media_button->getTypeSetting('bundles', []);
+      $allowed_media_type_ids = empty($embed_button_enabled_bundles)
+        ? $valid_media_type_ids
+        : array_intersect($embed_button_enabled_bundles, $valid_media_type_ids);
+
+      $state = \Drupal\media_library\MediaLibraryState::create(
+        'editor_entity_embed',
+        $allowed_media_type_ids,
+        in_array('image', $allowed_media_type_ids, TRUE) ? 'image' : reset($allowed_media_type_ids),
+        1
+      );
+      $config['DrupalEntity_mediaLibraryUrl'] = Url::fromRoute(
+        'media_library.ui',
+        [],
+        ['query' => $state->all()]
+      )->toString(TRUE)->getGeneratedUrl();
+      $config['DrupalEntity_mediaLibraryDialogOptions'] = \Drupal\media_library\MediaLibraryUiBuilder::dialogOptions();
+    }
+    return $config;
   }
 
 }
