@@ -32,9 +32,18 @@ export const CONSENT_PREFERENCES_READY_EVENT = 'consent-preferences:ready'
3232export class ConsentPreferencesElement extends LitElement {
3333 static registeredName = COMPONENT_TAG_NAME
3434
35+ private static readonly saveButtonDisabledClasses = [
36+ 'bg-gray-300' ,
37+ 'cursor-not-allowed' ,
38+ 'hover:bg-gray-300' ,
39+ ]
40+
41+ private static readonly saveButtonEnabledClasses = [ 'bg-spotlight' , 'hover:bg-spotlight-offset' ]
42+
3543 private allowAllBtn ! : HTMLButtonElement
3644 private denyAllBtn ! : HTMLButtonElement
3745 private saveBtn ! : HTMLButtonElement
46+ private toggleChangeHandler : ( ( ) => void ) | null = null
3847 private domReadyHandler : ( ( ) => void ) | null = null
3948 private beforePreparationHandler : ( ( ) => void ) | null = null
4049 private afterSwapHandler : ( ( ) => void ) | null = null
@@ -85,6 +94,8 @@ export class ConsentPreferencesElement extends LitElement {
8594 this . unsubscribeConsent = null
8695 }
8796
97+ this . removePreferenceToggleListeners ( )
98+
8899 this . isInitialized = false
89100 delete this . dataset [ 'consentPreferencesReady' ]
90101 }
@@ -135,6 +146,7 @@ export class ConsentPreferencesElement extends LitElement {
135146
136147 private syncConsentState ( consent : ConsentState ) : void {
137148 this . updateCheckboxes ( consent )
149+ this . updateSaveButtonState ( )
138150 }
139151
140152 private setViewTransitionsHandlers ( ) : void {
@@ -182,6 +194,83 @@ export class ConsentPreferencesElement extends LitElement {
182194 addButtonEventListeners ( this . allowAllBtn , ( ) => this . allowAll ( ) )
183195 addButtonEventListeners ( this . denyAllBtn , ( ) => this . denyAll ( ) )
184196 addButtonEventListeners ( this . saveBtn , ( ) => this . savePreferences ( ) )
197+
198+ if ( ! this . toggleChangeHandler ) {
199+ this . toggleChangeHandler = ( ) => this . updateSaveButtonState ( )
200+ }
201+
202+ this . bindPreferenceToggleListeners ( )
203+ }
204+
205+ private bindPreferenceToggleListeners ( ) : void {
206+ this . removePreferenceToggleListeners ( )
207+
208+ const analyticsCheckbox = document . getElementById ( 'analytics-cookies' )
209+ const functionalCheckbox = document . getElementById ( 'functional-cookies' )
210+ const marketingCheckbox = document . getElementById ( 'marketing-cookies' )
211+
212+ if ( ! this . toggleChangeHandler ) {
213+ return
214+ }
215+
216+ if ( isInputElement ( analyticsCheckbox ) ) {
217+ analyticsCheckbox . addEventListener ( 'change' , this . toggleChangeHandler )
218+ }
219+
220+ if ( isInputElement ( functionalCheckbox ) ) {
221+ functionalCheckbox . addEventListener ( 'change' , this . toggleChangeHandler )
222+ }
223+
224+ if ( isInputElement ( marketingCheckbox ) ) {
225+ marketingCheckbox . addEventListener ( 'change' , this . toggleChangeHandler )
226+ }
227+ }
228+
229+ private removePreferenceToggleListeners ( ) : void {
230+ const analyticsCheckbox = document . getElementById ( 'analytics-cookies' )
231+ const functionalCheckbox = document . getElementById ( 'functional-cookies' )
232+ const marketingCheckbox = document . getElementById ( 'marketing-cookies' )
233+
234+ if ( ! this . toggleChangeHandler ) {
235+ return
236+ }
237+
238+ if ( isInputElement ( analyticsCheckbox ) ) {
239+ analyticsCheckbox . removeEventListener ( 'change' , this . toggleChangeHandler )
240+ }
241+
242+ if ( isInputElement ( functionalCheckbox ) ) {
243+ functionalCheckbox . removeEventListener ( 'change' , this . toggleChangeHandler )
244+ }
245+
246+ if ( isInputElement ( marketingCheckbox ) ) {
247+ marketingCheckbox . removeEventListener ( 'change' , this . toggleChangeHandler )
248+ }
249+ }
250+
251+ private updateSaveButtonState ( ) : void {
252+ const currentPreferences = this . getCurrentPreferences ( )
253+ const savedPreferences = getConsentSnapshot ( )
254+
255+ const hasUnsavedChanges =
256+ ( currentPreferences . analytics ?? false ) !== ( savedPreferences . analytics ?? false ) ||
257+ ( currentPreferences . functional ?? false ) !== ( savedPreferences . functional ?? false ) ||
258+ ( currentPreferences . marketing ?? false ) !== ( savedPreferences . marketing ?? false )
259+
260+ this . saveBtn . disabled = ! hasUnsavedChanges
261+ this . saveBtn . setAttribute ( 'aria-disabled' , String ( ! hasUnsavedChanges ) )
262+
263+ const disabledClasses = ConsentPreferencesElement . saveButtonDisabledClasses
264+ const enabledClasses = ConsentPreferencesElement . saveButtonEnabledClasses
265+
266+ this . saveBtn . classList . remove ( ...disabledClasses , ...enabledClasses )
267+
268+ if ( hasUnsavedChanges ) {
269+ this . saveBtn . classList . add ( ...enabledClasses )
270+ return
271+ }
272+
273+ this . saveBtn . classList . add ( ...disabledClasses )
185274 }
186275
187276 private updateCheckboxes ( preferences : ConsentState ) : void {
@@ -201,6 +290,10 @@ export class ConsentPreferencesElement extends LitElement {
201290 }
202291
203292 private savePreferences ( ) : void {
293+ if ( this . saveBtn . disabled ) {
294+ return
295+ }
296+
204297 const preferences = this . getCurrentPreferences ( )
205298
206299 updateConsent ( 'analytics' , preferences . analytics ?? false )
0 commit comments