diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index eb4a0a6..fe75aa3 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -1,23 +1,25 @@
-name: "Continuous Integration"
+name: Continuous Integration
 
 on:
   push:
+    branches:
+      - master
+      - '*.x'
   pull_request:
   schedule:
     - cron: '0 0 * * *'
 
 jobs:
-  phpunit:
-
+  tests:
     runs-on: ubuntu-latest
 
     strategy:
       fail-fast: true
       matrix:
-        php: [8.1, 8.2]
+        php: [8.2, 8.3, 8.4]
         stability: [prefer-stable]
 
-    name: PHP ${{ matrix.php }} - ${{ matrix.stability }}
+    name: PHP ${{ matrix.php }} - STABILITY ${{ matrix.stability }}
 
     steps:
       - name: Checkout code
@@ -27,7 +29,7 @@ jobs:
         uses: shivammathur/setup-php@v2
         with:
           php-version: ${{ matrix.php }}
-          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, memcached
+          extensions: oci8
           tools: composer:v2
           coverage: none
 
diff --git a/.github/workflows/pint.yml b/.github/workflows/pint.yml
new file mode 100644
index 0000000..c07577f
--- /dev/null
+++ b/.github/workflows/pint.yml
@@ -0,0 +1,33 @@
+name: PHP Linting
+
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+      - '*.x'
+
+jobs:
+  pint:
+    name: Pint
+
+    runs-on: ubuntu-latest
+
+    permissions:
+      contents: write
+      pull-requests: write
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          ref: ${{ github.head_ref }}
+
+      - name: "laravel-pint"
+        uses: aglipanci/laravel-pint-action@latest
+        with:
+          preset: laravel
+          verboseMode: true
+
+      - uses: stefanzweifel/git-auto-commit-action@v5
+        with:
+          commit_message: "fix: pint :robot:"
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 68eede7..4dccad0 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -1,52 +1,39 @@
-name: "Static Analysis"
+name: Static Analysis
 
 on:
   push:
-    paths:
-      - .github/workflows/static-analysis.yml
-      - composer.*
-      - phpstan.neon.dist
-      - src/**
-      - tests/**
+    branches:
+      - master
+      - '*.x'
 
   pull_request:
-    paths:
-      - .github/workflows/static-analysis.yml
-      - composer.*
-      - phpstan.neon.dist
-      - src/**
-      - tests/**
 
   schedule:
     - cron: '0 0 * * *'
 
 jobs:
   static-analysis-phpstan:
-    name: "Static Analysis with PHPStan"
-    runs-on: ubuntu-latest
 
-    strategy:
-      matrix:
-        php-version:
-          - "8.1"
+    name: Source Code
+    runs-on: ubuntu-latest
 
     steps:
-      - name: "Checkout code"
-        uses: "actions/checkout@v4"
+      - name: Checkout code
+        uses: actions/checkout@v4
 
-      - name: "Install PHP"
-        uses: "shivammathur/setup-php@v2"
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
         with:
-          coverage: "none"
-          php-version: "${{ matrix.php-version }}"
-          tools: "cs2pr"
+          php-version: 8.2
+          tools: composer:v2
+          coverage: none
 
       - name: Install dependencies
-        uses: nick-fields/retry@v2
+        uses: nick-fields/retry@v3
         with:
           timeout_minutes: 5
           max_attempts: 5
           command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress
 
-      - name: Execute type checking
-        run: vendor/bin/phpstan --configuration="phpstan.neon.dist"
+      - name: Run Static Analysis
+        run: vendor/bin/phpstan
diff --git a/.styleci.yml b/.styleci.yml
deleted file mode 100644
index 0285f17..0000000
--- a/.styleci.yml
+++ /dev/null
@@ -1 +0,0 @@
-preset: laravel
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44f4a37..954868c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,42 +1,21 @@
 # Laravel DataTables Buttons Plugin CHANGELOG.
 
-## v10.0.9 - 2024-02-27
+## v12.1.3 - 2025-04-07
 
-- fix: Update composer.json to use Larastan org #184
+- fix: custom ajax action #197
 
-## v10.0.8 - 2023-11-15
+## v12.1.2 - 2025-03-18
 
-- fix: unnecessary exception thrown #183
+- fix: stubs with generics #196
 
-## v10.0.7 - 2023-07-31
+## v12.1.1 - 2025-02-26
 
-- fix: use callback function if exportRender method is set #177
+- fix: stubs #195
 
-## v10.0.6 - 2023-02-28
+## v12.1.0 - 2025-02-26
 
-- fix: export package integration error message #174
+- feat: Macroable DataTable Base Class #193
 
-## v10.0.5 - 2023-02-28
+## v12.0.0 - 2025-02-26
 
-- fix: prevent redeclaring export query generator function (Laravel Octane) #173
-
-## v10.0.4 - 2023-02-21
-
-- fix: stubs - remove redundant docs #172
-- fix: default model namespace
-
-## v10.0.3 - 2023-02-20
-
-- fix: default model namespace config #171
-
-## v10.0.2 - 2023-02-20
-
-- fix: scopes when using api resource #170
-
-## v10.0.1 - 2023-02-20
-
-- fix: applyScopes method to support Collection #168
-
-## v10.0.0 - 2023-02-07
-
-- Add Laravel 10 compatibility #169
+- Laravel 12.x support
diff --git a/README.md b/README.md
index b580f37..fb669a2 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,20 @@
 # Laravel DataTables Buttons Plugin
 
-[![Laravel 10.x](https://img.shields.io/badge/Laravel-10.x-orange.svg)](http://laravel.com)
+[![Laravel 12.x](https://img.shields.io/badge/Laravel-12.x-orange.svg)](http://laravel.com)
 [![Latest Stable Version](https://img.shields.io/packagist/v/yajra/laravel-datatables-buttons.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
+[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
+
 [![Continuous Integration](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/continuous-integration.yml)
 [![Static Analysis](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/static-analysis.yml)
 [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yajra/laravel-datatables-buttons/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yajra/laravel-datatables-buttons/?branch=master)
 [![Total Downloads](https://img.shields.io/packagist/dt/yajra/laravel-datatables-buttons.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
-[![License](https://img.shields.io/github/license/mashape/apistatus.svg)](https://packagist.org/packages/yajra/laravel-datatables-buttons)
 
 This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for handling server-side function of exporting the table as csv, excel, pdf and printing.
 
 ## Requirements
 
-- [PHP >= 8.1](http://php.net/)
-- [Laravel 10.x](https://github.com/laravel/framework)
+- [PHP >= 8.2](http://php.net/)
+- [Laravel 12.x](https://github.com/laravel/framework)
 - [Laravel DataTables](https://github.com/yajra/laravel-datatables)
 - [jQuery DataTables v1.10.x](http://datatables.net/)
 - [jQuery DataTables Buttons Extension](https://datatables.net/reference/button/)
@@ -29,10 +30,12 @@ This package is a plugin of [Laravel DataTables](https://github.com/yajra/larave
 | 8.x and below | 4.x     |
 | 9.x           | 9.x     |
 | 10.x          | 10.x    |
+| 11.x          | 11.x    |
+| 12.x          | 12.x    |
 
 ## Quick Installation
 
-`composer require yajra/laravel-datatables-buttons:^10`
+`composer require yajra/laravel-datatables-buttons:^12`
 
 #### Service Provider (Optional on Laravel 5.5)
 
diff --git a/UPGADE.md b/UPGADE.md
new file mode 100644
index 0000000..c5ce3a6
--- /dev/null
+++ b/UPGADE.md
@@ -0,0 +1,22 @@
+# UPGRADE GUIDE
+
+## Upgrade from 10.x to 11.x
+
+1. Update the composer.json file and change the version of the package to `^11.0`:
+
+```json
+"require": {
+    "yajra/laravel-datatables-buttons": "^11.0"
+}
+```
+
+2. Run `composer update` to update the package.
+
+3. If you are using a custom class of laravel-excel to export the data, you need to update the collection method and include the return type `Collection|LazyCollection` in the method signature.
+
+```php
+public function collection(): Collection|LazyCollection
+{
+    return $this->collection;
+}
+```
diff --git a/composer.json b/composer.json
index 6b986dc..00654c9 100644
--- a/composer.json
+++ b/composer.json
@@ -1,65 +1,78 @@
 {
-  "name": "yajra/laravel-datatables-buttons",
-  "description": "Laravel DataTables Buttons Plugin.",
-  "keywords": [
-    "laravel",
-    "datatables",
-    "buttons",
-    "jquery"
-  ],
-  "license": "MIT",
-  "authors": [
-    {
-      "name": "Arjay Angeles",
-      "email": "aqangeles@gmail.com"
-    }
-  ],
-  "require": {
-    "php": "^8.1",
-    "yajra/laravel-datatables-oracle": "^10",
-    "yajra/laravel-datatables-html": "^10",
-    "illuminate/console": "^10"
-  },
-  "require-dev": {
-    "maatwebsite/excel": "^3.1.46",
-    "larastan/larastan": "^2.4",
-    "orchestra/testbench": "^8",
-    "rap2hpoutre/fast-excel": "^5.1",
-    "barryvdh/laravel-snappy": "^1.0.1"
-  },
-  "autoload": {
-    "psr-4": {
-      "Yajra\\DataTables\\": "src/"
-    }
-  },
-  "autoload-dev": {
-    "psr-4": {
-      "Yajra\\DataTables\\Buttons\\Tests\\": "tests/"
-    }
-  },
-  "extra": {
-    "branch-alias": {
-      "dev-master": "10.0-dev"
+    "name": "yajra/laravel-datatables-buttons",
+    "description": "Laravel DataTables Buttons Plugin.",
+    "keywords": [
+        "laravel",
+        "datatables",
+        "buttons",
+        "jquery"
+    ],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Arjay Angeles",
+            "email": "aqangeles@gmail.com"
+        }
+    ],
+    "require": {
+        "php": "^8.2",
+        "yajra/laravel-datatables-oracle": "^12",
+        "yajra/laravel-datatables-html": "^12",
+        "illuminate/console": "^12"
     },
-    "laravel": {
-      "providers": [
-        "Yajra\\DataTables\\ButtonsServiceProvider"
-      ]
-    }
-  },
-  "suggest": {
-    "yajra/laravel-datatables-export": "Exporting of dataTables (excel, csv and PDF) via livewire and queue worker.",
-    "maatwebsite/excel": "Exporting of dataTables (excel, csv and PDF) using maatwebsite package.",
-    "rap2hpoutre/fast-excel": "Faster exporting of dataTables using fast-excel package.",
-    "dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF.",
-    "barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view."
-  },
-  "minimum-stability": "dev",
-  "prefer-stable": true,
-  "funding": [
-    {
-      "type": "github",
-      "url": "https://github.com/sponsors/yajra"
-    }
-  ]
+    "require-dev": {
+        "larastan/larastan": "^3.1",
+        "orchestra/testbench": "^10",
+        "laravel/pint": "^1.21",
+        "rector/rector": "^2.0",
+        "maatwebsite/excel": "^3.1.64",
+        "rap2hpoutre/fast-excel": "^5.6"
+    },
+    "autoload": {
+        "psr-4": {
+            "Yajra\\DataTables\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Yajra\\DataTables\\Buttons\\Tests\\": "tests/"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "12.x-dev"
+        },
+        "laravel": {
+            "providers": [
+                "Yajra\\DataTables\\ButtonsServiceProvider"
+            ]
+        }
+    },
+    "suggest": {
+        "yajra/laravel-datatables-export": "Exporting of dataTables (excel, csv and PDF) via livewire and queue worker.",
+        "maatwebsite/excel": "Exporting of dataTables (excel, csv and PDF) using maatwebsite package.",
+        "rap2hpoutre/fast-excel": "Faster exporting of dataTables using fast-excel package.",
+        "dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF.",
+        "barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view."
+    },
+    "scripts": {
+        "test": "./vendor/bin/phpunit",
+        "pint": "./vendor/bin/pint",
+        "rector": "./vendor/bin/rector",
+        "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist",
+        "pr": [
+            "@pint",
+            "@rector",
+            "@stan",
+            "@test"
+        ]
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "funding": [
+        {
+            "type": "github",
+            "url": "https://github.com/sponsors/yajra"
+        }
+    ]
 }
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index af382bc..7822d95 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -10,10 +10,17 @@ parameters:
 
     ignoreErrors:
         - '#Unsafe usage of new static\(\).#'
-        - '#Command "datatables:html" does not have option*#'
+        -   identifier: missingType.generics
+        -   identifier: missingType.iterableValue
+        -   identifier: argument.type
+        -   identifier: method.nonObject
+        -   identifier: foreach.nonIterable
+        -   identifier: assign.propertyType
+        -   identifier: return.type
+        -   identifier: offsetAccess.nonOffsetAccessible
+        -   identifier: property.defaultValue
+        -   identifier: binaryOp.invalid
+        -   identifier: encapsedStringPart.nonString
+        -   identifier: return.missing
 
     excludePaths:
-
-    checkMissingIterableValueType: false
-
-    checkGenericClassInNonGenericObjectType: false
diff --git a/rector.php b/rector.php
new file mode 100644
index 0000000..ca7ca05
--- /dev/null
+++ b/rector.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
+use Rector\Config\RectorConfig;
+use Rector\Set\ValueObject\LevelSetList;
+
+return static function (RectorConfig $rectorConfig): void {
+    $rectorConfig->paths([
+        __DIR__.'/src',
+        __DIR__.'/tests',
+    ]);
+
+    // register a single rule
+    $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
+
+    // define sets of rules
+    $rectorConfig->sets([
+        LevelSetList::UP_TO_PHP_82,
+    ]);
+};
diff --git a/src/ButtonsServiceProvider.php b/src/ButtonsServiceProvider.php
index 23ea9c9..cdb273c 100644
--- a/src/ButtonsServiceProvider.php
+++ b/src/ButtonsServiceProvider.php
@@ -12,8 +12,6 @@ class ButtonsServiceProvider extends ServiceProvider
 {
     /**
      * Bootstrap the application events.
-     *
-     * @return void
      */
     public function boot(): void
     {
@@ -54,8 +52,6 @@ protected function registerCommands(): void
 
     /**
      * Register the service provider.
-     *
-     * @return void
      */
     public function register(): void
     {
diff --git a/src/Exports/DataTablesCollectionExport.php b/src/Exports/DataTablesCollectionExport.php
index 0719820..1e2f743 100644
--- a/src/Exports/DataTablesCollectionExport.php
+++ b/src/Exports/DataTablesCollectionExport.php
@@ -12,30 +12,18 @@ abstract class DataTablesCollectionExport implements FromCollection, WithHeading
 {
     use Exportable;
 
-    /**
-     * @var Collection|LazyCollection
-     */
-    protected $collection;
-
-    /**
-     * @param  Collection|LazyCollection|null  $collection
-     */
-    public function __construct($collection = null)
+    protected LazyCollection|Collection $collection;
+
+    public function __construct(Collection|LazyCollection|null $collection = null)
     {
         $this->collection = $collection ?? new Collection;
     }
 
-    /**
-     * @return Collection|LazyCollection
-     */
-    public function collection()
+    public function collection(): Collection|LazyCollection
     {
         return $this->collection;
     }
 
-    /**
-     * @return array
-     */
     public function headings(): array
     {
         /** @var array $first */
diff --git a/src/Generators/DataTablesHtmlCommand.php b/src/Generators/DataTablesHtmlCommand.php
index 5406ca0..95db37b 100644
--- a/src/Generators/DataTablesHtmlCommand.php
+++ b/src/Generators/DataTablesHtmlCommand.php
@@ -37,7 +37,6 @@ class DataTablesHtmlCommand extends DataTablesMakeCommand
      * Build the class with the given name.
      *
      * @param  string  $name
-     * @return string
      *
      * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
      */
@@ -48,18 +47,16 @@ protected function buildClass($name): string
         $stub = $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
 
         $this->replaceBuilder($stub)
-             ->replaceColumns($stub)
-             ->replaceButtons($stub)
-             ->replaceDOM($stub)
-             ->replaceTableId($stub);
+            ->replaceColumns($stub)
+            ->replaceButtons($stub)
+            ->replaceDOM($stub)
+            ->replaceTableId($stub);
 
         return $stub;
     }
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
     protected function getStub(): string
     {
@@ -72,7 +69,6 @@ protected function getStub(): string
      * Parse the name and format according to the root namespace.
      *
      * @param  string  $name
-     * @return string
      */
     protected function qualifyClass($name): string
     {
@@ -92,6 +88,6 @@ protected function qualifyClass($name): string
             $name = preg_replace('#datatablehtml$#i', 'DataTableHtml', $name);
         }
 
-        return $this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name;
+        return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name;
     }
 }
diff --git a/src/Generators/DataTablesMakeCommand.php b/src/Generators/DataTablesMakeCommand.php
index 2a4c2d8..0a96770 100644
--- a/src/Generators/DataTablesMakeCommand.php
+++ b/src/Generators/DataTablesMakeCommand.php
@@ -61,7 +61,6 @@ public function handle()
      * Build the class with the given name.
      *
      * @param  string  $name
-     * @return string
      *
      * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
      */
@@ -70,32 +69,28 @@ protected function buildClass($name): string
         $stub = parent::buildClass($name);
 
         $this->replaceModelImport($stub)
-             ->replaceModel($stub)
-             ->replaceBuilder($stub)
-             ->replaceColumns($stub)
-             ->replaceButtons($stub)
-             ->replaceDOM($stub)
-             ->replaceTableId($stub)
-             ->replaceAction($stub)
-             ->replaceFilename($stub);
+            ->replaceModel($stub)
+            ->replaceBuilder($stub)
+            ->replaceColumns($stub)
+            ->replaceButtons($stub)
+            ->replaceDOM($stub)
+            ->replaceTableId($stub)
+            ->replaceAction($stub)
+            ->replaceFilename($stub);
 
         return $stub;
     }
 
     /**
      * Get DataTable class base name without the suffix.
-     *
-     * @return string
      */
     protected function getDataTableBaseName(): string
     {
-        return (string) preg_replace('#datatable$#i', '', $this->getNameInput());
+        return (string) preg_replace('#datatable$#i', '', (string) $this->getNameInput());
     }
 
     /**
      * Prepare model name from input.
-     *
-     * @return string
      */
     protected function prepareModelName(): string
     {
@@ -105,7 +100,6 @@ protected function prepareModelName(): string
     /**
      * Replace the filename.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceFilename(string &$stub): static
@@ -117,9 +111,6 @@ protected function replaceFilename(string &$stub): static
 
     /**
      * Replace the action.
-     *
-     * @param  string  $stub
-     * @return static
      */
     protected function replaceAction(string &$stub): static
     {
@@ -130,8 +121,6 @@ protected function replaceAction(string &$stub): static
 
     /**
      * Set the action view to be used.
-     *
-     * @return string
      */
     protected function getAction(): string
     {
@@ -148,7 +137,6 @@ protected function getAction(): string
     /**
      * Replace columns.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceTableId(string &$stub): static
@@ -161,7 +149,6 @@ protected function replaceTableId(string &$stub): static
     /**
      * Replace dom.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceDOM(string &$stub): static
@@ -177,7 +164,6 @@ protected function replaceDOM(string &$stub): static
     /**
      * Replace buttons.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceButtons(string &$stub): static
@@ -189,8 +175,6 @@ protected function replaceButtons(string &$stub): static
 
     /**
      * Get the columns to be used.
-     *
-     * @return string
      */
     protected function getButtons(): string
     {
@@ -209,10 +193,6 @@ protected function getButtons(): string
 
     /**
      * Parse array from definition.
-     *
-     * @param  string  $definition
-     * @param  int  $indentation
-     * @return string
      */
     protected function parseButtons(string $definition, int $indentation = 24): string
     {
@@ -239,7 +219,6 @@ protected function parseButtons(string $definition, int $indentation = 24): stri
     /**
      * Replace columns.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceColumns(string &$stub): static
@@ -251,8 +230,6 @@ protected function replaceColumns(string &$stub): static
 
     /**
      * Get the columns to be used.
-     *
-     * @return string
      */
     protected function getColumns(): string
     {
@@ -278,10 +255,6 @@ protected function getColumns(): string
 
     /**
      * Parse array from definition.
-     *
-     * @param  array|string  $definition
-     * @param  int  $indentation
-     * @return string
      */
     protected function parseColumns(array|string $definition, int $indentation = 12): string
     {
@@ -338,14 +311,13 @@ protected function qualifyClass($name)
             $name = preg_replace('#datatable$#i', 'DataTable', $name);
         }
 
-        return $this->getDefaultNamespace(trim($rootNamespace, '\\')).'\\'.$name;
+        return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name;
     }
 
     /**
      * Get the default namespace for the class.
      *
      * @param  string  $rootNamespace
-     * @return string
      */
     protected function getDefaultNamespace($rootNamespace): string
     {
@@ -354,9 +326,6 @@ protected function getDefaultNamespace($rootNamespace): string
 
     /**
      * Replace model name.
-     *
-     * @param  string  $stub
-     * @return static
      */
     protected function replaceModel(string &$stub): static
     {
@@ -369,16 +338,12 @@ protected function replaceModel(string &$stub): static
 
     /**
      * Get model name to use.
-     *
-     * @return string
      */
     protected function getModel(): string
     {
         /** @var string $modelFromOption */
         $modelFromOption = $this->option('model');
-        $modelNamespaceFromOption = $this->option('model-namespace')
-            ? $this->option('model-namespace')
-            : config('datatables-buttons.namespace.model');
+        $modelNamespaceFromOption = $this->option('model-namespace') ?: config('datatables-buttons.namespace.model');
 
         $name = $modelFromOption ?: $this->prepareModelName();
         $modelNamespace = $modelNamespaceFromOption ?: $this->laravel->getNamespace();
@@ -393,7 +358,6 @@ protected function getModel(): string
     /**
      * Replace model import.
      *
-     * @param  string  $stub
      * @return $this
      */
     protected function replaceModelImport(string &$stub): static
@@ -405,8 +369,6 @@ protected function replaceModelImport(string &$stub): static
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
     protected function getStub(): string
     {
diff --git a/src/Generators/DataTablesScopeCommand.php b/src/Generators/DataTablesScopeCommand.php
index 78ee636..c0aa5fd 100644
--- a/src/Generators/DataTablesScopeCommand.php
+++ b/src/Generators/DataTablesScopeCommand.php
@@ -31,7 +31,6 @@ class DataTablesScopeCommand extends GeneratorCommand
      * Get the default namespace for the class.
      *
      * @param  string  $rootNamespace
-     * @return string
      */
     protected function getDefaultNamespace($rootNamespace): string
     {
@@ -40,8 +39,6 @@ protected function getDefaultNamespace($rootNamespace): string
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
     protected function getStub(): string
     {
diff --git a/src/Generators/stubs/builder.stub b/src/Generators/stubs/builder.stub
index 2ed2af7..511be79 100644
--- a/src/Generators/stubs/builder.stub
+++ b/src/Generators/stubs/builder.stub
@@ -13,7 +13,7 @@ class DummyClass extends DataTable
     /**
      * Build the DataTable class.
      *
-     * @param QueryBuilder $query Results from query() method.
+     * @param QueryBuilder<ModelName> $query Results from query() method.
      */
     public function dataTable(QueryBuilder $query): EloquentDataTable
     {
@@ -24,6 +24,8 @@ class DummyClass extends DataTable
 
     /**
      * Get the query source of dataTable.
+     *
+     * @return QueryBuilder<ModelName>
      */
     public function query(ModelName $model): QueryBuilder
     {
diff --git a/src/Generators/stubs/datatables.stub b/src/Generators/stubs/datatables.stub
index 512be60..1a574c1 100644
--- a/src/Generators/stubs/datatables.stub
+++ b/src/Generators/stubs/datatables.stub
@@ -17,7 +17,7 @@ class DummyClass extends DataTable
     /**
      * Build the DataTable class.
      *
-     * @param QueryBuilder $query Results from query() method.
+     * @param QueryBuilder<ModelName> $query Results from query() method.
      */
     public function dataTable(QueryBuilder $query): EloquentDataTable
     {
@@ -28,6 +28,8 @@ class DummyClass extends DataTable
 
     /**
      * Get the query source of dataTable.
+     *
+     * @return QueryBuilder<ModelName>
      */
     public function query(ModelName $model): QueryBuilder
     {
@@ -43,7 +45,6 @@ class DummyClass extends DataTable
                     ->setTableId('DummyTableId')
                     ->columns($this->getColumns())
                     ->minifiedAjax()
-                    //->dom('DummyDOM')
                     ->orderBy(1)
                     ->selectStyleSingle()
                     ->buttons([
diff --git a/src/Generators/stubs/html.stub b/src/Generators/stubs/html.stub
index 37d1dcc..2d1c421 100644
--- a/src/Generators/stubs/html.stub
+++ b/src/Generators/stubs/html.stub
@@ -2,6 +2,7 @@
 
 namespace DummyNamespace;
 
+use Yajra\DataTables\Html\Builder;
 use Yajra\DataTables\Html\Button;
 use Yajra\DataTables\Html\Column;
 use Yajra\DataTables\Html\DataTableHtml;
@@ -17,15 +18,15 @@ class DummyClass extends DataTableHtml
      */
     public function handle(): Builder
     {
-        return $this->setTableId('DummyTableId')
-                    ->columns($this->getColumns())
-                    ->minifiedAjax()
-                    //->dom('DummyDOM')
-                    ->orderBy(1)
-                    ->selectStyleSingle()
-                    ->buttons([
-                        DummyButtons
-                    ]);
+        return $this->getHtmlBuilder()
+            ->setTableId('DummyTableId')
+            ->columns($this->getColumns())
+            ->minifiedAjax()
+            ->orderBy(1)
+            ->selectStyleSingle()
+            ->buttons([
+                DummyButtons
+            ]);
     }
 
     /**
diff --git a/src/Html/DataTableHtml.php b/src/Html/DataTableHtml.php
index d09d7c8..92456f4 100644
--- a/src/Html/DataTableHtml.php
+++ b/src/Html/DataTableHtml.php
@@ -25,13 +25,11 @@ public static function make(): Builder
     }
 
     /**
-     * @param  string  $method
-     * @param  mixed  $parameters
      * @return \Yajra\DataTables\Html\Builder
      *
      * @throws \Exception
      */
-    public function __call(string $method, $parameters)
+    public function __call(string $method, mixed $parameters)
     {
         if (method_exists($this->getHtmlBuilder(), $method)) {
             return $this->getHtmlBuilder()->{$method}(...$parameters);
diff --git a/src/Services/DataTable.php b/src/Services/DataTable.php
index 07a7d84..64b1a3e 100644
--- a/src/Services/DataTable.php
+++ b/src/Services/DataTable.php
@@ -12,9 +12,12 @@
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
 use Illuminate\Http\Response;
+use Illuminate\Support\Arr;
 use Illuminate\Support\Collection;
 use Illuminate\Support\LazyCollection;
+use Illuminate\Support\Traits\Macroable;
 use Maatwebsite\Excel\ExcelServiceProvider;
+use OpenSpout\Common\Entity\Style\Style;
 use Rap2hpoutre\FastExcel\FastExcel;
 use Yajra\DataTables\Contracts\DataTableButtons;
 use Yajra\DataTables\Contracts\DataTableScope;
@@ -27,47 +30,37 @@
 
 abstract class DataTable implements DataTableButtons
 {
+    use Macroable;
+
     /**
      * DataTables print preview view.
      *
      * @phpstan-var view-string
-     *
-     * @var string
      */
     protected string $printPreview = 'datatables::print';
 
     /**
      * Name of the dataTable variable.
-     *
-     * @var string
      */
     protected string $dataTableVariable = 'dataTable';
 
     /**
      * List of columns to be excluded from export.
-     *
-     * @var array
      */
     protected array $excludeFromExport = [];
 
     /**
      * List of columns to be excluded from printing.
-     *
-     * @var array
      */
     protected array $excludeFromPrint = [];
 
     /**
      * List of columns to be exported.
-     *
-     * @var string|array
      */
     protected string|array $exportColumns = '*';
 
     /**
      * List of columns to be printed.
-     *
-     * @var string|array
      */
     protected string|array $printColumns = '*';
 
@@ -80,8 +73,6 @@ abstract class DataTable implements DataTableButtons
 
     /**
      * Html builder.
-     *
-     * @var \Yajra\DataTables\Html\Builder|null
      */
     protected ?Builder $htmlBuilder = null;
 
@@ -94,15 +85,11 @@ abstract class DataTable implements DataTableButtons
 
     /**
      * Export filename.
-     *
-     * @var string
      */
     protected string $filename = '';
 
     /**
      * Custom attributes set on the class.
-     *
-     * @var array
      */
     protected array $attributes = [];
 
@@ -124,20 +111,13 @@ abstract class DataTable implements DataTableButtons
      * Available button actions. When calling an action, the value will be used
      * as the function name (so it should be available)
      * If you want to add or disable an action, overload and modify this property.
-     *
-     * @var array
      */
     protected array $actions = ['print', 'csv', 'excel', 'pdf'];
 
-    /**
-     * @var \Yajra\DataTables\Utilities\Request|null
-     */
     protected ?Request $request = null;
 
     /**
      * Flag to use fast-excel package for export.
-     *
-     * @var bool
      */
     protected bool $fastExcel = false;
 
@@ -146,8 +126,6 @@ abstract class DataTable implements DataTableButtons
      * Note: Disabling this flag can improve you export time.
      * Enabled by default to emulate the same output
      * with laravel-excel.
-     *
-     * @var bool
      */
     protected bool $fastExcelCallback = true;
 
@@ -160,22 +138,16 @@ abstract class DataTable implements DataTableButtons
 
     /**
      * CSV export typewriter.
-     *
-     * @var string
      */
     protected string $csvWriter = 'Csv';
 
     /**
      * Excel export typewriter.
-     *
-     * @var string
      */
     protected string $excelWriter = 'Xlsx';
 
     /**
      * PDF export typewriter.
-     *
-     * @var string
      */
     protected string $pdfWriter = 'Dompdf';
 
@@ -196,17 +168,10 @@ public function __construct()
      *
      * @phpstan-param view-string|null $view
      *
-     * @param  string|null  $view
-     * @param  array  $data
-     * @param  array  $mergeData
      * @return mixed
      */
-    public function render(string $view = null, array $data = [], array $mergeData = [])
+    public function render(?string $view = null, array $data = [], array $mergeData = [])
     {
-        if ($this->request()->ajax() && $this->request()->wantsJson()) {
-            return app()->call([$this, 'ajax']);
-        }
-
         /** @var string $action */
         $action = $this->request()->get('action');
         $actionMethod = $action === 'print' ? 'printPreview' : $action;
@@ -218,14 +183,16 @@ public function render(string $view = null, array $data = [], array $mergeData =
             return app()->call($callback);
         }
 
+        if ($this->request()->ajax() && $this->request()->wantsJson()) {
+            return app()->call($this->ajax(...));
+        }
+
         /** @phpstan-ignore-next-line  */
         return view($view, $data, $mergeData)->with($this->dataTableVariable, $this->getHtmlBuilder());
     }
 
     /**
      * Get DataTables Request instance.
-     *
-     * @return \Yajra\DataTables\Utilities\Request
      */
     public function request(): Request
     {
@@ -238,8 +205,6 @@ public function request(): Request
 
     /**
      * Display ajax response.
-     *
-     * @return \Illuminate\Http\JsonResponse
      */
     public function ajax(): JsonResponse
     {
@@ -283,8 +248,6 @@ public function printPreview(): Renderable
 
     /**
      * Get mapped columns versus final decorated output.
-     *
-     * @return array
      */
     protected function getDataForPrint(): array
     {
@@ -295,8 +258,6 @@ protected function getDataForPrint(): array
 
     /**
      * Get printable columns.
-     *
-     * @return array|\Illuminate\Support\Collection
      */
     protected function printColumns(): array|Collection
     {
@@ -305,8 +266,6 @@ protected function printColumns(): array|Collection
 
     /**
      * Get filtered print columns definition from html builder.
-     *
-     * @return \Illuminate\Support\Collection
      */
     protected function getPrintColumnsFromBuilder(): Collection
     {
@@ -315,8 +274,6 @@ protected function getPrintColumnsFromBuilder(): Collection
 
     /**
      * Get filtered export columns definition from html builder.
-     *
-     * @return \Illuminate\Support\Collection
      */
     protected function getExportColumnsFromBuilder(): Collection
     {
@@ -325,8 +282,6 @@ protected function getExportColumnsFromBuilder(): Collection
 
     /**
      * Get columns definition from html builder.
-     *
-     * @return \Illuminate\Support\Collection
      */
     protected function getColumnsFromBuilder(): Collection
     {
@@ -345,8 +300,6 @@ public function html()
 
     /**
      * Get DataTables Html Builder instance.
-     *
-     * @return \Yajra\DataTables\Html\Builder
      */
     public function builder(): Builder
     {
@@ -363,24 +316,16 @@ public function builder(): Builder
 
     /**
      * Map ajax response to columns definition.
-     *
-     * @param  array|Collection  $columns
-     * @param  string  $type
-     * @return array
      */
-    protected function mapResponseToColumns($columns, string $type): array
+    protected function mapResponseToColumns(array|\Illuminate\Support\Collection $columns, string $type): array
     {
         $transformer = new DataArrayTransformer;
 
-        return array_map(function ($row) use ($columns, $type, $transformer) {
-            return $transformer->transform($row, $columns, $type);
-        }, $this->getAjaxResponseData());
+        return array_map(fn ($row) => $transformer->transform($row, $columns, $type), $this->getAjaxResponseData());
     }
 
     /**
      * Get decorated data as defined in datatables ajax response.
-     *
-     * @return array
      */
     protected function getAjaxResponseData(): array
     {
@@ -390,7 +335,7 @@ protected function getAjaxResponseData(): array
         ]);
 
         /** @var JsonResponse $response */
-        $response = app()->call([$this, 'ajax']);
+        $response = app()->call($this->ajax(...));
 
         /** @var array{data: array} $data */
         $data = $response->getData(true);
@@ -398,9 +343,6 @@ protected function getAjaxResponseData(): array
         return $data['data'];
     }
 
-    /**
-     * @return \Yajra\DataTables\Html\Builder
-     */
     protected function getHtmlBuilder(): Builder
     {
         $builder = $this->html();
@@ -414,7 +356,6 @@ protected function getHtmlBuilder(): Builder
     /**
      * Add html builder callback hook.
      *
-     * @param  callable  $callback
      * @return $this
      */
     public function withHtml(callable $callback): static
@@ -427,7 +368,6 @@ public function withHtml(callable $callback): static
     /**
      * Add callback before sending the response.
      *
-     * @param  callable  $callback
      * @return $this
      */
     public function before(callable $callback): static
@@ -440,7 +380,6 @@ public function before(callable $callback): static
     /**
      * Add callback after the response was processed.
      *
-     * @param  callable  $callback
      * @return $this
      */
     public function response(callable $callback): static
@@ -505,8 +444,6 @@ protected function buildExcelFile()
 
     /**
      * Get export filename.
-     *
-     * @return string
      */
     public function getFilename(): string
     {
@@ -516,7 +453,6 @@ public function getFilename(): string
     /**
      * Set export filename.
      *
-     * @param  string  $filename
      * @return $this
      */
     public function setFilename(string $filename): static
@@ -528,8 +464,6 @@ public function setFilename(string $filename): static
 
     /**
      * Get filename for export.
-     *
-     * @return string
      */
     protected function filename(): string
     {
@@ -538,8 +472,6 @@ protected function filename(): string
 
     /**
      * Get mapped columns versus final decorated output.
-     *
-     * @return array
      */
     protected function getDataForExport(): array
     {
@@ -560,9 +492,6 @@ protected function exportColumns(): Collection
 
     /**
      * Convert array to collection of Column class.
-     *
-     * @param  array  $columns
-     * @return Collection
      */
     private function toColumnsCollection(array $columns): Collection
     {
@@ -570,7 +499,7 @@ private function toColumnsCollection(array $columns): Collection
 
         foreach ($columns as $column) {
             if (isset($column['data'])) {
-                $column['title'] = $column['title'] ?? $column['data'];
+                $column['title'] ??= $column['data'];
                 $collection->push(new Column($column));
             } else {
                 $data = [];
@@ -604,7 +533,7 @@ public function csv()
         }
 
         // @phpstan-ignore-next-line
-        return $this->buildExcelFile()->download($path, $this->csvWriter);
+        return $excelFile->download($path, $this->csvWriter);
     }
 
     /**
@@ -616,7 +545,7 @@ public function csv()
      */
     public function pdf()
     {
-        if ('snappy' == config('datatables-buttons.pdf_generator', 'snappy')) {
+        if (config('datatables-buttons.pdf_generator', 'snappy') == 'snappy') {
             return $this->snappyPdf();
         }
 
@@ -627,7 +556,6 @@ public function pdf()
     /**
      * PDF version of the table using print preview blade template.
      *
-     * @return \Illuminate\Http\Response
      *
      * @throws \Yajra\DataTables\Exceptions\Exception
      */
@@ -652,7 +580,6 @@ public function snappyPdf(): Response
     /**
      * Add basic array query scopes.
      *
-     * @param  \Yajra\DataTables\Contracts\DataTableScope  $scope
      * @return $this
      */
     public function addScope(DataTableScope $scope): static
@@ -665,7 +592,6 @@ public function addScope(DataTableScope $scope): static
     /**
      * Push multiples scopes to array query scopes.
      *
-     * @param  array  $scopes
      * @return $this
      */
     public function addScopes(array $scopes): static
@@ -678,8 +604,6 @@ public function addScopes(array $scopes): static
     /**
      * Set a custom class attribute.
      *
-     * @param  array|string  $key
-     * @param  mixed|null  $value
      * @return $this
      */
     public function with(array|string $key, mixed $value = null): static
@@ -696,7 +620,6 @@ public function with(array|string $key, mixed $value = null): static
     /**
      * Dynamically retrieve the value of an attribute.
      *
-     * @param  string  $key
      * @return mixed|null
      */
     public function __get(string $key)
@@ -723,24 +646,16 @@ protected function applyScopes(
 
     /**
      * Determine if the DataTable has scopes.
-     *
-     * @param  array  $scopes
-     * @param  bool  $validateAll
-     * @return bool
      */
     protected function hasScopes(array $scopes, bool $validateAll = false): bool
     {
-        $filteredScopes = array_filter($this->scopes, function ($scope) use ($scopes) {
-            return in_array(get_class($scope), $scopes);
-        });
+        $filteredScopes = array_filter($this->scopes, fn ($scope) => in_array($scope::class, $scopes));
 
         return $validateAll ? count($filteredScopes) === count($scopes) : ! empty($filteredScopes);
     }
 
     /**
      * Get default builder parameters.
-     *
-     * @return array
      */
     protected function getBuilderParameters(): array
     {
@@ -750,10 +665,6 @@ protected function getBuilderParameters(): array
         return $defaults;
     }
 
-    /**
-     * @param  array|\Illuminate\Support\Collection  $collection
-     * @return \Illuminate\Support\LazyCollection
-     */
     protected function convertToLazyCollection(array|Collection $collection): LazyCollection
     {
         if (is_array($collection)) {
@@ -763,27 +674,35 @@ protected function convertToLazyCollection(array|Collection $collection): LazyCo
         return $collection->lazy();
     }
 
-    /**
-     * @return \Closure
-     */
     public function fastExcelCallback(): Closure
     {
         return function ($row) {
             $mapped = [];
 
-            $this->exportColumns()->each(function (Column $column) use (&$mapped, $row) {
-                if ($column['exportable']) {
-                    $mapped[$column['title']] = $row[$column['data']];
-                }
-            });
+            $this->exportColumns()
+                ->reject(fn (Column $column) => $column->exportable === false)
+                ->each(function (Column $column) use (&$mapped, $row) {
+                    $callback = $column->exportRender ?? null;
+                    $key = $column->data;
+
+                    if (is_array($key)) {
+                        $data = Arr::get($row, $key['_']);
+                    } else {
+                        $data = Arr::get($row, $key);
+                    }
+
+                    if (is_callable($callback)) {
+                        $mapped[$column->title] = $callback($row, $data);
+                    } else {
+                        $mapped[$column->title] = $data;
+                    }
+                });
 
             return $mapped;
         };
     }
 
     /**
-     * @return \Rap2hpoutre\FastExcel\FastExcel
-     *
      * @throws \Yajra\DataTables\Exceptions\Exception
      */
     protected function buildFastExcelFile(): FastExcel
@@ -804,6 +723,13 @@ protected function buildFastExcelFile(): FastExcel
         $dataTable = app()->call([$this, 'dataTable'], compact('query'));
         $dataTable->skipPaging();
 
+        $styles = [];
+        $this->exportColumns()
+            ->reject(fn (Column $column) => $column->exportable === false || ! $column->exportFormat)
+            ->each(function (Column $column) use (&$styles) {
+                $styles[$column->title] = (new Style)->setFormat($column->exportFormat);
+            });
+
         if ($dataTable instanceof QueryDataTable) {
             $queryGenerator = function ($dataTable): Generator {
                 foreach ($dataTable->getFilteredQuery()->cursor() as $row) {
@@ -811,9 +737,9 @@ protected function buildFastExcelFile(): FastExcel
                 }
             };
 
-            return new FastExcel($queryGenerator($dataTable));
+            return (new FastExcel($queryGenerator($dataTable)))->setColumnStyles($styles);
         }
 
-        return new FastExcel($dataTable->toArray()['data']);
+        return (new FastExcel($dataTable->toArray()['data']))->setColumnStyles($styles);
     }
 }
diff --git a/src/Services/DataTablesExportHandler.php b/src/Services/DataTablesExportHandler.php
index 0b1e7e8..8cc53b3 100644
--- a/src/Services/DataTablesExportHandler.php
+++ b/src/Services/DataTablesExportHandler.php
@@ -4,6 +4,4 @@
 
 use Yajra\DataTables\Exports\DataTablesCollectionExport;
 
-class DataTablesExportHandler extends DataTablesCollectionExport
-{
-}
+class DataTablesExportHandler extends DataTablesCollectionExport {}
diff --git a/src/Transformers/DataArrayTransformer.php b/src/Transformers/DataArrayTransformer.php
index 24b6b4d..bd393e5 100644
--- a/src/Transformers/DataArrayTransformer.php
+++ b/src/Transformers/DataArrayTransformer.php
@@ -11,10 +11,7 @@ class DataArrayTransformer
     /**
      * Transform row data by column's definition.
      *
-     * @param  array  $row
      * @param  array|Collection<array-key, Column>  $columns
-     * @param  string  $type
-     * @return array
      */
     public function transform(array $row, array|Collection $columns, string $type = 'printable'): array
     {
@@ -28,10 +25,7 @@ public function transform(array $row, array|Collection $columns, string $type =
     /**
      * Transform row column by collection.
      *
-     * @param  array  $row
      * @param  Collection<array-key, Column>  $columns
-     * @param  string  $type
-     * @return array
      */
     protected function buildColumnByCollection(array $row, Collection $columns, string $type = 'printable'): array
     {
@@ -49,7 +43,7 @@ protected function buildColumnByCollection(array $row, Collection $columns, stri
 
                 if ($type == 'exportable') {
                     $title = $this->decodeContent($title);
-                    $data = is_array($data) ? json_encode($data) : $this->decodeContent($data);
+                    $data = is_array($data) ? json_encode($data, JSON_THROW_ON_ERROR) : $this->decodeContent($data);
                 }
 
                 if (isset($column->exportRender)) {
@@ -66,9 +60,6 @@ protected function buildColumnByCollection(array $row, Collection $columns, stri
 
     /**
      * Decode content to a readable text value.
-     *
-     * @param  mixed  $data
-     * @return mixed
      */
     protected function decodeContent(mixed $data): mixed
     {
diff --git a/src/config/config.php b/src/config/config.php
index 1276d13..62d1365 100644
--- a/src/config/config.php
+++ b/src/config/config.php
@@ -29,7 +29,7 @@
     /*
      * Set Custom stub folder
      */
-    //'stub' => '/resources/custom_stub',
+    // 'stub' => '/resources/custom_stub',
 
     /*
      * PDF generator to be used when converting the table to pdf.
diff --git a/tests/DataTableServiceTest.php b/tests/DataTableServiceTest.php
index 0afcebb..91b1b66 100644
--- a/tests/DataTableServiceTest.php
+++ b/tests/DataTableServiceTest.php
@@ -5,16 +5,18 @@
 use Illuminate\Foundation\Testing\DatabaseTransactions;
 use Illuminate\Http\Response;
 use Illuminate\Support\Collection;
+use PHPUnit\Framework\Attributes\Test;
 use Symfony\Component\HttpFoundation\BinaryFileResponse;
 use Yajra\DataTables\Buttons\Tests\DataTables\UsersDataTable;
 use Yajra\DataTables\Buttons\Tests\Models\User;
 use Yajra\DataTables\EloquentDataTable;
+use Yajra\DataTables\Services\DataTable;
 
 class DataTableServiceTest extends TestCase
 {
     use DatabaseTransactions;
 
-    /** @test */
+    #[Test]
     public function it_can_handle_ajax_request(): void
     {
         $response = $this->getAjax('/users');
@@ -26,7 +28,7 @@ public function it_can_handle_ajax_request(): void
         ]);
     }
 
-    /** @test */
+    #[Test]
     public function it_returns_view_on_normal_get_request(): void
     {
         $response = $this->get('users');
@@ -35,7 +37,7 @@ public function it_returns_view_on_normal_get_request(): void
         $response->assertSeeText('LaravelDataTables');
     }
 
-    /** @test */
+    #[Test]
     public function it_can_return_a_csv_file(): void
     {
         $response = $this->get('users?action=csv');
@@ -43,7 +45,7 @@ public function it_can_return_a_csv_file(): void
         $this->assertInstanceOf(BinaryFileResponse::class, $response->baseResponse);
     }
 
-    /** @test */
+    #[Test]
     public function it_can_return_a_xls_file(): void
     {
         $response = $this->get('users?action=excel');
@@ -51,7 +53,7 @@ public function it_can_return_a_xls_file(): void
         $this->assertInstanceOf(BinaryFileResponse::class, $response->baseResponse);
     }
 
-    /** @test */
+    #[Test]
     public function it_can_return_a_pdf_file(): void
     {
         $response = $this->get('users?action=pdf');
@@ -59,7 +61,7 @@ public function it_can_return_a_pdf_file(): void
         $this->assertInstanceOf(Response::class, $response->baseResponse);
     }
 
-    /** @test */
+    #[Test]
     public function it_allows_before_response_callback(): void
     {
         $response = $this->getAjax('users/before');
@@ -69,7 +71,7 @@ public function it_allows_before_response_callback(): void
         $this->assertEquals($row['name'].'X', $row['nameX']);
     }
 
-    /** @test */
+    #[Test]
     public function it_allows_response_callback(): void
     {
         $response = $this->getAjax('users/response');
@@ -79,28 +81,36 @@ public function it_allows_response_callback(): void
         $this->assertEquals(1, $response->json('recordsFiltered'));
     }
 
+    #[Test]
+    public function it_is_macroable(): void
+    {
+        $dataTable = new class extends DataTable {};
+
+        $this->assertObjectHasProperty('macros', $dataTable);
+        $this->assertTrue(method_exists($dataTable, 'macro'), 'Method macro does not exist.');
+        $this->assertTrue(method_exists($dataTable, 'mixin'), 'Method mixin does not exist.');
+
+        DataTable::macro('macroMethod', fn () => 'macro');
+
+        $this->assertEquals('macro', $dataTable->macroMethod());
+    }
+
     protected function setUp(): void
     {
         parent::setUp();
 
         $router = $this->app['router'];
-        $router->get('/users', function (UsersDataTable $dataTable) {
-            return $dataTable->render('tests::users');
-        });
-
-        $router->get('/users/before', function (UsersDataTable $dataTable) {
-            return $dataTable->before(function (EloquentDataTable $dataTable) {
-                $dataTable->addColumn('nameX', fn (User $user) => $user->name.'X');
-            })->render('tests::users');
-        });
-
-        $router->get('/users/response', function (UsersDataTable $dataTable) {
-            return $dataTable->response(function (Collection $data) {
-                $data['recordsTotal'] = 2;
-                $data['recordsFiltered'] = 1;
-
-                return $data;
-            })->render('tests::users');
-        });
+        $router->get('/users', fn (UsersDataTable $dataTable) => $dataTable->render('tests::users'));
+
+        $router->get('/users/before', fn (UsersDataTable $dataTable) => $dataTable->before(function (EloquentDataTable $dataTable) {
+            $dataTable->addColumn('nameX', fn (User $user) => $user->name.'X');
+        })->render('tests::users'));
+
+        $router->get('/users/response', fn (UsersDataTable $dataTable) => $dataTable->response(function (Collection $data) {
+            $data['recordsTotal'] = 2;
+            $data['recordsFiltered'] = 1;
+
+            return $data;
+        })->render('tests::users'));
     }
 }
diff --git a/tests/DataTables/UsersDataTable.php b/tests/DataTables/UsersDataTable.php
index 66e8e29..0a05c98 100644
--- a/tests/DataTables/UsersDataTable.php
+++ b/tests/DataTables/UsersDataTable.php
@@ -10,9 +10,6 @@
 
 class UsersDataTable extends DataTable
 {
-    /**
-     * @throws \Yajra\DataTables\Exceptions\Exception
-     */
     public function dataTable(Builder $query): EloquentDataTable
     {
         return (new EloquentDataTable($query))
@@ -27,12 +24,12 @@ public function query(User $user): Builder
     public function html(): \Yajra\DataTables\Html\Builder
     {
         return $this->builder()
-                    ->setTableId('users-table')
-                    ->minifiedAjax()
-                    ->columns([
-                        Column::make('id'),
-                        Column::make('name'),
-                    ]);
+            ->setTableId('users-table')
+            ->minifiedAjax()
+            ->columns([
+                Column::make('id'),
+                Column::make('name'),
+            ]);
     }
 
     protected function filename(): string
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 094d576..d063f36 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,7 +2,6 @@
 
 namespace Yajra\DataTables\Buttons\Tests;
 
-use Barryvdh\Snappy\ServiceProvider;
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Testing\TestResponse;
 use Orchestra\Testbench\TestCase as BaseTestCase;
@@ -111,7 +110,6 @@ protected function getPackageProviders($app): array
             DataTablesServiceProvider::class,
             ButtonsServiceProvider::class,
             HtmlServiceProvider::class,
-            ServiceProvider::class,
         ];
     }
 
