From 2104514f6e7b64e49b34effb1e6fd0ac90720b0b Mon Sep 17 00:00:00 2001
From: Ellet <hello@freshplatform.net>
Date: Sat, 11 Nov 2023 04:34:41 +0300
Subject: [PATCH] Update flutter_quill and flutter_quill_extensions (#1520)

* Update flutter_quill and flutter_quill_extensions
---
 CHANGELOG.md                                  |   8 +
 doc/todo.md                                   |   1 +
 .../android/app/src/main/AndroidManifest.xml  |   6 +
 example/lib/pages/home_page.dart              |  44 ++-
 example/pubspec.yaml                          |   5 +-
 example/web/index.html                        |   5 +
 flutter_quill_extensions/CHANGELOG.md         |   4 +
 .../embeds/editor/image/image.dart            |  41 ++-
 .../embeds/editor/image/image_menu.dart       |   9 +-
 .../toolbar/camera_button/camera_button.dart  |  15 +-
 .../embeds/widgets/image_resizer.dart         |   4 +-
 .../models/config/editor/image/image.dart     |  18 +-
 flutter_quill_extensions/pubspec.yaml         |   2 +-
 lib/flutter_quill.dart                        |   2 +
 .../models/config/editor/configurations.dart  |   8 +-
 .../config/raw_editor/configurations.dart     | 290 ++++++++++++++++++
 lib/src/utils/extensions/build_context.dart   |   2 +-
 lib/src/utils/string.dart                     |   4 +-
 lib/src/widgets/editor/editor.dart            | 117 +++----
 lib/src/widgets/raw_editor/raw_editor.dart    | 250 +--------------
 .../raw_editor/raw_editor_actions.dart        |  18 +-
 .../widgets/raw_editor/raw_editor_state.dart  | 178 +++++------
 ...editor_state_selection_delegate_mixin.dart |  32 +-
 ..._editor_state_text_input_client_mixin.dart |  37 ++-
 .../widgets/toolbar/buttons/quill_icon.dart   |   8 +
 .../toolbar/buttons/select_header_style.dart  |   2 +
 lib/src/widgets/utils/provider.dart           |   8 +-
 pubspec.yaml                                  |   2 +-
 28 files changed, 642 insertions(+), 478 deletions(-)
 create mode 100644 lib/src/models/config/raw_editor/configurations.dart

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a9b7268..0cba5b33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## [8.4.2]
+- **Breaking change**: The `QuillRawEditor` configurations has been moved to a seperated class, also the `readOnly` has been renamed to `isReadOnly`, if you are using the `QuillEditor` you don't have to change anything
+- Allow the developer to use override the `TextInputAction` in both `QuillRawEditor` and `QuillEditor`
+- You can use now the `QuillRawEditor` without `QuillEditorProvider`
+- Bug fixes
+- Add implementation of image cropping in the `example`
+- Update the `QuillToolbarIconButton` to use the material 3 buttons
+
 ## [8.4.1]
 - Add `copyWith` in `OptionalSize` class
 
diff --git a/doc/todo.md b/doc/todo.md
index 7b8aa9b8..d31c9c73 100644
--- a/doc/todo.md
+++ b/doc/todo.md
@@ -27,6 +27,7 @@ This is a todo list page that added recently and will be updated soon.
 
  1. Improve the Raw Quill Editor, for more [info](https://github.com/singerdmx/flutter-quill/issues/1509)
  2. Provide more support to all the platforms
+ 3. Extract the shared properties between `QuillRawEditorConfigurations` and `QuillEditorConfigurations`
 
 ### Bugs
 
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 1d6e0b64..6176738c 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -42,6 +42,12 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity
+         android:name="com.yalantis.ucrop.UCropActivity"
+         android:screenOrientation="portrait"
+         android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
+
         <!-- Don't delete the meta-data below.
              This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
         <meta-data
diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart
index c36e834c..5880cf2e 100644
--- a/example/lib/pages/home_page.dart
+++ b/example/lib/pages/home_page.dart
@@ -15,6 +15,7 @@ import 'package:flutter_quill/flutter_quill.dart';
 import 'package:flutter_quill_extensions/flutter_quill_extensions.dart';
 import 'package:flutter_quill_extensions/logic/services/image_picker/image_picker.dart';
 import 'package:flutter_quill_extensions/presentation/embeds/widgets/image.dart';
+import 'package:image_cropper/image_cropper.dart';
 import 'package:path/path.dart' as path;
 import 'package:path_provider/path_provider.dart';
 
@@ -455,6 +456,42 @@ class _HomePageState extends State<HomePage> {
     );
   }
 
+  /// When inserting an image
+  OnImageInsertCallback get onImageInsert {
+    return (image, controller) async {
+      final croppedFile = await ImageCropper().cropImage(
+        sourcePath: image,
+        aspectRatioPresets: [
+          CropAspectRatioPreset.square,
+          CropAspectRatioPreset.ratio3x2,
+          CropAspectRatioPreset.original,
+          CropAspectRatioPreset.ratio4x3,
+          CropAspectRatioPreset.ratio16x9
+        ],
+        uiSettings: [
+          AndroidUiSettings(
+            toolbarTitle: 'Cropper',
+            toolbarColor: Colors.deepOrange,
+            toolbarWidgetColor: Colors.white,
+            initAspectRatio: CropAspectRatioPreset.original,
+            lockAspectRatio: false,
+          ),
+          IOSUiSettings(
+            title: 'Cropper',
+          ),
+          WebUiSettings(
+            context: context,
+          ),
+        ],
+      );
+      final newImage = croppedFile?.path;
+      if (newImage == null) {
+        return;
+      }
+      controller.insertImageBlock(imageSource: newImage);
+    };
+  }
+
   QuillToolbar get quillToolbar {
     final customButtons = [
       QuillToolbarCustomButtonOptions(
@@ -481,13 +518,14 @@ class _HomePageState extends State<HomePage> {
         configurations: QuillToolbarConfigurations(
           customButtons: customButtons,
           embedButtons: FlutterQuillEmbeds.toolbarButtons(
+            cameraButtonOptions: const QuillToolbarCameraButtonOptions(),
             imageButtonOptions: QuillToolbarImageButtonOptions(
               imageButtonConfigurations: QuillToolbarImageConfigurations(
                 onImageInsertedCallback: (image) async {
                   _onImagePickCallback(File(image));
                 },
+                onImageInsertCallback: onImageInsert,
               ),
-              // webImagePickImpl: _webImagePickImpl,
             ),
           ),
           buttonOptions: QuillToolbarButtonOptions(
@@ -496,7 +534,6 @@ class _HomePageState extends State<HomePage> {
             ),
           ),
         ),
-        // afterButtonPressed: _focusNode.requestFocus,
       );
     }
     if (isDesktop(supportWeb: false)) {
@@ -504,6 +541,7 @@ class _HomePageState extends State<HomePage> {
         configurations: QuillToolbarConfigurations(
           customButtons: customButtons,
           embedButtons: FlutterQuillEmbeds.toolbarButtons(
+            cameraButtonOptions: const QuillToolbarCameraButtonOptions(),
             imageButtonOptions: QuillToolbarImageButtonOptions(
               imageButtonConfigurations: QuillToolbarImageConfigurations(
                 onImageInsertedCallback: (image) async {
@@ -525,6 +563,7 @@ class _HomePageState extends State<HomePage> {
       configurations: QuillToolbarConfigurations(
         customButtons: customButtons,
         embedButtons: FlutterQuillEmbeds.toolbarButtons(
+          cameraButtonOptions: const QuillToolbarCameraButtonOptions(),
           videoButtonOptions: QuillToolbarVideoButtonOptions(
             videoConfigurations: QuillToolbarVideoConfigurations(
               onVideoInsertedCallback: (video) =>
@@ -533,6 +572,7 @@ class _HomePageState extends State<HomePage> {
           ),
           imageButtonOptions: QuillToolbarImageButtonOptions(
             imageButtonConfigurations: QuillToolbarImageConfigurations(
+              onImageInsertCallback: onImageInsert,
               onImageInsertedCallback: (image) async {
                 _onImagePickCallback(File(image));
               },
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 5ff55f23..ccdf1958 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -17,10 +17,11 @@ dependencies:
   path_provider: ^2.1.1
   # filesystem_picker: ^4.0.0
   file_picker: ^6.1.1
-  flutter_quill: ^8.2.5
-  flutter_quill_extensions: ^0.6.3
+  flutter_quill: ^8.4.1
+  flutter_quill_extensions: ^0.6.5
   path: ^1.8.3
   desktop_drop: ^0.4.4
+  image_cropper: ^5.0.0
 
 dependency_overrides:
   flutter_quill:
diff --git a/example/web/index.html b/example/web/index.html
index 45cf2ca3..1029dffd 100644
--- a/example/web/index.html
+++ b/example/web/index.html
@@ -32,6 +32,11 @@
   <title>example</title>
   <link rel="manifest" href="manifest.json">
 
+   <!-- Croppie -->
+   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.css" />
+   <script defer src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.js"></script>
+   <script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.js"></script>
+
   <script>
     // The value below is injected by flutter build, do not touch.
     const serviceWorkerVersion = null;
diff --git a/flutter_quill_extensions/CHANGELOG.md b/flutter_quill_extensions/CHANGELOG.md
index ffb6cd2c..07532371 100644
--- a/flutter_quill_extensions/CHANGELOG.md
+++ b/flutter_quill_extensions/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.6
+- Add `onImageClicked` in the `QuillEditorImageEmbedConfigurations`
+- Fix image resizing on mobile
+
 ## 0.6.5
 - Support the new improved platform checking of `flutter_quill`
 - Update the Image embed builder logic
diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart b/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart
index 3e6cac2c..8badfa3a 100644
--- a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart
+++ b/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart
@@ -112,6 +112,20 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
         QuillSharedExtensionsConfigurations.get(context: context)
             .imageSaverService;
     return GestureDetector(
+      onTap: configurations.onImageClicked ??
+          () => showDialog(
+                context: context,
+                builder: (context) {
+                  return ImageOptionsMenu(
+                    controller: controller,
+                    configurations: configurations,
+                    imageSource: imageSource,
+                    imageSize: imageSize,
+                    isReadOnly: readOnly,
+                    imageSaverService: imageSaverService,
+                  );
+                },
+              ),
       child: Builder(
         builder: (context) {
           if (margin != null) {
@@ -123,19 +137,6 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
           return image;
         },
       ),
-      onTap: () => showDialog(
-        context: context,
-        builder: (context) {
-          return ImageOptionsMenu(
-            controller: controller,
-            configurations: configurations,
-            imageSource: imageSource,
-            imageSize: imageSize,
-            isReadOnly: readOnly,
-            imageSaverService: imageSaverService,
-          );
-        },
-      ),
     );
   }
 }
@@ -191,10 +192,16 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
     // It css value as string but we will try to support it anyway
 
     // TODO: This could be improved much better
-    final cssHeightValue = double.tryParse(
-        (attrs[Attribute.height.key] ?? '').replaceFirst('px', ''));
-    final cssWidthValue = double.tryParse(
-        (attrs[Attribute.width.key] ?? '').replaceFirst('px', ''));
+    final cssHeightValue = double.tryParse(((base.isMobile(supportWeb: false)
+                ? attrs[Attribute.mobileHeight]
+                : attrs[Attribute.height.key]) ??
+            '')
+        .replaceFirst('px', ''));
+    final cssWidthValue = double.tryParse(((!base.isMobile(supportWeb: false)
+                ? attrs[Attribute.width.key]
+                : attrs[Attribute.mobileWidth]) ??
+            '')
+        .replaceFirst('px', ''));
 
     if (cssHeightValue != null) {
       imageSize = imageSize.copyWith(height: cssHeightValue);
diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart b/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart
index 6fc71864..e6dc2cb0 100644
--- a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart
+++ b/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart
@@ -1,6 +1,5 @@
 import 'package:flutter/cupertino.dart' show showCupertinoModalPopup;
 import 'package:flutter/material.dart';
-// import 'package:flutter/services.dart' show Clipboard, ClipboardData;
 import 'package:flutter_quill/extensions.dart'
     show isDesktop, isMobile, replaceStyleStringWithSize;
 import 'package:flutter_quill/flutter_quill.dart'
@@ -51,7 +50,7 @@ class ImageOptionsMenu extends StatelessWidget {
                   builder: (context) {
                     final screenSize = MediaQuery.sizeOf(context);
                     return ImageResizer(
-                      onImageResize: (w, h) {
+                      onImageResize: (width, height) {
                         final res = getEmbedNode(
                           controller,
                           controller.selection.start,
@@ -59,8 +58,8 @@ class ImageOptionsMenu extends StatelessWidget {
 
                         final attr = replaceStyleStringWithSize(
                           getImageStyleString(controller),
-                          width: w,
-                          height: h,
+                          width: width,
+                          height: height,
                           isMobile: isMobile(supportWeb: false),
                         );
                         controller
@@ -94,7 +93,7 @@ class ImageOptionsMenu extends StatelessWidget {
               );
               // TODO: Implement the copy image
               // await Clipboard.setData(
-              //   ClipboardData(text: '$imageUrl'),
+              //   ClipboardData(),
               // );
               navigator.pop();
             },
diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart b/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart
index be7d7a14..f31171a6 100644
--- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart
+++ b/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart
@@ -1,5 +1,3 @@
-// ignore_for_file: use_build_context_synchronously
-
 import 'package:flutter/material.dart';
 import 'package:flutter_quill/flutter_quill.dart';
 import 'package:flutter_quill/translations.dart';
@@ -104,6 +102,7 @@ class QuillToolbarCameraButton extends StatelessWidget {
       size: iconSize * 1.77,
       fillColor: iconFillColor,
       borderRadius: iconTheme?.borderRadius ?? 2,
+      // isDesktop(supportWeb: false) ? null :
       onPressed: () => _sharedOnPressed(context),
     );
   }
@@ -126,11 +125,9 @@ class QuillToolbarCameraButton extends StatelessWidget {
     BuildContext context,
     QuillController controller,
   ) async {
-    // if (onVideoPickCallback == null && onImagePickCallback == null) {
-    //   throw ArgumentError(
-    //     'onImagePickCallback and onVideoPickCallback are both null',
-    //   );
-    // }
+    final imagePickerService =
+        QuillSharedExtensionsConfigurations.get(context: context)
+            .imagePickerService;
 
     final cameraAction = await _getCameraAction(context);
 
@@ -138,10 +135,6 @@ class QuillToolbarCameraButton extends StatelessWidget {
       return;
     }
 
-    final imagePickerService =
-        QuillSharedExtensionsConfigurations.get(context: context)
-            .imagePickerService;
-
     switch (cameraAction) {
       case CameraAction.video:
         final videoFile = await imagePickerService.pickVideo(
diff --git a/flutter_quill_extensions/lib/presentation/embeds/widgets/image_resizer.dart b/flutter_quill_extensions/lib/presentation/embeds/widgets/image_resizer.dart
index 92f2fb7c..8d709426 100644
--- a/flutter_quill_extensions/lib/presentation/embeds/widgets/image_resizer.dart
+++ b/flutter_quill_extensions/lib/presentation/embeds/widgets/image_resizer.dart
@@ -48,7 +48,9 @@ class ImageResizerState extends State<ImageResizer> {
       case TargetPlatform.fuchsia:
         return _showMaterialMenu();
       default:
-        throw 'Not supposed to be invoked for $defaultTargetPlatform';
+        throw UnsupportedError(
+          'Not supposed to be invoked for $defaultTargetPlatform',
+        );
     }
   }
 
diff --git a/flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart b/flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart
index 518b61ed..ed7e5abe 100644
--- a/flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart
+++ b/flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart
@@ -1,5 +1,6 @@
 import 'dart:io' show File;
 
+import 'package:flutter/foundation.dart' show VoidCallback;
 import 'package:flutter_quill/extensions.dart';
 import 'package:meta/meta.dart' show immutable;
 
@@ -12,12 +13,11 @@ import '../../../../embeds/embed_types/image.dart';
 @immutable
 class QuillEditorImageEmbedConfigurations {
   const QuillEditorImageEmbedConfigurations({
-    @Deprecated('This will be deleted in 0.7.0 as we will have one menu')
-    this.forceUseMobileOptionMenuForImageClick = false,
     ImageEmbedBuilderOnRemovedCallback? onImageRemovedCallback,
     this.shouldRemoveImageCallback,
     this.imageProviderBuilder,
     this.imageErrorWidgetBuilder,
+    this.onImageClicked,
   }) : _onImageRemovedCallback = onImageRemovedCallback;
 
   /// [onImageRemovedCallback] is called when an image is
@@ -101,15 +101,7 @@ class QuillEditorImageEmbedConfigurations {
   ///
   final ImageEmbedBuilderErrorWidgetBuilder? imageErrorWidgetBuilder;
 
-  /// [forceUseMobileOptionMenuForImageClick] is a boolean
-  /// flag that, when set to `true`,
-  /// enforces the use of the mobile-specific option menu for image clicks in
-  /// other platforms like desktop, this option doesn't affect mobile. it will
-  /// not affect web
-  ///  This option
-  /// can be used to override the default behavior based on the platform.
-  ///
-  final bool forceUseMobileOptionMenuForImageClick;
+  final VoidCallback? onImageClicked;
 
   static ImageEmbedBuilderOnRemovedCallback get defaultOnImageRemovedCallback {
     return (imageUrl) async {
@@ -162,10 +154,6 @@ class QuillEditorImageEmbedConfigurations {
       imageProviderBuilder: imageProviderBuilder ?? this.imageProviderBuilder,
       imageErrorWidgetBuilder:
           imageErrorWidgetBuilder ?? this.imageErrorWidgetBuilder,
-      // ignore: deprecated_member_use_from_same_package
-      forceUseMobileOptionMenuForImageClick:
-          forceUseMobileOptionMenuForImageClick ??
-              this.forceUseMobileOptionMenuForImageClick,
     );
   }
 }
diff --git a/flutter_quill_extensions/pubspec.yaml b/flutter_quill_extensions/pubspec.yaml
index 3df390cd..548e27d1 100644
--- a/flutter_quill_extensions/pubspec.yaml
+++ b/flutter_quill_extensions/pubspec.yaml
@@ -1,6 +1,6 @@
 name: flutter_quill_extensions
 description: Embed extensions for flutter_quill including image, video, formula and etc.
-version: 0.6.5
+version: 0.6.6
 homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions
 repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions
 
diff --git a/lib/flutter_quill.dart b/lib/flutter_quill.dart
index f70653ca..07770bbe 100644
--- a/lib/flutter_quill.dart
+++ b/lib/flutter_quill.dart
@@ -1,6 +1,7 @@
 library flutter_quill;
 
 export 'src/models/config/quill_configurations.dart';
+export 'src/models/config/raw_editor/configurations.dart';
 export 'src/models/config/toolbar/base_configurations.dart';
 export 'src/models/documents/attribute.dart';
 export 'src/models/documents/document.dart';
@@ -22,6 +23,7 @@ export 'src/models/themes/quill_icon_theme.dart';
 export 'src/utils/embeds.dart';
 export 'src/utils/extensions/build_context.dart';
 export 'src/widgets/controller.dart';
+export 'src/widgets/cursor.dart';
 export 'src/widgets/default_styles.dart';
 export 'src/widgets/editor/editor.dart';
 export 'src/widgets/embeds.dart';
diff --git a/lib/src/models/config/editor/configurations.dart b/lib/src/models/config/editor/configurations.dart
index 117e8dc2..c6e0f5de 100644
--- a/lib/src/models/config/editor/configurations.dart
+++ b/lib/src/models/config/editor/configurations.dart
@@ -2,7 +2,7 @@
 import 'package:equatable/equatable.dart';
 import 'package:flutter/foundation.dart' show Brightness, Uint8List, immutable;
 import 'package:flutter/material.dart'
-    show TextCapitalization, TextSelectionThemeData;
+    show TextCapitalization, TextInputAction, TextSelectionThemeData;
 import 'package:flutter/widgets.dart';
 import 'package:meta/meta.dart' show experimental;
 
@@ -71,6 +71,7 @@ class QuillEditorConfigurations extends Equatable {
     this.elementOptions = const QuillEditorElementOptions(),
     this.builder,
     this.magnifierConfiguration,
+    this.textInputAction = TextInputAction.newline,
   });
 
   /// The text placeholder in the quill editor
@@ -316,6 +317,9 @@ class QuillEditorConfigurations extends Equatable {
   @experimental
   final TextMagnifierConfiguration? magnifierConfiguration;
 
+  /// Default to [TextInputAction.newline]
+  final TextInputAction textInputAction;
+
   @override
   List<Object?> get props => [
         placeholder,
@@ -369,6 +373,7 @@ class QuillEditorConfigurations extends Equatable {
     QuillEditorElementOptions? elementOptions,
     QuillEditorBuilder? builder,
     TextMagnifierConfiguration? magnifierConfiguration,
+    TextInputAction? textInputAction,
   }) {
     return QuillEditorConfigurations(
       placeholder: placeholder ?? this.placeholder,
@@ -425,6 +430,7 @@ class QuillEditorConfigurations extends Equatable {
       builder: builder ?? this.builder,
       magnifierConfiguration:
           magnifierConfiguration ?? this.magnifierConfiguration,
+      textInputAction: textInputAction ?? this.textInputAction,
     );
   }
 }
diff --git a/lib/src/models/config/raw_editor/configurations.dart b/lib/src/models/config/raw_editor/configurations.dart
new file mode 100644
index 00000000..b7bdebe3
--- /dev/null
+++ b/lib/src/models/config/raw_editor/configurations.dart
@@ -0,0 +1,290 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/foundation.dart' show Brightness, Uint8List;
+import 'package:flutter/material.dart'
+    show
+        AdaptiveTextSelectionToolbar,
+        PointerDownEvent,
+        TextCapitalization,
+        TextInputAction;
+import 'package:flutter/widgets.dart'
+    show
+        Action,
+        BuildContext,
+        Color,
+        ContentInsertionConfiguration,
+        EdgeInsets,
+        EdgeInsetsGeometry,
+        FocusNode,
+        Intent,
+        ScrollController,
+        ScrollPhysics,
+        ShortcutActivator,
+        TextFieldTapRegion,
+        TextSelectionControls,
+        ValueChanged,
+        Widget;
+import 'package:meta/meta.dart' show immutable;
+
+import '../../../widgets/controller.dart';
+import '../../../widgets/cursor.dart';
+import '../../../widgets/default_styles.dart';
+import '../../../widgets/delegate.dart';
+import '../../../widgets/link.dart';
+import '../../../widgets/raw_editor/raw_editor.dart';
+import '../../../widgets/raw_editor/raw_editor_state.dart';
+import '../../themes/quill_dialog_theme.dart';
+
+@immutable
+class QuillRawEditorConfigurations extends Equatable {
+  const QuillRawEditorConfigurations({
+    required this.controller,
+    required this.focusNode,
+    required this.scrollController,
+    required this.scrollBottomInset,
+    required this.cursorStyle,
+    required this.selectionColor,
+    required this.selectionCtrls,
+    required this.embedBuilder,
+    required this.autoFocus,
+    this.showCursor = true,
+    this.scrollable = true,
+    this.padding = EdgeInsets.zero,
+    this.isReadOnly = false,
+    this.placeholder,
+    this.onLaunchUrl,
+    this.contextMenuBuilder = defaultContextMenuBuilder,
+    this.showSelectionHandles = false,
+    this.textCapitalization = TextCapitalization.none,
+    this.maxHeight,
+    this.minHeight,
+    this.maxContentWidth,
+    this.customStyles,
+    this.customShortcuts,
+    this.customActions,
+    this.expands = false,
+    this.isOnTapOutsideEnabled = true,
+    this.onTapOutside,
+    this.keyboardAppearance = Brightness.light,
+    this.enableInteractiveSelection = true,
+    this.scrollPhysics,
+    this.linkActionPickerDelegate = defaultLinkActionPickerDelegate,
+    this.customStyleBuilder,
+    this.customRecognizerBuilder,
+    this.floatingCursorDisabled = false,
+    this.onImagePaste,
+    this.customLinkPrefixes = const <String>[],
+    this.dialogTheme,
+    this.contentInsertionConfiguration,
+    this.textInputAction = TextInputAction.newline,
+    this.requestKeyboardFocusOnCheckListChanged = false,
+  });
+
+  /// Controls the document being edited.
+  final QuillController controller;
+
+  /// Controls whether this editor has keyboard focus.
+  final FocusNode focusNode;
+  final ScrollController scrollController;
+  final bool scrollable;
+  final double scrollBottomInset;
+
+  /// Additional space around the editor contents.
+  final EdgeInsetsGeometry padding;
+
+  /// Whether the text can be changed.
+  ///
+  /// When this is set to true, the text cannot be modified
+  /// by any shortcut or keyboard operation. The text is still selectable.
+  ///
+  /// Defaults to false. Must not be null.
+  final bool isReadOnly;
+
+  final String? placeholder;
+
+  /// Callback which is triggered when the user wants to open a URL from
+  /// a link in the document.
+  final ValueChanged<String>? onLaunchUrl;
+
+  /// Builds the text selection toolbar when requested by the user.
+  ///
+  /// See also:
+  ///   * [EditableText.contextMenuBuilder], which builds the default
+  ///     text selection toolbar for [EditableText].
+  ///
+  /// If not provided, no context menu will be shown.
+  final QuillEditorContextMenuBuilder? contextMenuBuilder;
+
+  static Widget defaultContextMenuBuilder(
+    BuildContext context,
+    QuillRawEditorState state,
+  ) {
+    return TextFieldTapRegion(
+      child: AdaptiveTextSelectionToolbar.buttonItems(
+        buttonItems: state.contextMenuButtonItems,
+        anchors: state.contextMenuAnchors,
+      ),
+    );
+  }
+
+  /// Whether to show selection handles.
+  ///
+  /// When a selection is active, there will be two handles at each side of
+  /// boundary, or one handle if the selection is collapsed. The handles can be
+  /// dragged to adjust the selection.
+  ///
+  /// See also:
+  ///
+  ///  * [showCursor], which controls the visibility of the cursor.
+  final bool showSelectionHandles;
+
+  /// Whether to show cursor.
+  ///
+  /// The cursor refers to the blinking caret when the editor is focused.
+  ///
+  /// See also:
+  ///
+  ///  * [cursorStyle], which controls the cursor visual representation.
+  ///  * [showSelectionHandles], which controls the visibility of the selection
+  ///    handles.
+  final bool showCursor;
+
+  /// The style to be used for the editing cursor.
+  final CursorStyle cursorStyle;
+
+  /// Configures how the platform keyboard will select an uppercase or
+  /// lowercase keyboard.
+  ///
+  /// Only supports text keyboards, other keyboard types will ignore this
+  /// configuration. Capitalization is locale-aware.
+  ///
+  /// Defaults to [TextCapitalization.none]. Must not be null.
+  ///
+  /// See also:
+  ///
+  ///  * [TextCapitalization], for a description of each capitalization behavior
+  final TextCapitalization textCapitalization;
+
+  /// The maximum height this editor can have.
+  ///
+  /// If this is null then there is no limit to the editor's height and it will
+  /// expand to fill its parent.
+  final double? maxHeight;
+
+  /// The minimum height this editor can have.
+  final double? minHeight;
+
+  /// The maximum width to be occupied by the content of this editor.
+  ///
+  /// If this is not null and and this editor's width is larger than this value
+  /// then the contents will be constrained to the provided maximum width and
+  /// horizontally centered. This is mostly useful on devices with wide screens.
+  final double? maxContentWidth;
+
+  /// Allows to override [DefaultStyles].
+  final DefaultStyles? customStyles;
+
+  /// Whether this widget's height will be sized to fill its parent.
+  ///
+  /// If set to true and wrapped in a parent widget like [Expanded] or
+  ///
+  /// Defaults to false.
+  final bool expands;
+
+  /// Whether this editor should focus itself if nothing else is already
+  /// focused.
+  ///
+  /// If true, the keyboard will open as soon as this text field obtains focus.
+  /// Otherwise, the keyboard is only shown after the user taps the text field.
+  ///
+  /// Defaults to false. Cannot be null.
+  final bool autoFocus;
+
+  /// The color to use when painting the selection.
+  final Color selectionColor;
+
+  /// Delegate for building the text selection handles and toolbar.
+  ///
+  /// The [QuillRawEditor] widget used on its own will not trigger the display
+  /// of the selection toolbar by itself. The toolbar is shown by calling
+  /// [QuillRawEditorState.showToolbar] in response to
+  /// an appropriate user event.
+  final TextSelectionControls selectionCtrls;
+
+  /// The appearance of the keyboard.
+  ///
+  /// This setting is only honored on iOS devices.
+  ///
+  /// Defaults to [Brightness.light].
+  final Brightness keyboardAppearance;
+
+  /// If true, then long-pressing this TextField will select text and show the
+  /// cut/copy/paste menu, and tapping will move the text caret.
+  ///
+  /// True by default.
+  ///
+  /// If false, most of the accessibility support for selecting text, copy
+  /// and paste, and moving the caret will be disabled.
+  final bool enableInteractiveSelection;
+
+  bool get selectionEnabled => enableInteractiveSelection;
+
+  /// The [ScrollPhysics] to use when vertically scrolling the input.
+  ///
+  /// If not specified, it will behave according to the current platform.
+  ///
+  /// See [Scrollable.physics].
+  final ScrollPhysics? scrollPhysics;
+
+  final Future<String?> Function(Uint8List imageBytes)? onImagePaste;
+
+  /// Contains user-defined shortcuts map.
+  ///
+  /// [https://docs.flutter.dev/development/ui/advanced/actions-and-shortcuts#shortcuts]
+  final Map<ShortcutActivator, Intent>? customShortcuts;
+
+  /// Contains user-defined actions.
+  ///
+  /// [https://docs.flutter.dev/development/ui/advanced/actions-and-shortcuts#actions]
+  final Map<Type, Action<Intent>>? customActions;
+
+  /// Builder function for embeddable objects.
+  final EmbedsBuilder embedBuilder;
+  final LinkActionPickerDelegate linkActionPickerDelegate;
+  final CustomStyleBuilder? customStyleBuilder;
+  final CustomRecognizerBuilder? customRecognizerBuilder;
+  final bool floatingCursorDisabled;
+  final List<String> customLinkPrefixes;
+
+  /// Configures the dialog theme.
+  final QuillDialogTheme? dialogTheme;
+
+  /// Configuration of handler for media content inserted via the system input
+  /// method.
+  ///
+  /// See [https://api.flutter.dev/flutter/widgets/EditableText/contentInsertionConfiguration.html]
+  final ContentInsertionConfiguration? contentInsertionConfiguration;
+
+  /// Whether the [onTapOutside] should be triggered or not
+  /// Defaults to `true`
+  /// it have default implementation, check [onTapOuside] for more
+  final bool isOnTapOutsideEnabled;
+
+  /// This will run only when [isOnTapOutsideEnabled] is true
+  /// by default on desktop and web it will unfocus
+  /// on mobile it will only unFocus if the kind property of
+  /// event [PointerDownEvent] is [PointerDeviceKind.unknown]
+  /// you can override this to fit your needs
+  final Function(PointerDownEvent event, FocusNode focusNode)? onTapOutside;
+
+  /// When there is a change the check list values
+  /// should we request keyboard focus??
+  final bool requestKeyboardFocusOnCheckListChanged;
+
+  final TextInputAction textInputAction;
+
+  @override
+  List<Object?> get props => [
+        isReadOnly,
+        placeholder,
+      ];
+}
diff --git a/lib/src/utils/extensions/build_context.dart b/lib/src/utils/extensions/build_context.dart
index 74d34292..2786b2fa 100644
--- a/lib/src/utils/extensions/build_context.dart
+++ b/lib/src/utils/extensions/build_context.dart
@@ -2,7 +2,7 @@ import 'package:flutter/widgets.dart' show BuildContext;
 
 import '../../../flutter_quill.dart';
 
-// TODO: The comments of this file might needs to be updated.
+// TODO: The comments of this file is outdated and needs to be updated
 
 /// Public shared extension
 extension BuildContextExt on BuildContext {
diff --git a/lib/src/utils/string.dart b/lib/src/utils/string.dart
index 2975cf60..7473eed8 100644
--- a/lib/src/utils/string.dart
+++ b/lib/src/utils/string.dart
@@ -20,13 +20,13 @@ Map<String, String> parseKeyValuePairs(String s, Set<String> targetKeys) {
 }
 
 String replaceStyleStringWithSize(
-  String s, {
+  String cssStyle, {
   required double width,
   required double height,
   required bool isMobile,
 }) {
   final result = <String, String>{};
-  final pairs = s.split(';');
+  final pairs = cssStyle.split(';');
   for (final pair in pairs) {
     final index = pair.indexOf(':');
     if (index < 0) {
diff --git a/lib/src/widgets/editor/editor.dart b/lib/src/widgets/editor/editor.dart
index dea30332..52d39528 100644
--- a/lib/src/widgets/editor/editor.dart
+++ b/lib/src/widgets/editor/editor.dart
@@ -13,7 +13,6 @@ import '../../../flutter_quill.dart';
 import '../../models/documents/nodes/container.dart' as container_node;
 import '../../utils/platform.dart';
 import '../box.dart';
-import '../cursor.dart';
 import '../delegate.dart';
 import '../float_cursor.dart';
 import '../text_selection.dart';
@@ -247,60 +246,64 @@ class QuillEditorState extends State<QuillEditor>
         builder: configurations.builder,
         child: QuillRawEditor(
           key: _editorKey,
-          controller: context.requireQuillController,
-          focusNode: widget.focusNode,
-          scrollController: widget.scrollController,
-          scrollable: configurations.scrollable,
-          scrollBottomInset: configurations.scrollBottomInset,
-          padding: configurations.padding,
-          readOnly: configurations.readOnly,
-          placeholder: configurations.placeholder,
-          onLaunchUrl: configurations.onLaunchUrl,
-          contextMenuBuilder: showSelectionToolbar
-              ? (configurations.contextMenuBuilder ??
-                  QuillRawEditor.defaultContextMenuBuilder)
-              : null,
-          showSelectionHandles: isMobile(
-            platform: theme.platform,
-            supportWeb: true,
+          configurations: QuillRawEditorConfigurations(
+            controller: context.requireQuillController,
+            focusNode: widget.focusNode,
+            scrollController: widget.scrollController,
+            scrollable: configurations.scrollable,
+            scrollBottomInset: configurations.scrollBottomInset,
+            padding: configurations.padding,
+            isReadOnly: configurations.readOnly,
+            placeholder: configurations.placeholder,
+            onLaunchUrl: configurations.onLaunchUrl,
+            contextMenuBuilder: showSelectionToolbar
+                ? (configurations.contextMenuBuilder ??
+                    QuillRawEditorConfigurations.defaultContextMenuBuilder)
+                : null,
+            showSelectionHandles: isMobile(
+              platform: theme.platform,
+              supportWeb: true,
+            ),
+            showCursor: configurations.showCursor ?? true,
+            cursorStyle: CursorStyle(
+              color: cursorColor,
+              backgroundColor: Colors.grey,
+              width: 2,
+              radius: cursorRadius,
+              offset: cursorOffset,
+              paintAboveText:
+                  configurations.paintCursorAboveText ?? paintCursorAboveText,
+              opacityAnimates: cursorOpacityAnimates,
+            ),
+            textCapitalization: configurations.textCapitalization,
+            minHeight: configurations.minHeight,
+            maxHeight: configurations.maxHeight,
+            maxContentWidth: configurations.maxContentWidth,
+            customStyles: configurations.customStyles,
+            expands: configurations.expands,
+            autoFocus: configurations.autoFocus,
+            selectionColor: selectionColor,
+            selectionCtrls:
+                configurations.textSelectionControls ?? textSelectionControls,
+            keyboardAppearance: configurations.keyboardAppearance,
+            enableInteractiveSelection:
+                configurations.enableInteractiveSelection,
+            scrollPhysics: configurations.scrollPhysics,
+            embedBuilder: _getEmbedBuilder,
+            linkActionPickerDelegate: configurations.linkActionPickerDelegate,
+            customStyleBuilder: configurations.customStyleBuilder,
+            customRecognizerBuilder: configurations.customRecognizerBuilder,
+            floatingCursorDisabled: configurations.floatingCursorDisabled,
+            onImagePaste: configurations.onImagePaste,
+            customShortcuts: configurations.customShortcuts,
+            customActions: configurations.customActions,
+            customLinkPrefixes: configurations.customLinkPrefixes,
+            isOnTapOutsideEnabled: configurations.isOnTapOutsideEnabled,
+            onTapOutside: configurations.onTapOutside,
+            dialogTheme: configurations.dialogTheme,
+            contentInsertionConfiguration:
+                configurations.contentInsertionConfiguration,
           ),
-          showCursor: configurations.showCursor,
-          cursorStyle: CursorStyle(
-            color: cursorColor,
-            backgroundColor: Colors.grey,
-            width: 2,
-            radius: cursorRadius,
-            offset: cursorOffset,
-            paintAboveText:
-                configurations.paintCursorAboveText ?? paintCursorAboveText,
-            opacityAnimates: cursorOpacityAnimates,
-          ),
-          textCapitalization: configurations.textCapitalization,
-          minHeight: configurations.minHeight,
-          maxHeight: configurations.maxHeight,
-          maxContentWidth: configurations.maxContentWidth,
-          customStyles: configurations.customStyles,
-          expands: configurations.expands,
-          autoFocus: configurations.autoFocus,
-          selectionColor: selectionColor,
-          selectionCtrls:
-              configurations.textSelectionControls ?? textSelectionControls,
-          keyboardAppearance: configurations.keyboardAppearance,
-          enableInteractiveSelection: configurations.enableInteractiveSelection,
-          scrollPhysics: configurations.scrollPhysics,
-          embedBuilder: _getEmbedBuilder,
-          linkActionPickerDelegate: configurations.linkActionPickerDelegate,
-          customStyleBuilder: configurations.customStyleBuilder,
-          customRecognizerBuilder: configurations.customRecognizerBuilder,
-          floatingCursorDisabled: configurations.floatingCursorDisabled,
-          onImagePaste: configurations.onImagePaste,
-          customShortcuts: configurations.customShortcuts,
-          customActions: configurations.customActions,
-          customLinkPrefixes: configurations.customLinkPrefixes,
-          enableUnfocusOnTapOutside: configurations.isOnTapOutsideEnabled,
-          dialogTheme: configurations.dialogTheme,
-          contentInsertionConfiguration:
-              configurations.contentInsertionConfiguration,
         ),
       ),
     );
@@ -435,15 +438,15 @@ class _QuillEditorSelectionGestureDetectorBuilder
       return false;
     }
     final pos = renderEditor!.getPositionForOffset(details.globalPosition);
-    final result =
-        editor!.widget.controller.document.querySegmentLeafNode(pos.offset);
+    final result = editor!.widget.configurations.controller.document
+        .querySegmentLeafNode(pos.offset);
     final line = result.line;
     if (line == null) {
       return false;
     }
     final segmentLeaf = result.leaf;
     if (segmentLeaf == null && line.length == 1) {
-      editor!.widget.controller.updateSelection(
+      editor!.widget.configurations.controller.updateSelection(
         TextSelection.collapsed(offset: pos.offset),
         ChangeSource.local,
       );
diff --git a/lib/src/widgets/raw_editor/raw_editor.dart b/lib/src/widgets/raw_editor/raw_editor.dart
index 55b9a590..9514651b 100644
--- a/lib/src/widgets/raw_editor/raw_editor.dart
+++ b/lib/src/widgets/raw_editor/raw_editor.dart
@@ -1,245 +1,25 @@
 import 'package:flutter/material.dart';
-import 'package:flutter/services.dart' show Uint8List;
 
-import '../../models/themes/quill_dialog_theme.dart';
-import '../controller.dart';
-import '../cursor.dart';
-import '../default_styles.dart';
-import '../delegate.dart';
-import '../link.dart';
+import '../../models/config/raw_editor/configurations.dart';
 import 'raw_editor_state.dart';
 
 class QuillRawEditor extends StatefulWidget {
-  const QuillRawEditor({
-    required this.controller,
-    required this.focusNode,
-    required this.scrollController,
-    required this.scrollBottomInset,
-    required this.cursorStyle,
-    required this.selectionColor,
-    required this.selectionCtrls,
-    required this.embedBuilder,
-    required this.autoFocus,
+  QuillRawEditor({
+    required this.configurations,
     super.key,
-    this.scrollable = true,
-    this.padding = EdgeInsets.zero,
-    this.readOnly = false,
-    this.placeholder,
-    this.onLaunchUrl,
-    this.contextMenuBuilder = defaultContextMenuBuilder,
-    this.showSelectionHandles = false,
-    bool? showCursor,
-    this.textCapitalization = TextCapitalization.none,
-    this.maxHeight,
-    this.minHeight,
-    this.maxContentWidth,
-    this.customStyles,
-    this.customShortcuts,
-    this.customActions,
-    this.expands = false,
-    this.enableUnfocusOnTapOutside = true,
-    this.keyboardAppearance = Brightness.light,
-    this.enableInteractiveSelection = true,
-    this.scrollPhysics,
-    this.linkActionPickerDelegate = defaultLinkActionPickerDelegate,
-    this.customStyleBuilder,
-    this.customRecognizerBuilder,
-    this.floatingCursorDisabled = false,
-    this.onImagePaste,
-    this.customLinkPrefixes = const <String>[],
-    this.dialogTheme,
-    this.contentInsertionConfiguration,
-  })  : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'),
-        assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'),
-        assert(maxHeight == null || minHeight == null || maxHeight >= minHeight,
+  })  : assert(
+            configurations.maxHeight == null || configurations.maxHeight! > 0,
             'maxHeight cannot be null'),
-        showCursor = showCursor ?? true;
-
-  /// Controls the document being edited.
-  final QuillController controller;
-
-  /// Controls whether this editor has keyboard focus.
-  final FocusNode focusNode;
-  final ScrollController scrollController;
-  final bool scrollable;
-  final double scrollBottomInset;
-  final bool enableUnfocusOnTapOutside;
-
-  /// Additional space around the editor contents.
-  final EdgeInsetsGeometry padding;
-
-  /// Whether the text can be changed.
-  ///
-  /// When this is set to true, the text cannot be modified
-  /// by any shortcut or keyboard operation. The text is still selectable.
-  ///
-  /// Defaults to false. Must not be null.
-  final bool readOnly;
-
-  final String? placeholder;
-
-  /// Callback which is triggered when the user wants to open a URL from
-  /// a link in the document.
-  final ValueChanged<String>? onLaunchUrl;
-
-  /// Builds the text selection toolbar when requested by the user.
-  ///
-  /// See also:
-  ///   * [EditableText.contextMenuBuilder], which builds the default
-  ///     text selection toolbar for [EditableText].
-  ///
-  /// If not provided, no context menu will be shown.
-  final QuillEditorContextMenuBuilder? contextMenuBuilder;
-
-  static Widget defaultContextMenuBuilder(
-    BuildContext context,
-    QuillRawEditorState state,
-  ) {
-    return TextFieldTapRegion(
-      child: AdaptiveTextSelectionToolbar.buttonItems(
-        buttonItems: state.contextMenuButtonItems,
-        anchors: state.contextMenuAnchors,
-      ),
-    );
-  }
-
-  /// Whether to show selection handles.
-  ///
-  /// When a selection is active, there will be two handles at each side of
-  /// boundary, or one handle if the selection is collapsed. The handles can be
-  /// dragged to adjust the selection.
-  ///
-  /// See also:
-  ///
-  ///  * [showCursor], which controls the visibility of the cursor.
-  final bool showSelectionHandles;
-
-  /// Whether to show cursor.
-  ///
-  /// The cursor refers to the blinking caret when the editor is focused.
-  ///
-  /// See also:
-  ///
-  ///  * [cursorStyle], which controls the cursor visual representation.
-  ///  * [showSelectionHandles], which controls the visibility of the selection
-  ///    handles.
-  final bool showCursor;
-
-  /// The style to be used for the editing cursor.
-  final CursorStyle cursorStyle;
-
-  /// Configures how the platform keyboard will select an uppercase or
-  /// lowercase keyboard.
-  ///
-  /// Only supports text keyboards, other keyboard types will ignore this
-  /// configuration. Capitalization is locale-aware.
-  ///
-  /// Defaults to [TextCapitalization.none]. Must not be null.
-  ///
-  /// See also:
-  ///
-  ///  * [TextCapitalization], for a description of each capitalization behavior
-  final TextCapitalization textCapitalization;
-
-  /// The maximum height this editor can have.
-  ///
-  /// If this is null then there is no limit to the editor's height and it will
-  /// expand to fill its parent.
-  final double? maxHeight;
-
-  /// The minimum height this editor can have.
-  final double? minHeight;
-
-  /// The maximum width to be occupied by the content of this editor.
-  ///
-  /// If this is not null and and this editor's width is larger than this value
-  /// then the contents will be constrained to the provided maximum width and
-  /// horizontally centered. This is mostly useful on devices with wide screens.
-  final double? maxContentWidth;
-
-  /// Allows to override [DefaultStyles].
-  final DefaultStyles? customStyles;
-
-  /// Whether this widget's height will be sized to fill its parent.
-  ///
-  /// If set to true and wrapped in a parent widget like [Expanded] or
-  ///
-  /// Defaults to false.
-  final bool expands;
-
-  /// Whether this editor should focus itself if nothing else is already
-  /// focused.
-  ///
-  /// If true, the keyboard will open as soon as this text field obtains focus.
-  /// Otherwise, the keyboard is only shown after the user taps the text field.
-  ///
-  /// Defaults to false. Cannot be null.
-  final bool autoFocus;
-
-  /// The color to use when painting the selection.
-  final Color selectionColor;
-
-  /// Delegate for building the text selection handles and toolbar.
-  ///
-  /// The [QuillRawEditor] widget used on its own will not trigger the display
-  /// of the selection toolbar by itself. The toolbar is shown by calling
-  /// [QuillRawEditorState.showToolbar] in response to
-  /// an appropriate user event.
-  final TextSelectionControls selectionCtrls;
-
-  /// The appearance of the keyboard.
-  ///
-  /// This setting is only honored on iOS devices.
-  ///
-  /// Defaults to [Brightness.light].
-  final Brightness keyboardAppearance;
-
-  /// If true, then long-pressing this TextField will select text and show the
-  /// cut/copy/paste menu, and tapping will move the text caret.
-  ///
-  /// True by default.
-  ///
-  /// If false, most of the accessibility support for selecting text, copy
-  /// and paste, and moving the caret will be disabled.
-  final bool enableInteractiveSelection;
-
-  bool get selectionEnabled => enableInteractiveSelection;
-
-  /// The [ScrollPhysics] to use when vertically scrolling the input.
-  ///
-  /// If not specified, it will behave according to the current platform.
-  ///
-  /// See [Scrollable.physics].
-  final ScrollPhysics? scrollPhysics;
-
-  final Future<String?> Function(Uint8List imageBytes)? onImagePaste;
-
-  /// Contains user-defined shortcuts map.
-  ///
-  /// [https://docs.flutter.dev/development/ui/advanced/actions-and-shortcuts#shortcuts]
-  final Map<ShortcutActivator, Intent>? customShortcuts;
-
-  /// Contains user-defined actions.
-  ///
-  /// [https://docs.flutter.dev/development/ui/advanced/actions-and-shortcuts#actions]
-  final Map<Type, Action<Intent>>? customActions;
-
-  /// Builder function for embeddable objects.
-  final EmbedsBuilder embedBuilder;
-  final LinkActionPickerDelegate linkActionPickerDelegate;
-  final CustomStyleBuilder? customStyleBuilder;
-  final CustomRecognizerBuilder? customRecognizerBuilder;
-  final bool floatingCursorDisabled;
-  final List<String> customLinkPrefixes;
-
-  /// Configures the dialog theme.
-  final QuillDialogTheme? dialogTheme;
-
-  /// Configuration of handler for media content inserted via the system input
-  /// method.
-  ///
-  /// See [https://api.flutter.dev/flutter/widgets/EditableText/contentInsertionConfiguration.html]
-  final ContentInsertionConfiguration? contentInsertionConfiguration;
+        assert(
+            configurations.minHeight == null || configurations.minHeight! >= 0,
+            'minHeight cannot be null'),
+        assert(
+            configurations.maxHeight == null ||
+                configurations.minHeight == null ||
+                configurations.maxHeight! >= configurations.minHeight!,
+            'maxHeight cannot be null');
+
+  final QuillRawEditorConfigurations configurations;
 
   @override
   State<StatefulWidget> createState() => QuillRawEditorState();
diff --git a/lib/src/widgets/raw_editor/raw_editor_actions.dart b/lib/src/widgets/raw_editor/raw_editor_actions.dart
index e0564d3f..54a7eba7 100644
--- a/lib/src/widgets/raw_editor/raw_editor_actions.dart
+++ b/lib/src/widgets/raw_editor/raw_editor_actions.dart
@@ -76,7 +76,8 @@ class QuillEditorDeleteTextAction<T extends DirectionalTextEditingIntent>
 
   @override
   bool get isActionEnabled =>
-      !state.widget.readOnly && state.textEditingValue.selection.isValid;
+      !state.widget.configurations.isReadOnly &&
+      state.textEditingValue.selection.isValid;
 }
 
 class QuillEditorUpdateTextSelectionAction<
@@ -93,8 +94,8 @@ class QuillEditorUpdateTextSelectionAction<
     final selection = state.textEditingValue.selection;
     assert(selection.isValid);
 
-    final collapseSelection =
-        intent.collapseSelection || !state.widget.selectionEnabled;
+    final collapseSelection = intent.collapseSelection ||
+        !state.widget.configurations.selectionEnabled;
     // Collapse to the logical start/end.
     TextSelection collapse(TextSelection selection) {
       assert(selection.isValid);
@@ -217,7 +218,8 @@ class QuillEditorExtendSelectionOrCaretPositionAction extends ContextAction<
 
   @override
   bool get isActionEnabled =>
-      state.widget.selectionEnabled && state.textEditingValue.selection.isValid;
+      state.widget.configurations.selectionEnabled &&
+      state.textEditingValue.selection.isValid;
 }
 
 class QuillEditorUpdateTextSelectionToAdjacentLineAction<
@@ -251,8 +253,8 @@ class QuillEditorUpdateTextSelectionToAdjacentLineAction<
   void invoke(T intent, [BuildContext? context]) {
     assert(state.textEditingValue.selection.isValid);
 
-    final collapseSelection =
-        intent.collapseSelection || !state.widget.selectionEnabled;
+    final collapseSelection = intent.collapseSelection ||
+        !state.widget.configurations.selectionEnabled;
     final value = state.textEditingValue;
     if (!value.selection.isValid) {
       return;
@@ -307,7 +309,7 @@ class QuillEditorSelectAllAction extends ContextAction<SelectAllTextIntent> {
   }
 
   @override
-  bool get isActionEnabled => state.widget.selectionEnabled;
+  bool get isActionEnabled => state.widget.configurations.selectionEnabled;
 }
 
 class QuillEditorCopySelectionAction
@@ -559,7 +561,7 @@ class QuillEditorApplyLinkAction extends Action<QuillEditorApplyLinkIntent> {
         return LinkStyleDialog(
           text: initialTextLink.text,
           link: initialTextLink.link,
-          dialogTheme: state.widget.dialogTheme,
+          dialogTheme: state.widget.configurations.dialogTheme,
         );
       },
     );
diff --git a/lib/src/widgets/raw_editor/raw_editor_state.dart b/lib/src/widgets/raw_editor/raw_editor_state.dart
index 0775686c..0c6d6ee6 100644
--- a/lib/src/widgets/raw_editor/raw_editor_state.dart
+++ b/lib/src/widgets/raw_editor/raw_editor_state.dart
@@ -32,7 +32,6 @@ import '../../models/structs/vertical_spacing.dart';
 import '../../utils/cast.dart';
 import '../../utils/delta.dart';
 import '../../utils/embeds.dart';
-import '../../utils/extensions/build_context.dart';
 import '../../utils/platform.dart';
 import '../controller.dart';
 import '../cursor.dart';
@@ -77,12 +76,12 @@ class QuillRawEditorState extends EditorState
   // Cursors
   late CursorCont _cursorCont;
 
-  QuillController get controller => widget.controller;
+  QuillController get controller => widget.configurations.controller;
 
   // Focus
   bool _didAutoFocus = false;
 
-  bool get _hasFocus => widget.focusNode.hasFocus;
+  bool get _hasFocus => widget.configurations.focusNode.hasFocus;
 
   // Theme
   DefaultStyles? _styles;
@@ -109,10 +108,11 @@ class QuillRawEditorState extends EditorState
 
   @override
   void insertContent(KeyboardInsertedContent content) {
-    assert(widget.contentInsertionConfiguration?.allowedMimeTypes
+    assert(widget.configurations.contentInsertionConfiguration?.allowedMimeTypes
             .contains(content.mimeType) ??
         false);
-    widget.contentInsertionConfiguration?.onContentInserted.call(content);
+    widget.configurations.contentInsertionConfiguration?.onContentInserted
+        .call(content);
   }
 
   /// Returns the [ContextMenuButtonItem]s representing the buttons in this
@@ -200,7 +200,7 @@ class QuillRawEditorState extends EditorState
           case ui.PointerDeviceKind.stylus:
           case ui.PointerDeviceKind.invertedStylus:
           case ui.PointerDeviceKind.unknown:
-            widget.focusNode.unfocus();
+            widget.configurations.focusNode.unfocus();
             break;
           case ui.PointerDeviceKind.trackpad:
             throw UnimplementedError(
@@ -211,7 +211,7 @@ class QuillRawEditorState extends EditorState
       case TargetPlatform.linux:
       case TargetPlatform.macOS:
       case TargetPlatform.windows:
-        widget.focusNode.unfocus();
+        widget.configurations.focusNode.unfocus();
         break;
       default:
         throw UnsupportedError(
@@ -227,8 +227,8 @@ class QuillRawEditorState extends EditorState
     super.build(context);
 
     var doc = controller.document;
-    if (doc.isEmpty() && widget.placeholder != null) {
-      final raw = widget.placeholder?.replaceAll(r'"', '\\"');
+    if (doc.isEmpty() && widget.configurations.placeholder != null) {
+      final raw = widget.configurations.placeholder?.replaceAll(r'"', '\\"');
       doc = Document.fromJson(
         jsonDecode(
           '[{"attributes":{"placeholder":true},"insert":"$raw\\n"}]',
@@ -246,24 +246,25 @@ class QuillRawEditorState extends EditorState
             document: doc,
             selection: controller.selection,
             hasFocus: _hasFocus,
-            scrollable: widget.scrollable,
+            scrollable: widget.configurations.scrollable,
             cursorController: _cursorCont,
             textDirection: _textDirection,
             startHandleLayerLink: _startHandleLayerLink,
             endHandleLayerLink: _endHandleLayerLink,
             onSelectionChanged: _handleSelectionChanged,
             onSelectionCompleted: _handleSelectionCompleted,
-            scrollBottomInset: widget.scrollBottomInset,
-            padding: widget.padding,
-            maxContentWidth: widget.maxContentWidth,
-            floatingCursorDisabled: widget.floatingCursorDisabled,
+            scrollBottomInset: widget.configurations.scrollBottomInset,
+            padding: widget.configurations.padding,
+            maxContentWidth: widget.configurations.maxContentWidth,
+            floatingCursorDisabled:
+                widget.configurations.floatingCursorDisabled,
             children: _buildChildren(doc, context),
           ),
         ),
       ),
     );
 
-    if (widget.scrollable) {
+    if (widget.configurations.scrollable) {
       /// Since [SingleChildScrollView] does not implement
       /// `computeDistanceToActualBaseline` it prevents the editor from
       /// providing its baseline metrics. To address this issue we wrap
@@ -277,7 +278,7 @@ class QuillRawEditorState extends EditorState
         padding: baselinePadding,
         child: QuillSingleChildScrollView(
           controller: _scrollController,
-          physics: widget.scrollPhysics,
+          physics: widget.configurations.scrollPhysics,
           viewportBuilder: (_, offset) => CompositedTransformTarget(
             link: _toolbarLayerLink,
             child: MouseRegion(
@@ -288,17 +289,18 @@ class QuillRawEditorState extends EditorState
                 document: doc,
                 selection: controller.selection,
                 hasFocus: _hasFocus,
-                scrollable: widget.scrollable,
+                scrollable: widget.configurations.scrollable,
                 textDirection: _textDirection,
                 startHandleLayerLink: _startHandleLayerLink,
                 endHandleLayerLink: _endHandleLayerLink,
                 onSelectionChanged: _handleSelectionChanged,
                 onSelectionCompleted: _handleSelectionCompleted,
-                scrollBottomInset: widget.scrollBottomInset,
-                padding: widget.padding,
-                maxContentWidth: widget.maxContentWidth,
+                scrollBottomInset: widget.configurations.scrollBottomInset,
+                padding: widget.configurations.padding,
+                maxContentWidth: widget.configurations.maxContentWidth,
                 cursorController: _cursorCont,
-                floatingCursorDisabled: widget.floatingCursorDisabled,
+                floatingCursorDisabled:
+                    widget.configurations.floatingCursorDisabled,
                 children: _buildChildren(doc, context),
               ),
             ),
@@ -307,11 +309,11 @@ class QuillRawEditorState extends EditorState
       );
     }
 
-    final constraints = widget.expands
+    final constraints = widget.configurations.expands
         ? const BoxConstraints.expand()
         : BoxConstraints(
-            minHeight: widget.minHeight ?? 0.0,
-            maxHeight: widget.maxHeight ?? double.infinity,
+            minHeight: widget.configurations.minHeight ?? 0.0,
+            maxHeight: widget.configurations.maxHeight ?? double.infinity,
           );
 
     // Please notice that this change will make the check fixed
@@ -321,13 +323,11 @@ class QuillRawEditorState extends EditorState
     final isDesktopMacOS = isMacOS(supportWeb: true);
 
     return TextFieldTapRegion(
-      enabled: widget.enableUnfocusOnTapOutside,
+      enabled: widget.configurations.isOnTapOutsideEnabled,
       onTapOutside: (event) {
-        final onTapOutside =
-            context.requireQuillEditorConfigurations.onTapOutside;
+        final onTapOutside = widget.configurations.onTapOutside;
         if (onTapOutside != null) {
-          context.requireQuillEditorConfigurations.onTapOutside
-              ?.call(event, widget.focusNode);
+          onTapOutside.call(event, widget.configurations.focusNode);
           return;
         }
         _defaultOnTapOutside(event);
@@ -463,14 +463,14 @@ class QuillRawEditorState extends EditorState
               meta: isDesktopMacOS,
             ): const OpenSearchIntent(),
           }, {
-            ...?widget.customShortcuts
+            ...?widget.configurations.customShortcuts
           }),
           child: Actions(
             actions: mergeMaps<Type, Action<Intent>>(_actions, {
-              ...?widget.customActions,
+              ...?widget.configurations.customActions,
             }),
             child: Focus(
-              focusNode: widget.focusNode,
+              focusNode: widget.configurations.focusNode,
               onKey: _onKey,
               child: QuillKeyboardListener(
                 child: Container(
@@ -549,7 +549,7 @@ class QuillRawEditorState extends EditorState
         controller.document.queryChild(controller.selection.baseOffset);
 
     KeyEventResult insertTabCharacter() {
-      if (widget.readOnly) {
+      if (widget.configurations.isReadOnly) {
         return KeyEventResult.ignored;
       }
       controller.replaceText(controller.selection.baseOffset, 0, '\t', null);
@@ -657,10 +657,9 @@ class QuillRawEditorState extends EditorState
   /// Updates the checkbox positioned at [offset] in document
   /// by changing its attribute according to [value].
   void _handleCheckboxTap(int offset, bool value) {
-    final requestKeyboardFocusOnCheckListChanged = context
-        .requireQuillEditorConfigurations
-        .requestKeyboardFocusOnCheckListChanged;
-    if (!widget.readOnly) {
+    final requestKeyboardFocusOnCheckListChanged =
+        widget.configurations.requestKeyboardFocusOnCheckListChanged;
+    if (!widget.configurations.isReadOnly) {
       _disableScrollControllerAnimateOnce = true;
       final currentSelection = controller.selection.copyWith();
       final attribute = value ? Attribute.checked : Attribute.unchecked;
@@ -717,26 +716,27 @@ class QuillRawEditorState extends EditorState
           block: node,
           controller: controller,
           textDirection: getDirectionOfNode(node),
-          scrollBottomInset: widget.scrollBottomInset,
+          scrollBottomInset: widget.configurations.scrollBottomInset,
           verticalSpacing: _getVerticalSpacingForBlock(node, _styles),
           textSelection: controller.selection,
-          color: widget.selectionColor,
+          color: widget.configurations.selectionColor,
           styles: _styles,
-          enableInteractiveSelection: widget.enableInteractiveSelection,
+          enableInteractiveSelection:
+              widget.configurations.enableInteractiveSelection,
           hasFocus: _hasFocus,
           contentPadding: attrs.containsKey(Attribute.codeBlock.key)
               ? const EdgeInsets.all(16)
               : null,
-          embedBuilder: widget.embedBuilder,
+          embedBuilder: widget.configurations.embedBuilder,
           linkActionPicker: _linkActionPicker,
-          onLaunchUrl: widget.onLaunchUrl,
+          onLaunchUrl: widget.configurations.onLaunchUrl,
           cursorCont: _cursorCont,
           indentLevelCounts: indentLevelCounts,
           clearIndents: clearIndents,
           onCheckboxTap: _handleCheckboxTap,
-          readOnly: widget.readOnly,
-          customStyleBuilder: widget.customStyleBuilder,
-          customLinkPrefixes: widget.customLinkPrefixes,
+          readOnly: widget.configurations.isReadOnly,
+          customStyleBuilder: widget.configurations.customStyleBuilder,
+          customLinkPrefixes: widget.configurations.customLinkPrefixes,
         );
         result.add(
           Directionality(
@@ -760,15 +760,15 @@ class QuillRawEditorState extends EditorState
     final textLine = TextLine(
       line: node,
       textDirection: _textDirection,
-      embedBuilder: widget.embedBuilder,
-      customStyleBuilder: widget.customStyleBuilder,
-      customRecognizerBuilder: widget.customRecognizerBuilder,
+      embedBuilder: widget.configurations.embedBuilder,
+      customStyleBuilder: widget.configurations.customStyleBuilder,
+      customRecognizerBuilder: widget.configurations.customRecognizerBuilder,
       styles: _styles!,
-      readOnly: widget.readOnly,
+      readOnly: widget.configurations.isReadOnly,
       controller: controller,
       linkActionPicker: _linkActionPicker,
-      onLaunchUrl: widget.onLaunchUrl,
-      customLinkPrefixes: widget.customLinkPrefixes,
+      onLaunchUrl: widget.configurations.onLaunchUrl,
+      customLinkPrefixes: widget.configurations.customLinkPrefixes,
     );
     final editableTextLine = EditableTextLine(
         node,
@@ -778,8 +778,8 @@ class QuillRawEditorState extends EditorState
         _getVerticalSpacingForLine(node, _styles),
         _textDirection,
         controller.selection,
-        widget.selectionColor,
-        widget.enableInteractiveSelection,
+        widget.configurations.selectionColor,
+        widget.configurations.enableInteractiveSelection,
         _hasFocus,
         MediaQuery.devicePixelRatioOf(context),
         _cursorCont);
@@ -842,12 +842,12 @@ class QuillRawEditorState extends EditorState
 
     controller.addListener(_didChangeTextEditingValueListener);
 
-    _scrollController = widget.scrollController;
+    _scrollController = widget.configurations.scrollController;
     _scrollController.addListener(_updateSelectionOverlayForScroll);
 
     _cursorCont = CursorCont(
-      show: ValueNotifier<bool>(widget.showCursor),
-      style: widget.cursorStyle,
+      show: ValueNotifier<bool>(widget.configurations.showCursor),
+      style: widget.configurations.cursorStyle,
       tickerProvider: this,
     );
 
@@ -882,7 +882,7 @@ class QuillRawEditorState extends EditorState
     }
 
     // Focus
-    widget.focusNode.addListener(_handleFocusChanged);
+    widget.configurations.focusNode.addListener(_handleFocusChanged);
   }
 
   // KeyboardVisibilityController only checks for keyboards that
@@ -915,8 +915,8 @@ class QuillRawEditorState extends EditorState
         ? defaultStyles.merge(parentStyles)
         : defaultStyles;
 
-    if (widget.customStyles != null) {
-      _styles = _styles!.merge(widget.customStyles!);
+    if (widget.configurations.customStyles != null) {
+      _styles = _styles!.merge(widget.configurations.customStyles!);
     }
 
     _requestAutoFocusIfShould();
@@ -924,9 +924,9 @@ class QuillRawEditorState extends EditorState
 
   Future<void> _requestAutoFocusIfShould() async {
     final focusManager = FocusScope.of(context);
-    if (!_didAutoFocus && widget.autoFocus) {
+    if (!_didAutoFocus && widget.configurations.autoFocus) {
       await Future.delayed(Duration.zero); // To avoid exceptions
-      focusManager.autofocus(widget.focusNode);
+      focusManager.autofocus(widget.configurations.focusNode);
       _didAutoFocus = true;
     }
   }
@@ -935,28 +935,29 @@ class QuillRawEditorState extends EditorState
   void didUpdateWidget(QuillRawEditor oldWidget) {
     super.didUpdateWidget(oldWidget);
 
-    _cursorCont.show.value = widget.showCursor;
-    _cursorCont.style = widget.cursorStyle;
+    _cursorCont.show.value = widget.configurations.showCursor;
+    _cursorCont.style = widget.configurations.cursorStyle;
 
-    if (controller != oldWidget.controller) {
-      oldWidget.controller.removeListener(_didChangeTextEditingValue);
+    if (controller != oldWidget.configurations.controller) {
+      oldWidget.configurations.controller
+          .removeListener(_didChangeTextEditingValue);
       controller.addListener(_didChangeTextEditingValue);
       updateRemoteValueIfNeeded();
     }
 
-    if (widget.scrollController != _scrollController) {
+    if (widget.configurations.scrollController != _scrollController) {
       _scrollController.removeListener(_updateSelectionOverlayForScroll);
-      _scrollController = widget.scrollController;
+      _scrollController = widget.configurations.scrollController;
       _scrollController.addListener(_updateSelectionOverlayForScroll);
     }
 
-    if (widget.focusNode != oldWidget.focusNode) {
-      oldWidget.focusNode.removeListener(_handleFocusChanged);
-      widget.focusNode.addListener(_handleFocusChanged);
+    if (widget.configurations.focusNode != oldWidget.configurations.focusNode) {
+      oldWidget.configurations.focusNode.removeListener(_handleFocusChanged);
+      widget.configurations.focusNode.addListener(_handleFocusChanged);
       updateKeepAlive();
     }
 
-    if (controller.selection != oldWidget.controller.selection) {
+    if (controller.selection != oldWidget.configurations.controller.selection) {
       _selectionOverlay?.update(textEditingValue);
     }
 
@@ -964,19 +965,20 @@ class QuillRawEditorState extends EditorState
     if (!shouldCreateInputConnection) {
       closeConnectionIfNeeded();
     } else {
-      if (oldWidget.readOnly && _hasFocus) {
+      if (oldWidget.configurations.isReadOnly && _hasFocus) {
         openConnectionIfNeeded();
       }
     }
 
     // in case customStyles changed in new widget
-    if (widget.customStyles != null) {
-      _styles = _styles!.merge(widget.customStyles!);
+    if (widget.configurations.customStyles != null) {
+      _styles = _styles!.merge(widget.configurations.customStyles!);
     }
   }
 
   bool _shouldShowSelectionHandles() {
-    return widget.showSelectionHandles && !controller.selection.isCollapsed;
+    return widget.configurations.showSelectionHandles &&
+        !controller.selection.isCollapsed;
   }
 
   @override
@@ -988,7 +990,7 @@ class QuillRawEditorState extends EditorState
     _selectionOverlay?.dispose();
     _selectionOverlay = null;
     controller.removeListener(_didChangeTextEditingValueListener);
-    widget.focusNode.removeListener(_handleFocusChanged);
+    widget.configurations.focusNode.removeListener(_handleFocusChanged);
     _cursorCont.dispose();
     _clipboardStatus
       ..removeListener(_onChangedClipboardStatus)
@@ -1088,12 +1090,13 @@ class QuillRawEditorState extends EditorState
         startHandleLayerLink: _startHandleLayerLink,
         endHandleLayerLink: _endHandleLayerLink,
         renderObject: renderEditor,
-        selectionCtrls: widget.selectionCtrls,
+        selectionCtrls: widget.configurations.selectionCtrls,
         selectionDelegate: this,
         clipboardStatus: _clipboardStatus,
-        contextMenuBuilder: widget.contextMenuBuilder == null
+        contextMenuBuilder: widget.configurations.contextMenuBuilder == null
             ? null
-            : (context) => widget.contextMenuBuilder!(context, this),
+            : (context) =>
+                widget.configurations.contextMenuBuilder!(context, this),
       );
       _selectionOverlay!.handlesVisible = _shouldShowSelectionHandles();
       _selectionOverlay!.showHandles();
@@ -1127,7 +1130,8 @@ class QuillRawEditorState extends EditorState
 
   Future<LinkMenuAction> _linkActionPicker(Node linkNode) async {
     final link = linkNode.style.attributes[Attribute.link.key]!.value!;
-    return widget.linkActionPickerDelegate(context, link, linkNode);
+    return widget.configurations
+        .linkActionPickerDelegate(context, link, linkNode);
   }
 
   bool _showCaretOnScreenScheduled = false;
@@ -1140,13 +1144,13 @@ class QuillRawEditorState extends EditorState
   bool _disableScrollControllerAnimateOnce = false;
 
   void _showCaretOnScreen() {
-    if (!widget.showCursor || _showCaretOnScreenScheduled) {
+    if (!widget.configurations.showCursor || _showCaretOnScreenScheduled) {
       return;
     }
 
     _showCaretOnScreenScheduled = true;
     SchedulerBinding.instance.addPostFrameCallback((_) {
-      if (widget.scrollable || _scrollController.hasClients) {
+      if (widget.configurations.scrollable || _scrollController.hasClients) {
         _showCaretOnScreenScheduled = false;
 
         if (!mounted) {
@@ -1213,7 +1217,7 @@ class QuillRawEditorState extends EditorState
         _showCaretOnScreen();
       }
     } else {
-      widget.focusNode.requestFocus();
+      widget.configurations.focusNode.requestFocus();
     }
   }
 
@@ -1291,7 +1295,7 @@ class QuillRawEditorState extends EditorState
     _pastePlainText = controller.getPlainText();
     _pasteStyleAndEmbed = controller.getAllIndividualSelectionStylesAndEmbed();
 
-    if (widget.readOnly) {
+    if (widget.configurations.isReadOnly) {
       return;
     }
     final selection = textEditingValue.selection;
@@ -1311,7 +1315,7 @@ class QuillRawEditorState extends EditorState
   /// Paste text from [Clipboard].
   @override
   Future<void> pasteText(SelectionChangedCause cause) async {
-    if (widget.readOnly) {
+    if (widget.configurations.isReadOnly) {
       return;
     }
 
@@ -1372,7 +1376,7 @@ class QuillRawEditorState extends EditorState
       return;
     }
 
-    final onImagePaste = widget.onImagePaste;
+    final onImagePaste = widget.configurations.onImagePaste;
     if (onImagePaste != null) {
       final image = await Pasteboard.image;
 
@@ -1411,7 +1415,7 @@ class QuillRawEditorState extends EditorState
   }
 
   @override
-  bool get wantKeepAlive => widget.focusNode.hasFocus;
+  bool get wantKeepAlive => widget.configurations.focusNode.hasFocus;
 
   @override
   AnimationController get floatingCursorResetController =>
diff --git a/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart b/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart
index 0ad2c1c7..46617573 100644
--- a/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart
+++ b/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart
@@ -14,17 +14,18 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
     implements TextSelectionDelegate {
   @override
   TextEditingValue get textEditingValue {
-    return widget.controller.plainTextEditingValue;
+    return widget.configurations.controller.plainTextEditingValue;
   }
 
   set textEditingValue(TextEditingValue value) {
     final cursorPosition = value.selection.extentOffset;
-    final oldText = widget.controller.document.toPlainText();
+    final oldText = widget.configurations.controller.document.toPlainText();
     final newText = value.text;
     final diff = getDiff(oldText, newText, cursorPosition);
     if (diff.deleted == '' && diff.inserted == '') {
       // Only changing selection range
-      widget.controller.updateSelection(value.selection, ChangeSource.local);
+      widget.configurations.controller
+          .updateSelection(value.selection, ChangeSource.local);
       return;
     }
 
@@ -34,7 +35,7 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
     insertedText =
         containsEmbed ? _adjustInsertedText(diff.inserted) : diff.inserted;
 
-    widget.controller.replaceText(
+    widget.configurations.controller.replaceText(
         diff.start, diff.deleted.length, insertedText, value.selection);
 
     _applyPasteStyleAndEmbed(insertedText, diff.start, containsEmbed);
@@ -51,18 +52,22 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
 
         final local = pos + offset;
         if (styleAndEmbed is Embeddable) {
-          widget.controller.replaceText(local, 0, styleAndEmbed, null);
+          widget.configurations.controller
+              .replaceText(local, 0, styleAndEmbed, null);
         } else {
           final style = styleAndEmbed as Style;
           if (style.isInline) {
-            widget.controller
+            widget.configurations.controller
                 .formatTextStyle(local, pasteStyleAndEmbed[i].length!, style);
           } else if (style.isBlock) {
-            final node = widget.controller.document.queryChild(local).node;
+            final node = widget.configurations.controller.document
+                .queryChild(local)
+                .node;
             if (node != null &&
                 pasteStyleAndEmbed[i].length == node.length - 1) {
               for (final attribute in style.values) {
-                widget.controller.document.format(local, 0, attribute);
+                widget.configurations.controller.document
+                    .format(local, 0, attribute);
               }
             }
           }
@@ -164,15 +169,18 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
   }
 
   @override
-  bool get cutEnabled => widget.contextMenuBuilder != null && !widget.readOnly;
+  bool get cutEnabled =>
+      widget.configurations.contextMenuBuilder != null &&
+      !widget.configurations.isReadOnly;
 
   @override
-  bool get copyEnabled => widget.contextMenuBuilder != null;
+  bool get copyEnabled => widget.configurations.contextMenuBuilder != null;
 
   @override
   bool get pasteEnabled =>
-      widget.contextMenuBuilder != null && !widget.readOnly;
+      widget.configurations.contextMenuBuilder != null &&
+      !widget.configurations.isReadOnly;
 
   @override
-  bool get selectAllEnabled => widget.contextMenuBuilder != null;
+  bool get selectAllEnabled => widget.configurations.contextMenuBuilder != null;
 }
diff --git a/lib/src/widgets/raw_editor/raw_editor_state_text_input_client_mixin.dart b/lib/src/widgets/raw_editor/raw_editor_state_text_input_client_mixin.dart
index 01411570..cc0ac14c 100644
--- a/lib/src/widgets/raw_editor/raw_editor_state_text_input_client_mixin.dart
+++ b/lib/src/widgets/raw_editor/raw_editor_state_text_input_client_mixin.dart
@@ -1,8 +1,8 @@
 import 'dart:ui';
 
-import 'package:flutter/animation.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/scheduler.dart';
+import 'package:flutter/animation.dart' show Curves;
+import 'package:flutter/foundation.dart' show kIsWeb;
+import 'package:flutter/scheduler.dart' show SchedulerBinding;
 import 'package:flutter/services.dart';
 
 import '../../models/documents/document.dart';
@@ -27,7 +27,8 @@ mixin RawEditorStateTextInputClientMixin on EditorState
   /// - cmd/ctrl+c shortcut to copy.
   /// - cmd/ctrl+a to select all.
   /// - Changing the selection using a physical keyboard.
-  bool get shouldCreateInputConnection => kIsWeb || !widget.readOnly;
+  bool get shouldCreateInputConnection =>
+      kIsWeb || !widget.configurations.isReadOnly;
 
   /// Returns `true` if there is open input connection.
   bool get hasConnection =>
@@ -36,9 +37,10 @@ mixin RawEditorStateTextInputClientMixin on EditorState
   /// Opens or closes input connection based on the current state of
   /// [focusNode] and [value].
   void openOrCloseConnection() {
-    if (widget.focusNode.hasFocus && widget.focusNode.consumeKeyboardToken()) {
+    if (widget.configurations.focusNode.hasFocus &&
+        widget.configurations.focusNode.consumeKeyboardToken()) {
       openConnectionIfNeeded();
-    } else if (!widget.focusNode.hasFocus) {
+    } else if (!widget.configurations.focusNode.hasFocus) {
       closeConnectionIfNeeded();
     }
   }
@@ -54,14 +56,16 @@ mixin RawEditorStateTextInputClientMixin on EditorState
         this,
         TextInputConfiguration(
           inputType: TextInputType.multiline,
-          readOnly: widget.readOnly,
-          inputAction: TextInputAction.newline,
-          enableSuggestions: !widget.readOnly,
-          keyboardAppearance: widget.keyboardAppearance,
-          textCapitalization: widget.textCapitalization,
-          allowedMimeTypes: widget.contentInsertionConfiguration == null
-              ? const <String>[]
-              : widget.contentInsertionConfiguration!.allowedMimeTypes,
+          readOnly: widget.configurations.isReadOnly,
+          inputAction: widget.configurations.textInputAction,
+          enableSuggestions: !widget.configurations.isReadOnly,
+          keyboardAppearance: widget.configurations.keyboardAppearance,
+          textCapitalization: widget.configurations.textCapitalization,
+          allowedMimeTypes:
+              widget.configurations.contentInsertionConfiguration == null
+                  ? const <String>[]
+                  : widget.configurations.contentInsertionConfiguration!
+                      .allowedMimeTypes,
         ),
       );
 
@@ -187,9 +191,10 @@ mixin RawEditorStateTextInputClientMixin on EditorState
     final cursorPosition = value.selection.extentOffset;
     final diff = getDiff(oldText, text, cursorPosition);
     if (diff.deleted.isEmpty && diff.inserted.isEmpty) {
-      widget.controller.updateSelection(value.selection, ChangeSource.local);
+      widget.configurations.controller
+          .updateSelection(value.selection, ChangeSource.local);
     } else {
-      widget.controller.replaceText(
+      widget.configurations.controller.replaceText(
           diff.start, diff.deleted.length, diff.inserted, value.selection);
     }
   }
diff --git a/lib/src/widgets/toolbar/buttons/quill_icon.dart b/lib/src/widgets/toolbar/buttons/quill_icon.dart
index 37e5b81a..8c2b9637 100644
--- a/lib/src/widgets/toolbar/buttons/quill_icon.dart
+++ b/lib/src/widgets/toolbar/buttons/quill_icon.dart
@@ -28,6 +28,14 @@ class QuillToolbarIconButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    // return IconButton(
+    //   onPressed: () {
+    //     onPressed?.call();
+    //     afterPressed?.call();
+    //   },
+    //   icon: icon ?? const SizedBox.shrink(),
+    //   tooltip: tooltip,
+    // );
     return ConstrainedBox(
       constraints: BoxConstraints.tightFor(width: size, height: size),
       child: UtilityWidgets.maybeTooltip(
diff --git a/lib/src/widgets/toolbar/buttons/select_header_style.dart b/lib/src/widgets/toolbar/buttons/select_header_style.dart
index 865a619d..b8179cf8 100644
--- a/lib/src/widgets/toolbar/buttons/select_header_style.dart
+++ b/lib/src/widgets/toolbar/buttons/select_header_style.dart
@@ -145,6 +145,8 @@ class QuillToolbarSelectHeaderStyleButtonsState
       }
       final theme = Theme.of(context);
       final isSelected = _selectedAttribute == attribute;
+      // TODO: This needs to be updated to materail 3 as well just like in
+      // quill_icon.dart
       return Padding(
         padding: const EdgeInsets.symmetric(horizontal: !kIsWeb ? 1.0 : 5.0),
         child: ConstrainedBox(
diff --git a/lib/src/widgets/utils/provider.dart b/lib/src/widgets/utils/provider.dart
index 6a9028e0..12a49553 100644
--- a/lib/src/widgets/utils/provider.dart
+++ b/lib/src/widgets/utils/provider.dart
@@ -98,7 +98,7 @@ class QuillToolbarProvider extends InheritedWidget {
             'because '
             'The provider is $provider. Please make sure to wrap this widget'
             ' with'
-            ' QuillProvider widget. '
+            ' QuillToolbarProvider widget. '
             'You might using QuillToolbar so make sure to'
             ' wrap them with the quill provider widget and setup the required '
             'configurations',
@@ -157,8 +157,8 @@ class QuillBaseToolbarProvider extends InheritedWidget {
             'because '
             'The provider is $provider. Please make sure to wrap this widget'
             ' with'
-            ' QuillProvider widget. '
-            'You might using QuillToolbar so make sure to'
+            ' QuillBaseToolbarProvider widget. '
+            'You might using QuillBaseToolbar so make sure to'
             ' wrap them with the quill provider widget and setup the required '
             'configurations',
         'QuillProvider',
@@ -214,7 +214,7 @@ class QuillEditorProvider extends InheritedWidget {
             'because '
             'The provider is $provider. Please make sure to wrap this widget'
             ' with'
-            ' QuillProvider widget. '
+            ' QuillEditorProvider widget. '
             'You might using QuillEditor so make sure to'
             ' wrap them with the quill provider widget and setup the required '
             'configurations',
diff --git a/pubspec.yaml b/pubspec.yaml
index 437590ff..deca5dd6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
 name: flutter_quill
 description: A rich text editor built for the modern Android, iOS, web and desktop platforms. It is the WYSIWYG editor and a Quill component for Flutter.
-version: 8.4.1
+version: 8.4.2
 homepage: https://1o24bbs.com/c/bulletjournal/108
 repository: https://github.com/singerdmx/flutter-quill