diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index dd673d4289e770443d3955e9dc59f67478ae07ac..800b8aff2652f3e35a0fdb582ad437e0892a5fbc 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -15,7 +15,7 @@ If you discover a security vulnerability within Laravel, please send an email to
 ```
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: OpenPGP v2.0.8
-Comment: https://sela.io/pgp/
+Comment: Report Security Vulnerabilities to taylor@laravel.com
 
 xsFNBFugFSQBEACxEKhIY9IoJzcouVTIYKJfWFGvwFgbRjQWBiH3QdHId5vCrbWo
 s2l+4Rv03gMG+yHLJ3rWElnNdRaNdQv59+lShrZF7Bvu7Zvc0mMNmFOM/mQ/K2Lt
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f336ecfd1e86506821ed7fe8538a5aeebff6ef71..272a76345b1259d10672e68b987ef09a271b918a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
 # Release Notes
 
-## [Unreleased](https://github.com/laravel/prompts/compare/v0.1.23...main)
+## [Unreleased](https://github.com/laravel/prompts/compare/v0.1.24...main)
+
+## [v0.1.24](https://github.com/laravel/prompts/compare/v0.1.23...v0.1.24) - 2024-06-17
+
+* Allow re-rendering during progress callback by [@jessarcher](https://github.com/jessarcher) in https://github.com/laravel/prompts/pull/155
 
 ## [v0.1.23](https://github.com/laravel/prompts/compare/v0.1.22...v0.1.23) - 2024-05-27
 
diff --git a/playground/text.php b/playground/text.php
index 2f596d1802c8feffbc31d3213257b785540fcc2c..ea13970fc1e41a3eda63c34df49cb0838b284f51 100644
--- a/playground/text.php
+++ b/playground/text.php
@@ -13,6 +13,7 @@ $email = text(
         default => null,
     },
     hint: 'We will never share your email address with anyone else.',
+    transform: fn ($value) => strtolower($value),
 );
 
 var_dump($email);
diff --git a/playground/textarea.php b/playground/textarea.php
index 070305f2b981d46fa69b34c7c4e345d2f7431da0..9e498cef69263e4cf7f53ef55cf06f9f5e2acff7 100644
--- a/playground/textarea.php
+++ b/playground/textarea.php
@@ -4,11 +4,11 @@ use function Laravel\Prompts\textarea;
 
 require __DIR__.'/../vendor/autoload.php';
 
-$email = textarea(
+$story = textarea(
     label: 'Tell me a story',
     placeholder: 'Weave me a tale',
 );
 
-var_dump($email);
+var_dump($story);
 
 echo str_repeat(PHP_EOL, 5);
diff --git a/src/Concerns/FakesInputOutput.php b/src/Concerns/FakesInputOutput.php
index e136db1de8871426bbd008d57badd3dfd1f46925..5bbf53fa5db037d58936970ea92319cd3389fd3f 100644
--- a/src/Concerns/FakesInputOutput.php
+++ b/src/Concerns/FakesInputOutput.php
@@ -35,7 +35,7 @@ trait FakesInputOutput
 
         static::$terminal = $mock;
 
-        self::setOutput(new BufferedConsoleOutput());
+        self::setOutput(new BufferedConsoleOutput);
     }
 
     /**
diff --git a/src/Concerns/Termwind.php b/src/Concerns/Termwind.php
index 798348c67a3ce594936372c164bc53a449d15680..301776b1619cd13606922208c6901a4874fae785 100644
--- a/src/Concerns/Termwind.php
+++ b/src/Concerns/Termwind.php
@@ -11,7 +11,7 @@ trait Termwind
 {
     protected function termwind(string $html)
     {
-        renderUsing($output = new BufferedConsoleOutput());
+        renderUsing($output = new BufferedConsoleOutput);
 
         render($html);
 
diff --git a/src/ConfirmPrompt.php b/src/ConfirmPrompt.php
index 23b8a97f5bcea1fb7e7615331ecb5b79fb34f0a9..3abccf07c39f3dd876ee70353c2b6e9cdac6863a 100644
--- a/src/ConfirmPrompt.php
+++ b/src/ConfirmPrompt.php
@@ -2,6 +2,8 @@
 
 namespace Laravel\Prompts;
 
+use Closure;
+
 class ConfirmPrompt extends Prompt
 {
     /**
@@ -20,6 +22,7 @@ class ConfirmPrompt extends Prompt
         public bool|string $required = false,
         public mixed $validate = null,
         public string $hint = '',
+        public ?Closure $transform = null,
     ) {
         $this->confirmed = $default;
 
diff --git a/src/FormBuilder.php b/src/FormBuilder.php
index 621c19b86ca8e441f885e1398368a19ecff1848c..4e5bd5d2ef6b720960319c4c79433769c1c30832 100644
--- a/src/FormBuilder.php
+++ b/src/FormBuilder.php
@@ -78,7 +78,7 @@ class FormBuilder
     /**
      * Prompt the user for text input.
      */
-    public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self
+    public function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(text(...), get_defined_vars());
     }
@@ -86,7 +86,7 @@ class FormBuilder
     /**
      * Prompt the user for multiline text input.
      */
-    public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null): self
+    public function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5, ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(textarea(...), get_defined_vars());
     }
@@ -94,7 +94,7 @@ class FormBuilder
     /**
      * Prompt the user for input, hiding the value.
      */
-    public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self
+    public function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(password(...), get_defined_vars());
     }
@@ -105,7 +105,7 @@ class FormBuilder
      * @param  array<int|string, string>|Collection<int|string, string>  $options
      * @param  true|string  $required
      */
-    public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null): self
+    public function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(select(...), get_defined_vars());
     }
@@ -116,7 +116,7 @@ class FormBuilder
      * @param  array<int|string, string>|Collection<int|string, string>  $options
      * @param  array<int|string>|Collection<int, int|string>  $default
      */
-    public function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null): self
+    public function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(multiselect(...), get_defined_vars());
     }
@@ -124,7 +124,7 @@ class FormBuilder
     /**
      * Prompt the user to confirm an action.
      */
-    public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self
+    public function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(confirm(...), get_defined_vars());
     }
@@ -142,7 +142,7 @@ class FormBuilder
      *
      * @param  array<string>|Collection<int, string>|Closure(string): array<string>  $options
      */
-    public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null): self
+    public function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(suggest(...), get_defined_vars());
     }
@@ -153,7 +153,7 @@ class FormBuilder
      * @param  Closure(string): array<int|string, string>  $options
      * @param  true|string  $required
      */
-    public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null): self
+    public function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(search(...), get_defined_vars());
     }
@@ -163,7 +163,7 @@ class FormBuilder
      *
      * @param  Closure(string): array<int|string, string>  $options
      */
-    public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null): self
+    public function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?string $name = null, ?Closure $transform = null): self
     {
         return $this->runPrompt(multisearch(...), get_defined_vars());
     }
diff --git a/src/MultiSearchPrompt.php b/src/MultiSearchPrompt.php
index 5aac82b567bdec649d4e464c0754d29b8bdec1ae..083f56b9d01ae6246026bc78e7680bacb21dfd43 100644
--- a/src/MultiSearchPrompt.php
+++ b/src/MultiSearchPrompt.php
@@ -42,6 +42,7 @@ class MultiSearchPrompt extends Prompt
         public bool|string $required = false,
         public mixed $validate = null,
         public string $hint = '',
+        public ?Closure $transform = null,
     ) {
         $this->trackTypedValue(submit: false, ignore: fn ($key) => Key::oneOf([Key::SPACE, Key::HOME, Key::END, Key::CTRL_A, Key::CTRL_E], $key) && $this->highlighted !== null);
 
diff --git a/src/MultiSelectPrompt.php b/src/MultiSelectPrompt.php
index 2dee528568bf97bdcfe430437eeb1aa865b13a19..c28bedf8b9571cf2d126429f7b7db35b73d46801 100644
--- a/src/MultiSelectPrompt.php
+++ b/src/MultiSelectPrompt.php
@@ -2,6 +2,7 @@
 
 namespace Laravel\Prompts;
 
+use Closure;
 use Illuminate\Support\Collection;
 
 class MultiSelectPrompt extends Prompt
@@ -43,6 +44,7 @@ class MultiSelectPrompt extends Prompt
         public bool|string $required = false,
         public mixed $validate = null,
         public string $hint = '',
+        public ?Closure $transform = null,
     ) {
         $this->options = $options instanceof Collection ? $options->all() : $options;
         $this->default = $default instanceof Collection ? $default->all() : $default;
diff --git a/src/PasswordPrompt.php b/src/PasswordPrompt.php
index 31802c1e96fcc930ffa86069d58ec6c05fe9deba..41b755a69bd7c14351a54a0dc42694ccfbf64253 100644
--- a/src/PasswordPrompt.php
+++ b/src/PasswordPrompt.php
@@ -2,6 +2,8 @@
 
 namespace Laravel\Prompts;
 
+use Closure;
+
 class PasswordPrompt extends Prompt
 {
     use Concerns\TypedValue;
@@ -15,6 +17,7 @@ class PasswordPrompt extends Prompt
         public bool|string $required = false,
         public mixed $validate = null,
         public string $hint = '',
+        public ?Closure $transform = null,
     ) {
         $this->trackTypedValue();
     }
diff --git a/src/Prompt.php b/src/Prompt.php
index 1d0709c9351397f5e0dc31df0d2de89360ce3074..560bc154f39e2f2dee8d9e22f03608dfc91b1211 100644
--- a/src/Prompt.php
+++ b/src/Prompt.php
@@ -50,6 +50,11 @@ abstract class Prompt
      */
     public bool|string $required;
 
+    /**
+     * The transformation callback.
+     */
+    public ?Closure $transform = null;
+
     /**
      * The validator callback or rules.
      */
@@ -137,10 +142,10 @@ abstract class Prompt
                     }
 
                     if ($key === Key::CTRL_U && self::$revertUsing) {
-                        throw new FormRevertedException();
+                        throw new FormRevertedException;
                     }
 
-                    return $this->value();
+                    return $this->transformedValue();
                 }
             }
         } finally {
@@ -187,7 +192,7 @@ abstract class Prompt
      */
     protected static function output(): OutputInterface
     {
-        return self::$output ??= new ConsoleOutput();
+        return self::$output ??= new ConsoleOutput;
     }
 
     /**
@@ -207,7 +212,7 @@ abstract class Prompt
      */
     public static function terminal(): Terminal
     {
-        return static::$terminal ??= new Terminal();
+        return static::$terminal ??= new Terminal;
     }
 
     /**
@@ -277,7 +282,7 @@ abstract class Prompt
      */
     protected function submit(): void
     {
-        $this->validate($this->value());
+        $this->validate($this->transformedValue());
 
         if ($this->state !== 'error') {
             $this->state = 'submit';
@@ -322,12 +327,32 @@ abstract class Prompt
         }
 
         if ($this->validated) {
-            $this->validate($this->value());
+            $this->validate($this->transformedValue());
         }
 
         return true;
     }
 
+    /**
+     * Transform the input.
+     */
+    private function transform(mixed $value): mixed
+    {
+        if (is_null($this->transform)) {
+            return $value;
+        }
+
+        return call_user_func($this->transform, $value);
+    }
+
+    /**
+     * Get the transformed value of the prompt.
+     */
+    protected function transformedValue(): mixed
+    {
+        return $this->transform($this->value());
+    }
+
     /**
      * Validate the input.
      */
diff --git a/src/SearchPrompt.php b/src/SearchPrompt.php
index b9b820cefab68305cac52fab7d50027eb3c878a3..259b4299e1fb65f35626e7af8c10cb56b6f9bfd6 100644
--- a/src/SearchPrompt.php
+++ b/src/SearchPrompt.php
@@ -31,6 +31,7 @@ class SearchPrompt extends Prompt
         public mixed $validate = null,
         public string $hint = '',
         public bool|string $required = true,
+        public ?Closure $transform = null,
     ) {
         if ($this->required === false) {
             throw new InvalidArgumentException('Argument [required] must be true or a string.');
diff --git a/src/SelectPrompt.php b/src/SelectPrompt.php
index 081f09c7b0e43f4b29fe06810dc1bc17a5fc0bf8..8d48a73007236b4d309c52466fc4a77c1425ded0 100644
--- a/src/SelectPrompt.php
+++ b/src/SelectPrompt.php
@@ -2,6 +2,7 @@
 
 namespace Laravel\Prompts;
 
+use Closure;
 use Illuminate\Support\Collection;
 use InvalidArgumentException;
 
@@ -29,6 +30,7 @@ class SelectPrompt extends Prompt
         public mixed $validate = null,
         public string $hint = '',
         public bool|string $required = true,
+        public ?Closure $transform = null,
     ) {
         if ($this->required === false) {
             throw new InvalidArgumentException('Argument [required] must be true or a string.');
diff --git a/src/SuggestPrompt.php b/src/SuggestPrompt.php
index dd8d2553cc6aecd6c17b3cc3204ab9d2dd512247..73efbdca1a5eadcf7d6bf31a6e5f069d1d7df256 100644
--- a/src/SuggestPrompt.php
+++ b/src/SuggestPrompt.php
@@ -39,6 +39,7 @@ class SuggestPrompt extends Prompt
         public bool|string $required = false,
         public mixed $validate = null,
         public string $hint = '',
+        public ?Closure $transform = null,
     ) {
         $this->options = $options instanceof Collection ? $options->all() : $options;
 
diff --git a/src/Terminal.php b/src/Terminal.php
index b91fea89fa8582a562c9240303d552a39827fd77..631b2a5a0a0805b2456b03d8a7c92a65b59a81e8 100644
--- a/src/Terminal.php
+++ b/src/Terminal.php
@@ -23,7 +23,7 @@ class Terminal
      */
     public function __construct()
     {
-        $this->terminal = new SymfonyTerminal();
+        $this->terminal = new SymfonyTerminal;
     }
 
     /**
diff --git a/src/TextPrompt.php b/src/TextPrompt.php
index 74a41a5e023373707343824847d1d5f1566fa380..db63f81bf7892d75d2a1517277e23b5006b2da9e 100644
--- a/src/TextPrompt.php
+++ b/src/TextPrompt.php
@@ -2,6 +2,8 @@
 
 namespace Laravel\Prompts;
 
+use Closure;
+
 class TextPrompt extends Prompt
 {
     use Concerns\TypedValue;
@@ -16,6 +18,7 @@ class TextPrompt extends Prompt
         public bool|string $required = false,
         public mixed $validate = null,
         public string $hint = '',
+        public ?Closure $transform = null,
     ) {
         $this->trackTypedValue($default);
     }
diff --git a/src/TextareaPrompt.php b/src/TextareaPrompt.php
index 859469a4862cfbe919d9d09d32b7f0a9fe43e8c4..e5a336668df77f5684acf9ef0caa7e9180cf7af8 100644
--- a/src/TextareaPrompt.php
+++ b/src/TextareaPrompt.php
@@ -2,6 +2,8 @@
 
 namespace Laravel\Prompts;
 
+use Closure;
+
 class TextareaPrompt extends Prompt
 {
     use Concerns\Scrolling;
@@ -24,6 +26,7 @@ class TextareaPrompt extends Prompt
         public mixed $validate = null,
         public string $hint = '',
         int $rows = 5,
+        public ?Closure $transform = null,
     ) {
         $this->scroll = $rows;
 
diff --git a/src/Themes/Default/TableRenderer.php b/src/Themes/Default/TableRenderer.php
index 185f450017abe7ee9816b1ec59a4fcafabf2841f..c2d17bb94a92d224624a7fe26cdffc562de581cf 100644
--- a/src/Themes/Default/TableRenderer.php
+++ b/src/Themes/Default/TableRenderer.php
@@ -14,7 +14,7 @@ class TableRenderer extends Renderer
      */
     public function __invoke(Table $table): string
     {
-        $tableStyle = (new TableStyle())
+        $tableStyle = (new TableStyle)
             ->setHorizontalBorderChars('─')
             ->setVerticalBorderChars('│', '│')
             ->setCellHeaderFormat($this->dim('<fg=default>%s</>'))
@@ -26,7 +26,7 @@ class TableRenderer extends Renderer
             $tableStyle->setCrossingChars('┼', '<fg=gray>┌', '┬', '┐', '┤', '┘</>', '┴', '└', '├');
         }
 
-        $buffered = new BufferedConsoleOutput();
+        $buffered = new BufferedConsoleOutput;
 
         (new SymfonyTable($buffered))
             ->setHeaders($table->headers)
diff --git a/src/helpers.php b/src/helpers.php
index f49a9912e56d9ad1e23eb5d4def45b7149c3ca06..65545e037c024870264c5f20b6c1dbae12a20a06 100644
--- a/src/helpers.php
+++ b/src/helpers.php
@@ -9,7 +9,7 @@ if (! function_exists('\Laravel\Prompts\text')) {
     /**
      * Prompt the user for text input.
      */
-    function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = ''): string
+    function text(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): string
     {
         return (new TextPrompt(...func_get_args()))->prompt();
     }
@@ -19,9 +19,9 @@ if (! function_exists('\Laravel\Prompts\textarea')) {
     /**
      * Prompt the user for multiline text input.
      */
-    function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, ?Closure $validate = null, string $hint = '', int $rows = 5): string
+    function textarea(string $label, string $placeholder = '', string $default = '', bool|string $required = false, mixed $validate = null, string $hint = '', int $rows = 5, ?Closure $transform = null): string
     {
-        return (new TextareaPrompt($label, $placeholder, $default, $required, $validate, $hint, $rows))->prompt();
+        return (new TextareaPrompt(...func_get_args()))->prompt();
     }
 }
 
@@ -29,7 +29,7 @@ if (! function_exists('\Laravel\Prompts\password')) {
     /**
      * Prompt the user for input, hiding the value.
      */
-    function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = ''): string
+    function password(string $label, string $placeholder = '', bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): string
     {
         return (new PasswordPrompt(...func_get_args()))->prompt();
     }
@@ -42,7 +42,7 @@ if (! function_exists('\Laravel\Prompts\select')) {
      * @param  array<int|string, string>|Collection<int|string, string>  $options
      * @param  true|string  $required
      */
-    function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true): int|string
+    function select(string $label, array|Collection $options, int|string|null $default = null, int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?Closure $transform = null): int|string
     {
         return (new SelectPrompt(...func_get_args()))->prompt();
     }
@@ -56,7 +56,7 @@ if (! function_exists('\Laravel\Prompts\multiselect')) {
      * @param  array<int|string>|Collection<int, int|string>  $default
      * @return array<int|string>
      */
-    function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.'): array
+    function multiselect(string $label, array|Collection $options, array|Collection $default = [], int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?Closure $transform = null): array
     {
         return (new MultiSelectPrompt(...func_get_args()))->prompt();
     }
@@ -66,7 +66,7 @@ if (! function_exists('\Laravel\Prompts\confirm')) {
     /**
      * Prompt the user to confirm an action.
      */
-    function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = ''): bool
+    function confirm(string $label, bool $default = true, string $yes = 'Yes', string $no = 'No', bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): bool
     {
         return (new ConfirmPrompt(...func_get_args()))->prompt();
     }
@@ -88,7 +88,7 @@ if (! function_exists('\Laravel\Prompts\suggest')) {
      *
      * @param  array<string>|Collection<int, string>|Closure(string): array<string>  $options
      */
-    function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = ''): string
+    function suggest(string $label, array|Collection|Closure $options, string $placeholder = '', string $default = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = '', ?Closure $transform = null): string
     {
         return (new SuggestPrompt(...func_get_args()))->prompt();
     }
@@ -101,7 +101,7 @@ if (! function_exists('\Laravel\Prompts\search')) {
      * @param  Closure(string): array<int|string, string>  $options
      * @param  true|string  $required
      */
-    function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true): int|string
+    function search(string $label, Closure $options, string $placeholder = '', int $scroll = 5, mixed $validate = null, string $hint = '', bool|string $required = true, ?Closure $transform = null): int|string
     {
         return (new SearchPrompt(...func_get_args()))->prompt();
     }
@@ -114,7 +114,7 @@ if (! function_exists('\Laravel\Prompts\multisearch')) {
      * @param  Closure(string): array<int|string, string>  $options
      * @return array<int|string>
      */
-    function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.'): array
+    function multisearch(string $label, Closure $options, string $placeholder = '', int $scroll = 5, bool|string $required = false, mixed $validate = null, string $hint = 'Use the space bar to select options.', ?Closure $transform = null): array
     {
         return (new MultiSearchPrompt(...func_get_args()))->prompt();
     }
@@ -244,6 +244,6 @@ if (! function_exists('\Laravel\Prompts\progress')) {
 if (! function_exists('\Laravel\Prompts\form')) {
     function form(): FormBuilder
     {
-        return new FormBuilder();
+        return new FormBuilder;
     }
 }
diff --git a/tests/Feature/ConfirmPromptTest.php b/tests/Feature/ConfirmPromptTest.php
index 79d703fd3bdc72ca0772e5ac2d8fd1ef860d6fdc..4d61fff38dd999c9b126a7458730d4f334b90759 100644
--- a/tests/Feature/ConfirmPromptTest.php
+++ b/tests/Feature/ConfirmPromptTest.php
@@ -65,6 +65,17 @@ it('allows the labels to be changed', function () {
     Prompt::assertOutputContains('No, gracias');
 });
 
+it('transforms values', function () {
+    Prompt::fake([Key::ENTER]);
+
+    $result = confirm(
+        label: 'Are you sure?',
+        transform: fn ($value) => ! $value,
+    );
+
+    expect($result)->toBeFalse();
+});
+
 it('validates', function () {
     Prompt::fake([Key::ENTER, 'y', Key::ENTER]);
 
diff --git a/tests/Feature/MultiSearchPromptTest.php b/tests/Feature/MultiSearchPromptTest.php
index 5b7a9b313f0ac14203c2b0d14a989276d30cd1c5..b5ce5dc3785da1562c33e9edb974e70a6572b94c 100644
--- a/tests/Feature/MultiSearchPromptTest.php
+++ b/tests/Feature/MultiSearchPromptTest.php
@@ -252,6 +252,22 @@ it('supports no default results', function ($options, $expected) {
     ],
 ]);
 
+it('transforms values', function () {
+    Prompt::fake([Key::DOWN, Key::CTRL_A, Key::ENTER]);
+
+    $result = multisearch(
+        label: 'What are your favorite colors?',
+        options: fn () => [
+            'red' => 'Red',
+            'green' => 'Green',
+            'blue' => 'Blue',
+        ],
+        transform: fn ($value) => array_map('strtoupper', $value),
+    );
+
+    expect($result)->toBe(['RED', 'GREEN', 'BLUE']);
+});
+
 it('validates', function () {
     Prompt::fake(['a', Key::DOWN, Key::SPACE, Key::ENTER, Key::DOWN, Key::SPACE, Key::ENTER]);
 
diff --git a/tests/Feature/MultiSelectPromptTest.php b/tests/Feature/MultiSelectPromptTest.php
index df834a3f082958a22458ad708bf2aa60ed9877f5..1aa49e10547d17fd289828aeb28b6918dac7b5a1 100644
--- a/tests/Feature/MultiSelectPromptTest.php
+++ b/tests/Feature/MultiSelectPromptTest.php
@@ -104,6 +104,22 @@ it('accepts collections', function () {
     expect($result)->toBe(['Green']);
 });
 
+it('transforms values', function () {
+    Prompt::fake([Key::DOWN, Key::SPACE, Key::DOWN, Key::SPACE, Key::ENTER]);
+
+    $result = multiselect(
+        label: 'What are your favorite colors?',
+        options: [
+            'red' => 'Red',
+            'green' => 'Green',
+            'blue' => 'Blue',
+        ],
+        transform: fn ($value) => array_map('strtoupper', $value),
+    );
+
+    expect($result)->toBe(['GREEN', 'BLUE']);
+});
+
 it('validates', function () {
     Prompt::fake([Key::ENTER, Key::SPACE, Key::ENTER]);
 
diff --git a/tests/Feature/PasswordPromptTest.php b/tests/Feature/PasswordPromptTest.php
index 795e9e779a3361754154ba12e0fb6798cb8d2fb7..277149c3f4542aa480c0dbc61687a266fdfe8123 100644
--- a/tests/Feature/PasswordPromptTest.php
+++ b/tests/Feature/PasswordPromptTest.php
@@ -15,6 +15,19 @@ it('returns the input', function () {
     expect($result)->toBe('pass');
 });
 
+it('transforms values', function () {
+    Prompt::fake(['p', 'a', 's', 's', 'w', 'o', 'r', 'd', Key::ENTER]);
+
+    $dontUseInProduction = md5('password');
+
+    $result = password(
+        label: 'What is the password?',
+        transform: fn ($value) => md5($value)
+    );
+
+    expect($result)->toBe($dontUseInProduction);
+});
+
 it('validates', function () {
     Prompt::fake(['p', 'a', 's', Key::ENTER, 's', Key::ENTER]);
 
diff --git a/tests/Feature/SearchPromptTest.php b/tests/Feature/SearchPromptTest.php
index cf196a9c8ab25872f7e3d56ac5abdf156fcc5791..0a060cacdc6a1c1a1fed64ea0f4799095c9be558 100644
--- a/tests/Feature/SearchPromptTest.php
+++ b/tests/Feature/SearchPromptTest.php
@@ -97,6 +97,25 @@ it('returns the key when an associative array is passed', function () {
     expect($result)->toBe(3);
 });
 
+it('transforms values', function () {
+    Prompt::fake(['u', 'e', Key::DOWN, Key::ENTER]);
+
+    $result = search(
+        label: 'What is your favorite color?',
+        options: fn (string $value) => array_filter(
+            [
+                'red' => 'Red',
+                'green' => 'Green',
+                'blue' => 'Blue',
+            ],
+            fn ($option) => str_contains(strtolower($option), $value),
+        ),
+        transform: fn ($value) => strtoupper($value),
+    );
+
+    expect($result)->toBe('BLUE');
+});
+
 it('validates', function () {
     Prompt::fake([Key::DOWN, Key::ENTER, Key::DOWN, Key::ENTER]);
 
diff --git a/tests/Feature/SelectPromptTest.php b/tests/Feature/SelectPromptTest.php
index 32b4deaabe103bd71d009a1705711725adabd60a..8ea4689dee315992b322e4d48e745648a1508ba0 100644
--- a/tests/Feature/SelectPromptTest.php
+++ b/tests/Feature/SelectPromptTest.php
@@ -99,6 +99,22 @@ it('accepts default values when the options are keys with labels', function () {
     expect($result)->toBe('green');
 });
 
+it('transforms values', function () {
+    Prompt::fake([Key::DOWN, Key::ENTER]);
+
+    $result = select(
+        label: 'What is your favorite color?',
+        options: [
+            'Red',
+            'Green',
+            'Blue',
+        ],
+        transform: fn ($value) => strtolower($value),
+    );
+
+    expect($result)->toBe('green');
+});
+
 it('validates', function () {
     Prompt::fake([Key::ENTER, Key::DOWN, Key::ENTER]);
 
diff --git a/tests/Feature/SuggestPromptTest.php b/tests/Feature/SuggestPromptTest.php
index dd23d9c7cbaa2df79095a4a1d5c730be9b3986b4..384a7a6f62472024fcd3a102752dab09b475a87c 100644
--- a/tests/Feature/SuggestPromptTest.php
+++ b/tests/Feature/SuggestPromptTest.php
@@ -118,6 +118,18 @@ it('accepts a callback returning a collection', function () {
     expect($result)->toBe('Blue');
 });
 
+it('transforms values', function () {
+    Prompt::fake([Key::SPACE, 'J', 'e', 's', 's', Key::TAB, Key::ENTER]);
+
+    $result = suggest(
+        label: 'What is your name?',
+        options: ['Jess'],
+        transform: fn ($value) => trim($value),
+    );
+
+    expect($result)->toBe('Jess');
+});
+
 it('validates', function () {
     Prompt::fake([Key::ENTER, 'X', Key::ENTER]);
 
diff --git a/tests/Feature/TextPromptTest.php b/tests/Feature/TextPromptTest.php
index 541628adc8d9550b2b75a7708023f9dbdec471e0..f11ac538bf90371967bb07a772362657d58ae08b 100644
--- a/tests/Feature/TextPromptTest.php
+++ b/tests/Feature/TextPromptTest.php
@@ -30,6 +30,17 @@ it('accepts a default value', function () {
     expect($result)->toBe('Jess');
 });
 
+it('transforms values', function () {
+    Prompt::fake([Key::SPACE, 'J', 'e', 's', 's', Key::TAB, Key::ENTER]);
+
+    $result = text(
+        label: 'What is your name?',
+        transform: fn ($value) => trim($value),
+    );
+
+    expect($result)->toBe('Jess');
+});
+
 it('validates', function () {
     Prompt::fake(['J', 'e', 's', Key::ENTER, 's', Key::ENTER]);
 
diff --git a/tests/Feature/TextareaPromptTest.php b/tests/Feature/TextareaPromptTest.php
index 0720919542c90d55f772dc73635df7ef78830d6d..f5e21b17c95d129a62cd5b3b25b31cceb2671b50 100644
--- a/tests/Feature/TextareaPromptTest.php
+++ b/tests/Feature/TextareaPromptTest.php
@@ -26,6 +26,17 @@ it('accepts a default value', function () {
     expect($result)->toBe("Jess\nJoe");
 });
 
+it('transforms values', function () {
+    Prompt::fake([Key::SPACE, 'J', 'e', 's', 's', Key::SPACE, Key::CTRL_D]);
+
+    $result = textarea(
+        label: 'What is your name?',
+        transform: fn ($value) => trim($value),
+    );
+
+    expect($result)->toBe('Jess');
+});
+
 it('validates', function () {
     Prompt::fake(['J', 'e', 's', Key::CTRL_D, 's', Key::CTRL_D]);