{"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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"}