11import { Reaction } from '@semantic-ui/reactivity' ;
2- import { each , isArray , isClient , isObject } from '@semantic-ui/utils' ;
2+ import { each , isClient } from '@semantic-ui/utils' ;
33import { noChange , nothing } from 'lit' ;
44import { AsyncDirective } from 'lit/async-directive.js' ;
55import { directive , PartType } from 'lit/directive.js' ;
66
7+ import { serializeContent } from './serialize-content.js' ;
8+
79export class ReactiveConditionalDirective extends AsyncDirective {
810 constructor ( partInfo ) {
911 super ( partInfo ) ;
@@ -20,12 +22,20 @@ export class ReactiveConditionalDirective extends AsyncDirective {
2022 }
2123
2224 let content = nothing ;
25+ let initialFormatted = nothing ;
2326 let context = {
2427 message : `if/else statement: {#if ${ conditional . expression } }` ,
2528 conditional : conditional ,
2629 } ;
2730
28- // Create a new reaction that watches for reactive changes on client
31+ // Create a new reaction that watches for reactive changes on client.
32+ // formatForPart is invoked INSIDE the reaction (even on firstRun) so
33+ // its serialization reads — which call .value() on inner directive
34+ // markers — register signal deps on this reaction. Without that,
35+ // inner expressions in a branch never propagate signal changes
36+ // through this directive's setValue.
37+ // matchIndex gating is intentionally absent — content can change
38+ // within the same branch when inner expressions update.
2939 if ( isClient ) {
3040 this . reaction = Reaction . create ( ( comp ) => {
3141 if ( ! this . isConnected ) {
@@ -34,21 +44,25 @@ export class ReactiveConditionalDirective extends AsyncDirective {
3444 }
3545
3646 const result = this . getBranch ( this . conditional ) ;
37- const matchIndex = result . matchIndex ;
47+ this . matchIndex = result . matchIndex ;
3848 content = result . content ;
39- if ( ! comp . firstRun && this . matchIndex !== matchIndex ) {
40- this . matchIndex = matchIndex ;
41- this . setValue ( content ) ;
49+ const formatted = this . formatForPart ( content ) ;
50+ if ( comp . firstRun ) {
51+ initialFormatted = formatted ;
52+ }
53+ else {
54+ this . setValue ( formatted ) ;
4255 }
4356 return content ;
4457 } , { context } ) ;
4558 }
4659 else {
4760 const result = this . getBranch ( this . conditional ) ;
4861 content = result . content ;
62+ initialFormatted = this . formatForPart ( content ) ;
4963 }
5064
51- return this . formatForPart ( content ) ;
65+ return initialFormatted ;
5266 }
5367
5468 getBranch ( conditional ) {
@@ -87,43 +101,12 @@ export class ReactiveConditionalDirective extends AsyncDirective {
87101 switch ( this . partInfo . type ) {
88102 case PartType . ATTRIBUTE :
89103 case PartType . BOOLEAN_ATTRIBUTE :
90- return this . serializeContent ( content ) ;
91-
92- case PartType . CHILD :
93- case PartType . PROPERTY :
94- case PartType . EVENT :
95- case PartType . ELEMENT :
104+ return serializeContent ( content ) ;
96105 default :
97- // For element content, return as-is (TemplateResult objects are fine here)
98106 return content ;
99107 }
100108 }
101109
102- serializeContent ( content ) {
103- // Handle lit's nothing value
104- if ( content === nothing ) {
105- return '' ;
106- }
107-
108- if ( content ?. strings ) {
109- // For simple conditionals in attributes, just join the static strings
110- // This works for basic cases like {#if condition}text{/if}
111- return content . strings . join ( '' ) ;
112- }
113-
114- // Handle arrays and objects like reactive-data does
115- if ( isArray ( content ) || isObject ( content ) ) {
116- try {
117- return JSON . stringify ( content ) ;
118- }
119- catch ( e ) {
120- return String ( content ) ;
121- }
122- }
123-
124- return String ( content ) ;
125- }
126-
127110 disconnected ( ) {
128111 if ( this . reaction ) {
129112 this . reaction . stop ( ) ;
0 commit comments