Skip to content

Commit ff70fdd

Browse files
authored
Merge pull request #32 from hotwired-laravel/tm/make-bridge-components
Make bridge components
2 parents a9098a9 + 5b9d487 commit ff70fdd

21 files changed

+176
-173
lines changed

README.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ To make a new Stimulus controller, run:
4848
php artisan stimulus:make hello_controller
4949
```
5050

51-
This should create the file for you using a scaffolding to get the controller ready for you. When using Vite, it will also regenerate the `resources/js/controllers/index.js` file to register your newly created Stimulus controller automatically.
51+
This should create the controller for you. When using Vite, it will also regenerate the `resources/js/controllers/index.js` file to register your newly created Stimulus controller automatically.
5252

5353
There's also a hint comment on how you may use the controller in the DOM, something like this:
5454

@@ -60,6 +60,28 @@ export default class extends Controller {
6060
connect() {
6161
}
6262
}
63+
64+
### Making a new Hotwire Native Bridge Component
65+
66+
You may use the same `stimulus:make` command to generate a Hotwire Native Bridge component by passing the `--bridge=` option with the name of the native component. For instance, if you're working on a native Toast component, you may create it like:
67+
68+
```bash
69+
php artisan stimulus:make bridge/toast_controller --bridge=toast
70+
```
71+
72+
This should create a file for you using the bridge scaffolding. When using Vite, it will also generate the `resources/js/controllers/index.js` file to register your newly created Stimulus Bridge Component automatically.
73+
74+
Like regular Stimulus controllers, there's also a hint comment on how you may use the controller in the DOM:
75+
76+
```js
77+
import { BridgeComponent, BridgeElement } from "@hotwired/hotwire-native-bridge"
78+
79+
// Connects to data-controller="bridge--toast"
80+
export default class extends BridgeComponent {
81+
static component = "toast"
82+
83+
//
84+
}
6385
```
6486

6587
### Regenerate the Manifest

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"illuminate/contracts": "^11.0|^12.0"
2424
},
2525
"require-dev": {
26-
"laravel/pint": "^1.0",
26+
"laravel/pint": "^1.21",
2727
"nunomaduro/collision": "^8.1|^9.0",
2828
"orchestra/testbench": "^9.1|^10.0",
2929
"phpunit/phpunit": "^10.5|^11.0"

rector.php

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\ValueObject\PhpVersion;
7+
8+
return RectorConfig::configure()
9+
->withPaths([
10+
__DIR__.'/src',
11+
__DIR__.'/tests',
12+
])
13+
->withPreparedSets(
14+
deadCode: true,
15+
codeQuality: true,
16+
typeDeclarations: true,
17+
privatization: true,
18+
earlyReturn: true,
19+
)
20+
->withAttributesSets()
21+
->withPhpSets()
22+
->withPhpVersion(PhpVersion::PHP_82);

src/Commands/Concerns/InstallsForImportmap.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ protected function publishJsFilesForImportmaps()
4242
protected function registerImportmapPins()
4343
{
4444
$dependencies = collect($this->jsPackages())
45-
->map(fn ($version, $package) => "{$package}@{$version}")
45+
->map(fn ($version, $package): string => "{$package}@{$version}")
4646
->values()
4747
->all();
4848

4949
Process::forever()->run(array_merge([
5050
$this->phpBinary(),
5151
'artisan',
5252
'importmap:pin',
53-
], $dependencies), function ($_type, $output) {
53+
], $dependencies), function ($_type, $output): void {
5454
$this->output->write($output);
5555
});
5656

@@ -61,7 +61,7 @@ protected function registerImportmapPins()
6161
'vendor:publish',
6262
'--tag',
6363
'stimulus-laravel-assets',
64-
], function ($_type, $output) {
64+
], function ($_type, $output): void {
6565
$this->output->write($output);
6666
});
6767

src/Commands/Concerns/InstallsForNode.php

+31-33
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,33 @@
99
*/
1010
trait InstallsForNode
1111
{
12+
/**
13+
* @param bool $dev
14+
* @return void
15+
*/
16+
protected static function updateNodePackages(callable $callback, $dev = true)
17+
{
18+
if (! File::exists(base_path('package.json'))) {
19+
return;
20+
}
21+
22+
$configurationKey = $dev ? 'devDependencies' : 'dependencies';
23+
24+
$packages = json_decode(File::get(base_path('package.json')), true);
25+
26+
$packages[$configurationKey] = $callback(
27+
array_key_exists($configurationKey, $packages) ? $packages[$configurationKey] : [],
28+
$configurationKey
29+
);
30+
31+
ksort($packages[$configurationKey]);
32+
33+
File::put(
34+
base_path('package.json'),
35+
json_encode($packages, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT).PHP_EOL
36+
);
37+
}
38+
1239
protected function installsForNode()
1340
{
1441
$this->publishJsFilesForNode();
@@ -47,38 +74,9 @@ protected function publishJsFilesForNode()
4774

4875
protected function updateNpmPackagesForNode()
4976
{
50-
$this->updateNodePackages(function ($packages) {
51-
return array_merge(
52-
$packages,
53-
$this->jsPackages(),
54-
);
55-
});
56-
}
57-
58-
/**
59-
* @param bool $dev
60-
* @return void
61-
*/
62-
protected static function updateNodePackages(callable $callback, $dev = true)
63-
{
64-
if (! File::exists(base_path('package.json'))) {
65-
return;
66-
}
67-
68-
$configurationKey = $dev ? 'devDependencies' : 'dependencies';
69-
70-
$packages = json_decode(File::get(base_path('package.json')), true);
71-
72-
$packages[$configurationKey] = $callback(
73-
array_key_exists($configurationKey, $packages) ? $packages[$configurationKey] : [],
74-
$configurationKey
75-
);
76-
77-
ksort($packages[$configurationKey]);
78-
79-
File::put(
80-
base_path('package.json'),
81-
json_encode($packages, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT).PHP_EOL
82-
);
77+
$this->updateNodePackages(fn ($packages): array => array_merge(
78+
$packages,
79+
$this->jsPackages(),
80+
));
8381
}
8482
}

src/Commands/InstallCommand.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ public function handle(): int
4545
protected function jsPackages(): array
4646
{
4747
return array_merge(
48-
['@hotwired/stimulus' => '^3.1.0'],
49-
$this->hasOption('strada') ? ['@hotwired/strada' => '^1.0.0-beta1'] : [],
48+
['@hotwired/stimulus' => '^3.2'],
49+
$this->hasOption('strada') ? ['@hotwired/hotwire-native-bridge' => '^1.1'] : [],
5050
);
5151
}
5252

@@ -68,11 +68,16 @@ protected function runCommands($commands)
6868
}
6969
}
7070

71-
$process->run(function ($type, $line) {
71+
$process->run(function ($type, string $line): void {
7272
$this->output->write(' '.$line);
7373
});
7474
}
7575

76+
protected function phpBinary(): string
77+
{
78+
return (new PhpExecutableFinder)->find(false) ?: 'php';
79+
}
80+
7681
private function usingImportmaps(): bool
7782
{
7883
return File::exists($this->importmapsFile());
@@ -82,9 +87,4 @@ private function importmapsFile(): string
8287
{
8388
return base_path('routes/importmap.php');
8489
}
85-
86-
protected function phpBinary()
87-
{
88-
return (new PhpExecutableFinder)->find(false) ?: 'php';
89-
}
9090
}

src/Commands/MakeCommand.php

+6-8
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,22 @@
99

1010
class MakeCommand extends Command
1111
{
12-
public $signature = 'stimulus:make {name : The Controller name}';
12+
public $signature = 'stimulus:make {name : The Controller name} {--bridge= : The name of the bridge component to be created}';
1313

14-
public $description = 'Makes a new Stimulus Controller.';
14+
public $description = 'Makes a new Stimulus Controller or Bridge Component.';
1515

1616
public function handle(StimulusGenerator $generator): int
1717
{
18-
$this->components->info('Making Stimulus Controller');
18+
$this->components->info($this->option('bridge') ? 'Making a Stimulus Bridge Component' : 'Making Stimulus Controller');
1919

20-
$this->components->task('creating controller', function () use ($generator) {
21-
$generator->create($this->argument('name'));
20+
$this->components->task('creating file', function () use ($generator): true {
21+
$generator->create($this->argument('name'), bridge: $this->option('bridge'));
2222

2323
return true;
2424
});
2525

2626
if (! File::exists(base_path('routes/importmap.php'))) {
27-
$this->components->task('regenerating manifest', function () {
28-
return $this->callSilently(ManifestCommand::class);
29-
});
27+
$this->components->task('regenerating manifest', fn () => $this->callSilently(ManifestCommand::class));
3028

3129
if (file_exists(base_path('pnpm-lock.yaml'))) {
3230
Process::forever()->path(base_path())->run(['pnpm', 'run', 'build']);

src/Commands/ManifestCommand.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ class ManifestCommand extends Command
1212

1313
public $description = 'Updates the manifest based on the existing Stimulus controllers.';
1414

15-
public function handle(Manifest $generator)
15+
public function handle(Manifest $generator): int
1616
{
1717
$this->components->info('Regenerating Manifest');
1818

19-
$this->components->task('regenerating manifest', function () use ($generator) {
19+
$this->components->task('regenerating manifest', function () use ($generator): true {
2020
$manifest = $generator->generateFrom(config('stimulus-laravel.controllers_path'))->join(PHP_EOL);
2121
$manifestFile = resource_path('js/controllers/index.js');
2222

src/Commands/StradaMakeCommand.php

-48
This file was deleted.

src/Features.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
class Features
66
{
7-
public static function directives()
7+
public static function directives(): string
88
{
99
return 'directives';
1010
}

src/Manifest.php

+4-6
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ class Manifest
1212
public function generateFrom(string $controllersPath): Collection
1313
{
1414
return collect(File::allFiles($controllersPath))
15-
->filter(fn (SplFileInfo $file) => str_contains($file->getFilename(), '_controller'))
15+
->filter(fn (SplFileInfo $file): bool => str_contains($file->getFilename(), '_controller'))
1616
->values()
17-
->map(function (SplFileInfo $file) use ($controllersPath) {
17+
->map(function (SplFileInfo $file) use ($controllersPath): string {
1818
$controllerPath = $this->relativePathFrom($file->getRealPath(), $controllersPath);
1919
$modulePath = Str::of($controllerPath)->before('.')->replace(DIRECTORY_SEPARATOR, '/')->toString();
2020
$controllerClassName = Str::of($modulePath)
@@ -23,9 +23,7 @@ public function generateFrom(string $controllersPath): Collection
2323
->join('__');
2424
$tagName = Str::of($modulePath)->before('_controller')->replace('_', '-')->replace('/', '--')->toString();
2525

26-
$join = function ($paths) {
27-
return implode('/', $paths);
28-
};
26+
$join = (fn ($paths): string => implode('/', $paths));
2927

3028
return <<<JS
3129
@@ -35,7 +33,7 @@ public function generateFrom(string $controllersPath): Collection
3533
});
3634
}
3735

38-
private function relativePathFrom(string $controllerPath, string $basePath)
36+
private function relativePathFrom(string $controllerPath, string $basePath): string
3937
{
4038
return trim(str_replace($basePath, '', $controllerPath), DIRECTORY_SEPARATOR);
4139
}

0 commit comments

Comments
 (0)