{"version":3,"file":"FirstInteractionInstrumentation.cjs","names":["EmbraceInstrumentationBase","getSelector","KEY_EMB_TYPE","ATTR_FIRST_INTERACTION_INTERACTION_TYPE","ATTR_FIRST_INTERACTION_ELEMENT_TYPE","ATTR_FIRST_INTERACTION_ELEMENT_SELECTOR","ATTR_FIRST_INTERACTION_TIME","ATTR_FIRST_INTERACTION_X","ATTR_FIRST_INTERACTION_Y","FIRST_INTERACTION_EVENT_NAME","SeverityNumber"],"sources":["../../../../src/instrumentations/first-interaction/FirstInteractionInstrumentation/FirstInteractionInstrumentation.ts"],"sourcesContent":["import { SeverityNumber } from '@opentelemetry/api-logs';\nimport { EMB_TYPES, KEY_EMB_TYPE } from '../../../constants/attributes.ts';\nimport { getSelector } from '../../../utils/index.ts';\nimport { EmbraceInstrumentationBase } from '../../EmbraceInstrumentationBase/index.ts';\nimport type { FirstInteractionType } from './constants.ts';\nimport {\n  ATTR_FIRST_INTERACTION_ELEMENT_SELECTOR,\n  ATTR_FIRST_INTERACTION_ELEMENT_TYPE,\n  ATTR_FIRST_INTERACTION_INTERACTION_TYPE,\n  ATTR_FIRST_INTERACTION_TIME,\n  ATTR_FIRST_INTERACTION_X,\n  ATTR_FIRST_INTERACTION_Y,\n  FIRST_INTERACTION_EVENT_NAME,\n} from './constants.ts';\nimport type { FirstInteractionInstrumentationArgs } from './types.ts';\n\ninterface InteractionData {\n  interactionType: FirstInteractionType;\n  target: Element | null;\n  timestamp: number;\n  x?: number;\n  y?: number;\n}\n\n/*\n  Captures the first user input event in each session part and emits one log\n  per part. Listeners are detached after the first event is logged.\n*/\nexport class FirstInteractionInstrumentation extends EmbraceInstrumentationBase {\n  private readonly _onClick: (event: PointerEvent) => void;\n  private readonly _onKeyDown: (event: KeyboardEvent) => void;\n  private readonly _onScroll: (event: Event) => void;\n  private _listenersAttached = false;\n\n  public constructor({ diag, perf }: FirstInteractionInstrumentationArgs = {}) {\n    super({\n      instrumentationName: 'FirstInteractionInstrumentation',\n      instrumentationVersion: '1.0.0',\n      diag,\n      perf,\n      config: {},\n    });\n\n    this._onClick = (event: PointerEvent): void => {\n      this._handle({\n        interactionType: event.pointerType === 'touch' ? 'tap' : 'click',\n        target: event.target instanceof Element ? event.target : null,\n        timestamp: event.timeStamp,\n        x: event.clientX,\n        y: event.clientY,\n      });\n    };\n\n    this._onKeyDown = (event: KeyboardEvent): void => {\n      this._handle({\n        interactionType: 'keypress',\n        target: event.target instanceof Element ? event.target : null,\n        timestamp: event.timeStamp,\n      });\n    };\n\n    this._onScroll = (event: Event): void => {\n      this._handle({\n        interactionType: 'scroll',\n        target: null,\n        timestamp: event.timeStamp,\n      });\n    };\n\n    if (this._config.enabled) {\n      this.enable();\n    }\n  }\n\n  public override onEnable(): void {\n    this._attachListeners();\n    this.setSessionPartListeners({\n      start: () => {\n        this._attachListeners();\n      },\n    });\n  }\n\n  public override onDisable(): void {\n    this._detachListeners();\n  }\n\n  private _handle(data: InteractionData): void {\n    if (!this._listenersAttached) {\n      // It's possible two handlers fire in quick succession before the listeners\n      // are detached. We only want to process the first one.\n      return;\n    }\n\n    this._detachListeners();\n\n    try {\n      this._emit(data);\n    } catch (e) {\n      this._diag.error('failed to process first-interaction candidate', e);\n    }\n  }\n\n  private _attachListeners(): void {\n    if (this._listenersAttached) {\n      return;\n    }\n\n    const opts: AddEventListenerOptions = { capture: true, passive: true };\n\n    document.addEventListener('click', this._onClick, opts);\n    document.addEventListener('keydown', this._onKeyDown, opts);\n    document.addEventListener('scroll', this._onScroll, opts);\n\n    this._listenersAttached = true;\n  }\n\n  private _detachListeners(): void {\n    if (!this._listenersAttached) {\n      return;\n    }\n\n    const opts: EventListenerOptions = { capture: true };\n\n    document.removeEventListener('click', this._onClick, opts);\n    document.removeEventListener('keydown', this._onKeyDown, opts);\n    document.removeEventListener('scroll', this._onScroll, opts);\n\n    this._listenersAttached = false;\n  }\n\n  private _emit(data: InteractionData): void {\n    let elementType = 'document';\n    let elementSelector = '';\n\n    if (data.interactionType !== 'scroll' && data.target) {\n      elementType = data.target.tagName.toLowerCase();\n      elementSelector = getSelector(data.target);\n    }\n\n    const attributes: Record<string, string | number> = {\n      [KEY_EMB_TYPE]: EMB_TYPES.OTelLog,\n      [ATTR_FIRST_INTERACTION_INTERACTION_TYPE]: data.interactionType,\n      [ATTR_FIRST_INTERACTION_ELEMENT_TYPE]: elementType,\n      [ATTR_FIRST_INTERACTION_ELEMENT_SELECTOR]: elementSelector,\n      [ATTR_FIRST_INTERACTION_TIME]: this.perf.millisFromZeroTime(\n        data.timestamp,\n      ),\n    };\n\n    if (data.x !== undefined && data.y !== undefined) {\n      attributes[ATTR_FIRST_INTERACTION_X] = data.x;\n      attributes[ATTR_FIRST_INTERACTION_Y] = data.y;\n    }\n\n    this.logger.emit({\n      timestamp: this.perf.epochMillisFromOrigin(data.timestamp),\n      eventName: FIRST_INTERACTION_EVENT_NAME,\n      severityNumber: SeverityNumber.INFO,\n      attributes,\n    });\n  }\n}\n"],"mappings":";;;;;;;AA4BA,IAAa,kCAAb,cAAqDA,+EAAAA,2BAA2B;CAC9E;CACA;CACA;CACA,qBAA6B;CAE7B,YAAmB,EAAE,MAAM,SAA8C,CAAC,GAAG;EAC3E,MAAM;GACJ,qBAAqB;GACrB,wBAAwB;GACxB;GACA;GACA,QAAQ,CAAC;EACX,CAAC;EAED,KAAK,YAAY,UAA8B;GAC7C,KAAK,QAAQ;IACX,iBAAiB,MAAM,gBAAgB,UAAU,QAAQ;IACzD,QAAQ,MAAM,kBAAkB,UAAU,MAAM,SAAS;IACzD,WAAW,MAAM;IACjB,GAAG,MAAM;IACT,GAAG,MAAM;GACX,CAAC;EACH;EAEA,KAAK,cAAc,UAA+B;GAChD,KAAK,QAAQ;IACX,iBAAiB;IACjB,QAAQ,MAAM,kBAAkB,UAAU,MAAM,SAAS;IACzD,WAAW,MAAM;GACnB,CAAC;EACH;EAEA,KAAK,aAAa,UAAuB;GACvC,KAAK,QAAQ;IACX,iBAAiB;IACjB,QAAQ;IACR,WAAW,MAAM;GACnB,CAAC;EACH;EAEA,IAAI,KAAK,QAAQ,SACf,KAAK,OAAO;CAEhB;CAEA,WAAiC;EAC/B,KAAK,iBAAiB;EACtB,KAAK,wBAAwB,EAC3B,aAAa;GACX,KAAK,iBAAiB;EACxB,EACF,CAAC;CACH;CAEA,YAAkC;EAChC,KAAK,iBAAiB;CACxB;CAEA,QAAgB,MAA6B;EAC3C,IAAI,CAAC,KAAK,oBAGR;EAGF,KAAK,iBAAiB;EAEtB,IAAI;GACF,KAAK,MAAM,IAAI;EACjB,SAAS,GAAG;GACV,KAAK,MAAM,MAAM,iDAAiD,CAAC;EACrE;CACF;CAEA,mBAAiC;EAC/B,IAAI,KAAK,oBACP;EAGF,MAAM,OAAgC;GAAE,SAAS;GAAM,SAAS;EAAK;EAErE,SAAS,iBAAiB,SAAS,KAAK,UAAU,IAAI;EACtD,SAAS,iBAAiB,WAAW,KAAK,YAAY,IAAI;EAC1D,SAAS,iBAAiB,UAAU,KAAK,WAAW,IAAI;EAExD,KAAK,qBAAqB;CAC5B;CAEA,mBAAiC;EAC/B,IAAI,CAAC,KAAK,oBACR;EAGF,MAAM,OAA6B,EAAE,SAAS,KAAK;EAEnD,SAAS,oBAAoB,SAAS,KAAK,UAAU,IAAI;EACzD,SAAS,oBAAoB,WAAW,KAAK,YAAY,IAAI;EAC7D,SAAS,oBAAoB,UAAU,KAAK,WAAW,IAAI;EAE3D,KAAK,qBAAqB;CAC5B;CAEA,MAAc,MAA6B;EACzC,IAAI,cAAc;EAClB,IAAI,kBAAkB;EAEtB,IAAI,KAAK,oBAAoB,YAAY,KAAK,QAAQ;GACpD,cAAc,KAAK,OAAO,QAAQ,YAAY;GAC9C,kBAAkBC,0BAAAA,YAAY,KAAK,MAAM;EAC3C;EAEA,MAAM,aAA8C;IACjDC,6BAAAA,eAAAA;IACAC,qFAAAA,0CAA0C,KAAK;IAC/CC,qFAAAA,sCAAsC;IACtCC,qFAAAA,0CAA0C;IAC1CC,qFAAAA,8BAA8B,KAAK,KAAK,mBACvC,KAAK,SACP;EACF;EAEA,IAAI,KAAK,MAAM,KAAA,KAAa,KAAK,MAAM,KAAA,GAAW;GAChD,WAAWC,qFAAAA,4BAA4B,KAAK;GAC5C,WAAWC,qFAAAA,4BAA4B,KAAK;EAC9C;EAEA,KAAK,OAAO,KAAK;GACf,WAAW,KAAK,KAAK,sBAAsB,KAAK,SAAS;GACzD,WAAWC,qFAAAA;GACX,gBAAgBC,wBAAAA,eAAe;GAC/B;EACF,CAAC;CACH;AACF"}