{"version":3,"file":"components/live-chat-cls-fix.dc1f37b69808fad6f2e3.js","mappings":"kHAQA,MAAMA,EAEJC,kBAAoB,IACpBC,6BAA+B,IAC/BC,wBAA0B,wBAG1BC,WAAa,CAAEC,MAAO,KAAMC,OAAQ,MACpCC,oBAAsB,EAEtB,WAAAC,GACEC,KAAKC,iBAAgB,KACnBD,KAAKE,uBACLF,KAAKG,0BAA0B,GAEnC,CAQA,eAAAF,CAAgBG,EAAUC,EAAQ,GAC5BC,OAAOC,eACTH,IACSC,EAAQL,KAAKP,6BAA+BO,KAAKR,mBAC1DgB,YAAW,IAAMR,KAAKC,gBAAgBG,EAAUC,EAAQ,IAAIL,KAAKR,kBAErE,CAKA,oBAAAU,GACEI,OAAOC,eAAeE,GAAG,SAAS,KAChC,MAAM,WAAEC,GAAeJ,OAAOC,eAAeI,IAAI,SAC/B,aAAdD,IAIJV,KAAKY,aACLZ,KAAKa,uBAAsB,GAE/B,CAKA,wBAAAV,GACEG,OAAOC,eAAeE,GAAG,sBAAsB,EAAGC,iBAC9B,aAAdA,GAA2C,UAAdA,IAC/BV,KAAKY,aACLZ,KAAKa,uBACP,GAEJ,CAKA,UAAAD,GACEE,SAASC,eAAef,KAAKN,yBAAyBsB,MAAMC,QAAU,EACtEjB,KAAKL,WAAa,CAAEC,MAAO,KAAMC,OAAQ,MACzCG,KAAKF,oBAAsB,CAC7B,CAKA,oBAAAe,GACE,IAAIK,EAAUlB,KAAKmB,gBACnBnB,KAAKL,WAAauB,GAAWlB,KAAKL,WAClCK,KAAKF,oBAAsBoB,EAAU,EAAIlB,KAAKF,oBAAsBE,KAAKR,kBAErEQ,KAAKoB,cAAcC,SAASrB,KAAKL,WAAWC,OAAQyB,SAASrB,KAAKL,WAAWE,SAC/EiB,SAASC,eAAef,KAAKN,yBAAyBsB,MAAMC,QAAU,EAEtET,YAAW,IAAMR,KAAKa,wBAAwBb,KAAKR,kBAEvD,CAOA,aAAA2B,GACE,MAAMG,EAAUR,SAASC,eAAef,KAAKN,yBAC7C,IAAI6B,EAAgBD,EAAUA,EAAQN,MAAQ,CAAC,EAC/C,IAAK,IAAIQ,KAASxB,KAAKL,WACrB,GAAIK,KAAKL,WAAW6B,KAAWD,EAAcC,GAC3C,OAAOC,OAAOC,KAAK1B,KAAKL,YAAYgC,QAClC,CAACC,EAAQJ,KAAU,IAAMI,EAAQ,CAACJ,GAAQD,EAAcC,MACxD,CAAC,EAIT,CAYA,aAAAJ,CAAcxB,EAAOC,GAInB,OACGG,KAAK6B,gBAAgBjC,EAAOC,IAAWG,KAAKF,oBAJxB,MAKrBE,KAAKF,oBAJgB,GAMzB,CAYA,eAAA+B,CAAgBjC,EAAOC,GAKrB,OAAOiC,KAAKC,IAAInC,EAHQ,KACA,IAEsCkC,KAAKC,IAAIlC,EAJ9C,KAED,EAG1B,EAGFS,OAAO0B,iBAAiB,QAAQ,IAAM,IAAIzC,G","sources":["webpack://stdcheck-exposed-wp-theme/./themes/stdcheck-exposed/src/js/components/live-chat-cls-fix.js"],"sourcesContent":["/**\n * This class fixes the Cumulative Layout Shift (CLS) caused by the LiveChat widget\n *\n * LiveChat is a 3rd party widget that is loaded asynchronously and causes a Layout Shift when it is loaded due to\n * changing its size multiple times before stabilizing on the size it's going to be displayed in. This happens in less\n * than a couple of seconds, and the widget is transparent, so it's imperceptible to the user, but causes Google's Core\n * Web Vitals metrics to be affected.\n */\nclass LiveChatClsFixer {\n // Constants\n TIME_INCREMENT_MS = 100;\n WAIT_FOR_LIVECHAT_TIMEOUT_MS = 10000;\n LIVECHAT_DOM_ELEMENT_ID = 'chat-widget-container';\n\n // Fields\n dimensions = { width: null, height: null };\n timeSinceLastChange = 0;\n\n constructor() {\n this.waitForLiveChat(() => {\n this.preventClsOnPageLoad();\n this.preventClsWhenMinimizing();\n });\n }\n\n /**\n * Wait for the LiveChatWidget object to be available and execute a callback when it is.\n *\n * @param {function} callback A function to execute when the LiveChatWidget object is available\n * @param {Number} tries The number of attempts to wait for the LiveChatWidget object to be available\n */\n waitForLiveChat(callback, tries = 0) {\n if (window.LiveChatWidget) {\n callback();\n } else if (tries < this.WAIT_FOR_LIVECHAT_TIMEOUT_MS / this.TIME_INCREMENT_MS) {\n setTimeout(() => this.waitForLiveChat(callback, tries + 1), this.TIME_INCREMENT_MS);\n }\n }\n\n /**\n * Prevent a Layout Shift on page load by hiding the widget until its dimensions have stabilized.\n */\n preventClsOnPageLoad() {\n window.LiveChatWidget.on('ready', () => {\n const { visibility } = window.LiveChatWidget.get('state');\n if (visibility == 'maximized') {\n // No Layout Shift occurs if widget is maximized from a previous interaction.\n return;\n }\n this.hideWidget();\n this.showWidgetWhenStable();\n });\n }\n\n /**\n * Prevent a Layout Shift when the widget is minimized by hiding the widget until its dimensions have stabilized.\n */\n preventClsWhenMinimizing() {\n window.LiveChatWidget.on('visibility_changed', ({ visibility }) => {\n if (visibility == 'minimized' || visibility == 'hidden') {\n this.hideWidget();\n this.showWidgetWhenStable();\n }\n });\n }\n\n /**\n * Hide the widget and reset the variables for keeping track of changes.\n */\n hideWidget() {\n document.getElementById(this.LIVECHAT_DOM_ELEMENT_ID).style.opacity = 0;\n this.dimensions = { width: null, height: null };\n this.timeSinceLastChange = 0;\n }\n\n /**\n * Determine if the widget has stabilized and show it if it has.\n */\n showWidgetWhenStable() {\n let changes = this.detectChanges();\n this.dimensions = changes || this.dimensions;\n this.timeSinceLastChange = changes ? 0 : this.timeSinceLastChange + this.TIME_INCREMENT_MS;\n\n if (this.hasStabilized(parseInt(this.dimensions.width), parseInt(this.dimensions.height))) {\n document.getElementById(this.LIVECHAT_DOM_ELEMENT_ID).style.opacity = 1;\n } else {\n setTimeout(() => this.showWidgetWhenStable(), this.TIME_INCREMENT_MS);\n }\n }\n\n /**\n * Detect if the width and height of the widget have changed since the last iteration.\n *\n * @returns {Object|null} An object containing the width and height of the widget if they have changed, otherwise null\n */\n detectChanges() {\n const element = document.getElementById(this.LIVECHAT_DOM_ELEMENT_ID);\n let newDimensions = element ? element.style : {};\n for (let field in this.dimensions) {\n if (this.dimensions[field] !== newDimensions[field]) {\n return Object.keys(this.dimensions).reduce(\n (result, field) => ({ ...result, [field]: newDimensions[field] }),\n {}\n );\n }\n }\n }\n\n /**\n * Check if the width and height of the widget have stabilized and we can display it.\n *\n * The widget is considered stable and should not cause a Layout Shift based on our measurements if:\n * - it dimensions have been the minimized size stably for more than 1.5 seconds\n * - after 3 seconds, if it has stabilized to any size (this is also a fail-safe in case the minimized size changes)\n *\n * @param {Number} width The width of the widget\n * @param {Number} height The height of the widget\n */\n hasStabilized(width, height) {\n const TIME_STABLE_MS = 1500;\n const MAX_TIMEOUT_MS = 3000;\n\n return (\n (this.isMinimizedSize(width, height) && this.timeSinceLastChange > TIME_STABLE_MS) ||\n this.timeSinceLastChange > MAX_TIMEOUT_MS\n );\n }\n\n /**\n * Check if the width and height are close to the minimized size with a margin of error, as this size varies\n *\n * The minimized height varies from around 155 to 215 pixels, the minimized width varies from around 279 to 327 pixels\n * and there is a margin of error in case these sizes change slightly as we don't have full control of the 3rd party\n * widget\n *\n * @param {Number} width The width of the widget\n * @param {Number} height The height of the widget\n */\n isMinimizedSize(width, height) {\n const MINIMIZED_HEIGHT = 200;\n const MINIMIZED_WIDTH = 300;\n const MARGIN_OF_ERROR = 50;\n\n return Math.abs(width - MINIMIZED_WIDTH) < MARGIN_OF_ERROR && Math.abs(height - MINIMIZED_HEIGHT) < MARGIN_OF_ERROR;\n }\n}\n\nwindow.addEventListener('load', () => new LiveChatClsFixer());\n"],"names":["LiveChatClsFixer","TIME_INCREMENT_MS","WAIT_FOR_LIVECHAT_TIMEOUT_MS","LIVECHAT_DOM_ELEMENT_ID","dimensions","width","height","timeSinceLastChange","constructor","this","waitForLiveChat","preventClsOnPageLoad","preventClsWhenMinimizing","callback","tries","window","LiveChatWidget","setTimeout","on","visibility","get","hideWidget","showWidgetWhenStable","document","getElementById","style","opacity","changes","detectChanges","hasStabilized","parseInt","element","newDimensions","field","Object","keys","reduce","result","isMinimizedSize","Math","abs","addEventListener"],"sourceRoot":""}