diff --git a/playground/facade/clear.php b/playground/facade/clear.php new file mode 100644 index 0000000..5125d1d --- /dev/null +++ b/playground/facade/clear.php @@ -0,0 +1,17 @@ + match ($value) { + false => 'You must install dependencies.', + default => null, + }, + hint: 'Dependencies are required to run the application.', +); + +var_dump($confirmed); + +echo str_repeat(PHP_EOL, 2); diff --git a/playground/facade/form.php b/playground/facade/form.php new file mode 100644 index 0000000..29b1b61 --- /dev/null +++ b/playground/facade/form.php @@ -0,0 +1,97 @@ +intro('Welcome to Laravel') + ->suggest( + label: 'What is your name?', + placeholder: 'E.g. Taylor Otwell', + options: [ + 'Dries Vints', + 'Guus Leeuw', + 'James Brooks', + 'Jess Archer', + 'Joe Dixon', + 'Mior Muhammad Zaki Mior Khairuddin', + 'Nuno Maduro', + 'Taylor Otwell', + 'Tim MacDonald', + ], + validate: fn($value) => match (true) { + ! $value => 'Please enter your name.', + default => null, + }, + ) + ->text( + label: 'Where should we create your project?', + placeholder: 'E.g. ./laravel', + validate: fn($value) => match (true) { + ! $value => 'Please enter a path', + $value[0] !== '.' => 'Please enter a relative path', + default => null, + }, + name: 'path' + ) + ->textarea('Describe your project') + ->pause() + ->submit(); + +$moreResponses = Prompt::form() + ->password( + label: 'Provide a password', + validate: fn($value) => match (true) { + ! $value => 'Please enter a password.', + strlen($value) < 5 => 'Password should have at least 5 characters.', + default => null, + }, + ) + ->select( + label: 'Pick a project type', + default: 'ts', + options: [ + 'ts' => 'TypeScript', + 'js' => 'JavaScript', + ], + ) + ->multiselect( + label: 'Select additional tools.', + default: ['pint', 'eslint'], + options: [ + 'pint' => 'Pint', + 'eslint' => 'ESLint', + 'prettier' => 'Prettier', + ], + validate: function ($values) { + if (count($values) === 0) { + return 'Please select at least one tool.'; + } + } + ) + ->add(function () { + $install = Prompt::confirm( + label: 'Install dependencies?', + ); + + if ($install) { + Prompt::spin(fn() => sleep(3), 'Installing dependencies...'); + } + + return $install; + }, name: 'install') + ->confirm('Finish installation?') + ->add(fn($responses) => Prompt::note( + <<submit(); + +var_dump($responses, $moreResponses); diff --git a/playground/facade/index.php b/playground/facade/index.php new file mode 100644 index 0000000..221deb1 --- /dev/null +++ b/playground/facade/index.php @@ -0,0 +1,95 @@ + match (true) { + ! $value => 'Please enter your name.', + default => null, + }, +); + +$path = Prompt::text( + label: 'Where should we create your project?', + placeholder: 'E.g. ./laravel', + validate: fn($value) => match (true) { + ! $value => 'Please enter a path', + $value[0] !== '.' => 'Please enter a relative path', + default => null, + }, +); + +$password = Prompt::password( + label: 'Provide a password', + validate: fn($value) => match (true) { + ! $value => 'Please enter a password.', + strlen($value) < 5 => 'Password should have at least 5 characters.', + default => null, + }, +); + +$type = Prompt::select( + label: 'Pick a project type', + default: 'ts', + options: [ + 'ts' => 'TypeScript', + 'js' => 'JavaScript', + ], +); + +$tools = Prompt::multiselect( + label: 'Select additional tools.', + default: ['pint', 'eslint'], + options: [ + 'pint' => 'Pint', + 'eslint' => 'ESLint', + 'prettier' => 'Prettier', + ], + validate: function ($values) { + if (count($values) === 0) { + return 'Please select at least one tool.'; + } + } +); + +$install = Prompt::confirm( + label: 'Install dependencies?', +); + +if ($install) { + Prompt::spin(fn() => sleep(3), 'Installing dependencies...'); +} + +Prompt::error('Error'); +Prompt::warning('Warning'); +Prompt::alert('Alert'); + +Prompt::note(<< 'Taylor Otwell', + 'dries' => 'Dries Vints', + 'james' => 'James Brooks', + 'nuno' => 'Nuno Maduro', + 'mior' => 'Mior Muhammad Zaki', + 'jess' => 'Jess Archer', + 'guus' => 'Guus Leeuw', + 'tim' => 'Tim MacDonald', + 'joe' => 'Joe Dixon', +]); + +$selected = Prompt::multisearch( + label: 'Which users should receive the email?', + placeholder: 'Search...', + options: function ($value) use ($users) { + // Comment to show all results by default. + if (strlen($value) === 0) { + return []; + } + + usleep(100 * 1000); // Simulate a DB query. + + return $users->when( + strlen($value), + fn($users) => $users->filter(fn($name) => str_contains(strtolower($name), strtolower($value))) + )->all(); + }, + required: true, + validate: function ($values) { + if (in_array('jess', $values)) { + return 'Jess cannot receive emails'; + } + }, +); + +var_dump($selected); diff --git a/playground/facade/multiselect.php b/playground/facade/multiselect.php new file mode 100644 index 0000000..132cdc6 --- /dev/null +++ b/playground/facade/multiselect.php @@ -0,0 +1,26 @@ + 'View', + 'create' => 'Create', + 'update' => 'Update', + 'delete' => 'Delete', + 'restore' => 'Restore', + 'force-delete' => 'Force delete', + ], + validate: fn($values) => match (true) { + empty($values) => 'Please select at least one permission.', + default => null, + }, + hint: 'The permissions will determine what the user can do.', +); + +var_dump($permissions); + +echo str_repeat(PHP_EOL, 1); diff --git a/playground/facade/notes.php b/playground/facade/notes.php new file mode 100644 index 0000000..4e65187 --- /dev/null +++ b/playground/facade/notes.php @@ -0,0 +1,13 @@ + match (true) { + strlen($value) < 8 => 'Password should have at least 8 characters.', + default => null, + }, + hint: 'Your password will be encrypted and stored securely.', +); + +var_dump($password); + +echo str_repeat(PHP_EOL, 5); diff --git a/playground/facade/pause.php b/playground/facade/pause.php new file mode 100644 index 0000000..abaeaef --- /dev/null +++ b/playground/facade/pause.php @@ -0,0 +1,9 @@ +label = 'Arkansas is not a state! Nice try.'; + } + + return $item . ' added.'; + }, +); + +Prompt::progress( + label: 'Adding States With Label', + steps: $states, + callback: function ($item, $progress) { + usleep(250_000); + $progress + ->label('Adding ' . $item) + ->hint("{$item} has " . strlen($item) . ' characters'); + }, +); + +$progress = Prompt::progress( + label: 'Adding States Manually', + steps: $states, +); + +$progress->start(); + +foreach ($states as $state) { + usleep(250_000); + $progress + ->hint($state) + ->advance(); +} + +$progress->finish(); + +Prompt::progress( + 'Processing with Exception', + $states, + fn($item) => $item === 'Arkansas' ? throw new Exception('Issue with Arkansas!') : usleep(250_000), +); diff --git a/playground/facade/search.php b/playground/facade/search.php new file mode 100644 index 0000000..a316e4b --- /dev/null +++ b/playground/facade/search.php @@ -0,0 +1,38 @@ + "User $id", + range(0, $count) + ); + }, + validate: function ($value) { + if ($value === '0') { + return 'User 0 is not allowed to receive emails.'; + } + }, + hint: 'An email will be sent to the user.', +); + +var_dump($model); + +echo str_repeat(PHP_EOL, 6); diff --git a/playground/facade/select.php b/playground/facade/select.php new file mode 100644 index 0000000..d8aae03 --- /dev/null +++ b/playground/facade/select.php @@ -0,0 +1,47 @@ + 'Argentina', + 'australia' => 'Australia', + 'belgium' => 'Belgium', + 'brazil' => 'Brazil', + 'canada' => 'Canada', + 'chile' => 'Chile', + 'china' => 'China', + 'colombia' => 'Colombia', + 'egypt' => 'Egypt', + 'france' => 'France', + 'germany' => 'Germany', + 'india' => 'India', + 'italy' => 'Italy', + 'japan' => 'Japan', + 'kenya' => 'Kenya', + 'mexico' => 'Mexico', + 'morocco' => 'Morocco', + 'nigeria' => 'Nigeria', + 'new-zealand' => 'New Zealand', + 'portugal' => 'Portugal', + 'south-africa' => 'South Africa', + 'south-korea' => 'South Korea', + 'spain' => 'Spain', + 'switzerland' => 'Switzerland', + 'united-kingdom' => 'United Kingdom', + 'united-states' => 'United States', + ], + default: 'france', + validate: fn($value) => match ($value) { + 'spain' => 'Spain is not available yet.', + default => null + }, + hint: 'The country will determine the currency and the timezone of the user.', +); + +var_dump($role); + +echo str_repeat(PHP_EOL, 5); diff --git a/playground/facade/spin.php b/playground/facade/spin.php new file mode 100644 index 0000000..ea9fa3c --- /dev/null +++ b/playground/facade/spin.php @@ -0,0 +1,20 @@ + match (true) { + strlen($value) === 0 => 'Please enter a model name.', + default => null, + }, + hint: 'The model name should be singular.', +); + +var_dump($model); + +echo str_repeat(PHP_EOL, 6); diff --git a/playground/facade/table.php b/playground/facade/table.php new file mode 100644 index 0000000..112b7d9 --- /dev/null +++ b/playground/facade/table.php @@ -0,0 +1,20 @@ + match (true) { + strlen($value) === 0 => 'Please enter an email address.', + ! filter_var($value, FILTER_VALIDATE_EMAIL) => 'Please enter a valid email address.', + default => null, + }, + hint: 'We will never share your email address with anyone else.', + transform: fn($value) => strtolower($value), +); + +var_dump($email); + +echo str_repeat(PHP_EOL, 5); diff --git a/playground/facade/textarea.php b/playground/facade/textarea.php new file mode 100644 index 0000000..ad5ce11 --- /dev/null +++ b/playground/facade/textarea.php @@ -0,0 +1,14 @@ + $arguments + * + * @return mixed + */ + public static function __callStatic(string $name, array $arguments): mixed + { + return static::callHelperFunction($name, $arguments); + } + + + /** + * Calls the class' function. + * + * @param string $name + * @param array $arguments + * + * @return mixed + */ + public function __call(string $name, array $arguments): mixed + { + return $this::callHelperFunction($name, $arguments); + } + + /** + * Returns the qualified name of the function if it exists. + * + * @param string $name + * + * @return callable + * @throws BadMethodCallException + */ + protected static function resolveFunction(string $name): callable + { + $function = '\\Laravel\\Prompts\\' . $name; + + if (!function_exists($function) || !is_callable($function)) { + throw new BadMethodCallException( + sprintf( + 'Call to undefined method %s::%s()', + static::class, + $name + ) + ); + } + + return $function; + } + + /** + * Calls the helper function. + * + * @param string $name + * @param array $arguments + * + * @return mixed + */ + protected static function callHelperFunction(string $name, array $arguments): mixed + { + $function = static::resolveFunction($name); + + return $function(...$arguments); + } +} diff --git a/tests/Feature/PromptFacadeTest.php b/tests/Feature/PromptFacadeTest.php new file mode 100644 index 0000000..3c8f39b --- /dev/null +++ b/tests/Feature/PromptFacadeTest.php @@ -0,0 +1,26 @@ +throws(BadMethodCallException::class, 'Call to undefined method ' . FacadePrompt::class . '::notAFunction()'); + +it('Can be instantiated and call functions.', function () { + Prompt::fake(); + $prompt = new FacadePrompt(); + + $prompt->note('Dummy text'); + + Prompt::assertOutputContains('Dummy text'); +});