@@ -120,6 +120,35 @@ public function compile(): string
120120 }
121121 }
122122
123+ foreach (['class ' , 'style ' , 'id ' ] as $ attributeName ) {
124+ if (! isset ($ this ->expressionAttributes [$ attributeName ])) {
125+ continue ;
126+ }
127+
128+ $ exprKey = ': ' . $ attributeName ;
129+ $ exprValue = $ this ->expressionAttributes [$ attributeName ];
130+
131+ if ($ attributeName === 'id ' ) {
132+ // For id, expression takes precedence over static
133+ unset($ attributes ['id ' ]);
134+ $ attributes [$ exprKey ] = new MutableString ($ exprValue );
135+ continue ;
136+ }
137+
138+ // For class and style, merge with existing expressions if present
139+ if (isset ($ attributes [$ exprKey ])) {
140+ $ existingExpr = $ attributes [$ exprKey ]->trim ()->toString ();
141+
142+ // Combine expressions into an array if they're different
143+ // Combine both expressions using implode to handle arrays properly
144+ if ($ existingExpr !== $ exprValue ) {
145+ $ attributes [$ exprKey ] = new MutableString (sprintf ("implode(' ', array_filter([%s, %s])) " , $ existingExpr , $ exprValue ));
146+ }
147+ } else {
148+ $ attributes [$ exprKey ] = new MutableString ($ exprValue );
149+ }
150+ }
151+
123152 return sprintf (
124153 '<%s%s> ' ,
125154 $ matches ['tag ' ],
@@ -137,30 +166,43 @@ public function compile(): string
137166 );
138167
139168 // Add scoped variables
169+ // Merge all attribute keys to avoid duplicate parameters
170+ $ allAttributeKeys = arr ()
171+ ->merge ($ this ->dataAttributes ->keys ())
172+ ->merge ($ this ->expressionAttributes ->keys ())
173+ ->unique ();
174+
140175 $ compiled = $ compiled
141176 ->prepend (
142177 // Open the current scope
143178 sprintf (
144- '<?php (function ($attributes, $slots, $scopedVariables %s %s) { extract($scopedVariables, EXTR_SKIP); ?> ' ,
145- $ this ->dataAttributes ->isNotEmpty () ? (', ' . $ this ->dataAttributes ->map (fn (string $ _value , string $ key ) => "\${$ key }" )->implode (', ' )) : '' ,
146- $ this ->expressionAttributes ->isNotEmpty () ? (', ' . $ this ->expressionAttributes ->map (fn (string $ _value , string $ key ) => "\${$ key }" )->implode (', ' )) : '' ,
147- $ this ->scopedVariables ->isNotEmpty () ? (', ' . $ this ->scopedVariables ->map (fn (string $ name ) => "\${$ name }" )->implode (', ' )) : '' ,
179+ '<?php (function ($attributes, $slots, $scopedVariables %s) { extract($scopedVariables, EXTR_SKIP); ?> ' ,
180+ $ allAttributeKeys ->isNotEmpty () ? (', ' . $ allAttributeKeys ->map (fn (string $ key ) => "\${$ key }" )->implode (', ' )) : '' ,
148181 ),
149182 )
150183 ->append (
151184 // Close and call the current scope
152185 sprintf (
153- '<?php })(attributes: %s, slots: %s, scopedVariables: [%s] + ($scopedVariables ?? $this->currentView?->data ?? []) %s %s ) ?> ' ,
186+ '<?php })(attributes: %s, slots: %s, scopedVariables: [%s] + ($scopedVariables ?? $this->currentView?->data ?? []) %s) ?> ' ,
154187 ViewObjectExporter::export ($ this ->viewComponentAttributes ),
155188 ViewObjectExporter::export ($ slots ),
156189 $ this ->scopedVariables ->isNotEmpty ()
157190 ? $ this ->scopedVariables ->map (fn (string $ name ) => "' {$ name }' => \${$ name }" )->implode (', ' )
158191 : '' ,
159- $ this ->dataAttributes ->isNotEmpty ()
160- ? (', ' . $ this ->dataAttributes ->map (fn (mixed $ value , string $ key ) => "{$ key }: " . ViewObjectExporter::exportValue ($ value ))->implode (', ' ))
161- : '' ,
162- $ this ->expressionAttributes ->isNotEmpty ()
163- ? (', ' . $ this ->expressionAttributes ->map (fn (mixed $ value , string $ key ) => "{$ key }: " . $ value )->implode (', ' ))
192+ // Merge data and expression attributes, with expression taking precedence to avoid duplicates
193+ $ this ->dataAttributes
194+ ->merge ($ this ->expressionAttributes ->mapWithKeys (fn ($ value , $ key ) => yield $ key => $ value ))
195+ ->isNotEmpty ()
196+ ? (
197+ ', ' .
198+ $ this ->dataAttributes
199+ ->filter (fn ($ _value , $ key ) => ! isset ($ this ->expressionAttributes [$ key ]))
200+ ->merge ($ this ->expressionAttributes )
201+ ->map (fn (mixed $ value , string $ key ) => isset ($ this ->expressionAttributes [$ key ])
202+ ? "{$ key }: {$ value }"
203+ : ("{$ key }: " . ViewObjectExporter::exportValue ($ value )))
204+ ->implode (', ' )
205+ )
164206 : '' ,
165207 ),
166208 );
0 commit comments