@pendo/agent 2.284.0 → 2.285.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -454,7 +454,7 @@ function isMinifiedAgent(config) {
454
454
  return !config.unminified;
455
455
  }
456
456
  function isExtension(config) {
457
- return config.installType === 'extension';
457
+ return config.installType === 'extension'; // can't use isExtensionAgent() here because of circular dependency and ConfigReader not being ready yet
458
458
  }
459
459
  function shouldUseStagingAgent(config) {
460
460
  return !isExtension(config) && !isStagingEnvironment(config) && isStagingServer(config);
@@ -3666,6 +3666,9 @@ function getInstallType() {
3666
3666
  var installType = ConfigReader.get('installType');
3667
3667
  return installType || NATIVE_INSTALL_TYPE;
3668
3668
  }
3669
+ function isExtensionAgent() {
3670
+ return getInstallType() === EXTENSION_INSTALL_TYPE;
3671
+ }
3669
3672
  function subscriptionBucketPrefix(env) {
3670
3673
  if (env === PROD) {
3671
3674
  return 'pendo-static';
@@ -3765,6 +3768,7 @@ if (bodyStyle) {
3765
3768
  animations = _.isString(pdocument.body.style.webkitAnimation);
3766
3769
  }
3767
3770
  }
3771
+ var isChromeExtension = window.chrome && window.chrome.runtime && window.chrome.runtime.id;
3768
3772
  // Android has history.pushState, but it does not update location correctly
3769
3773
  // so let's not use the history API at all.
3770
3774
  // http://code.google.com/p/android/issues/detail?id=17471
@@ -3778,15 +3782,13 @@ var shouldWrapNativeHistory = _.memoize(function shouldWrapNativeHistory() {
3778
3782
  var historyDescriptors = window.history && _.isFunction(Object.getOwnPropertyDescriptors) && Object.getOwnPropertyDescriptors(window.history);
3779
3783
  var isHistoryWriteable = historyDescriptors && _.get(historyDescriptors, 'pushState.writable', true) && _.get(historyDescriptors, 'replaceState.writable', true);
3780
3784
  var hasAndroidSupport = !(android < 4);
3781
- var isExtension = getInstallType() === EXTENSION_INSTALL_TYPE;
3782
- return !!(hasNativeHistory && !isHistoryFrozen && isHistoryWriteable && hasAndroidSupport && !boxee && !isExtension);
3785
+ return !!(hasNativeHistory && !isHistoryFrozen && isHistoryWriteable && hasAndroidSupport && !boxee && !isExtensionAgent());
3783
3786
  });
3784
3787
  function shouldWrapHashChange() {
3785
3788
  var hasNativeHashChange = 'onhashchange' in window;
3786
3789
  // IE8 compatible mode lies
3787
3790
  var hasSupportedDocMode = (!documentMode || documentMode > 7);
3788
- var isExtension = getInstallType() === EXTENSION_INSTALL_TYPE;
3789
- return !!(hasNativeHashChange && hasSupportedDocMode && !isExtension);
3791
+ return !!(hasNativeHashChange && hasSupportedDocMode && !isExtensionAgent());
3790
3792
  }
3791
3793
  function isMobileUserAgent() {
3792
3794
  return (/Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i).test(getUA());
@@ -3820,7 +3822,8 @@ var sniffer = {
3820
3822
  addEventListener: _.isFunction(window.addEventListener),
3821
3823
  MutationObserver: isNativeCode(window.MutationObserver),
3822
3824
  isMinimumIEVersion,
3823
- isMobileUserAgent: _.memoize(isMobileUserAgent)
3825
+ isMobileUserAgent: _.memoize(isMobileUserAgent),
3826
+ isChromeExtension
3824
3827
  };
3825
3828
 
3826
3829
  var isBrowserInQuirksmode = function () {
@@ -3902,8 +3905,8 @@ var SERVER = '';
3902
3905
  var ASSET_HOST = '';
3903
3906
  var ASSET_PATH = '';
3904
3907
  var DESIGNER_SERVER = '';
3905
- var VERSION = '2.284.0_';
3906
- var PACKAGE_VERSION = '2.284.0';
3908
+ var VERSION = '2.285.0_';
3909
+ var PACKAGE_VERSION = '2.285.0';
3907
3910
  var LOADER = 'xhr';
3908
3911
  /* eslint-enable agent-eslint-rules/no-gulp-env-references */
3909
3912
  /**
@@ -3930,10 +3933,6 @@ var overwriteBuiltConfigWithPendoConfig = function () {
3930
3933
  var versionSuffix = isExtensionAgent() ? ENV + '_ext' : ENV;
3931
3934
  VERSION = PACKAGE_VERSION + '_' + versionSuffix;
3932
3935
  };
3933
- function isExtensionAgent() {
3934
- const installType = getPendoConfigValue('installType') || getPendoConfigFromEnclosingScope().installType;
3935
- return installType === EXTENSION_INSTALL_TYPE;
3936
- }
3937
3936
  function isProdAgent() {
3938
3937
  return ENV.indexOf('prod') !== -1;
3939
3938
  }
@@ -9464,8 +9463,13 @@ function getAssetHost() {
9464
9463
  }
9465
9464
  return assetHost;
9466
9465
  }
9466
+ function isLocalAgent(assetHost) {
9467
+ return assetHost.indexOf('localhost') >= 0 || assetHost.indexOf('local.pendo.io') >= 0;
9468
+ }
9467
9469
  function getAssetUrl(filename) {
9468
- return `${getAssetHost()}/${ASSET_PATH ? ASSET_PATH + '/' : ''}${filename}`;
9470
+ const assetHost = getAssetHost();
9471
+ const file = isLocalAgent(assetHost) ? filename.replace('.min.js', '.js') : filename;
9472
+ return `${assetHost}/${ASSET_PATH ? ASSET_PATH + '/' : ''}${file}`;
9469
9473
  }
9470
9474
 
9471
9475
  function treatAsAdoptPartner() {
@@ -13827,36 +13831,44 @@ function setFrameVisibility(visibility) {
13827
13831
  return store.dispatch('frames/updateFrameVisibility', { visibility });
13828
13832
  }
13829
13833
 
13830
- var PublicEvents = (function () {
13831
- var events = Eventable.call({});
13832
- var useAsync = {
13833
- validateGuide: 1,
13834
- validateLauncher: 1,
13835
- validateGlobalScript: 1
13836
- };
13837
- var internalEvents = {
13838
- ready: 1,
13839
- deliverablesLoaded: 1,
13840
- guidesFailed: 1,
13841
- guidesLoaded: 1,
13842
- onClickCaptured: 1
13843
- };
13844
- _.each([
13845
- // Supported events
13846
- 'ready',
13847
- 'onClickCaptured',
13848
- 'deliverablesLoaded',
13849
- 'guidesFailed',
13850
- 'guidesLoaded',
13851
- 'validateGuide',
13852
- 'validateLauncher',
13853
- 'validateGlobalScript'
13854
- ], function (eventName) {
13834
+ const useAsync = {
13835
+ validateGuide: 1,
13836
+ validateLauncher: 1,
13837
+ validateGlobalScript: 1
13838
+ };
13839
+ const internalEvents = {
13840
+ ready: 1,
13841
+ deliverablesLoaded: 1,
13842
+ guidesFailed: 1,
13843
+ guidesLoaded: 1,
13844
+ onClickCaptured: 1
13845
+ };
13846
+ const supportedPublicEvents = [
13847
+ 'ready',
13848
+ 'onClickCaptured',
13849
+ 'deliverablesLoaded',
13850
+ 'guidesFailed',
13851
+ 'guidesLoaded',
13852
+ 'validateGuide',
13853
+ 'validateLauncher',
13854
+ 'validateGlobalScript'
13855
+ ];
13856
+ function forwardInternalEvents(Events) {
13857
+ const unsubscribes = _.reduce(supportedPublicEvents, function (unsubscribes, eventName) {
13855
13858
  if (internalEvents[eventName]) {
13856
- Events[eventName].on(function (event) {
13859
+ const forward = function (event) {
13857
13860
  return PublicEvents[eventName].apply(PublicEvents[eventName], event.data);
13858
- });
13861
+ };
13862
+ Events[eventName].on(forward);
13863
+ unsubscribes.push(() => Events[eventName].off(forward));
13859
13864
  }
13865
+ return unsubscribes;
13866
+ }, []);
13867
+ return () => _.each(unsubscribes, (unsubscribe) => unsubscribe());
13868
+ }
13869
+ var PublicEvents = (function () {
13870
+ var events = Eventable.call({});
13871
+ _.each(supportedPublicEvents, function (eventName) {
13860
13872
  events[eventName] = function (callback) {
13861
13873
  if (_.isFunction(callback)) {
13862
13874
  return events.on(eventName, callback);
@@ -14677,10 +14689,12 @@ var GuideRuntime = (function (agentEvents) {
14677
14689
  var EventChannel = agentEvents.runtime;
14678
14690
  const pluginAddGlobalScripts = [];
14679
14691
  function initialize() {
14692
+ EventChannel.on(handleEvent);
14680
14693
  const globalScripts = ConfigReader.get('guides.globalScripts');
14681
14694
  _.each(globalScripts, GuideRuntime.addGlobalScript);
14682
14695
  }
14683
14696
  function teardown() {
14697
+ EventChannel.off(handleEvent);
14684
14698
  _.each(pluginAddGlobalScripts, GuideRuntime.removeGlobalScript);
14685
14699
  }
14686
14700
  function addGlobalScript(obj) {
@@ -14816,7 +14830,7 @@ var GuideRuntime = (function (agentEvents) {
14816
14830
  return 'hidden';
14817
14831
  return step.seenState;
14818
14832
  }
14819
- EventChannel.on(function (evt) {
14833
+ function handleEvent(evt) {
14820
14834
  var step = evt.data[0];
14821
14835
  evt.step = step;
14822
14836
  delete evt.data;
@@ -14841,7 +14855,7 @@ var GuideRuntime = (function (agentEvents) {
14841
14855
  delete evt.cancel;
14842
14856
  }
14843
14857
  return evt;
14844
- });
14858
+ }
14845
14859
  function GuideRuntimeContext(step) {
14846
14860
  this.step = step;
14847
14861
  _.each(['read', 'write', 'clear'], function (action) {
@@ -15864,6 +15878,16 @@ function vertical(elementPos, screenDim, layoutDir) {
15864
15878
  return TOP;
15865
15879
  }
15866
15880
 
15881
+ const TOOLTIP_CONSTANTS = {
15882
+ DEFAULT_CARET_OFFSET: 10,
15883
+ BOUNDARY_MARGIN_RIGHT: 0.98,
15884
+ BOUNDARY_MARGIN_LEFT: 0.02,
15885
+ Z_INDEX: {
15886
+ DEFAULT: '300000',
15887
+ CARET: 11,
15888
+ BORDER_CARET: 10
15889
+ }
15890
+ };
15867
15891
  var BuildingBlockTooltips = (function () {
15868
15892
  return {
15869
15893
  createBBTooltip,
@@ -15882,8 +15906,25 @@ var BuildingBlockTooltips = (function () {
15882
15906
  attachBBAdvanceActions,
15883
15907
  attachScrollHandlers,
15884
15908
  isBuildingBlockGuideRelativeToElement,
15885
- positionStepForTooltip
15909
+ positionStepForTooltip,
15910
+ patchGuideContainerWidthForResponsiveTooltips
15886
15911
  };
15912
+ function patchGuideContainerWidthForResponsiveTooltips(step, providedGuideContainer, json) {
15913
+ const guideContainer = providedGuideContainer || getGuideContainer(step);
15914
+ if (!guideContainer)
15915
+ return;
15916
+ const element = step.element || getElementForGuideStep(step);
15917
+ if (!element)
15918
+ return;
15919
+ const width = guideContainer.style.width;
15920
+ if (!width || width.indexOf('vw') === -1) {
15921
+ return;
15922
+ }
15923
+ const tooltipContext = getTooltipPositioningContext(step, element, json, guideContainer);
15924
+ if (!tooltipContext)
15925
+ return;
15926
+ calculateVwRelativeToLayoutDir(guideContainer, tooltipContext);
15927
+ }
15887
15928
  function positionStepForTooltip(step, json, guideContainerEle) {
15888
15929
  // This directly modifies step.guideElement object
15889
15930
  createBBTooltip(json, step.element, step, guideContainerEle);
@@ -15896,39 +15937,58 @@ var BuildingBlockTooltips = (function () {
15896
15937
  function buildTooltipCSSName() {
15897
15938
  return treatAsMobileDevice() ? MOBILE_TOOLTIP_CSS_NAME : TOOLTIP_CSS_NAME;
15898
15939
  }
15899
- function createBBTooltip(domJson, element, step, guideContainer) {
15900
- if (!step.guideElement)
15901
- return;
15902
- var tooltipDiv = step.guideElement;
15903
- tooltipDiv.addClass(buildTooltipCSSName());
15940
+ function getTooltipPositioningContext(step, element, json, guideContainer) {
15904
15941
  var elementPos = getOffsetPosition(element);
15942
+ var screenPos = getScreenPosition(element);
15943
+ var screenDimensions = getScreenDimensions();
15944
+ var layoutDir = step.attributes.layoutDir || 'auto';
15905
15945
  // RETURN IF THE FOUND ELEMENT IS NOT VISIBLE ON THE SCREEN.
15906
15946
  if (elementPos.height === 0 && elementPos.width === 0) {
15907
15947
  return null;
15908
15948
  }
15909
- var screenPos = getScreenPosition(element);
15949
+ const elementIsNotVisible = step && !step.elementPathRule;
15910
15950
  var containerTruthTest = function (block) { return block.props.id === 'pendo-guide-container'; };
15911
- var containerDomJson = findDomBlockInDomJson(domJson, containerTruthTest);
15951
+ var containerDomJson = findDomBlockInDomJson(json, containerTruthTest);
15912
15952
  if (!containerDomJson)
15913
- return;
15914
- var layoutDir = step.attributes.layoutDir;
15915
- var tooltipSizes = {
15916
- height: guideContainer.offsetHeight,
15917
- width: guideContainer.offsetWidth
15918
- };
15953
+ return null;
15919
15954
  var caretDimensions = {
15920
15955
  height: parseInt(containerDomJson.props['data-caret-height'], 10) || 0,
15921
15956
  width: parseInt(containerDomJson.props['data-caret-width'], 10) || 0,
15922
15957
  backgroundColor: containerDomJson.props.style['background-color'],
15923
- offset: 10
15958
+ offset: TOOLTIP_CONSTANTS.DEFAULT_CARET_OFFSET,
15959
+ borderWidth: 0
15924
15960
  };
15925
- attachBBAdvanceActions(step);
15926
15961
  if (containerDomJson.props.style.border) {
15927
15962
  var guideBorderArray = containerDomJson.props.style.border.split(' ');
15928
15963
  caretDimensions.borderColor = guideBorderArray[2];
15929
15964
  caretDimensions.borderWidth = parseInt(guideBorderArray[0], 10);
15930
15965
  }
15931
- var tooltipDimensions = getBBTooltipDimensions(elementPos, tooltipSizes, caretDimensions, layoutDir, screenPos);
15966
+ const tooltipSizes = {
15967
+ width: guideContainer.offsetWidth,
15968
+ height: guideContainer.offsetHeight,
15969
+ layoutDir
15970
+ };
15971
+ return {
15972
+ elementPos,
15973
+ screenPos,
15974
+ screenDimensions,
15975
+ caretDimensions,
15976
+ tooltipSizes,
15977
+ containerDomJson,
15978
+ elementIsNotVisible
15979
+ };
15980
+ }
15981
+ function createBBTooltip(domJson, element, step, guideContainer) {
15982
+ if (!step.guideElement)
15983
+ return;
15984
+ const tooltipContext = getTooltipPositioningContext(step, element, domJson, guideContainer);
15985
+ if (!tooltipContext)
15986
+ return null;
15987
+ const { elementPos, tooltipSizes, screenPos, caretDimensions } = tooltipContext;
15988
+ var tooltipDiv = step.guideElement;
15989
+ tooltipDiv.addClass(buildTooltipCSSName());
15990
+ attachBBAdvanceActions(step);
15991
+ var tooltipDimensions = getBBTooltipDimensions(elementPos, { height: tooltipSizes.height, width: tooltipSizes.width }, caretDimensions, step.attributes.layoutDir, screenPos);
15932
15992
  if (step) {
15933
15993
  step.dim = tooltipDimensions;
15934
15994
  }
@@ -15946,15 +16006,13 @@ var BuildingBlockTooltips = (function () {
15946
16006
  guideContainer.style.position = 'absolute';
15947
16007
  }
15948
16008
  if (caretDimensions.height && caretDimensions.width) {
15949
- buildTooltipCaret(tooltipDiv, tooltipDimensions, caretDimensions);
16009
+ buildTooltipCaret(tooltipDiv, tooltipDimensions, caretDimensions, elementPos);
15950
16010
  }
15951
- var inheritedZIndex = '300000';
16011
+ var inheritedZIndex = TOOLTIP_CONSTANTS.Z_INDEX.DEFAULT;
15952
16012
  if (guideContainer && guideContainer.style && guideContainer.style['z-index']) {
15953
16013
  inheritedZIndex = guideContainer.style['z-index'];
15954
16014
  }
15955
- //
15956
16015
  // styles for OUTER Guide
15957
- //
15958
16016
  tooltipDiv.css({
15959
16017
  'z-index': inheritedZIndex
15960
16018
  });
@@ -16021,7 +16079,7 @@ var BuildingBlockTooltips = (function () {
16021
16079
  tooltipDimensions.hbias = horizontal(elementPos, screenDimensions, layoutDirection);
16022
16080
  tooltipDimensions.vbias = vertical(elementPos, screenDimensions, layoutDirection);
16023
16081
  tooltipDimensions.layoutDir = determineTooltipPosition(tooltipDimensions, screenDimensions, screenPos, layoutDirection);
16024
- var tooltipPosition = positionBBTooltipWithBias(tooltipDimensions, elementPos, screenDimensions);
16082
+ var tooltipPosition = positionBBTooltipWithBias(tooltipDimensions, elementPos, screenDimensions, caretSizes);
16025
16083
  tooltipDimensions.top = tooltipPosition.top;
16026
16084
  tooltipDimensions.left = tooltipPosition.left;
16027
16085
  // Adjust tooltip top/left for the size of the caret
@@ -16039,6 +16097,32 @@ var BuildingBlockTooltips = (function () {
16039
16097
  }
16040
16098
  return tooltipDimensions;
16041
16099
  }
16100
+ function calculateVwRelativeToLayoutDir(guideContainer, tooltipContext) {
16101
+ const { elementPos, tooltipSizes, screenDimensions, caretDimensions, elementIsNotVisible } = tooltipContext;
16102
+ const caretFullWidth = (parseInt(caretDimensions.width, 10) || 0);
16103
+ const maxWidth = parseInt(guideContainer.style.maxWidth, 10);
16104
+ const minWidth = parseInt(guideContainer.style.minWidth, 10);
16105
+ const percentage = parseFloat(guideContainer.style.width) / 100;
16106
+ if (elementIsNotVisible) {
16107
+ tooltipSizes.width -= caretFullWidth;
16108
+ }
16109
+ else if (tooltipSizes.layoutDir === 'left') {
16110
+ const availableSpaceToTheLeftOfElement = elementPos.left - caretFullWidth;
16111
+ tooltipSizes.width = Math.max(0, availableSpaceToTheLeftOfElement * percentage);
16112
+ }
16113
+ else if (tooltipSizes.layoutDir === 'right') {
16114
+ const availableSpaceToTheRightOfElement = screenDimensions.width - elementPos.right - caretFullWidth;
16115
+ tooltipSizes.width = Math.max(0, availableSpaceToTheRightOfElement * percentage);
16116
+ }
16117
+ if (maxWidth && tooltipSizes.width > maxWidth) {
16118
+ tooltipSizes.width = maxWidth;
16119
+ }
16120
+ if (minWidth && tooltipSizes.width < minWidth) {
16121
+ tooltipSizes.width = minWidth;
16122
+ }
16123
+ // We need to patch the vw to the available space for the tooltip, otherwise 100vw would be the entire screen
16124
+ guideContainer.style.width = tooltipSizes.width + 'px';
16125
+ }
16042
16126
  function determineTooltipPosition(tooltipDimensions, screenDimensions, screenPos, layoutDirection) {
16043
16127
  if (layoutDirection && layoutDirection !== 'auto') {
16044
16128
  return layoutDirection;
@@ -16096,15 +16180,14 @@ var BuildingBlockTooltips = (function () {
16096
16180
  return position;
16097
16181
  return tooltipDimensions.hbias ? tooltipDimensions.hbias : 'bottom';
16098
16182
  }
16099
- function positionBBTooltipWithBias(tooltipDimensions, elementPosition, screenDimensions) {
16183
+ function positionBBTooltipWithBias(tooltipDimensions, elementPosition, screenDimensions, caretSizes) {
16100
16184
  if (tooltipDimensions.layoutDir === 'top' || tooltipDimensions.layoutDir === 'bottom') {
16101
- return calculateToolTipPositionForTopBottom(tooltipDimensions, screenDimensions, elementPosition, tooltipDimensions.layoutDir, tooltipDimensions.hbias);
16185
+ return calculateToolTipPositionForTopBottom(tooltipDimensions, screenDimensions, elementPosition, tooltipDimensions.layoutDir, tooltipDimensions.hbias, caretSizes);
16102
16186
  }
16103
16187
  return calculateToolTipPositionForLeftRight(tooltipDimensions, screenDimensions, elementPosition, tooltipDimensions.vbias);
16104
16188
  }
16105
- function calculateToolTipPositionForTopBottom(tooltipDimensions, screenDimensions, elementPosition, layoutDirection, horizontalBias) {
16189
+ function calculateToolTipPositionForTopBottom(tooltipDimensions, screenDimensions, elementPosition, layoutDirection, horizontalBias, caretSizes) {
16106
16190
  var height = tooltipDimensions.height;
16107
- var width = tooltipDimensions.width;
16108
16191
  var tooltipPosition = {
16109
16192
  top: null,
16110
16193
  left: null
@@ -16115,22 +16198,95 @@ var BuildingBlockTooltips = (function () {
16115
16198
  else if (layoutDirection === 'top') {
16116
16199
  tooltipPosition.top = elementPosition.top - height;
16117
16200
  }
16201
+ const boundaries = getBoundaries();
16118
16202
  if (horizontalBias === 'right') {
16119
- var leftVal = elementPosition.left + (elementPosition.width / 2);
16120
- if (leftVal + tooltipDimensions.width > screenDimensions.width) {
16121
- leftVal -= (leftVal + tooltipDimensions.width - screenDimensions.width);
16122
- }
16123
- tooltipPosition.left = leftVal;
16203
+ tooltipPosition.left = calculateRightBiasPosition(elementPosition, tooltipDimensions, caretSizes, screenDimensions, boundaries.right, boundaries.left);
16124
16204
  }
16125
16205
  else if (horizontalBias === 'left') {
16126
- tooltipPosition.left = elementPosition.left - width + (elementPosition.width / 2);
16206
+ tooltipPosition.left = calculateLeftBiasPosition(elementPosition, tooltipDimensions, caretSizes, boundaries.right, boundaries.left);
16127
16207
  }
16128
16208
  else {
16129
16209
  // ASSUME CENTER
16130
- tooltipPosition.left = elementPosition.left + (elementPosition.width / 2) - (width / 2);
16210
+ tooltipPosition.left = calculateCenterBiasPosition(elementPosition, tooltipDimensions, boundaries.right, boundaries.left);
16131
16211
  }
16132
16212
  return tooltipPosition;
16133
16213
  }
16214
+ function getBoundaries() {
16215
+ return {
16216
+ right: window.innerWidth * TOOLTIP_CONSTANTS.BOUNDARY_MARGIN_RIGHT,
16217
+ left: window.innerWidth * TOOLTIP_CONSTANTS.BOUNDARY_MARGIN_LEFT
16218
+ };
16219
+ }
16220
+ function calculateCaretPadding(caretSizes) {
16221
+ return caretSizes.offset + caretSizes.width + caretSizes.borderWidth;
16222
+ }
16223
+ function calculateRightBiasPosition(elementPosition, tooltipDimensions, caretSizes, screenDimensions, rightBoundary, leftBoundary) {
16224
+ const caretPadding = calculateCaretPadding(caretSizes);
16225
+ const width = tooltipDimensions.width;
16226
+ var leftVal = elementPosition.left + (elementPosition.width / 2) - caretPadding;
16227
+ if (leftVal + tooltipDimensions.width > screenDimensions.width) {
16228
+ leftVal -= (leftVal + tooltipDimensions.width - screenDimensions.width);
16229
+ }
16230
+ const tooltipRight = leftVal + width;
16231
+ if (tooltipRight > rightBoundary) {
16232
+ const overflow = tooltipRight - rightBoundary;
16233
+ if (leftVal - overflow < leftBoundary) {
16234
+ return spaceEvenly(leftVal, width);
16235
+ }
16236
+ else {
16237
+ return leftVal - overflow;
16238
+ }
16239
+ }
16240
+ return leftVal;
16241
+ }
16242
+ function calculateLeftBiasPosition(elementPosition, tooltipDimensions, caretSizes, rightBoundary, leftBoundary) {
16243
+ const caretPadding = calculateCaretPadding(caretSizes);
16244
+ const width = tooltipDimensions.width;
16245
+ var leftVal = elementPosition.left - width + (elementPosition.width / 2) + caretPadding;
16246
+ if (leftVal < leftBoundary) {
16247
+ const overflow = leftBoundary - leftVal;
16248
+ const tooltipRight = leftVal + width;
16249
+ if (tooltipRight + overflow > rightBoundary) {
16250
+ return spaceEvenly(leftVal, width);
16251
+ }
16252
+ else {
16253
+ return leftVal + overflow;
16254
+ }
16255
+ }
16256
+ return leftVal;
16257
+ }
16258
+ function calculateCenterBiasPosition(elementPosition, tooltipDimensions, rightBoundary, leftBoundary) {
16259
+ const width = tooltipDimensions.width;
16260
+ var leftVal = elementPosition.left + (elementPosition.width / 2) - (width / 2);
16261
+ let tooltipRight = leftVal + width;
16262
+ if (tooltipRight > rightBoundary) {
16263
+ const overflow = tooltipRight - rightBoundary;
16264
+ leftVal -= overflow;
16265
+ if (leftVal < leftBoundary) {
16266
+ return spaceEvenly(leftVal, width);
16267
+ }
16268
+ }
16269
+ else if (leftVal < leftBoundary) {
16270
+ const overflow = leftBoundary - leftVal;
16271
+ leftVal += overflow;
16272
+ let tooltipRight = leftVal + width;
16273
+ if (tooltipRight > rightBoundary) {
16274
+ return spaceEvenly(leftVal, width);
16275
+ }
16276
+ }
16277
+ return leftVal;
16278
+ }
16279
+ function spaceEvenly(leftVal, width) {
16280
+ const availableLeftSpace = leftVal;
16281
+ const availableRightSpace = window.innerWidth - (leftVal + width);
16282
+ if (availableLeftSpace > availableRightSpace) {
16283
+ return leftVal - (availableLeftSpace - availableRightSpace) / 2;
16284
+ }
16285
+ else if (availableRightSpace > availableLeftSpace) {
16286
+ return leftVal + (availableRightSpace - availableLeftSpace) / 2;
16287
+ }
16288
+ return leftVal;
16289
+ }
16134
16290
  function calculateToolTipPositionForLeftRight(tooltipDimensions, screenDimensions, elementPosition, verticalBias) {
16135
16291
  var height = tooltipDimensions.height;
16136
16292
  var width = tooltipDimensions.width;
@@ -16161,12 +16317,12 @@ var BuildingBlockTooltips = (function () {
16161
16317
  }
16162
16318
  return tooltipPosition;
16163
16319
  }
16164
- function buildTooltipCaret(tooltipDiv, tooltipDimensions, caretDimensions) {
16320
+ function buildTooltipCaret(tooltipDiv, tooltipDimensions, caretDimensions, elementPos) {
16165
16321
  var caretDiv = document.createElement('div');
16166
16322
  caretDiv.setAttribute('class', 'pendo-tooltip-caret pendo-tooltip-caret--' + tooltipDimensions.layoutDir);
16167
16323
  caretDiv.style.position = 'absolute';
16168
- caretDiv.style.zIndex = 11;
16169
- updateCaretStyles(caretDiv, tooltipDimensions, caretDimensions);
16324
+ caretDiv.style.zIndex = TOOLTIP_CONSTANTS.Z_INDEX.CARET;
16325
+ updateCaretStyles(caretDiv, tooltipDimensions, caretDimensions, elementPos);
16170
16326
  var guideDiv = tooltipDiv.find('#pendo-guide-container')[0].parentNode;
16171
16327
  guideDiv.appendChild(caretDiv);
16172
16328
  if (!caretDimensions.borderWidth)
@@ -16174,35 +16330,20 @@ var BuildingBlockTooltips = (function () {
16174
16330
  var borderCaret = buildBorderCaret(caretDiv, caretDimensions, tooltipDimensions.layoutDir);
16175
16331
  guideDiv.appendChild(borderCaret);
16176
16332
  }
16177
- function updateCaretStyles(caretDiv, tooltipDimensions, caretDimensions) {
16333
+ function updateCaretStyles(caretDiv, tooltipDimensions, caretDimensions, elementPos) {
16178
16334
  if (tooltipDimensions.layoutDir === 'top' || tooltipDimensions.layoutDir === 'bottom') {
16179
- styleTopOrBottomCaret(caretDiv, tooltipDimensions, caretDimensions);
16335
+ styleTopOrBottomCaret(caretDiv, tooltipDimensions, caretDimensions, elementPos);
16180
16336
  }
16181
16337
  if (tooltipDimensions.layoutDir === 'left' || tooltipDimensions.layoutDir === 'right') {
16182
16338
  styleLeftOrRightCaret(caretDiv, tooltipDimensions, caretDimensions);
16183
16339
  }
16184
16340
  }
16185
- function styleTopOrBottomCaret(caret, tooltipDimensions, caretDimensions) {
16186
- var screenDimensions = getScreenDimensions();
16341
+ function styleTopOrBottomCaret(caret, tooltipDimensions, caretDimensions, elementPos) {
16187
16342
  caret.style['border-left'] = caretDimensions.width + 'px solid transparent';
16188
16343
  caret.style['border-right'] = caretDimensions.width + 'px solid transparent';
16189
16344
  caret.style.right = '';
16190
- if (tooltipDimensions.hbias === LEFT) {
16191
- var maxArrowLeft = tooltipDimensions.width - caretDimensions.width * 2 - caretDimensions.offset - caretDimensions.borderWidth;
16192
- caret.style.left = maxArrowLeft + 'px';
16193
- tooltipDimensions.left += caretDimensions.offset + caretDimensions.width + caretDimensions.borderWidth;
16194
- }
16195
- else if (tooltipDimensions.hbias === RIGHT) {
16196
- caret.style.left = (caretDimensions.offset + caretDimensions.borderWidth) + 'px';
16197
- tooltipDimensions.left -= caretDimensions.offset + caretDimensions.width + caretDimensions.borderWidth;
16198
- if (tooltipDimensions.left + tooltipDimensions.width > screenDimensions.width) {
16199
- tooltipDimensions.left = tooltipDimensions.left - (tooltipDimensions.left + tooltipDimensions.width - screenDimensions.width);
16200
- }
16201
- tooltipDimensions.left = Math.max(0, tooltipDimensions.left);
16202
- }
16203
- else { // ASSUME CENTER
16204
- caret.style.left = (tooltipDimensions.width / 2) - caretDimensions.width + 'px';
16205
- }
16345
+ const caretOffset = calculateCaretOffset(elementPos, tooltipDimensions, caretDimensions, tooltipDimensions.hbias);
16346
+ caret.style.left = caretOffset + 'px';
16206
16347
  // Tooltip is below element, put caret on the top of the tooltip
16207
16348
  if (tooltipDimensions.layoutDir === 'bottom') {
16208
16349
  caret.style['border-bottom'] = caretDimensions.height + 'px solid ' + caretDimensions.backgroundColor;
@@ -16227,6 +16368,23 @@ var BuildingBlockTooltips = (function () {
16227
16368
  }
16228
16369
  return caret;
16229
16370
  }
16371
+ function calculateCaretOffset(elementPos, tooltipDimensions, caretDimensions, bias) {
16372
+ if (elementPos && elementPos.left) {
16373
+ const elementCenter = elementPos.left + (elementPos.width / 2);
16374
+ return elementCenter - tooltipDimensions.left - caretDimensions.width; // always center the tooltip on the element
16375
+ }
16376
+ else {
16377
+ if (bias === 'left') {
16378
+ return tooltipDimensions.width - caretDimensions.width * 2 - caretDimensions.offset - caretDimensions.borderWidth;
16379
+ }
16380
+ else if (bias === 'right') {
16381
+ return caretDimensions.offset + caretDimensions.borderWidth;
16382
+ }
16383
+ else { // center
16384
+ return (tooltipDimensions.width / 2) - caretDimensions.width;
16385
+ }
16386
+ }
16387
+ }
16230
16388
  function styleLeftOrRightCaret(caret, tooltipDimensions, caretDimensions) {
16231
16389
  var screenDimensions = getScreenDimensions();
16232
16390
  caret.style['border-top'] = caretDimensions.width + 'px solid transparent';
@@ -16275,7 +16433,7 @@ var BuildingBlockTooltips = (function () {
16275
16433
  function buildBorderCaret(caret, caretDimensions, tooltipLayoutDirection) {
16276
16434
  var borderCaret = caret.cloneNode();
16277
16435
  borderCaret.setAttribute('class', 'pendo-tooltip-caret-border');
16278
- borderCaret.style.zIndex = 10;
16436
+ borderCaret.style.zIndex = TOOLTIP_CONSTANTS.Z_INDEX.BORDER_CARET;
16279
16437
  updateBorderCaretStyles(borderCaret, caretDimensions, tooltipLayoutDirection, caret);
16280
16438
  return borderCaret;
16281
16439
  }
@@ -16362,7 +16520,7 @@ var BuildingBlockTooltips = (function () {
16362
16520
  height: parseInt(ttContainer[0].getAttribute('data-caret-height'), 10) || 0,
16363
16521
  width: parseInt(ttContainer[0].getAttribute('data-caret-width'), 10) || 0,
16364
16522
  backgroundColor: ttContainer[0].style['background-color'],
16365
- offset: 10,
16523
+ offset: TOOLTIP_CONSTANTS.DEFAULT_CARET_OFFSET,
16366
16524
  borderColor: ttContainerStyles.borderColor,
16367
16525
  borderWidth: parseInt(ttContainerStyles.borderWidth, 10)
16368
16526
  };
@@ -16371,7 +16529,7 @@ var BuildingBlockTooltips = (function () {
16371
16529
  var caretDiv = ttdiv.find('.pendo-tooltip-caret')[0];
16372
16530
  var borderCaret = ttdiv.find('.pendo-tooltip-caret-border')[0];
16373
16531
  if (caretDiv) {
16374
- updateCaretStyles(caretDiv, tooltipDimensions, caretStyles);
16532
+ updateCaretStyles(caretDiv, tooltipDimensions, caretStyles, elPos);
16375
16533
  }
16376
16534
  if (borderCaret) {
16377
16535
  updateBorderCaretStyles(borderCaret, caretStyles, tooltipDimensions.layoutDir, caretDiv);
@@ -17853,7 +18011,7 @@ var identify = makeSafe(function (visitor_id, account_id) {
17853
18011
  });
17854
18012
  var isSelfHosted = function () {
17855
18013
  var scripts = dom('script');
17856
- var selfHosted = isSelfHostedUrl(scripts) && (getInstallType() !== 'extension');
18014
+ var selfHosted = isSelfHostedUrl(scripts) && !isExtensionAgent();
17857
18015
  return selfHosted;
17858
18016
  };
17859
18017
  var isSelfHostedUrl = function (scripts) {
@@ -17890,7 +18048,6 @@ function handleIdentifyEvent(event) {
17890
18048
  ConfigReader.setLocalConfig(options);
17891
18049
  store.commit('metadata/setMetadata', options);
17892
18050
  }
17893
- Events.identify.on(handleIdentifyEvent);
17894
18051
 
17895
18052
  /*
17896
18053
  * Extension API
@@ -26527,6 +26684,7 @@ function initIdentityEvents() {
26527
26684
  }
26528
26685
  }
26529
26686
  });
26687
+ Events.identify.on(handleIdentifyEvent);
26530
26688
  initialized = true;
26531
26689
  }
26532
26690
 
@@ -26857,6 +27015,7 @@ const initialize = makeSafe(function (options) {
26857
27015
  // Disable content pre-fetch for guide center
26858
27016
  pendo$1.disableGuideCenterContentSearch = options.disableGuideCenterContentSearch;
26859
27017
  // Register handlers passed through pendo_options
27018
+ teardownFns.push(forwardInternalEvents(Events));
26860
27019
  registerEventHandlers(options);
26861
27020
  teardownFns.push(initGuides()); // this is safe. loadGuides actually does the loading.
26862
27021
  initIdentityEvents(); // setup identify and meta event listeners
@@ -27219,6 +27378,9 @@ var BuildingBlockGuides = (function () {
27219
27378
  }
27220
27379
  fixGuideStyleDocument(getGuideAttachPoint(), guideToAppend[0], step.id);
27221
27380
  sizeElements(guideToAppend);
27381
+ if (relativeToElement) {
27382
+ BuildingBlockTooltips.patchGuideContainerWidthForResponsiveTooltips(step, guideContainer[0], json);
27383
+ }
27222
27384
  // We want to prevent announcement modules from running this code
27223
27385
  // because it will cause some elements to resize incorrectly to the
27224
27386
  // announcement *module* container instead of the announcement *guide* container
@@ -28309,25 +28471,28 @@ IntervalJob.prototype.stop = function () {
28309
28471
  };
28310
28472
 
28311
28473
  var urlFor = ajax.urlFor;
28474
+ // Define the valid attribute-action combinations once
28475
+ var attrActionEnum = {
28476
+ search: ['AllowOnlyKeys', 'ExcludeKeys', 'AddTo', 'Replace', 'Clear'],
28477
+ hash: ['Replace', 'Clear'],
28478
+ pathname: ['Replace', 'Clear', 'AddTo'],
28479
+ hostname: ['Replace'],
28480
+ href: ['Replace', 'ForceSecure'],
28481
+ protocol: ['ForceSecure']
28482
+ };
28312
28483
  function UrlAttrTransform(attr, action, data) {
28313
- var attrActionEnum = {
28314
- search: ['AllowOnlyKeys', 'ExcludeKeys', 'AddTo', 'Replace', 'Clear'],
28315
- hash: ['Replace', 'Clear'],
28316
- pathname: ['Replace'],
28317
- hostname: ['Replace'],
28318
- href: ['Replace', 'ForceSecure'],
28319
- protocol: ['ForceSecure']
28320
- };
28321
28484
  if (_.isObject(attr)) {
28322
28485
  action = attr.action;
28323
28486
  data = attr.data;
28324
28487
  attr = attr.attr;
28325
28488
  }
28326
28489
  if (!attrActionEnum[attr]) {
28327
- throw new Error('Invalid URL attribute type: ' + attr);
28490
+ var validAttrs = _.keys(attrActionEnum).join(', ');
28491
+ throw new Error('Invalid URL attribute type: "' + attr + '". Valid attributes are: ' + validAttrs + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
28328
28492
  }
28329
28493
  if (!_.contains(attrActionEnum[attr], action)) {
28330
- throw new Error('Invalid transform (' + action + ') for attribute (' + attr + ')');
28494
+ var validActions = attrActionEnum[attr].join(', ');
28495
+ throw new Error('Invalid transform action: "' + action + '" for attribute "' + attr + '". Valid actions for "' + attr + '" are: ' + validActions + '. Example: {attr: "' + attr + '", action: "' + attrActionEnum[attr][0] + '", data: ...}');
28331
28496
  }
28332
28497
  this.attr = attr;
28333
28498
  this.action = action;
@@ -28353,11 +28518,36 @@ UrlAttrTransform.prototype.applyToURL = function (url) {
28353
28518
  if (_.isFunction(data)) {
28354
28519
  data = data(url[attr], url);
28355
28520
  }
28521
+ // AddTo only works for search and pathname attributes; otherwise, do nothing
28522
+ if (attr !== 'search' && attr !== 'pathname') {
28523
+ return url;
28524
+ }
28525
+ if (attr === 'pathname') {
28526
+ // Ensure pathname starts with '/' and append the new segment
28527
+ var currentPath = url.pathname;
28528
+ var newSegment = data;
28529
+ if (!newSegment.startsWith('/')) {
28530
+ newSegment = '/' + newSegment;
28531
+ }
28532
+ if (currentPath.endsWith('/')) {
28533
+ url.pathname = currentPath + newSegment.substring(1);
28534
+ }
28535
+ else {
28536
+ url.pathname = currentPath + newSegment;
28537
+ }
28538
+ return url;
28539
+ }
28540
+ // For search attribute, use the existing urlFor logic
28356
28541
  var href = url.href;
28357
28542
  return new URL(urlFor(href, data));
28358
28543
  },
28359
28544
  Clear(url, attr) {
28360
- url[attr] = '';
28545
+ if (attr === 'pathname') {
28546
+ url.pathname = '/';
28547
+ }
28548
+ else {
28549
+ url[attr] = '';
28550
+ }
28361
28551
  return url;
28362
28552
  },
28363
28553
  Replace(url, attr, data) {
@@ -28389,7 +28579,67 @@ UrlAttrTransform.fromJSON = function (obj) {
28389
28579
  if (obj instanceof UrlAttrTransform) {
28390
28580
  return obj;
28391
28581
  }
28392
- return new UrlAttrTransform(obj.attr, obj.action, obj.data);
28582
+ // Validate input is an object
28583
+ if (!_.isObject(obj)) {
28584
+ throw new Error('UrlAttrTransform.fromJSON expects an object. Received: ' + typeof obj + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
28585
+ }
28586
+ // Validate required properties
28587
+ if (!obj.attr) {
28588
+ var allValidAttrs = _.keys(attrActionEnum).join(', ');
28589
+ throw new Error('UrlAttrTransform is missing required "attr" property. Valid attributes are: ' + allValidAttrs + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
28590
+ }
28591
+ if (!obj.action) {
28592
+ var attrValidActions = attrActionEnum[obj.attr] ? attrActionEnum[obj.attr].join(', ') : 'AllowOnlyKeys, ExcludeKeys, AddTo, Replace, Clear';
28593
+ throw new Error('UrlAttrTransform is missing required "action" property. Valid actions depend on the attribute. For "' + obj.attr + '" attribute, valid actions are: ' + attrValidActions + '. Example: {attr: "' + obj.attr + '", action: "AddTo", data: {key: "value"}}');
28594
+ }
28595
+ // Validate attribute and action combination
28596
+ if (!attrActionEnum[obj.attr]) {
28597
+ var validAttrs = _.keys(attrActionEnum).join(', ');
28598
+ throw new Error('Invalid attribute "' + obj.attr + '". Valid attributes are: ' + validAttrs + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
28599
+ }
28600
+ if (!_.contains(attrActionEnum[obj.attr], obj.action)) {
28601
+ var validActions = attrActionEnum[obj.attr].join(', ');
28602
+ throw new Error('Invalid action "' + obj.action + '" for attribute "' + obj.attr + '". Valid actions for "' + obj.attr + '" are: ' + validActions + '. Example: {attr: "' + obj.attr + '", action: "' + attrActionEnum[obj.attr][0] + '", data: ...}');
28603
+ }
28604
+ // Validate data property for actions that require it
28605
+ var actionsRequiringData = ['AllowOnlyKeys', 'ExcludeKeys', 'AddTo', 'Replace'];
28606
+ if (_.contains(actionsRequiringData, obj.action) && obj.data === undefined) {
28607
+ var dataExample = obj.action === 'Replace' ? '"newValue"'
28608
+ : (obj.action === 'AddTo' ? '{key1: "value1"}' : '["key1", "key2"]');
28609
+ throw new Error('Action "' + obj.action + '" requires a "data" property. Example: {attr: "' + obj.attr + '", action: "' + obj.action + '", data: ' + dataExample + '}');
28610
+ }
28611
+ // Validate data types for specific actions
28612
+ if (obj.action === 'AllowOnlyKeys' || obj.action === 'ExcludeKeys') {
28613
+ if (!_.isArray(obj.data)) {
28614
+ throw new Error('Action "' + obj.action + '" requires "data" to be an array of strings. Example: {attr: "' + obj.attr + '", action: "' + obj.action + '", data: ["key1", "key2"]}');
28615
+ }
28616
+ }
28617
+ if (obj.action === 'AddTo') {
28618
+ if (obj.attr === 'pathname') {
28619
+ // For pathname, data can be a string, object, or function
28620
+ if (!_.isString(obj.data) && !_.isObject(obj.data) && !_.isFunction(obj.data)) {
28621
+ throw new Error('Action "AddTo" for pathname requires "data" to be a string, object, or function. Example: {attr: "pathname", action: "AddTo", data: "additional/segment"}');
28622
+ }
28623
+ }
28624
+ else {
28625
+ // For other attributes (like search), data must be an object or function
28626
+ if (!_.isObject(obj.data) && !_.isFunction(obj.data)) {
28627
+ throw new Error('Action "AddTo" requires "data" to be an object or function. Example: {attr: "search", action: "AddTo", data: {key1: "value1", key2: "value2"}}');
28628
+ }
28629
+ }
28630
+ }
28631
+ try {
28632
+ return new UrlAttrTransform(obj.attr, obj.action, obj.data);
28633
+ }
28634
+ catch (error) {
28635
+ // If it's already a detailed error from our validation, re-throw it
28636
+ if (error.message.includes('Invalid attribute') || error.message.includes('Invalid action') ||
28637
+ error.message.includes('requires') || error.message.includes('expects')) {
28638
+ throw error;
28639
+ }
28640
+ // Otherwise, wrap the original error with context
28641
+ throw new Error('Failed to create UrlAttrTransform: ' + error.message + '. Transform object: ' + JSON.stringify(obj));
28642
+ }
28393
28643
  };
28394
28644
 
28395
28645
  function isURL(u) {
@@ -35573,7 +35823,7 @@ const EventProperties = (function () {
35573
35823
  return;
35574
35824
  }
35575
35825
  var value = collectEventProperty(ep);
35576
- if (value) {
35826
+ if (doesExist(value)) {
35577
35827
  result['_pendo_' + ep.name] = value;
35578
35828
  }
35579
35829
  }
@@ -36390,7 +36640,7 @@ const EmbeddedGuides = (function () {
36390
36640
  _ = globalPendo._;
36391
36641
  exportPublicEmbeddedGuideApi(pendo);
36392
36642
  pluginApi.Events.on('deliverablesLoaded', clearEmbeddedGuides);
36393
- pluginApi.Events.on('guideLoopStopped', hideAllEmbeddedGuides);
36643
+ pluginApi.Events.on('guideLoopStopped', onGuidesStopped);
36394
36644
  pluginApi.Events.on('guideListChanged', initializeEmbeddedGuides);
36395
36645
  pluginApi.Events.on('urlChanged', setForceShowFirstStepFlags);
36396
36646
  pluginApi.GuideLoop.addUpdatePhase(processEmbeddedGuides);
@@ -36401,7 +36651,7 @@ const EmbeddedGuides = (function () {
36401
36651
  function teardown() {
36402
36652
  clearEmbeddedGuides();
36403
36653
  pluginApi.Events.off('deliverablesLoaded', clearEmbeddedGuides);
36404
- pluginApi.Events.off('guideLoopStopped', hideAllEmbeddedGuides);
36654
+ pluginApi.Events.off('guideLoopStopped', onGuidesStopped);
36405
36655
  pluginApi.Events.off('guideListChanged', initializeEmbeddedGuides);
36406
36656
  pluginApi.Events.off('urlChanged', setForceShowFirstStepFlags);
36407
36657
  pluginApi.GuideLoop.removeUpdatePhase(processEmbeddedGuides);
@@ -36411,6 +36661,14 @@ const EmbeddedGuides = (function () {
36411
36661
  this.removeResizeEvent();
36412
36662
  _oldEmbeddedGuides.length = 0;
36413
36663
  }
36664
+ function onGuidesStopped() {
36665
+ // The guideLoopStopped event sometimes is sent when the guide loop is restarted, for example when a guide is advanced.
36666
+ // Do not hide embedded guides in these cases.
36667
+ // The delayGuides flag is set when guides are manually stopped, and unset when guides are manually started.
36668
+ if (pluginApi.ConfigReader.get('delayGuides')) {
36669
+ hideAllEmbeddedGuides();
36670
+ }
36671
+ }
36414
36672
  function processEmbeddedGuides() {
36415
36673
  _.forEach(embeddedGuides, function (guide) {
36416
36674
  guide.process();
@@ -37965,6 +38223,9 @@ function stubSnippetMethods(pendo) {
37965
38223
  };
37966
38224
  });
37967
38225
  }
38226
+ function isConfiguredForMV3(config) {
38227
+ return config && config.useAssetHostForDesigner;
38228
+ }
37968
38229
  function initAgent(pendo, PendoConfig) {
37969
38230
  setPendoConfig(PendoConfig);
37970
38231
  overwriteBuiltConfigWithPendoConfig();
@@ -37972,6 +38233,9 @@ function initAgent(pendo, PendoConfig) {
37972
38233
  return false;
37973
38234
  if (pendo && pendo.VERSION)
37974
38235
  return false;
38236
+ if (sniffer.isChromeExtension && !isConfiguredForMV3(PendoConfig)) {
38237
+ console.warn('Pendo Agent detected running in a Chrome extension with setup that is incompatible with manifest V3. Please follow the linked instructions to maintain manifest V3 compatibility: https://www.npmjs.com/package/@pendo/agent#manifest-v3-extensions');
38238
+ }
37975
38239
  if (ConfigReader.get('disablePendo')) {
37976
38240
  stubSnippetMethods(pendo);
37977
38241
  return false;
@@ -40882,8 +41146,8 @@ function stringifyStylesheet(s2) {
40882
41146
  return null;
40883
41147
  }
40884
41148
  let sheetHref = s2.href;
40885
- if (!sheetHref && s2.ownerNode && s2.ownerNode.ownerDocument) {
40886
- sheetHref = s2.ownerNode.ownerDocument.baseURI;
41149
+ if (!sheetHref && s2.ownerNode) {
41150
+ sheetHref = s2.ownerNode.baseURI;
40887
41151
  }
40888
41152
  const stringifiedRules = Array.from(
40889
41153
  rules2,