@adhese/sdk 1.3.2 → 1.3.3-nightly-20241115134641

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @adhese/sdk
2
2
 
3
+ ## 1.3.3-nightly-20241115134641
4
+
5
+ ### Patch Changes
6
+
7
+ - 177bb55: Make sure that the clean element function does not work when rendeMode is none
8
+
3
9
  ## 1.3.2
4
10
 
5
11
  ### Patch Changes
@@ -218,17 +218,16 @@ function createSlot(slotOptions) {
218
218
  }
219
219
  }
220
220
  function cleanElement() {
221
- if (!element.value)
221
+ if (!element.value || renderMode === "none")
222
222
  return;
223
223
  element.value.innerHTML = "";
224
224
  element.value.style.position = "";
225
- data.value = null;
226
- originalData.value = null;
227
225
  }
228
226
  function dispose() {
229
227
  cleanElement();
230
228
  element.value = null;
231
229
  data.value = null;
230
+ originalData.value = null;
232
231
  domObserver.disconnect();
233
232
  runOnDispose();
234
233
  isDisposed.value = true;
@@ -1 +1 @@
1
- {"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(Object.entries(slotOptions).filter(([,value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(initialData) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\n return;\n\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n }\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n return response;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n runOnEmpty();\n\n return null;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\n }\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\n }\n }\n\n function cleanElement(): void {\n if (!element.value)\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n\n data.value = null;\n originalData.value = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\n });\n\n context.hooks.onInit(async () => {\n status.value = 'initialized';\n\n runOnInit();\n\n if (initialData) {\n status.value = 'loaded';\n return;\n }\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = await slotContext.value?.request() ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["renderIframe","renderInline","doNothing","effectScope","ref","uniqueId","useSlotHooks","reactive","useQueryDetector","computed","generateName","watch","useDomLoaded","shallowRef","useRenderIntersectionObserver","useViewabilityObserver","addTrackingPixel","extRequestAd","logger","waitForDomLoad","pick","omit"],"mappings":"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"}
1
+ {"version":3,"file":"slot.cjs","sources":["../../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(Object.entries(slotOptions).filter(([,value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(initialData) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\n return;\n\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n }\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n return response;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n runOnEmpty();\n\n return null;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\n }\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\n }\n }\n\n function cleanElement(): void {\n if (!element.value || renderMode === 'none')\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n originalData.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\n });\n\n context.hooks.onInit(async () => {\n status.value = 'initialized';\n\n runOnInit();\n\n if (initialData) {\n status.value = 'loaded';\n return;\n }\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = await slotContext.value?.request() ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["renderIframe","renderInline","doNothing","effectScope","ref","uniqueId","useSlotHooks","reactive","useQueryDetector","computed","generateName","watch","useDomLoaded","shallowRef","useRenderIntersectionObserver","useViewabilityObserver","addTrackingPixel","extRequestAd","logger","waitForDomLoad","pick","omit"],"mappings":";;;;;;;AAgCA,MAAM,kBAAyF;AAAA,EAC7F,QAAQA,UAAA;AAAA,EACR,QAAQC,UAAA;AAAA,EACR,MAAMC,UAAA;AACR;AAEA,MAAM,iBAAiB;AAAA,EACrB,YAAY;AAAA,EACZ,MAAM;AACR;AASO,SAAS,WAAW,aAA4C;AACrE,QAAM,QAAQC,UAAAA;AAEP,SAAA,MAAM,IAAI,MAAM;AACf,UAAA,cAAcC,cAA8B,IAAI;AACtD,UAAM,UAAU,YAAY,QAAQ,MAAM,gBAAgB;AAAA,MACxD,GAAG;AAAA,MACH,GAAI,OAAO,YAAY,OAAO,QAAQ,WAAW,EAAE,OAAO,CAAC,CAAE,EAAA,KAAK,MAAM,UAAU,MAAS,CAAC;AAAA,IAAA,CAC7F;AAEK,UAAA;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,aAAa;AAAA,MACb,OAAO;AAAA,IACL,IAAA;AAEJ,UAAM,KAAKC,UAAAA;AACL,UAAA;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IAAA,IACDC,iBAAa,aAAA,SAAS,WAAW;AAE/B,UAAA,aAAaF,cAAI,KAAK;AACtB,UAAA,aAAaG,UAAAA,SAAS,IAAI,IAAI,OAAO,QAAQ,QAAQ,cAAc,EAAE,CAAC,CAAC;AAEvE,UAAA,CAAC,QAAQ,oBAAoB,IAAIC,cAAAA,iBAAiB,SAAS,OAAO,QAAQ,WAAW,WACvF;AAAA,MACE,CAAC,QAAQ,MAAM,GAAG;AAAA,IAEpB,IAAA,OAAO,YAAY,QAAQ,OAAO,IAAI,CAAA,SAAQ,CAAC,KAAK,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC;AAEvE,UAAA,SAASC,UAAAA,SAAS,MAAM,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,OAAO,KAAK;AAE1F,UAAA,OAAOL,cAAqB,WAAW;AACvC,UAAA,eAAeA,UAAAA,IAAI,KAAK,KAAK;AAC7B,UAAA,OAAOK,UAAAA,SAAS,MAAMC,UAAAA,aAAa,QAAQ,QAAQ,UAAU,OAAO,OAAO,QAAQ,IAAI,CAAC;AAExF,UAAA,SAASN,cAAqC,cAAc;AAE5DO,cAAAA,MAAA,MAAM,OAAO,SAAS,YAAY;;AACtC,UAAI,YAAY;AACd;AAEF,YAAM,QAAQ,QAAM,iBAAY,UAAZ,mBAAmB;AAEvC,UAAI,CAAC;AACH;AAEF,wBAAY,UAAZ,mBAAmB;AAEnB,WAAK,QAAQ;AACb,mBAAa,QAAQ;AAAA,IAAA,CACtB;AAEK,UAAA,cAAcC,8BAAa,OAAO;AAElC,UAAA,UAAUC,qBAA+B,IAAI;AAEnD,aAAS,aAAiC;AACxC,UAAI,EAAE,OAAO,QAAQ,sBAAsB,YAAY,CAAC,QAAQ;AAC9D,eAAO,QAAQ;AAEjB,UAAI,CAAC,YAAY;AACR,eAAA;AAET,aAAO,SAAS,cAA2B,IAAI,QAAQ,iBAAiB,EAAE;AAAA,IAC5E;AAEMF,cAAAA,MAAA,SAAS,OAAO,YAAY,eAAe;AAC3C,UAAA,OAAO,UAAU,WAAW,OAAO,UAAU,WAAW,OAAO,UAAU,WAAW;AACtF;AAAA,MACF;AAEI,UAAA,eAAe,QAAQ,KAAK,OAAO;AACrC,eAAO,QAAQ;AAEf;AAAA,MACF;AAEA,UAAI,eAAe,cAAe,eAAe,QAAQ,eAAe;AACtE;AAEF,YAAM,OAAO;AAAA,IAAA,CACd;AAEK,UAAA,cAAc,IAAI,iBAAiB,MAAM;AAC7C,cAAQ,QAAQ;IAAW,CAC5B;AAEW,gBAAA,QAAQ,SAAS,MAAM;AAAA,MACjC,WAAW;AAAA,MACX,SAAS;AAAA,IAAA,CACV;AAEDA,cAAA;AAAA,MACE;AAAA,MACA,MAAM;AACJ,gBAAQ,QAAQ;MAClB;AAAA,MACA,EAAE,WAAW,MAAM,MAAM,KAAK;AAAA,IAAA;AAGhC,UAAM,eAAeG,iBAAAA,8BAA8B;AAAA,MACjD;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAEKH,oBAAA,cAAc,OAAO,oBAAoB;;AACzC,UAAA,mBAAmB,OAAO,UAAU;AAChC,gBAAA,iBAAY,UAAZ,mBAAmB;AAAA,IAAO,GACjC,EAAE,WAAW,KAAA,CAAM;AAEtB,UAAM,UAAU,MAAM;AACC;IAAA,CACtB;AAED,UAAM,uBAAuBI,iBAAAA,uBAAuB;AAAA,MAClD;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,eAAe;;AACnB,aAAA,uBAAY,UAAZ,mBAAmB,SAAnB,mBAAyB,2BAA2B;AACtD,wBAAc,QAAQC,4BAAiB,uBAAY,UAAZ,mBAAmB,SAAnB,mBAAyB,yBAAyB;AAEzF,kBAAQ,OAAO,MAAM,yCAAwC,iBAAY,UAAZ,mBAAmB,IAAI,EAAE;AAAA,QACxF;AAAA,MACF;AAAA,IAAA,CACD;AAEK,UAAA,iCAAiCZ,cAA6B,IAAI;AAClE,UAAA,sBAAsBA,cAAI,KAAK;AACrC,UAAM,UAAU,MAAM;AACpB,UAAI,+BAA+B;AACjC,uCAA+B,MAAM;IAAO,CAC/C;AACKO,cAAAA,MAAA,QAAQ,OAAO,WAAW,cAAc;;AACxC,UAAA,cAAc,YAAY,cAAc,YAAY;AACtD,6CAA+B,UAA/B,mBAAsC;AACtC,uCAA+B,QAAQ;AAAA,MACzC;AAAA,IAAA,CACD;AAED,mBAAe,UAAoC;AAC7C,UAAA;AACE,YAAA,QAAQ,eAAe,CAAC,aAAa;AAChC,iBAAA;AAET,eAAO,QAAQ;AAEX,YAAA,WAAW,MAAM,mBAAmB,IAAI;AAE5C,YAAI,CAAC,UAAU;AACb,qBAAW,MAAMM,WAAAA,UAAa;AAAA,YAC5B,MAAM;AAAA,cACJ,MAAM,KAAK;AAAA,cACX;AAAA,YACF;AAAA,YACA;AAAA,UAAA,CACD;AAAA,QACH;AAEI,YAAA;AACS,qBAAA,MAAM,aAAa,QAAQ;AAExC,aAAK,QAAQ;AAEb,YAAI,CAAC,aAAa;AAChB,uBAAa,QAAQ;AAEhB,eAAA,QAAQ,WAAW,WAAW;AAErC,YAAI,CAAC;AACU;AAER,eAAA;AAAA,eAEF,OAAO;AACZ,eAAO,QAAQ;AAEfC,eAAA,OAAO,MAAM,gCAAgC,KAAK,KAAK,IAAI,KAAK;AAErD,mBAAA,IAAI,MAAM,gCAAgC,KAAK,KAAK,IAAI,EAAE,OAAO,MAAM,CAAC,CAAC;AAE7E,eAAA;AAAA,MACT;AAAA,IACF;AAEA,mBAAe,OAAO,YAAoD;AACpE,UAAA;AACE,YAAA,QAAQ,eAAe,CAAC,aAAa;AAChC,iBAAA;AAET,eAAO,QAAQ;AACf,cAAMC,UAAe,eAAA;AACrB,gBAAQ,QAAQ;AAEhB,YAAI,WAAW,cAAc,KAAK,SAAS,aAAa,SAAS,MAAM;AAE5D,mBAAA,YAAY,MAAM,kBAAkB,QAAQ;AAEvD,YAAI,CAAC,QAAQ,SAAS,eAAe,QAAQ;AAC3CD,wBAAO,MAAM,oCAAoC,OAAO,KAAK,uBAAuB,YAAY,KAAK;AAE9F,iBAAA;AAAA,QACT;AAEA,YAAI,CAAC,UAAU;AACb,iBAAO,QAAQ;AACfA,iBAAA,OAAO,MAAM,4BAA4B,KAAK,KAAK,EAAE;AAE1C;AAEJ,iBAAA;AAAA,QACT;AAEA,YAAI,QAAO,qCAAU,SAAQ,YAAY,eAAe,QAAQ;AACxD,gBAAA,QAAQ,kCAAkC,KAAK,KAAK;AACnDA,iBAAAA,OAAA,MAAM,OAAO,OAAO;AAErB,gBAAA,IAAI,MAAM,KAAK;AAAA,QACvB;AAEI,YAAA,eAAe,UAAU,QAAQ,OAAO;AAC1C,0BAAgB,UAAU,EAAE;AAAA,YAC1B,GAAG;AAAA,YACH,GAAGE,UAAK,KAAA,SAAS,CAAC,SAAS,QAAQ,CAAC;AAAA,UAAA,GAClB,QAAQ,KAAK;AAAA,QACnC;AAEI,YAAA,SAAS,qBAAqB,CAAC,+BAA+B;AACjC,yCAAA,QAAQJ,UAAAA,iBAAiB,SAAS,iBAAiB;AAEpF,4BAAoB,QAAQ;AAE5BE,eAAA,OAAO,MAAM,iBAAiB,KAAK,KAAK,IAAI;AAAA,UAC1C,iBAAiB;AAAA,UACjB,UAAU,QAAQ;AAAA,UAClB;AAAA,UACA;AAAA,QAAA,CACD;AAED,eAAO,QAAQ;AAEf,oBAAY,QAAQ;AAEpB,eAAO,QAAQ;AAAA,eAEV,OAAO;AACZ,eAAO,QAAQ;AAEfA,eAAA,OAAO,MAAM,GAAG,KAAK,IAAI,OAAO;AAErB,mBAAA,IAAI,MAAM,KAAe,CAAC;AAE9B,eAAA;AAAA,MACT;AAAA,IACF;AAEA,aAAS,eAAqB;AACxB,UAAA,CAAC,QAAQ,SAAS,eAAe;AACnC;AAEF,cAAQ,MAAM,YAAY;AAClB,cAAA,MAAM,MAAM,WAAW;AAAA,IACjC;AAEA,aAAS,UAAgB;AACV;AAEb,cAAQ,QAAQ;AAEhB,WAAK,QAAQ;AACb,mBAAa,QAAQ;AAErB,kBAAY,WAAW;AAEV;AAEb,iBAAW,QAAQ;AAEnB,YAAM,KAAK;AAAA,IACb;AAEA,UAAM,QAAQX,UAAAA,SAAS;AAAA,MACrB,UAAU,QAAQ,YAAY;AAAA,MAC9B,aAAa,QAAQ,eAAe;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAASc,UAAA,KAAK,SAAS,CAAC,SAAS,CAAC;AAAA,MAClC,GAAG;AAAA,IAAA,CACJ;AAEKV,oBAAA,OAAO,CAAC,aAAa;AACzB,kBAAY,QAAQ;AAAA,IAAA,GACnB;AAAA,MACD,MAAM;AAAA,MACN,WAAW;AAAA,IAAA,CACZ;AAEO,YAAA,MAAM,OAAO,YAAY;;AAC/B,aAAO,QAAQ;AAEL;AAEV,UAAI,aAAa;AACf,eAAO,QAAQ;AACf;AAAA,MACF;AAEA,UAAI,QAAQ,aAAa;AACvB;AAAA,MACF;AAEA,WAAK,QAAQ,QAAM,iBAAY,UAAZ,mBAAmB,cAAa;AAAA,IAAA,CACpD;AAEM,WAAA;AAAA,EAAA,CACR;AACH;;"}
package/dist/slot/slot.js CHANGED
@@ -216,17 +216,16 @@ function createSlot(slotOptions) {
216
216
  }
217
217
  }
218
218
  function cleanElement() {
219
- if (!element.value)
219
+ if (!element.value || renderMode === "none")
220
220
  return;
221
221
  element.value.innerHTML = "";
222
222
  element.value.style.position = "";
223
- data.value = null;
224
- originalData.value = null;
225
223
  }
226
224
  function dispose() {
227
225
  cleanElement();
228
226
  element.value = null;
229
227
  data.value = null;
228
+ originalData.value = null;
230
229
  domObserver.disconnect();
231
230
  runOnDispose();
232
231
  isDisposed.value = true;
@@ -1 +1 @@
1
- {"version":3,"file":"slot.js","sources":["../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(Object.entries(slotOptions).filter(([,value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(initialData) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\n return;\n\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n }\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n return response;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n runOnEmpty();\n\n return null;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\n }\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\n }\n }\n\n function cleanElement(): void {\n if (!element.value)\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n\n data.value = null;\n originalData.value = null;\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\n });\n\n context.hooks.onInit(async () => {\n status.value = 'initialized';\n\n runOnInit();\n\n if (initialData) {\n status.value = 'loaded';\n return;\n }\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = await slotContext.value?.request() ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["extRequestAd"],"mappings":"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"}
1
+ {"version":3,"file":"slot.js","sources":["../../src/slot/slot.ts"],"sourcesContent":["import type { AdheseAd } from '@adhese/sdk';\nimport type { AdheseSlot, AdheseSlotContext, AdheseSlotOptions, RenderMode } from './slot.types';\nimport {\n addTrackingPixel,\n computed,\n doNothing,\n effectScope,\n generateName,\n omit,\n pick,\n reactive,\n type Ref,\n ref,\n renderIframe,\n renderInline,\n type RenderOptions,\n shallowRef,\n uniqueId,\n type UnwrapRef,\n waitForDomLoad,\n watch,\n} from '@adhese/sdk-shared';\nimport { logger } from '../logger/logger';\nimport { useQueryDetector } from '../queryDetector/queryDetector';\nimport { requestAd as extRequestAd } from '../requestAds/requestAds';\nimport {\n useDomLoaded,\n useRenderIntersectionObserver,\n useSlotHooks,\n useViewabilityObserver,\n} from './slot.composables';\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n none: doNothing,\n};\n\nconst defaultOptions = {\n renderMode: 'iframe',\n type: 'normal',\n} satisfies Partial<AdheseSlotOptions>;\n\n/**\n * Create a new slot instance. This slot instance can be used to request and render ads.\n *\n * @param slotOptions {AdheseSlotOptions} The options to create the slot with.\n *\n * @return AdheseSlot The created slot instance.\n */\nexport function createSlot(slotOptions: AdheseSlotOptions): AdheseSlot {\n const scope = effectScope();\n\n return scope.run(() => {\n const slotContext = ref<AdheseSlotContext | null>(null);\n const options = slotOptions.context.hooks.runOnSlotCreate({\n ...defaultOptions,\n ...(Object.fromEntries(Object.entries(slotOptions).filter(([,value]) => value !== undefined)) as AdheseSlotOptions),\n });\n\n const {\n containingElement,\n slot,\n context,\n pluginOptions,\n initialData = null,\n renderMode = 'iframe',\n type = 'normal',\n } = options;\n\n const id = uniqueId();\n const {\n runOnBeforeRender,\n runOnRender,\n runOnBeforeRequest,\n runOnRequest,\n runOnInit,\n runOnDispose,\n runOnEmpty,\n runOnError,\n ...hooks\n } = useSlotHooks(options, slotContext);\n\n const isDisposed = ref(false);\n const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));\n\n const [device, disposeQueryDetector] = useQueryDetector(context, typeof options.format === 'string'\n ? {\n [options.format]: '(min-width: 0px)',\n }\n : Object.fromEntries(options.format.map(item => [item.format, item.query])));\n\n const format = computed(() => typeof options.format === 'string' ? options.format : device.value);\n\n const data = ref<AdheseAd | null>(initialData) as Ref<AdheseAd | null>;\n const originalData = ref(data.value) as Ref<AdheseAd | null>;\n const name = computed(() => generateName(options.context.location, format.value, options.slot));\n\n const status = ref<UnwrapRef<AdheseSlot>['status']>('initializing');\n\n watch(name, async (newName, oldName) => {\n if (newName === oldName)\n return;\n\n const newAd = await slotContext.value?.request();\n\n if (!newAd)\n return;\n\n slotContext.value?.cleanElement();\n\n data.value = newAd;\n originalData.value = newAd;\n });\n\n const isDomLoaded = useDomLoaded(context);\n\n const element = shallowRef<HTMLElement | null>(null);\n\n function getElement(): HTMLElement | null {\n if (!(typeof options.containingElement === 'string' || !options.containingElement))\n return options.containingElement;\n\n if (!isDomLoaded.value)\n return null;\n\n return document.querySelector<HTMLElement>(`#${options.containingElement}`);\n }\n\n watch(element, async (newElement, oldElement) => {\n if (status.value === 'empty' || status.value === 'error' || status.value === 'loading') {\n return;\n }\n\n if (newElement === null && data.value) {\n status.value = 'loaded';\n\n return;\n }\n\n if (newElement === oldElement || (oldElement === null && newElement === null))\n return;\n\n await render();\n });\n\n const domObserver = new MutationObserver(() => {\n element.value = getElement();\n });\n\n domObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n watch(\n isDomLoaded,\n () => {\n element.value = getElement();\n },\n { immediate: true, deep: true },\n );\n\n const isInViewport = useRenderIntersectionObserver({\n options,\n element,\n hooks,\n });\n\n watch(isInViewport, async (newIsInViewport) => {\n if (newIsInViewport && status.value !== 'rendered')\n await slotContext.value?.render();\n }, { immediate: true });\n\n hooks.onDispose(() => {\n disposeQueryDetector();\n });\n\n const isViewabilityTracked = useViewabilityObserver({\n context,\n slotContext,\n hooks,\n onTracked(trackingPixel) {\n if (slotContext.value?.data?.viewableImpressionCounter) {\n trackingPixel.value = addTrackingPixel(slotContext.value?.data?.viewableImpressionCounter);\n\n context.logger.debug(`Viewability tracking pixel fired for ${slotContext.value?.name}`);\n }\n },\n });\n\n const impressionTrackingPixelElement = ref<HTMLImageElement | null>(null);\n const isImpressionTracked = ref(false);\n hooks.onDispose(() => {\n if (impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value.remove();\n });\n watch(status, async (newStatus, oldStatus) => {\n if (newStatus === 'loaded' && oldStatus === 'rendered') {\n impressionTrackingPixelElement.value?.remove();\n impressionTrackingPixelElement.value = null;\n }\n });\n\n async function request(): Promise<AdheseAd | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'loading';\n\n let response = await runOnBeforeRequest(null);\n\n if (!response) {\n response = await extRequestAd({\n slot: {\n name: name.value,\n parameters,\n },\n context,\n });\n }\n\n if (response)\n response = await runOnRequest(response);\n\n data.value = response;\n\n if (!originalData.value)\n originalData.value = response;\n\n status.value = response ? 'loaded' : 'empty';\n\n if (!response)\n cleanElement();\n\n return response;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`Error requesting ad for slot ${name.value}`, error);\n\n runOnError(new Error(`Error requesting ad for slot ${name.value}`, { cause: error }));\n\n return null;\n }\n }\n\n async function render(adToRender?: AdheseAd): Promise<HTMLElement | null> {\n try {\n if (options.lazyLoading && !isInViewport.value)\n return null;\n\n status.value = 'rendering';\n await waitForDomLoad();\n element.value = getElement();\n\n let renderAd = adToRender ?? data.value ?? originalData.value ?? await request();\n\n renderAd = renderAd && await runOnBeforeRender(renderAd);\n\n if (!element.value && renderMode !== 'none') {\n logger.debug(`Could not render slot for format ${format.value}. No element found.`, slotContext.value);\n\n return null;\n }\n\n if (!renderAd) {\n status.value = 'empty';\n logger.debug(`No ad to render for slot ${name.value}`);\n\n runOnEmpty();\n\n return null;\n }\n\n if (typeof renderAd?.tag !== 'string' && renderMode !== 'none') {\n const error = `Could not render slot for slot ${name.value}. A valid tag doesn't exist or is not HTML string.`;\n logger.error(error, options);\n\n throw new Error(error);\n }\n\n if (renderMode !== 'none' && element.value) {\n renderFunctions[renderMode]({\n ...renderAd,\n ...pick(options, ['width', 'height']),\n } as RenderOptions, element.value);\n }\n\n if (renderAd.impressionCounter && !impressionTrackingPixelElement.value)\n impressionTrackingPixelElement.value = addTrackingPixel(renderAd.impressionCounter);\n\n isImpressionTracked.value = true;\n\n logger.debug(`Slot rendered ${name.value}`, {\n renderedElement: element,\n location: context.location,\n format,\n containingElement,\n });\n\n status.value = 'rendered';\n\n runOnRender(renderAd);\n\n return element.value;\n }\n catch (error) {\n status.value = 'error';\n\n logger.error(`${error}`, options);\n\n runOnError(new Error(error as string));\n\n return null;\n }\n }\n\n function cleanElement(): void {\n if (!element.value || renderMode === 'none')\n return;\n\n element.value.innerHTML = '';\n element.value.style.position = '';\n }\n\n function dispose(): void {\n cleanElement();\n\n element.value = null;\n\n data.value = null;\n originalData.value = null;\n\n domObserver.disconnect();\n\n runOnDispose();\n\n isDisposed.value = true;\n\n scope.stop();\n }\n\n const state = reactive({\n location: context.location ?? '',\n lazyLoading: options.lazyLoading ?? false,\n type,\n slot,\n parameters,\n format,\n name,\n data,\n isViewabilityTracked,\n isImpressionTracked,\n status,\n element,\n isDisposed,\n id,\n pluginOptions,\n isVisible: isInViewport,\n render,\n request,\n dispose,\n cleanElement,\n options: omit(options, ['context']),\n ...hooks,\n });\n\n watch(state, (newState) => {\n slotContext.value = newState;\n }, {\n deep: true,\n immediate: true,\n });\n\n context.hooks.onInit(async () => {\n status.value = 'initialized';\n\n runOnInit();\n\n if (initialData) {\n status.value = 'loaded';\n return;\n }\n\n if (options.lazyLoading) {\n return;\n }\n\n data.value = await slotContext.value?.request() ?? null;\n });\n\n return state;\n })!;\n}\n"],"names":["extRequestAd"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adhese/sdk",
3
3
  "type": "module",
4
- "version": "1.3.2",
4
+ "version": "1.3.3-nightly-20241115134641",
5
5
  "description": "Adhese SDK",
6
6
  "license": "GPL-3.0",
7
7
  "repository": {