simedkom/app/Http/Middleware/DynamicFilamentTheme.php

279 lines
12 KiB
PHP

<?php
namespace App\Http\Middleware;
use Closure;
use Filament\Facades\Filament;
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Filament\Support\Facades\FilamentView;
use Filament\View\PanelsRenderHook;
use Illuminate\Http\Request;
use Illuminate\Support\HtmlString;
use Symfony\Component\HttpFoundation\Response;
class DynamicFilamentTheme
{
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$user = Filament::auth()->user();
if ($user && $user->settings) {
// Register Colors
FilamentColor::register([
'primary' => match ($user->settings->primary_color) {
'blue' => Color::Blue,
'sky' => Color::Sky,
'cyan' => Color::Cyan,
'emerald' => Color::Emerald,
'teal' => Color::Teal,
'lime' => Color::Lime,
'amber' => Color::Amber,
'orange' => Color::Orange,
'rose' => Color::Rose,
'fuchsia' => Color::Fuchsia,
'violet' => Color::Violet,
'indigo' => Color::Indigo,
default => Color::Blue,
},
]);
// Register Top Navigation
$panel = Filament::getCurrentOrDefaultPanel();
if ($panel && method_exists($panel, 'topNavigation')) {
$panel->topNavigation((bool) $user->settings->top_navigation);
}
// Register Font & UI Styles
$font = $user->settings->font ?? 'Inter';
$radius = match ($user->settings->border_radius ?? 'md') {
'none' => '0px',
'md' => '0.375rem',
'lg' => '0.5rem',
'xl' => '0.75rem',
'2xl' => '1rem',
default => '0.5rem',
};
$maxWidth = match ($user->settings->content_width ?? 'full') {
'centered' => '80rem',
default => 'none',
};
FilamentView::registerRenderHook(
PanelsRenderHook::HEAD_END,
fn () => new HtmlString("
<link rel='preconnect' href='https://fonts.googleapis.com'>
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
<link href='https://fonts.googleapis.com/css2?family={$font}:wght@400;500;600;700&display=swap' rel='stylesheet'>
<style>
:root {
--font-family: '{$font}', sans-serif;
--c-border-radius: {$radius};
/* ── DataChangeInfolist tokens (light) ── */
--dcr-bg: #ffffff;
--dcr-border: #e4e4e7;
--dcr-header-bg: #fafafa;
--dcr-header-border: #e4e4e7;
--dcr-title: #18181b;
--dcr-desc: #71717a;
--dcr-key-bg: #fafafa;
--dcr-key-border: #f4f4f5;
--dcr-key-color: #71717a;
--dcr-val-color: #18181b;
--dcr-row-border: #f4f4f5;
--dcr-muted: #a1a1aa;
/* diff */
--dcr-old-bg: #fff5f5;
--dcr-old-border: #fee2e2;
--dcr-old-color: #18181b;
--dcr-new-bg: #f0fdf4;
--dcr-new-color: #18181b;
/* badge: neutral */
--dcr-badge-bg: #f4f4f5;
--dcr-badge-color: #52525b;
--dcr-badge-border: #e4e4e7;
/* badge: destructive */
--dcr-badge-del-bg: #fef2f2;
--dcr-badge-del-color: #b91c1c;
--dcr-badge-del-border: #fecaca;
/* badge: success */
--dcr-badge-add-bg: #f0fdf4;
--dcr-badge-add-color: #15803d;
--dcr-badge-add-border: #bbf7d0;
/* alert */
--dcr-alert-bg: #f8fafc;
--dcr-alert-border: #e2e8f0;
--dcr-alert-color: #475569;
/* icon */
--dcr-icon-del: #b91c1c;
--dcr-icon-add: #15803d;
--dcr-icon-edit: #52525b;
/* file */
--dcr-link: #3b82f6;
--dcr-img-border: #e4e4e7;
}
.dark {
/* ── DataChangeInfolist tokens (dark) ── */
--dcr-bg: #09090b;
--dcr-border: #27272a;
--dcr-header-bg: #18181b;
--dcr-header-border: #27272a;
--dcr-title: #fafafa;
--dcr-desc: #71717a;
--dcr-key-bg: #18181b;
--dcr-key-border: #27272a;
--dcr-key-color: #71717a;
--dcr-val-color: #e4e4e7;
--dcr-row-border: #27272a;
--dcr-muted: #52525b;
/* diff */
--dcr-old-bg: #1c0c0c;
--dcr-old-border: #3f1c22;
--dcr-old-color: #fca5a5;
--dcr-new-bg: #0c1c0e;
--dcr-new-color: #86efac;
/* badge: neutral */
--dcr-badge-bg: #27272a;
--dcr-badge-color: #a1a1aa;
--dcr-badge-border: #3f3f46;
/* badge: destructive */
--dcr-badge-del-bg: #1c0c0c;
--dcr-badge-del-color: #f87171;
--dcr-badge-del-border: #7f1d1d;
/* badge: success */
--dcr-badge-add-bg: #0c1c0e;
--dcr-badge-add-color: #4ade80;
--dcr-badge-add-border: #14532d;
/* alert */
--dcr-alert-bg: #18181b;
--dcr-alert-border: #27272a;
--dcr-alert-color: #a1a1aa;
/* icon */
--dcr-icon-del: #f87171;
--dcr-icon-add: #4ade80;
--dcr-icon-edit: #a1a1aa;
/* file */
--dcr-link: #60a5fa;
--dcr-img-border: #3f3f46;
}
/* Override Filament maximum width if centered */
.fi-main-ctn {
max-width: {$maxWidth} !important;
margin-left: auto !important;
margin-right: auto !important;
}
/* Apply border radius to common elements and specific components */
.fi-section,
.fi-section-header,
.fi-section-content,
.fi-btn,
.fi-input,
.fi-card,
.fi-modal-window,
.fi-dropdown-panel,
.fi-popover,
.fi-ta-content,
.fi-ta-header-cell,
.fi-ta-cell,
.fi-ta-row,
.fi-ta-ctn,
.fi-ta-content-grid-item,
.fi-ta-filters,
.fi-ta-filters-dropdown,
.fi-ta-actions,
.fi-badge,
.fi-avatar,
.fi-fo-wizard,
.fi-fo-wizard-header,
.fi-fo-wizard-step,
.fi-wi-widget,
.fi-wi-stats-overview-stat,
.fi-wi-stats-overview-stat-ctn,
.fi-in-repeatable-entry-item,
.fi-in-section,
.fi-in-grid,
.fi-ac-action,
.fi-ac-btn,
.fi-ac-user-menu,
.fi-ac-user-avatar,
.fi-no-notification,
.fi-no-notification-content,
.fi-empty-state,
.fi-fo-field-wrp,
.fi-fo-field-wrp-inner,
.fi-fo-fieldset,
.fi-fo-checkbox,
.fi-fo-radio,
.fi-fo-toggle,
.fi-fo-color-picker,
.fi-fo-date-time-picker,
.fi-fo-date-time-picker-popover,
.fi-fo-select-option,
.fi-main-aside,
.fi-sidebar-item,
.fi-sidebar-group,
.fi-tabs,
.fi-tabs-item,
.fi-tabs-item-active,
.fi-fo-spatie-media-library-file-upload,
.fi-fo-tags-input,
.fi-fo-select-tags,
.filepond--root,
.filepond--panel-root,
.filepond--item-panel,
.filepond--image-preview-wrapper,
.filepond--file-info-main {
border-radius: {$radius} !important;
}
/* Handle nested rounded elements that might resist override */
.fi-input-wrp,
.fi-fo-text-input,
.fi-fo-select,
.fi-fo-textarea,
.fi-fo-file-upload,
.fi-fo-file-upload-wrp,
.fi-fo-file-upload-item,
.fi-fo-file-upload-preview,
.fi-fo-rich-editor,
.fi-fo-markdown-editor,
.fi-fo-key-value,
.fi-fo-spatie-media-library-file-upload-wrp,
.fi-fo-spatie-media-library-file-upload-item,
.fi-fo-spatie-media-library-file-upload-preview {
border-radius: {$radius} !important;
}
/* TRULY PERVASIVE OVERRIDE: Any element with a rounded class should obey */
/* (Excluding rounded-full to preserve circles like avatars/toggles) */
[class*='rounded-']:not(.rounded-full):not([class*='rounded-full']) {
border-radius: {$radius} !important;
}
/* Custom helper for custom views & override standard Tailwind rounded classes */
.custom-rounded,
.rounded,
.rounded-md,
.rounded-lg,
.rounded-xl,
.rounded-2xl {
border-radius: {$radius} !important;
}
</style>
")
);
}
return $next($request);
}
}