77use Filament \Schemas \Components \Fieldset ;
88use Filament \Schemas \Components \Grid ;
99use Filament \Schemas \Components \Section ;
10+ use Illuminate \Database \Eloquent \Model ;
11+ use Illuminate \Support \Collection ;
1012use Relaticle \CustomFields \Enums \CustomFieldSectionType ;
13+ use Relaticle \CustomFields \Enums \CustomFieldsFeature ;
14+ use Relaticle \CustomFields \FeatureSystem \FeatureManager ;
15+ use Relaticle \CustomFields \Models \CustomField ;
1116use Relaticle \CustomFields \Models \CustomFieldSection ;
17+ use Relaticle \CustomFields \Services \Visibility \BackendVisibilityService ;
18+ use Relaticle \CustomFields \Services \Visibility \CoreVisibilityLogicService ;
19+ use Relaticle \CustomFields \Services \Visibility \FrontendVisibilityService ;
1220
13- final class SectionComponentFactory
21+ final readonly class SectionComponentFactory
1422{
15- public function create (CustomFieldSection $ customFieldSection ): Section |Fieldset |Grid
16- {
17- return match ($ customFieldSection ->type ) {
23+ public function __construct (
24+ private FrontendVisibilityService $ frontendVisibilityService ,
25+ private BackendVisibilityService $ backendVisibilityService ,
26+ private CoreVisibilityLogicService $ coreLogic ,
27+ ) {}
28+
29+ /**
30+ * @param Collection<int, CustomField>|null $allFields
31+ */
32+ public function create (
33+ CustomFieldSection $ customFieldSection ,
34+ ?Collection $ allFields = null ,
35+ ?Model $ record = null
36+ ): Section |Fieldset |Grid {
37+ $ component = match ($ customFieldSection ->type ) {
1838 CustomFieldSectionType::SECTION => Section::make ($ customFieldSection ->name )
1939 ->columnSpanFull ()
2040 ->description ($ customFieldSection ->description )
@@ -25,5 +45,52 @@ public function create(CustomFieldSection $customFieldSection): Section|Fieldset
2545 ->columns (12 ),
2646 CustomFieldSectionType::HEADLESS => Grid::make (12 )->columnSpanFull (),
2747 };
48+
49+ if ($ this ->shouldApplySectionVisibility ($ customFieldSection )) {
50+ $ this ->applySectionVisibility ($ component , $ customFieldSection , $ allFields , $ record );
51+ }
52+
53+ return $ component ;
54+ }
55+
56+ private function shouldApplySectionVisibility (CustomFieldSection $ section ): bool
57+ {
58+ return FeatureManager::isEnabled (CustomFieldsFeature::SECTION_CONDITIONAL_VISIBILITY )
59+ && $ this ->coreLogic ->hasSectionVisibilityConditions ($ section );
60+ }
61+
62+ /**
63+ * @param Collection<int, CustomField>|null $allFields
64+ */
65+ private function applySectionVisibility (
66+ Section |Fieldset |Grid $ component ,
67+ CustomFieldSection $ section ,
68+ ?Collection $ allFields ,
69+ ?Model $ record
70+ ): void {
71+ $ jsExpression = $ this ->frontendVisibilityService ->buildSectionVisibilityExpression (
72+ $ section ,
73+ $ allFields
74+ );
75+
76+ if ($ jsExpression !== null ) {
77+ // Use visibleJs only -- do NOT combine with visible()
78+ // Server-side visible(false) prevents the component from rendering,
79+ // which blocks visibleJs from ever executing
80+ $ component ->visibleJs ($ jsExpression );
81+
82+ return ;
83+ }
84+
85+ // Fallback: server-side evaluation when JS can't be generated
86+ if ($ record instanceof Model) {
87+ $ component ->visible (
88+ fn (): bool => $ this ->backendVisibilityService ->isSectionVisible (
89+ $ record ,
90+ $ section ,
91+ $ allFields ?? collect ()
92+ )
93+ );
94+ }
2895 }
2996}
0 commit comments