Skip to content

Commit 37569f0

Browse files
committed
Merging so I can do streaming prep
1 parent 884c325 commit 37569f0

25 files changed

+279
-351
lines changed

packages/flux-themes/README.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Flux Themes
22

3-
This package sets up a Laravel application to use [FluxUI](https://fluxui.dev). It has one command that you can run when setting up a new site that will let you set or choose a color scheme from Flux's themes and it will make all of the required edits to the `tailwind.config.js` package and `app.css` package to run Flux and use your chosen color scheme.
3+
This package sets up a Laravel application to use [FluxUI](https://fluxui.dev). It has one command that you can run when setting up a new site that will let you set or choose a color scheme from Flux's themes and it will make all of the required edits to `app.css` package to run Flux and use your chosen color scheme.
44

55
Some of our applications are "white label" type SaaS applications that we want our users to be able to theme to match
66
their brands. This package provides the functionality to make that happen.
@@ -29,8 +29,7 @@ There are currently no configuration options for this package.
2929

3030
`php artisan flux-theme:set {color?}`
3131

32-
Run this command to set the color scheme for your site. This will handle the entire FluxUI setup in both the `app.css`
33-
and `tailwind.config.js` file. If you don't pass a color, you'll be prompted to choose your color.
32+
Run this command to set the color scheme for your site. This will handle the entire FluxUI setup in the `app.css` file. If you don't pass a color, you'll be prompted to choose your color.
3433

3534
One thing to note is that an additional entry is added to the `content` block of the `tailwind.config.css` file that
3635
adds a wildcard path to all of our packages. We do this for our own purposes. You can safely leave this line in place

packages/flux-themes/src/Actions/DetectPackagesWithTemplates.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ class DetectPackagesWithTemplates
88
{
99
public function __invoke()
1010
{
11-
return collect(File::directories(base_path('vendor/artisan-build')))
12-
->filter(fn($directory) => File::isDirectory("{$directory}/resources/views"))
13-
->map(fn($directory) => str_replace(base_path(), '../..', $directory));
11+
$vendor_directory = config('flux-themes.vendor_directory', base_path('vendor/artisan-build'));
12+
13+
return collect(File::directories($vendor_directory))
14+
->filter(fn ($directory) => File::isDirectory("{$directory}/resources/views"))
15+
->map(fn ($directory) => str_replace(base_path(), '../..', $directory));
1416

1517
}
1618
}

packages/flux-themes/src/Actions/WriteToTailwindConfig.php

-90
This file was deleted.

packages/flux-themes/src/Commands/SetThemeCommand.php

+13-8
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
namespace ArtisanBuild\FluxThemes\Commands;
44

5-
use ArtisanBuild\FluxThemes\Actions\WriteToAppCss;
6-
use ArtisanBuild\FluxThemes\Actions\WriteToTailwindConfig;
75
use ArtisanBuild\FluxThemes\Enums\Colors;
6+
use ArtisanBuild\FluxThemes\Pipeline\EnsureRequiredImportsExist;
7+
use ArtisanBuild\FluxThemes\Pipeline\EnsureRequiredSourcePathsExist;
88
use ArtisanBuild\FluxThemes\Theme;
99
use Illuminate\Console\Command;
10+
use Illuminate\Support\Facades\Pipeline;
11+
use Stripe\File;
1012

1113
use function Laravel\Prompts\search;
1214

@@ -18,7 +20,6 @@ class SetThemeCommand extends Command
1820

1921
public function handle(): int
2022
{
21-
$config = $this->option('tailwind_config') ?? base_path('tailwind.config.js');
2223
$css = $this->option('css_file') ?? resource_path('css/app.css');
2324
$color = $this->argument('color');
2425

@@ -39,15 +40,19 @@ public function handle(): int
3940

4041
$theme = new Theme(
4142
css_file: $css,
42-
tailwind_config: $config,
4343
);
4444

4545
$theme = $theme_color->set($theme);
4646

47-
$this->info('Writing the app.css file');
48-
app(WriteToAppCss::class)(theme: $theme);
49-
$this->info('Writing to tailwind.config.php file');
50-
app(WriteToTailwindConfig::class)(theme: $theme);
47+
Pipeline::send($theme)->through([
48+
EnsureRequiredImportsExist::class,
49+
EnsureRequiredSourcePathsExist::class,
50+
// Handle the gray override
51+
// Set the highlight color variables
52+
// Remove double line breaks
53+
// Ensure one new line at the end of the contents
54+
// Write the contents to the app.css file
55+
]);
5156

5257
return self::SUCCESS;
5358
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace ArtisanBuild\FluxThemes\Pipeline;
4+
5+
use ArtisanBuild\FluxThemes\Theme;
6+
use Closure;
7+
use Illuminate\Support\Str;
8+
9+
class EnsureRequiredImportsExist
10+
{
11+
public function __invoke(Theme $theme, Closure $next): Theme
12+
{
13+
if (! Str::of($theme->css)->contains("@import 'tailwindcss';")) {
14+
$theme->css = implode("\n", ["@import 'tailwindcss';", $theme->css])."\n";
15+
}
16+
17+
if (! Str::of($theme->css)->contains("@import '../../vendor/livewire/flux/dist/flux.css';")) {
18+
$theme->css = str_replace("@import 'tailwindcss';", implode("\n", [
19+
"@import 'tailwindcss';",
20+
"@import '../../vendor/livewire/flux/dist/flux.css';",
21+
]), $theme->css)."\n";
22+
}
23+
24+
return $next($theme);
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace ArtisanBuild\FluxThemes\Pipeline;
4+
5+
use ArtisanBuild\FluxThemes\Actions\DetectPackagesWithTemplates;
6+
use ArtisanBuild\FluxThemes\Theme;
7+
use Closure;
8+
9+
class EnsureRequiredSourcePathsExist
10+
{
11+
public function __construct(private readonly DetectPackagesWithTemplates $packages_with_templates) {}
12+
13+
public function __invoke(Theme $theme, Closure $next): Theme
14+
{
15+
$laravel = [
16+
"@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';",
17+
"@source '../../storage/framework/views/*.php';",
18+
"@source '../../resources/**/*.blade.php';",
19+
"@source '.../../resources/**/*.js';",
20+
"@source '../../resources/**/*.vue';",
21+
];
22+
$flux = [
23+
"@source '../../vendor/livewire/flux/stubs/**/*.blade.php';",
24+
"@source '../../vendor/livewire/flux-pro/stubs/**/*.blade.php';",
25+
];
26+
$packages = ($this->packages_with_templates)()
27+
->map(fn ($package) => "@source '{$package}/resources/views/*.blade.php';")
28+
->toArray();
29+
30+
$required = array_merge($laravel, $flux, $packages);
31+
32+
// Filter out paths that already exist in the CSS
33+
$missing_paths = collect($required)->reject(fn ($path): bool => str_contains($theme->css, (string) $path));
34+
35+
if ($missing_paths->isNotEmpty()) {
36+
// Convert CSS content to collection of lines
37+
$lines = collect(explode("\n", $theme->css));
38+
39+
// Get the index of the last @import by checking all lines
40+
$last_import_index = $lines
41+
->reduce(fn ($carry, $line, $index) => str_contains((string) $line, '@import') ? $index : $carry, -1);
42+
43+
if ($last_import_index !== -1) {
44+
// Get all lines up to and including the last @import
45+
$before = $lines->take($last_import_index + 1);
46+
// Get all remaining lines
47+
$after = $lines->skip($last_import_index + 1);
48+
49+
// Ensure we add a newline after imports if there isn't one
50+
if ($missing_paths->isNotEmpty() && trim((string) $before->last()) !== '') {
51+
$missing_paths->prepend('');
52+
}
53+
54+
// Rebuild the CSS content
55+
$theme->css = $before
56+
->merge($missing_paths)
57+
->when($after->isNotEmpty(), fn ($collection) => $collection->merge([''])->merge($after))
58+
->filter()
59+
->implode("\n");
60+
} else {
61+
// If no @import found, add at the beginning
62+
$theme->css = $missing_paths
63+
->merge(['']) // Add a blank line between imports and content
64+
->merge($lines)
65+
->filter()
66+
->implode("\n");
67+
}
68+
}
69+
70+
return $next($theme);
71+
}
72+
}

packages/flux-themes/src/Theme.php

+42-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace ArtisanBuild\FluxThemes;
44

55
use ArtisanBuild\FluxThemes\Enums\Grays;
6+
use Illuminate\Support\Facades\File;
7+
use Illuminate\Support\Str;
68

79
class Theme
810
{
@@ -23,9 +25,47 @@ class Theme
2325

2426
public Grays $gray = Grays::Slate;
2527

26-
public function __construct(public ?string $css_file = null, public ?string $tailwind_config = null)
28+
public array $configuration;
29+
30+
public string $css;
31+
32+
public function __construct(public ?string $css_file = null)
2733
{
2834
$this->css_file ??= resource_path('css/app.css');
29-
$this->tailwind_config ??= base_path('tailwind.config.js');
35+
$this->css = File::get($this->css_file);
36+
$this->getCurrentConfiguration();
37+
}
38+
39+
public function getCurrentConfiguration()
40+
{
41+
$css = [
42+
'imports' => [],
43+
'sources' => [],
44+
'grays' => [],
45+
'colors' => [],
46+
];
47+
$block = null;
48+
foreach (File::lines($this->css_file) as $line) {
49+
if (Str::of($line)->trim()->startsWith(':root')) {
50+
$block = 'light';
51+
}
52+
if (Str::of($line)->trim()->startsWith('.dark')) {
53+
$block = 'dark';
54+
}
55+
if (Str::of($line)->trim()->startsWith('@import')) {
56+
$css['imports'][] = Str::of($line)->trim()->toString();
57+
}
58+
if (Str::of($line)->trim()->startsWith('@source')) {
59+
$css['sources'][] = Str::of($line)->trim()->toString();
60+
}
61+
if (Str::of($line)->trim()->startsWith('--color-zinc')) {
62+
$css['grays'][current(explode(':', Str::of($line)->trim()))] = Str::of($line)->trim()->toString();
63+
}
64+
if ($block !== null && Str::of($line)->trim()->startsWith('--color-accent')) {
65+
$css['colors'][$block][current(explode(':', Str::of($line)->trim()->toString()))] = Str::of($line)->trim()->toString();
66+
}
67+
68+
}
69+
$this->configuration = $css;
3070
}
3171
}

packages/flux-themes/src/Theme/LoadHeaderRightNavbarItems.php

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use ArtisanBuild\FluxThemes\Contracts\LoadsHeaderRightNavbarItems;
66
use ArtisanBuild\FluxThemes\Enums\NavbarItemTypes;
77
use ArtisanBuild\Verbstream\Http\Livewire\UserHeaderMenuComponent;
8-
use Illuminate\Support\Facades\File;
98
use Illuminate\Support\Facades\Route;
109

1110
class LoadHeaderRightNavbarItems implements LoadsHeaderRightNavbarItems
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use ArtisanBuild\FluxThemes\Pipeline\EnsureRequiredImportsExist;
4+
use Illuminate\Support\Facades\File;
5+
use Illuminate\Support\Facades\Pipeline;
6+
7+
describe('ensuring the required imports exist in app.css', function (): void {
8+
it('adds the required imports in the correct order if the existing file is blank', function (): void {
9+
$theme = new ArtisanBuild\FluxThemes\Theme(css_file: __DIR__.'/../files/blank_app.css');
10+
11+
$theme = Pipeline::send($theme)->through([
12+
EnsureRequiredImportsExist::class,
13+
])->thenReturn();
14+
15+
expect($theme->css)->toContain(implode("\n", ["@import 'tailwindcss';", "@import '../../vendor/livewire/flux/dist/flux.css';"]));
16+
})->skip();
17+
18+
it('adds the flux import in the correct location in the Laravel 12 default file', function (): void {
19+
$theme = new ArtisanBuild\FluxThemes\Theme(css_file: __DIR__.'/../files/laravel_12_default_app.css');
20+
21+
$theme = Pipeline::send($theme)->through([
22+
EnsureRequiredImportsExist::class,
23+
])->thenReturn();
24+
25+
expect($theme->css)->toContain(implode("\n", ["@import 'tailwindcss';", "@import '../../vendor/livewire/flux/dist/flux.css';"]))
26+
->and($theme->css)->toBe(File::get(__DIR__.'/../files/laravel_default_with_imports_and_paths.css'));
27+
})->skip();
28+
29+
});

0 commit comments

Comments
 (0)