Skip to content

Commit

Permalink
New Feature: A command to generate a Theme inside a module
Browse files Browse the repository at this point in the history
- Generate a theme in a module
  • Loading branch information
coolsam726 committed Apr 15, 2024
1 parent 526c495 commit ba916ea
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 12 deletions.
116 changes: 116 additions & 0 deletions src/Commands/ModuleMakeFilamentThemeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

namespace Coolsam\Modules\Commands;

use Coolsam\Modules\Facades\FilamentModules;
use Filament\Commands\MakeThemeCommand;
use Filament\Panel;
use Nwidart\Modules\Module;

use function Laravel\Prompts\text;

class ModuleMakeFilamentThemeCommand extends MakeThemeCommand
{
protected $signature = 'module:make:filament-theme {module?} {--pm=} {--F|force}';

protected $description = 'Create a new Filament theme in a module';

public function handle(): int
{
$module = $this->getModule();

$this->call('vendor:publish', [
'--provider' => 'Nwidart\Modules\LaravelModulesServiceProvider',
'--tag' => 'vite',
]);

$pm = $this->option('pm') ?? 'npm';

exec("{$pm} -v", $pmVersion, $pmVersionExistCode);

if ($pmVersionExistCode !== 0) {
$this->error('Node.js is not installed. Please install before continuing.');

return static::FAILURE;
}

$this->info("Using {$pm} v{$pmVersion[0]}");

$installCommand = match ($pm) {
'yarn' => 'yarn add',
default => "{$pm} install",
};
$cdCommand = 'cd '.$module->getPath();

exec("$cdCommand && {$installCommand} tailwindcss @tailwindcss/forms @tailwindcss/typography postcss postcss-nesting autoprefixer --save-dev");

// $panel = $this->argument('panel');

$cssFilePath = $module->resourcesPath('css/filament/theme.css');
$tailwindConfigFilePath = $module->resourcesPath('css/filament/tailwind.config.js');

if (! $this->option('force') && $this->checkForCollision([
$cssFilePath,
$tailwindConfigFilePath,
])) {
return static::INVALID;
}

$classPathPrefix = '';

$viewPathPrefix = '';

$this->copyStubToApp('filament-theme-css', $cssFilePath);
$this->copyStubToApp('filament-theme-tailwind-config', $tailwindConfigFilePath, [
'classPathPrefix' => $classPathPrefix,
'viewPathPrefix' => $viewPathPrefix,
]);

$this->components->info('Filament theme [resources/css/filament/theme.css] and [resources/css/filament/tailwind.config.js] created successfully in '.$module->getStudlyName().' module.');

$buildDirectory = 'build-'.$module->getLowerName();
$moduleStudlyName = $module->getStudlyName();

if (empty(glob($module->getExtraPath('vite.config.*s')))) {
$this->components->warn('Action is required to complete the theme setup:');
$this->components->bulletList([
"It looks like you don't have Vite installed in your module. Please use your asset bundling system of choice to compile `resources/css/filament/theme.css` into `public/$buildDirectory/css/filament/theme.css`.",
"If you're not currently using a bundler, we recommend using Vite. Alternatively, you can use the Tailwind CLI with the following command inside the $moduleStudlyName module:",
'npx tailwindcss --input ./resources/css/filament/theme.css --output ./public/'.$buildDirectory.'/css/filament/theme.css --config ./resources/css/filament/tailwind.config.js --minify',
"Make sure to register the theme in the {$moduleStudlyName} module plugin under the afterRegister() function using `->theme(asset('css/filament/theme.css'))`",
]);

return static::SUCCESS;
}

$postcssConfigPath = $module->getExtraPath('postcss.config.js');

if (! file_exists($postcssConfigPath)) {
$this->copyStubToApp('filament-theme-postcss', $postcssConfigPath);

$this->components->info('Filament theme [postcss.config.js] created successfully.');
}

$this->components->warn('Action is required to complete the theme setup:');
$this->components->bulletList([
"First, add a new item to the `input` array of `vite.config.js`: `resources/css/filament/theme.css` in the $moduleStudlyName module.",
"Next, register the theme in the {$module->getStudlyName()} module plugin under the `afterRegister()` method using `->viteTheme('resources/css/filament/theme.css', '$buildDirectory')`",
"Finally, run `{$pm} run build` from the root of this module to compile the theme.",
]);

return static::SUCCESS;
}

protected function getDefaultStubPath(): string
{
return __DIR__.'/stubs';
}

private function getModule(): Module
{
$moduleName = $this->argument('module') ?? text('In which Module should we create this?', 'e.g Blog', required: true);
$moduleStudlyName = str($moduleName)->studly()->toString();

return FilamentModules::getModule($moduleStudlyName);
}
}
3 changes: 3 additions & 0 deletions src/Commands/stubs/filament-theme-css.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import '../../../../../vendor/filament/filament/resources/css/theme.css';

@config 'tailwind.config.js';
7 changes: 7 additions & 0 deletions src/Commands/stubs/filament-theme-postcss.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
plugins: {
'tailwindcss/nesting': 'postcss-nesting',
tailwindcss: {},
autoprefixer: {},
},
}
10 changes: 10 additions & 0 deletions src/Commands/stubs/filament-theme-tailwind-config.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import preset from '../../../../../vendor/filament/filament/tailwind.config.preset'

export default {
presets: [preset],
content: [
'./app/Filament/**/*.php',
'./resources/views/filament/**/*.blade.php',
'../../vendor/filament/**/*.blade.php',
],
}
14 changes: 10 additions & 4 deletions src/Concerns/ModuleFilamentPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ public function register(Panel $panel): void
$module = $this->getModule();
$useClusters = config('filament-modules.clusters.enabled', false);
$panel->discoverPages(
in: $module->appPath('Filament' . DIRECTORY_SEPARATOR . 'Pages'),
in: $module->appPath('Filament'.DIRECTORY_SEPARATOR.'Pages'),
for: $module->appNamespace('\\Filament\\Pages')
);
$panel->discoverResources(
in: $module->appPath('Filament' . DIRECTORY_SEPARATOR . 'Resources'),
in: $module->appPath('Filament'.DIRECTORY_SEPARATOR.'Resources'),
for: $module->appNamespace('\\Filament\\Resources')
);
$panel->discoverWidgets(
in: $module->appPath('Filament' . DIRECTORY_SEPARATOR . 'Widgets'),
in: $module->appPath('Filament'.DIRECTORY_SEPARATOR.'Widgets'),
for: $module->appNamespace('\\Filament\\Widgets')
);

Expand All @@ -37,13 +37,14 @@ public function register(Panel $panel): void
);

if ($useClusters) {
$path = $module->appPath('Filament' . DIRECTORY_SEPARATOR . 'Clusters');
$path = $module->appPath('Filament'.DIRECTORY_SEPARATOR.'Clusters');
$namespace = $module->appNamespace('\\Filament\\Clusters');
$panel->discoverClusters(
in: $path,
for: $namespace,
);
}
$this->afterRegister($panel);
}

public static function make(): static
Expand All @@ -58,4 +59,9 @@ public static function get(): static

return $plugin;
}

public function afterRegister(Panel $panel)
{
// override this to implement additional logic
}
}
17 changes: 9 additions & 8 deletions src/ModulesServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function packageBooted(): void

// Handle Stubs
if (app()->runningInConsole()) {
foreach (app(Filesystem::class)->files(__DIR__ . '/../stubs/') as $file) {
foreach (app(Filesystem::class)->files(__DIR__.'/../stubs/') as $file) {
$this->publishes([
$file->getRealPath() => base_path("stubs/modules/{$file->getFilename()}"),
], 'modules-stubs');
Expand Down Expand Up @@ -114,6 +114,7 @@ protected function getCommands(): array
Commands\ModuleMakeFilamentResourceCommand::class,
Commands\ModuleMakeFilamentPageCommand::class,
Commands\ModuleMakeFilamentWidgetCommand::class,
Commands\ModuleMakeFilamentThemeCommand::class,
];
}

Expand Down Expand Up @@ -170,44 +171,44 @@ protected function registerModuleMacros(): void
$relativeNamespace = str_replace('App\\', '', $relativeNamespace);
$relativeNamespace = str_replace('App', '', $relativeNamespace);
$relativeNamespace = trim($relativeNamespace, '\\');
$relativeNamespace = '\\' . $relativeNamespace;
$relativeNamespace = '\\'.$relativeNamespace;

return $this->namespace($relativeNamespace);
});
Module::macro('appPath', function (string $relativePath = '') {
$appPath = $this->getExtraPath('app');

return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : '');
return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : '');
});

Module::macro('databasePath', function (string $relativePath = '') {
$appPath = $this->getExtraPath('database');

return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : '');
return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : '');
});

Module::macro('resourcesPath', function (string $relativePath = '') {
$appPath = $this->getExtraPath('resources');

return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : '');
return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : '');
});

Module::macro('migrationsPath', function (string $relativePath = '') {
$appPath = $this->databasePath('migrations');

return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : '');
return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : '');
});

Module::macro('seedersPath', function (string $relativePath = '') {
$appPath = $this->databasePath('seeders');

return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : '');
return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : '');
});

Module::macro('factoriesPath', function (string $relativePath = '') {
$appPath = $this->databasePath('factories');

return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : '');
return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : '');
});
}
}

0 comments on commit ba916ea

Please sign in to comment.