{"version":3,"file":"refapp-video.umd.js","sources":["../../src/components/base/prop-definitions.js","../../../shared/eventsTracking.js","../../src/lib/tagging/mixin.js","../../src/components/base/provider.vue","../../src/components/base/video.vue","../../src/components/base/content.vue","../../src/components/base/controls.vue","../../src/components/refapp-video.vue","../../src/widget.js"],"sourcesContent":["export const tagging = {\n  taggingId: {\n    type: String,\n    required: true,\n  },\n};\n\nexport const content = {\n  headingLevel: {\n    type: Number,\n    default: 3,\n  },\n  heading: {\n    type: String,\n    required: false,\n    default: null,\n  },\n  text: {\n    type: String,\n    required: false,\n    default: null,\n  },\n  ctalink: {\n    type: String,\n    required: false,\n    default: null,\n  },\n  ctatext: {\n    type: String,\n    required: false,\n    default: null,\n  },\n  alignment: {\n    type: String,\n    required: false,\n    default: 'center',\n  },\n  display: {\n    type: Object,\n    required: false,\n    default: () => ({\n      headingFont: 'sans',\n      contentFont: 'serif',\n    }),\n  },\n};\n\nexport const video = {\n  loop: {\n    type: Boolean,\n    default: false,\n  },\n  autoplay: {\n    type: Boolean,\n    default: false,\n  },\n  muted: {\n    type: Boolean,\n    default: true,\n  },\n  /**\n   * Sample source\n   * {\n   *   src: 'assets/video1.mp4',\n   *   type: 'video/mp4',\n   *   screenSize: 'sm',\n   * }\n   * Where screensizes are: sm (360p) | md (720p) | lg (1080p+)\n   * NB: at present size entries MUST BE IN ASCENDING ORDER\n   */\n  sources: {\n    required: true,\n    validator(value) {\n      return (\n        Array.isArray(value) &&\n        value.every((source) => ['src', 'type', 'screenSize'].every((key) => key in source))\n      );\n    },\n  },\n  controls: {\n    type: Boolean,\n    required: false,\n    default: false,\n  },\n  poster: {\n    type: String,\n    required: false,\n    default: '',\n  },\n};\n","export default class EventsTracking {\n  /**\n   * This class aims to remove code duplication among components by moving most of the tracking\n   * logic in one place and exposing generic methods that these components may consume in whatever\n   * manner they need.\n   * @param {String} taggingId String id used to identify a component and its tracking config\n   * @param {Object} componentInstance Execution scope of the component\n   * @returns {void}\n   */\n  constructor(taggingId, componentInstance) {\n    const brandLevelTaggingConfig = document.querySelector(\n      `[data-brand-level-tagging-id=\"${taggingId}\"]`,\n    );\n    const instanceTaggingConfig = document.getElementById(taggingId);\n    if (!instanceTaggingConfig) return;\n\n    const taggingConfiguration = this.tryParseJson(instanceTaggingConfig.textContent.trim());\n    let brandLevelTaggingConfiguration = {};\n    if (brandLevelTaggingConfig) {\n      brandLevelTaggingConfiguration = this.tryParseJson(\n        brandLevelTaggingConfig.textContent.trim(),\n      );\n    }\n\n    const trackedEvents = Object.keys(taggingConfiguration);\n\n    if (!taggingConfiguration || trackedEvents.length === 0) return;\n\n    const taggableComponent = document.querySelector(`[data-refapp-tagging-id=\"${taggingId}\"]`);\n    trackedEvents.forEach((event) =>\n      this.trackerInit(\n        taggableComponent,\n        taggingConfiguration[event],\n        brandLevelTaggingConfiguration[event],\n        event,\n        componentInstance[`${event}TrackerOptions`],\n      ),\n    );\n  }\n\n  /**\n   * The tracker init function assigns event listeners according to the configuration supplied\n   * @param {HTMLElement} taggableComponent Element to which the listener is to be added\n   * @param {Object} trackerConfig Configuration object for this particular event\n   * @param {Object} brandLevelConfig Addon configuration object for the brand level will be merged\n   * @param {String} eventName name of the HTML event to attach a listener to\n   * @param {Object} handlerOptions HTML event listener options, default values use capture phase\n   *                                and the listener is only executed once\n   * @returns {void}\n   */\n  trackerInit(\n    taggableComponent,\n    trackerConfig,\n    brandLevelConfig,\n    eventName,\n    handlerOptions = { capture: true, once: true },\n  ) {\n    if (!taggableComponent) return;\n\n    // monitor slider movement events, whichever the user interaction source\n    taggableComponent.addEventListener(\n      eventName,\n      this.handleEvent.bind(this, eventName, trackerConfig, brandLevelConfig),\n      handlerOptions,\n    );\n  }\n\n  /**\n   * Event handler passed to each of the tracked events\n   * @param {String} trackedEvent Name of the tracked event\n   * @param {Array} trackerConfig Array of same-type events\n   * @param {Array=} brandLevelConfig Array of brand-level properties to merge in the final event\n   * @param {Event} e Event instance received by the handler function\n   * @returns {void}\n   */\n  handleEvent(trackedEvent, trackerConfig, brandLevelConfig = [], e) {\n    const element = e.target.closest('[data-refapp-tagging-target]');\n    if (!element) return;\n\n    const taggingTarget = element.dataset?.refappTaggingTarget;\n\n    if (!taggingTarget) return;\n    const event = trackerConfig.find((c) => c.target === taggingTarget);\n    const extras = this.tryParseJson(e.target.dataset?.refappTaggingExtras);\n    const brandEvent = brandLevelConfig.find((c) => c.target === taggingTarget);\n\n    if (!event) return;\n\n    window.dataLayer = [\n      ...(window.dataLayer || []),\n      {\n        ...event.payload,\n        ...extras,\n        ...(brandEvent ? brandEvent.payload : {}),\n      },\n    ];\n  }\n\n  /**\n   * Utility function that attempts to parse a JSON string into a JS object\n   * @param {String} jsonString String to attempt to parse into a json object\n   * @returns {Object}\n   */\n  tryParseJson = (jsonString) => {\n    try {\n      return JSON.parse(jsonString);\n    } catch (e) {\n      return {};\n    }\n  };\n}\n","import EventsTracking from '../../../../shared/eventsTracking';\n\nexport default {\n  mounted() {\n    const { taggingId } = this;\n\n    this.clickTrackerOptions = { capture: false, once: false };\n    this.playbackTrackerOptions = { capture: true, once: true };\n    this.tracking = new EventsTracking(taggingId, this);\n  },\n};\n","<script setup>\n/**\n * HACK:\n * This empty script is required to make nested components work in Vue 3\n * while keeping compatibility with Vue 2 intact.\n */\n</script>\n\n<script>\nimport { computed } from 'vue';\nimport * as propDefs from './prop-definitions';\nimport tagging from '../../lib/tagging/mixin';\n\nconst { video: videoProps, content: contentProps, tagging: taggingProps } = propDefs;\n\nconst props = {\n  ...videoProps,\n  ...contentProps,\n  ...taggingProps,\n};\n\nexport default {\n  name: 'refapp-video-provider',\n  mixins: [tagging],\n  provide() {\n    return Object.keys(props).reduce((acc, curr) => {\n      acc[curr] = computed(() => this[curr]);\n      return acc;\n    }, {});\n  },\n  props,\n  render() {\n    const isVue3Slot = this.$slots.default instanceof Function;\n\n    if (isVue3Slot) {\n      return this.$slots.default();\n    }\n\n    return this.$slots.default;\n  },\n};\n</script>\n","<template>\n  <div v-if=\"canRender\" class=\"refapp-video\" :data-refapp-tagging-id=\"taggingId\">\n    <video\n      ref=\"refappVideo\"\n      :autoplay=\"autoplay\"\n      :muted=\"muted\"\n      :loop=\"loop\"\n      class=\"refapp-video__media\"\n      :poster=\"poster\"\n      disablePictureInPicture\n      playsinline\n      data-refapp-tagging-target=\"video\"\n    >\n      <source\n        v-for=\"s in sources\"\n        :key=\"s.src\"\n        :src=\"s.src\"\n        :type=\"s.type\"\n        :media=\"getSourceMediaQuery(s.screenSize)\"\n      />\n    </video>\n\n    <slot\n      name=\"controls\"\n      :muted=\"muted\"\n      :autoplay=\"autoplay\"\n      :controls=\"controls\"\n      :toggle-playback=\"togglePlayback\"\n      :toggle-audio=\"toggleAudio\"\n    />\n\n    <slot name=\"content\" />\n  </div>\n</template>\n\n<script setup>\n/**\n * HACK:\n * This empty script is required to make nested components work in Vue 3\n * while keeping compatibility with Vue 2 intact.\n */\n</script>\n\n<script>\nconst PLAYBACK_CLASS = 'refapp-video__controls-playback--paused';\n\n// sm (360p) | md (720p) | lg (1080p+)\nconst mediaQueries = {\n  sm: '(max-width:640px)',\n  md: '(max-width:1280px)',\n  lg: null,\n};\n\nexport default {\n  name: 'refapp-video-base',\n  inject: ['sources', 'autoplay', 'muted', 'loop', 'poster', 'controls', 'taggingId'],\n  data() {\n    return {\n      canRender: this.sources.some((src) => !!src),\n    };\n  },\n  mounted() {\n    const { refappVideo: video } = this.$refs;\n\n    if (!video) return;\n\n    const playbackControls = document.querySelector('.refapp-video__controls-playback');\n\n    const observer = new IntersectionObserver(\n      (entries) => {\n        entries.forEach((entry) => {\n          if (!entry.isIntersecting) {\n            video.pause();\n            playbackControls?.classList.add(PLAYBACK_CLASS);\n            return;\n          }\n\n          if (this.autoplay) {\n            video.play();\n            playbackControls?.classList.remove(PLAYBACK_CLASS);\n          }\n        });\n      },\n      {\n        rootMargin: '0px',\n        threshold: 0.1,\n      },\n    );\n\n    this.observer = observer;\n\n    observer.observe(video);\n  },\n\n  unmounted() {\n    const { refappVideo: video } = this.$refs;\n    video && this.observer.unobserve(video);\n  },\n\n  methods: {\n    togglePlayback(button) {\n      const { refappVideo: video } = this.$refs;\n      const isPlaybackStopped = video.paused || video.stopped;\n\n      const PLAYBACK_MODIFIER_CLASS = 'refapp-video__controls-playback--paused';\n      button.classList[isPlaybackStopped ? 'remove' : 'add'](PLAYBACK_MODIFIER_CLASS);\n\n      isPlaybackStopped ? video.play() : video.pause();\n    },\n\n    toggleAudio(button) {\n      const { refappVideo: video } = this.$refs;\n\n      const AUDIO_MODIFIER_CLASS = 'refapp-video__controls-audio--muted';\n      button.classList[video.muted ? 'remove' : 'add'](AUDIO_MODIFIER_CLASS);\n\n      video.muted = !video.muted;\n    },\n\n    getSourceMediaQuery(size) {\n      // do not apply a mediaquery if the requested size is not interpretable\n      if (!(size in mediaQueries)) return null;\n      return mediaQueries[size];\n    },\n  },\n};\n</script>\n","<template>\n  <div\n    v-if=\"heading || ctalink\"\n    :class=\"`refapp-video__content refapp-video__content--${alignment} font-${display.contentFont}`\"\n  >\n    <div>\n      <slot>\n        <component\n          :is=\"`h${headingLevel}`\"\n          v-if=\"heading\"\n          :class=\"`refapp-video__content-heading font-${display.headingFont}`\"\n        >\n          {{ heading }}\n        </component>\n\n        <p v-if=\"text\" class=\"refapp-video__content-text\">\n          {{ text }}\n        </p>\n      </slot>\n    </div>\n\n    <a\n      v-if=\"ctalink && ctatext\"\n      class=\"refapp-video__content-cta\"\n      :href=\"ctalink\"\n      target=\"_blank\"\n      data-refapp-tagging-target=\"cta\"\n    >\n      {{ ctatext }}\n    </a>\n  </div>\n</template>\n\n<script setup>\n/**\n * HACK:\n * This empty script is required to make nested components work in Vue 3\n * while keeping compatibility with Vue 2 intact.\n */\n</script>\n\n<script>\nexport default {\n  name: 'refapp-video-content',\n  inject: ['heading', 'headingLevel', 'text', 'ctalink', 'ctatext', 'alignment', 'display'],\n};\n</script>\n","<template>\n  <div v-if=\"controls\" class=\"refapp-video__controls\">\n    <button\n      ref=\"playbackControls\"\n      data-refapp-tagging-target=\"playbackControls\"\n      :class=\"{\n        'refapp-video__controls-playback': true,\n        'refapp-video__controls-playback--paused': !autoplay,\n      }\"\n      aria-label=\"Play / Pause\"\n      @click=\"(e) => $emit('playback', e.target)\"\n    ></button>\n    <button\n      ref=\"audioControls\"\n      data-refapp-tagging-target=\"audioControls\"\n      :class=\"{\n        'refapp-video__controls-audio': true,\n        'refapp-video__controls-audio--muted': muted,\n      }\"\n      aria-label=\"Audio on/ off\"\n      @click=\"(e) => $emit('audio', e.target)\"\n    ></button>\n  </div>\n</template>\n\n<script setup>\n/**\n * HACK:\n * This empty script is required to make nested components work in Vue 3\n * while keeping compatibility with Vue 2 intact.\n */\n</script>\n\n<script>\nexport default {\n  name: 'refapp-video-controls',\n  inject: ['muted', 'autoplay', 'controls'],\n};\n</script>\n","<template>\n  <refapp-video-base>\n    <template #controls=\"{ togglePlayback, toggleAudio }\">\n      <refapp-video-controls @playback=\"togglePlayback\" @audio=\"toggleAudio\" />\n    </template>\n    <template #content>\n      <refapp-video-content><slot></slot></refapp-video-content>\n    </template>\n  </refapp-video-base>\n</template>\n\n<script setup>\n/**\n * HACK:\n * This empty script is required to make nested components work in Vue 3\n * while keeping compatibility with Vue 2 intact.\n */\n</script>\n\n<script>\nimport RefappVideoContent from './base/content.vue';\nimport RefappVideoControls from './base/controls.vue';\nimport RefappVideoBase from './base/video.vue';\n\nexport default {\n  name: 'refapp-video',\n  components: {\n    RefappVideoControls,\n    RefappVideoContent,\n    RefappVideoBase,\n  },\n};\n</script>\n<style lang=\"scss\" src=\"../styles/entry.scss\"></style>\n","import RefappVideoProvider from './components/base/provider.vue';\nimport RefappVideoBase from './components/base/video.vue';\nimport RefappVideo from './components/refapp-video.vue';\n\nexport default {\n  install(app) {\n    const components = [RefappVideoProvider, RefappVideoBase, RefappVideo];\n    components.forEach((c) => app.component(c.name, c));\n  },\n};\n"],"names":["value","source","key","EventsTracking","taggingId","componentInstance","__publicField","jsonString","brandLevelTaggingConfig","instanceTaggingConfig","taggingConfiguration","brandLevelTaggingConfiguration","trackedEvents","taggableComponent","event","trackerConfig","brandLevelConfig","eventName","handlerOptions","trackedEvent","e","element","taggingTarget","_a","c","extras","_b","brandEvent","tagging","videoProps","contentProps","taggingProps","propDefs","props","acc","curr","computed","PLAYBACK_CLASS","mediaQueries","src","video","playbackControls","observer","entries","entry","button","isPlaybackStopped","size","RefappVideoControls","RefappVideoContent","RefappVideoBase","app","RefappVideoProvider","RefappVideo"],"mappings":"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"}