@dropins/tools 2.0.0 → 2.0.1-alpha-20260728135101

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/event-bus.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"event-bus.js","sources":["@dropins/tools/src/event-bus/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { Events } from './events-catalog';\n\nexport * from './events-catalog';\n\nconst hash = Date.now().toString(36).substring(2);\n\n/**\n * The `events` class provides static methods for event handling.\n * It allows subscribing to events, emitting events, and enabling or disabling event logging.\n *\n * @class\n * @extends {Events}\n *\n * @property {Function} on - Subscribes to an event.\n * @property {Function} emit - Emits an event.\n * @property {Function} enableLogger - Enables or disables event logging.\n * @property {Function} lastPayload - Returns the last payload of the event.\n */\nexport class events {\n static _identifier = hash;\n\n static _logger: BroadcastChannel | null = null;\n\n static _lastEvent: { [key: string]: { payload: any } } = {};\n\n /**\n * Returns a scoped event key.\n * @param scope - The scope to get the event from.\n * @returns - The scoped event key.\n */\n static _getScopedEvent(scope?: string) {\n return <K extends keyof Events>(event: K): K => {\n return (scope ? `${scope}/${String(event)}` : event) as K;\n };\n }\n\n /**\n * Returns the last payload of the event.\n * @param event – The event to get the last payload from.\n * @param options - Optional configuration for the event.\n * @returns – The last payload of the event.\n */\n static lastPayload<K extends keyof Events>(\n event: K,\n options?: { scope?: string }\n ): Events[K] | undefined {\n if (options?.scope) {\n event = this._getScopedEvent(options?.scope)(event);\n }\n\n return this._lastEvent[event as string]?.payload;\n }\n\n /**\n * Subscribes to an event.\n * @param event - The event to subscribe to.\n * @param handler - The event handler.\n * @param options - Optional configuration for the event handler.\n */\n static on<K extends keyof Events>(\n event: K,\n handler: (payload: Events[K]) => void,\n options?: { eager?: boolean; scope?: string }\n ) {\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n\n const subscriber = new BroadcastChannel('ElsieSDK/EventBus');\n\n // if scope is provided, get the scoped event key\n if (options?.scope) {\n event = this._getScopedEvent(options?.scope)(event);\n }\n\n if (options?.eager) {\n const lastEvent = this._lastEvent[event as string];\n\n if (lastEvent) {\n handler(lastEvent.payload);\n }\n }\n\n subscriber.addEventListener('message', ({ data }) => {\n // ignore events from other instances (only if identifier is set)\n if (this._identifier && this._identifier !== data.identifier) return;\n\n if (data.event === event) {\n handler(data.payload);\n }\n });\n\n // NOTE: disabled as it causes loading issues with \"bfcache\"\n // unsubscribe if leaving page\n // window.addEventListener('beforeunload', () => {\n // subscriber.close();\n // });\n\n return {\n off() {\n subscriber.close();\n },\n };\n }\n /**\n * Emits an event.\n * @param event - The event to emit.\n * @param payload - The event payload.\n * @param options - Optional configuration for the event.\n */\n\n static emit<K extends keyof Events>(\n event: K,\n payload: Events[K],\n options?: { scope?: string }\n ) {\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n\n const publisher = new BroadcastChannel('ElsieSDK/EventBus');\n\n // if scope is provided, get the scoped event key\n if (options?.scope) {\n event = this._getScopedEvent(options?.scope)(event);\n }\n\n publisher.postMessage({ event, identifier: this._identifier, payload });\n\n this._lastEvent[event as string] = {\n payload,\n };\n\n publisher.close();\n }\n /**\n * Enables or disables event logging.\n * @param enabled - Whether to enable or disable event logging.\n */\n static enableLogger(enabled: boolean) {\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n\n // reset logger\n this._logger?.close();\n this._logger = null;\n\n if (enabled === false) return;\n\n // create new logger\n this._logger = new BroadcastChannel('ElsieSDK/EventBus');\n\n this._logger.addEventListener('message', ({ data }) => {\n if (this._identifier && this._identifier !== data.identifier) return;\n console.group(`📡 Event (${data.identifier}) ➡ ${data.event}`);\n console.log(data.payload);\n console.groupEnd();\n });\n\n // NOTE: disabled as it causes loading issues with \"bfcache\"\n // unsubscribe if leaving page\n // window.addEventListener('beforeunload', () => {\n // this._logger?.close();\n // });\n }\n}\n"],"names":["hash","events","scope","event","options","_a","handler","subscriber","lastEvent","data","payload","publisher","enabled","__publicField"],"mappings":"oKAaA,MAAMA,EAAO,KAAK,IAAA,EAAM,SAAS,EAAE,EAAE,UAAU,CAAC,EAczC,MAAMC,CAAO,CAYlB,OAAO,gBAAgBC,EAAgB,CACrC,OAAgCC,GACtBD,EAAQ,GAAGA,CAAK,IAAI,OAAOC,CAAK,CAAC,GAAKA,CAElD,CAQA,OAAO,YACLA,EACAC,EACuB,CAzC3B,IAAAC,EA0CI,OAAID,GAAA,MAAAA,EAAS,QACXD,EAAQ,KAAK,gBAAgBC,GAAA,YAAAA,EAAS,KAAK,EAAED,CAAK,IAG7CE,EAAA,KAAK,WAAWF,CAAe,IAA/B,YAAAE,EAAkC,OAC3C,CAQA,OAAO,GACLF,EACAG,EACAF,EACA,CACA,GAAI,OAAO,iBAAqB,IAC9B,OAGF,MAAMG,EAAa,IAAI,iBAAiB,mBAAmB,EAO3D,GAJIH,GAAA,MAAAA,EAAS,QACXD,EAAQ,KAAK,gBAAgBC,GAAA,YAAAA,EAAS,KAAK,EAAED,CAAK,GAGhDC,GAAA,MAAAA,EAAS,MAAO,CAClB,MAAMI,EAAY,KAAK,WAAWL,CAAe,EAE7CK,GACFF,EAAQE,EAAU,OAAO,CAE7B,CAEA,OAAAD,EAAW,iBAAiB,UAAW,CAAC,CAAE,KAAAE,KAAW,CAE/C,KAAK,aAAe,KAAK,cAAgBA,EAAK,YAE9CA,EAAK,QAAUN,GACjBG,EAAQG,EAAK,OAAO,CAExB,CAAC,EAQM,CACL,KAAM,CACJF,EAAW,MAAA,CACb,CAAA,CAEJ,CAQA,OAAO,KACLJ,EACAO,EACAN,EACA,CACA,GAAI,OAAO,iBAAqB,IAC9B,OAGF,MAAMO,EAAY,IAAI,iBAAiB,mBAAmB,EAGtDP,GAAA,MAAAA,EAAS,QACXD,EAAQ,KAAK,gBAAgBC,GAAA,YAAAA,EAAS,KAAK,EAAED,CAAK,GAGpDQ,EAAU,YAAY,CAAE,MAAAR,EAAO,WAAY,KAAK,YAAa,QAAAO,EAAS,EAEtE,KAAK,WAAWP,CAAe,EAAI,CACjC,QAAAO,CAAA,EAGFC,EAAU,MAAA,CACZ,CAKA,OAAO,aAAaC,EAAkB,CAvIxC,IAAAP,EAwIQ,OAAO,iBAAqB,OAKhCA,EAAA,KAAK,UAAL,MAAAA,EAAc,QACd,KAAK,QAAU,KAEXO,IAAY,KAGhB,KAAK,QAAU,IAAI,iBAAiB,mBAAmB,EAEvD,KAAK,QAAQ,iBAAiB,UAAW,CAAC,CAAE,KAAAH,KAAW,CACjD,KAAK,aAAe,KAAK,cAAgBA,EAAK,aAClD,QAAQ,MAAM,aAAaA,EAAK,UAAU,OAAOA,EAAK,KAAK,EAAE,EAC7D,QAAQ,IAAIA,EAAK,OAAO,EACxB,QAAQ,SAAA,EACV,CAAC,GAOH,CACF,CAnJEI,EADWZ,EACJ,cAAcD,GAErBa,EAHWZ,EAGJ,UAAmC,MAE1CY,EALWZ,EAKJ,aAAkD,CAAA"}
1
+ {"version":3,"file":"event-bus.js","sources":["@dropins/tools/src/event-bus/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { Events } from './events-catalog';\n\nexport * from './events-catalog';\n\nconst hash = Date.now().toString(36).substring(2);\n\n/**\n * The `events` class provides static methods for event handling.\n * It allows subscribing to events, emitting events, and enabling or disabling event logging.\n *\n * @class\n * @extends {Events}\n *\n * @property {Function} on - Subscribes to an event.\n * @property {Function} emit - Emits an event.\n * @property {Function} enableLogger - Enables or disables event logging.\n * @property {Function} lastPayload - Returns the last payload of the event.\n */\nexport class events {\n static _identifier = hash;\n\n static _logger: BroadcastChannel | null = null;\n\n static _lastEvent: { [key: string]: { payload: any } } = {};\n\n /**\n * Returns a scoped event key.\n * @param scope - The scope to get the event from.\n * @returns - The scoped event key.\n */\n static _getScopedEvent(scope?: string) {\n return <K extends keyof Events>(event: K): K => {\n return (scope ? `${scope}/${String(event)}` : event) as K;\n };\n }\n\n /**\n * Returns the last payload of the event.\n * @param event – The event to get the last payload from.\n * @param options - Optional configuration for the event.\n * @returns – The last payload of the event.\n */\n static lastPayload<K extends keyof Events>(\n event: K,\n options?: { scope?: string },\n ): Events[K] | undefined {\n if (options?.scope) {\n event = this._getScopedEvent(options?.scope)(event);\n }\n\n return this._lastEvent[event as string]?.payload;\n }\n\n /**\n * Subscribes to an event.\n * @param event - The event to subscribe to.\n * @param handler - The event handler.\n * @param options - Optional configuration for the event handler.\n */\n static on<K extends keyof Events>(\n event: K,\n handler: (payload: Events[K]) => void,\n options?: { eager?: boolean; scope?: string },\n ) {\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n\n const subscriber = new BroadcastChannel('ElsieSDK/EventBus');\n\n // if scope is provided, get the scoped event key\n if (options?.scope) {\n event = this._getScopedEvent(options?.scope)(event);\n }\n\n if (options?.eager) {\n const lastEvent = this._lastEvent[event as string];\n\n if (lastEvent) {\n handler(lastEvent.payload);\n }\n }\n\n subscriber.addEventListener('message', ({ data }) => {\n // ignore events from other instances (only if identifier is set)\n if (this._identifier && this._identifier !== data.identifier) return;\n\n if (data.event === event) {\n handler(data.payload);\n }\n });\n\n // NOTE: disabled as it causes loading issues with \"bfcache\"\n // unsubscribe if leaving page\n // window.addEventListener('beforeunload', () => {\n // subscriber.close();\n // });\n\n return {\n off() {\n subscriber.close();\n },\n };\n }\n /**\n * Emits an event.\n * @param event - The event to emit.\n * @param payload - The event payload.\n * @param options - Optional configuration for the event.\n */\n\n static emit<K extends keyof Events>(\n event: K,\n payload: Events[K],\n options?: { scope?: string },\n ) {\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n\n const publisher = new BroadcastChannel('ElsieSDK/EventBus');\n\n // if scope is provided, get the scoped event key\n if (options?.scope) {\n event = this._getScopedEvent(options?.scope)(event);\n }\n\n publisher.postMessage({ event, identifier: this._identifier, payload });\n\n this._lastEvent[event as string] = {\n payload,\n };\n\n publisher.close();\n }\n /**\n * Enables or disables event logging.\n * @param enabled - Whether to enable or disable event logging.\n */\n static enableLogger(enabled: boolean) {\n if (typeof BroadcastChannel === 'undefined') {\n return;\n }\n\n // reset logger\n this._logger?.close();\n this._logger = null;\n\n if (enabled === false) return;\n\n // create new logger\n this._logger = new BroadcastChannel('ElsieSDK/EventBus');\n\n this._logger.addEventListener('message', ({ data }) => {\n if (this._identifier && this._identifier !== data.identifier) return;\n console.group(`📡 Event (${data.identifier}) ➡ ${data.event}`);\n console.log(data.payload);\n console.groupEnd();\n });\n\n // NOTE: disabled as it causes loading issues with \"bfcache\"\n // unsubscribe if leaving page\n // window.addEventListener('beforeunload', () => {\n // this._logger?.close();\n // });\n }\n}\n"],"names":["hash","events","scope","event","options","_a","handler","subscriber","lastEvent","data","payload","publisher","enabled","__publicField"],"mappings":"oKAaA,MAAMA,EAAO,KAAK,IAAA,EAAM,SAAS,EAAE,EAAE,UAAU,CAAC,EAczC,MAAMC,CAAO,CAYlB,OAAO,gBAAgBC,EAAgB,CACrC,OAAgCC,GACtBD,EAAQ,GAAGA,CAAK,IAAI,OAAOC,CAAK,CAAC,GAAKA,CAElD,CAQA,OAAO,YACLA,EACAC,EACuB,CAzC3B,IAAAC,EA0CI,OAAID,GAAA,MAAAA,EAAS,QACXD,EAAQ,KAAK,gBAAgBC,GAAA,YAAAA,EAAS,KAAK,EAAED,CAAK,IAG7CE,EAAA,KAAK,WAAWF,CAAe,IAA/B,YAAAE,EAAkC,OAC3C,CAQA,OAAO,GACLF,EACAG,EACAF,EACA,CACA,GAAI,OAAO,iBAAqB,IAC9B,OAGF,MAAMG,EAAa,IAAI,iBAAiB,mBAAmB,EAO3D,GAJIH,GAAA,MAAAA,EAAS,QACXD,EAAQ,KAAK,gBAAgBC,GAAA,YAAAA,EAAS,KAAK,EAAED,CAAK,GAGhDC,GAAA,MAAAA,EAAS,MAAO,CAClB,MAAMI,EAAY,KAAK,WAAWL,CAAe,EAE7CK,GACFF,EAAQE,EAAU,OAAO,CAE7B,CAEA,OAAAD,EAAW,iBAAiB,UAAW,CAAC,CAAE,KAAAE,KAAW,CAE/C,KAAK,aAAe,KAAK,cAAgBA,EAAK,YAE9CA,EAAK,QAAUN,GACjBG,EAAQG,EAAK,OAAO,CAExB,CAAC,EAQM,CACL,KAAM,CACJF,EAAW,MAAA,CACb,CAAA,CAEJ,CAQA,OAAO,KACLJ,EACAO,EACAN,EACA,CACA,GAAI,OAAO,iBAAqB,IAC9B,OAGF,MAAMO,EAAY,IAAI,iBAAiB,mBAAmB,EAGtDP,GAAA,MAAAA,EAAS,QACXD,EAAQ,KAAK,gBAAgBC,GAAA,YAAAA,EAAS,KAAK,EAAED,CAAK,GAGpDQ,EAAU,YAAY,CAAE,MAAAR,EAAO,WAAY,KAAK,YAAa,QAAAO,EAAS,EAEtE,KAAK,WAAWP,CAAe,EAAI,CACjC,QAAAO,CAAA,EAGFC,EAAU,MAAA,CACZ,CAKA,OAAO,aAAaC,EAAkB,CAvIxC,IAAAP,EAwIQ,OAAO,iBAAqB,OAKhCA,EAAA,KAAK,UAAL,MAAAA,EAAc,QACd,KAAK,QAAU,KAEXO,IAAY,KAGhB,KAAK,QAAU,IAAI,iBAAiB,mBAAmB,EAEvD,KAAK,QAAQ,iBAAiB,UAAW,CAAC,CAAE,KAAAH,KAAW,CACjD,KAAK,aAAe,KAAK,cAAgBA,EAAK,aAClD,QAAQ,MAAM,aAAaA,EAAK,UAAU,OAAOA,EAAK,KAAK,EAAE,EAC7D,QAAQ,IAAIA,EAAK,OAAO,EACxB,QAAQ,SAAA,EACV,CAAC,GAOH,CACF,CAnJEI,EADWZ,EACJ,cAAcD,GAErBa,EAHWZ,EAGJ,UAAmC,MAE1CY,EALWZ,EAKJ,aAAkD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-graphql.js","sources":["@dropins/tools/src/fetch-graphql/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport type Header = { [key: string]: string | null };\n\nexport type FetchOptions = {\n method?: 'GET' | 'POST';\n variables?: { [key: string]: any };\n signal?: AbortSignal;\n cache?:\n | 'default'\n | 'no-store'\n | 'reload'\n | 'no-cache'\n | 'force-cache'\n | 'only-if-cached';\n};\n\nexport type FetchQueryError = Array<{\n message: string;\n extensions: { category: string };\n}>;\n\nexport type BeforeHook = (requestInit: RequestInit) => RequestInit | Promise<RequestInit>;\nexport type AfterHook<T = any> = (\n requestInit: RequestInit,\n response: { errors?: FetchQueryError; data: T }\n) => { errors?: FetchQueryError; data: T } | Promise<{ errors?: FetchQueryError; data: T }>;\n\nconst defaultHeaders = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n};\n\nclass FetchGraphQLMesh {\n protected _endpoint?: string;\n\n public _fetchGraphQlHeaders: Header = {};\n\n public _beforeHooks: BeforeHook[] = [];\n\n public _afterHooks: AfterHook[] = [];\n\n get endpoint() {\n return this._endpoint;\n }\n\n get fetchGraphQlHeaders() {\n return this._fetchGraphQlHeaders;\n }\n\n /**\n * Sets the GraphQL endpoint.\n * @param endpoint - The GraphQL endpoint URL string.\n * @example\n * ```js\n * // Set endpoint as string\n * instance.setEndpoint('https://api.example.com/graphql');\n * ```\n */\n public setEndpoint(endpoint: string) {\n this._endpoint = endpoint;\n }\n\n /**\n * Sets the GraphQL headers.\n * @param key - The key of the header.\n * @param value - The value of the header.\n */\n public setFetchGraphQlHeader(key: string, value: string | null) {\n this._fetchGraphQlHeaders = {\n ...this._fetchGraphQlHeaders,\n [key]: value,\n };\n }\n\n /**\n * Removes a specific GraphQL header.\n * @param key - The key of the header.\n */\n public removeFetchGraphQlHeader(key: string) {\n delete this._fetchGraphQlHeaders[key];\n }\n\n /**\n * Gets the value of a specific GraphQL header.\n * @param key - The key of the header.\n * @returns The value of the header, or undefined if not found.\n */\n public getFetchGraphQlHeader(key: string): string | null | undefined {\n return this._fetchGraphQlHeaders[key];\n }\n\n /**\n * Sets the GraphQL headers.\n * @param header - The header object or a function that returns a header object.\n * If a function is provided, it will be called with the previous headers.\n * The returned object will be merged with the previous headers.\n * @example\n * ```js\n * // set headers\n * setFetchGraphQlHeaders({ test: 'test' });\n * \n * // merge with previous headers\n * setFetchGraphQlHeaders((prev) => ({\n * ...prev,\n * test: 'test2',\n * }));\n * ```\n */\n public setFetchGraphQlHeaders(header: Header | ((prev: Header) => Header)) {\n if (typeof header === 'function') {\n this._fetchGraphQlHeaders = {\n ...this._fetchGraphQlHeaders,\n ...header(this._fetchGraphQlHeaders),\n };\n } else {\n this._fetchGraphQlHeaders = { ...header };\n }\n }\n\n /**\n * Adds a hook executed before the GraphQL call.\n * @param hook - The hook function.\n * @example\n * ```js\n * // add before hook\n * addBeforeHook((requestInit) => console.log('About to execute ' + requestInit.method + ' call.'));\n *\n * // modify the requestInit before executing the request\n * addBeforeHook((requestInit) => {method: requestInit.method, body: 'new body'});\n * ```\n */\n public addBeforeHook(hook: BeforeHook): void {\n this._beforeHooks.push(hook);\n }\n\n /**\n * Adds a hook executed before the GraphQL call.\n * @param hook - The hook function.\n * @example\n * ```js\n * // add before hook\n * addAfterHook((requestInit, response) => console.log(\n * 'The result of ' + requestInit.method + ' call is ' + response.json().body\n * ));\n *\n * // modify the response\n * addAfterHook((requestInit, response) => new Response(JSON.stringify({ ...response, modified: true }));\n * ```\n */\n public addAfterHook(hook: AfterHook): void {\n this._afterHooks.push(hook);\n }\n \n /**\n * Collects all before hooks. Can be overridden by subclasses for inheritance.\n * @protected\n */\n protected _collectBeforeHooks(): BeforeHook[] {\n return this._beforeHooks;\n }\n \n /**\n * Collects all after hooks. Can be overridden by subclasses for inheritance.\n * @protected\n */\n protected _collectAfterHooks(): AfterHook[] {\n return this._afterHooks;\n }\n \n /**\n * Fetches GraphQL data.\n * @param query - The GraphQL query.\n * @param options - Optional configuration for the fetch request.\n * @returns\n */\n public async fetchGraphQl<T = any>(\n query: string,\n options?: FetchOptions\n ): Promise<{ errors?: FetchQueryError; data: T }> {\n const endpoint = this.endpoint;\n const fetchGraphQlHeaders = this.fetchGraphQlHeaders;\n\n if (!endpoint) throw Error('Missing \"url\"');\n\n const method = options?.method ?? 'POST';\n const cache = options?.cache;\n const signal = options?.signal;\n\n let body;\n const url = new URL(endpoint);\n const headers = {\n ...defaultHeaders,\n ...fetchGraphQlHeaders,\n };\n\n if (method === 'POST') {\n body = JSON.stringify({\n query,\n variables: options?.variables,\n });\n }\n\n if (method === 'GET') {\n url.searchParams.append('query', minimizeGraphQlQuery(query));\n\n if (options?.variables)\n url.searchParams.append('variables', JSON.stringify(options.variables));\n }\n\n let requestInit: RequestInit = {\n method,\n headers,\n body,\n cache,\n signal,\n };\n\n // Collect and execute before hooks\n const allBeforeHooks = this._collectBeforeHooks();\n requestInit = await allBeforeHooks.reduce(\n async (prev, hook) => hook(await prev),\n Promise.resolve(requestInit)\n );\n\n // Collect and execute after hooks\n const allAfterHooks = this._collectAfterHooks();\n return await fetch(url, requestInit).then((r) => r.json().then(\n (response) => allAfterHooks.reduce(\n async (result, hook) => hook(requestInit, await result),\n Promise.resolve(response)\n )\n ));\n }\n \n /**\n * Gets the configuration.\n */\n public getConfig() {\n return {\n endpoint: this.endpoint,\n fetchGraphQlHeaders: this.fetchGraphQlHeaders,\n };\n }\n\n public getMethods() {\n return {\n setEndpoint: this.setEndpoint.bind(this),\n setFetchGraphQlHeader: this.setFetchGraphQlHeader.bind(this),\n getFetchGraphQlHeader: this.getFetchGraphQlHeader.bind(this),\n removeFetchGraphQlHeader: this.removeFetchGraphQlHeader.bind(this),\n setFetchGraphQlHeaders: this.setFetchGraphQlHeaders.bind(this),\n fetchGraphQl: this.fetchGraphQl.bind(this),\n getConfig: this.getConfig.bind(this),\n addBeforeHook: this.addBeforeHook.bind(this),\n addAfterHook: this.addAfterHook.bind(this),\n };\n }\n}\n\nconst mesh = new FetchGraphQLMesh();\n\n/**\n * `FetchGraphQL` is a class that extends `FetchGraphQLMesh`.\n * It provides methods to get the GraphQL endpoint and headers with support for inheritance.\n *\n * @class\n *\n */\nexport class FetchGraphQL extends FetchGraphQLMesh {\n private _mode: 'standalone' | 'linked' | 'default' = 'default';\n private _source?: string | FetchGraphQL;\n\n get endpoint(): string | undefined {\n switch (this._mode) {\n case 'standalone':\n return this._source as string;\n case 'linked':\n return (this._source as FetchGraphQL)?.endpoint;\n case 'default':\n return mesh.endpoint;\n }\n }\n\n get fetchGraphQlHeaders(): Header { \n switch (this._mode) {\n case 'standalone':\n // Standalone instance - only use own headers\n return this._fetchGraphQlHeaders;\n case 'linked':\n // Linked to another instance - use linked instance's headers directly\n return (this._source as FetchGraphQL).fetchGraphQlHeaders;\n case 'default':\n // Default - inherit from global mesh\n return {\n ...mesh.fetchGraphQlHeaders,\n ...this._fetchGraphQlHeaders,\n };\n }\n }\n\n /**\n * Sets the GraphQL endpoint or links to another FetchGraphQL instance.\n * @param endpoint - The GraphQL endpoint URL string, or a FetchGraphQL instance to link to.\n * @example\n * ```js\n * // Set endpoint as string\n * instance.setEndpoint('https://api.example.com/graphql');\n * \n * // Link to another instance\n * const parent = new FetchGraphQL();\n * parent.setEndpoint('https://api.example.com/graphql');\n * \n * const child = new FetchGraphQL();\n * child.setEndpoint(parent); // Links to parent, shares endpoint, headers, and hooks\n * ```\n */\n public setEndpoint(endpoint: string | FetchGraphQL): void {\n if (endpoint instanceof FetchGraphQL) {\n // Link to another instance\n this._mode = 'linked';\n this._source = endpoint;\n } else {\n // Set string endpoint - become standalone\n this._mode = 'standalone';\n this._source = endpoint;\n }\n }\n\n /**\n * Sets a GraphQL header. When linked to another instance, this sets the header on the linked instance.\n * @param key - The key of the header.\n * @param value - The value of the header.\n */\n public setFetchGraphQlHeader(key: string, value: string | null): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).setFetchGraphQlHeader(key, value);\n } else {\n // Set on self\n super.setFetchGraphQlHeader(key, value);\n }\n }\n\n /**\n * Sets the GraphQL headers. When linked to another instance, this sets the headers on the linked instance.\n * @param header - The header object or a function that returns a header object.\n */\n public setFetchGraphQlHeaders(header: Header | ((prev: Header) => Header)): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).setFetchGraphQlHeaders(header);\n } else {\n // Set on self\n super.setFetchGraphQlHeaders(header);\n }\n }\n\n /**\n * Removes a specific GraphQL header. When linked to another instance, this removes the header from the linked instance.\n * @param key - The key of the header.\n */\n public removeFetchGraphQlHeader(key: string): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).removeFetchGraphQlHeader(key);\n } else {\n // Remove from self\n super.removeFetchGraphQlHeader(key);\n }\n }\n\n /**\n * Gets the value of a specific GraphQL header. When linked to another instance, this gets the header from the linked instance.\n * @param key - The key of the header.\n * @returns The value of the header, or undefined if not found.\n */\n public getFetchGraphQlHeader(key: string): string | null | undefined {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n return (this._source as FetchGraphQL).getFetchGraphQlHeader(key);\n }\n // Get from self\n return super.getFetchGraphQlHeader(key);\n }\n\n /**\n * Adds a before hook. When linked to another instance, this adds the hook to the linked instance.\n * @param hook - The hook function.\n */\n public addBeforeHook(hook: BeforeHook): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).addBeforeHook(hook);\n } else {\n // Add to self\n super.addBeforeHook(hook);\n }\n }\n\n /**\n * Adds an after hook. When linked to another instance, this adds the hook to the linked instance.\n * @param hook - The hook function.\n */\n public addAfterHook(hook: AfterHook): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).addAfterHook(hook);\n } else {\n // Add to self\n super.addAfterHook(hook);\n }\n }\n\n /**\n * Collects all before hooks. When linked, delegates to the linked instance.\n * @protected\n */\n protected _collectBeforeHooks(): BeforeHook[] {\n if (this._mode === 'linked') {\n return (this._source as FetchGraphQL)._collectBeforeHooks();\n }\n return this._beforeHooks;\n }\n \n /**\n * Collects all after hooks. When linked, delegates to the linked instance.\n * @protected\n */\n protected _collectAfterHooks(): AfterHook[] {\n if (this._mode === 'linked') {\n return (this._source as FetchGraphQL)._collectAfterHooks();\n }\n return this._afterHooks;\n }\n}\n\nfunction minimizeGraphQlQuery(query: string) {\n // Remove comments\n query = query.replace(/#.*/g, '');\n\n // Remove extra spaces, tabs, and line breaks\n query = query.replace(/\\s+/g, ' ');\n\n return query.trim();\n}\n/**\n * Exports several methods from the `mesh` object.\n *\n * @property {Function} setEndpoint - Sets the GraphQL endpoint.\n * @property {Function} setFetchGraphQlHeaders - Sets the GraphQL headers.\n * @property {Function} setFetchGraphQlHeader - Sets a specific GraphQL header.\n * @property {Function} getFetchGraphQlHeader - Gets the value of a specific GraphQL header.\n * @property {Function} removeFetchGraphQlHeader - Removes a specific GraphQL header.\n * @property {Function} fetchGraphQl - Fetches GraphQL data.\n * @property {Function} getConfig - Gets the configuration.\n * @property {Function} addBeforeHook - Adds a hook executed before the GraphQL call.\n * @property {Function} addAfterHook - Adds a hook executed after the GraphQL call.\n */\n\n// Global Mesh instance\nexport const {\n setEndpoint,\n setFetchGraphQlHeaders,\n setFetchGraphQlHeader,\n getFetchGraphQlHeader,\n removeFetchGraphQlHeader,\n fetchGraphQl,\n getConfig,\n addBeforeHook,\n addAfterHook,\n} = mesh.getMethods();\n"],"names":["defaultHeaders","FetchGraphQLMesh","__publicField","endpoint","key","value","header","hook","query","options","fetchGraphQlHeaders","method","cache","signal","body","url","headers","minimizeGraphQlQuery","requestInit","prev","allAfterHooks","r","response","result","mesh","FetchGraphQL","_a","setEndpoint","setFetchGraphQlHeaders","setFetchGraphQlHeader","getFetchGraphQlHeader","removeFetchGraphQlHeader","fetchGraphQl","getConfig","addBeforeHook","addAfterHook"],"mappings":"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"}
1
+ {"version":3,"file":"fetch-graphql.js","sources":["@dropins/tools/src/fetch-graphql/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nexport type Header = { [key: string]: string | null };\n\nexport type FetchOptions = {\n method?: 'GET' | 'POST';\n variables?: { [key: string]: any };\n signal?: AbortSignal;\n cache?:\n | 'default'\n | 'no-store'\n | 'reload'\n | 'no-cache'\n | 'force-cache'\n | 'only-if-cached';\n};\n\nexport type FetchQueryError = Array<{\n message: string;\n extensions: { category: string };\n}>;\n\nexport type BeforeHook = (\n requestInit: RequestInit,\n) => RequestInit | Promise<RequestInit>;\nexport type AfterHook<T = any> = (\n requestInit: RequestInit,\n response: { errors?: FetchQueryError; data: T },\n) =>\n | { errors?: FetchQueryError; data: T }\n | Promise<{ errors?: FetchQueryError; data: T }>;\n\nconst defaultHeaders = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n};\n\nclass FetchGraphQLMesh {\n protected _endpoint?: string;\n\n public _fetchGraphQlHeaders: Header = {};\n\n public _beforeHooks: BeforeHook[] = [];\n\n public _afterHooks: AfterHook[] = [];\n\n get endpoint() {\n return this._endpoint;\n }\n\n get fetchGraphQlHeaders() {\n return this._fetchGraphQlHeaders;\n }\n\n /**\n * Sets the GraphQL endpoint.\n * @param endpoint - The GraphQL endpoint URL string.\n * @example\n * ```js\n * // Set endpoint as string\n * instance.setEndpoint('https://api.example.com/graphql');\n * ```\n */\n public setEndpoint(endpoint: string) {\n this._endpoint = endpoint;\n }\n\n /**\n * Sets the GraphQL headers.\n * @param key - The key of the header.\n * @param value - The value of the header.\n */\n public setFetchGraphQlHeader(key: string, value: string | null) {\n this._fetchGraphQlHeaders = {\n ...this._fetchGraphQlHeaders,\n [key]: value,\n };\n }\n\n /**\n * Removes a specific GraphQL header.\n * @param key - The key of the header.\n */\n public removeFetchGraphQlHeader(key: string) {\n delete this._fetchGraphQlHeaders[key];\n }\n\n /**\n * Gets the value of a specific GraphQL header.\n * @param key - The key of the header.\n * @returns The value of the header, or undefined if not found.\n */\n public getFetchGraphQlHeader(key: string): string | null | undefined {\n return this._fetchGraphQlHeaders[key];\n }\n\n /**\n * Sets the GraphQL headers.\n * @param header - The header object or a function that returns a header object.\n * If a function is provided, it will be called with the previous headers.\n * The returned object will be merged with the previous headers.\n * @example\n * ```js\n * // set headers\n * setFetchGraphQlHeaders({ test: 'test' });\n *\n * // merge with previous headers\n * setFetchGraphQlHeaders((prev) => ({\n * ...prev,\n * test: 'test2',\n * }));\n * ```\n */\n public setFetchGraphQlHeaders(header: Header | ((prev: Header) => Header)) {\n if (typeof header === 'function') {\n this._fetchGraphQlHeaders = {\n ...this._fetchGraphQlHeaders,\n ...header(this._fetchGraphQlHeaders),\n };\n } else {\n this._fetchGraphQlHeaders = { ...header };\n }\n }\n\n /**\n * Adds a hook executed before the GraphQL call.\n * @param hook - The hook function.\n * @example\n * ```js\n * // add before hook\n * addBeforeHook((requestInit) => console.log('About to execute ' + requestInit.method + ' call.'));\n *\n * // modify the requestInit before executing the request\n * addBeforeHook((requestInit) => {method: requestInit.method, body: 'new body'});\n * ```\n */\n public addBeforeHook(hook: BeforeHook): void {\n this._beforeHooks.push(hook);\n }\n\n /**\n * Adds a hook executed before the GraphQL call.\n * @param hook - The hook function.\n * @example\n * ```js\n * // add before hook\n * addAfterHook((requestInit, response) => console.log(\n * 'The result of ' + requestInit.method + ' call is ' + response.json().body\n * ));\n *\n * // modify the response\n * addAfterHook((requestInit, response) => new Response(JSON.stringify({ ...response, modified: true }));\n * ```\n */\n public addAfterHook(hook: AfterHook): void {\n this._afterHooks.push(hook);\n }\n\n /**\n * Collects all before hooks. Can be overridden by subclasses for inheritance.\n * @protected\n */\n protected _collectBeforeHooks(): BeforeHook[] {\n return this._beforeHooks;\n }\n\n /**\n * Collects all after hooks. Can be overridden by subclasses for inheritance.\n * @protected\n */\n protected _collectAfterHooks(): AfterHook[] {\n return this._afterHooks;\n }\n\n /**\n * Fetches GraphQL data.\n * @param query - The GraphQL query.\n * @param options - Optional configuration for the fetch request.\n * @returns\n */\n public async fetchGraphQl<T = any>(\n query: string,\n options?: FetchOptions,\n ): Promise<{ errors?: FetchQueryError; data: T }> {\n const endpoint = this.endpoint;\n const fetchGraphQlHeaders = this.fetchGraphQlHeaders;\n\n if (!endpoint) throw Error('Missing \"url\"');\n\n const method = options?.method ?? 'POST';\n const cache = options?.cache;\n const signal = options?.signal;\n\n let body;\n const url = new URL(endpoint);\n const headers = {\n ...defaultHeaders,\n ...fetchGraphQlHeaders,\n };\n\n if (method === 'POST') {\n body = JSON.stringify({\n query,\n variables: options?.variables,\n });\n }\n\n if (method === 'GET') {\n url.searchParams.append('query', minimizeGraphQlQuery(query));\n\n if (options?.variables)\n url.searchParams.append('variables', JSON.stringify(options.variables));\n }\n\n let requestInit: RequestInit = {\n method,\n headers,\n body,\n cache,\n signal,\n };\n\n // Collect and execute before hooks\n const allBeforeHooks = this._collectBeforeHooks();\n requestInit = await allBeforeHooks.reduce(\n async (prev, hook) => hook(await prev),\n Promise.resolve(requestInit),\n );\n\n // Collect and execute after hooks\n const allAfterHooks = this._collectAfterHooks();\n return await fetch(url, requestInit).then((r) =>\n r\n .json()\n .then((response) =>\n allAfterHooks.reduce(\n async (result, hook) => hook(requestInit, await result),\n Promise.resolve(response),\n ),\n ),\n );\n }\n\n /**\n * Gets the configuration.\n */\n public getConfig() {\n return {\n endpoint: this.endpoint,\n fetchGraphQlHeaders: this.fetchGraphQlHeaders,\n };\n }\n\n public getMethods() {\n return {\n setEndpoint: this.setEndpoint.bind(this),\n setFetchGraphQlHeader: this.setFetchGraphQlHeader.bind(this),\n getFetchGraphQlHeader: this.getFetchGraphQlHeader.bind(this),\n removeFetchGraphQlHeader: this.removeFetchGraphQlHeader.bind(this),\n setFetchGraphQlHeaders: this.setFetchGraphQlHeaders.bind(this),\n fetchGraphQl: this.fetchGraphQl.bind(this),\n getConfig: this.getConfig.bind(this),\n addBeforeHook: this.addBeforeHook.bind(this),\n addAfterHook: this.addAfterHook.bind(this),\n };\n }\n}\n\nconst mesh = new FetchGraphQLMesh();\n\n/**\n * `FetchGraphQL` is a class that extends `FetchGraphQLMesh`.\n * It provides methods to get the GraphQL endpoint and headers with support for inheritance.\n *\n * @class\n *\n */\nexport class FetchGraphQL extends FetchGraphQLMesh {\n private _mode: 'standalone' | 'linked' | 'default' = 'default';\n private _source?: string | FetchGraphQL;\n\n get endpoint(): string | undefined {\n switch (this._mode) {\n case 'standalone':\n return this._source as string;\n case 'linked':\n return (this._source as FetchGraphQL)?.endpoint;\n case 'default':\n return mesh.endpoint;\n }\n }\n\n get fetchGraphQlHeaders(): Header {\n switch (this._mode) {\n case 'standalone':\n // Standalone instance - only use own headers\n return this._fetchGraphQlHeaders;\n case 'linked':\n // Linked to another instance - use linked instance's headers directly\n return (this._source as FetchGraphQL).fetchGraphQlHeaders;\n case 'default':\n // Default - inherit from global mesh\n return {\n ...mesh.fetchGraphQlHeaders,\n ...this._fetchGraphQlHeaders,\n };\n }\n }\n\n /**\n * Sets the GraphQL endpoint or links to another FetchGraphQL instance.\n * @param endpoint - The GraphQL endpoint URL string, or a FetchGraphQL instance to link to.\n * @example\n * ```js\n * // Set endpoint as string\n * instance.setEndpoint('https://api.example.com/graphql');\n *\n * // Link to another instance\n * const parent = new FetchGraphQL();\n * parent.setEndpoint('https://api.example.com/graphql');\n *\n * const child = new FetchGraphQL();\n * child.setEndpoint(parent); // Links to parent, shares endpoint, headers, and hooks\n * ```\n */\n public setEndpoint(endpoint: string | FetchGraphQL): void {\n if (endpoint instanceof FetchGraphQL) {\n // Link to another instance\n this._mode = 'linked';\n this._source = endpoint;\n } else {\n // Set string endpoint - become standalone\n this._mode = 'standalone';\n this._source = endpoint;\n }\n }\n\n /**\n * Sets a GraphQL header. When linked to another instance, this sets the header on the linked instance.\n * @param key - The key of the header.\n * @param value - The value of the header.\n */\n public setFetchGraphQlHeader(key: string, value: string | null): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).setFetchGraphQlHeader(key, value);\n } else {\n // Set on self\n super.setFetchGraphQlHeader(key, value);\n }\n }\n\n /**\n * Sets the GraphQL headers. When linked to another instance, this sets the headers on the linked instance.\n * @param header - The header object or a function that returns a header object.\n */\n public setFetchGraphQlHeaders(\n header: Header | ((prev: Header) => Header),\n ): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).setFetchGraphQlHeaders(header);\n } else {\n // Set on self\n super.setFetchGraphQlHeaders(header);\n }\n }\n\n /**\n * Removes a specific GraphQL header. When linked to another instance, this removes the header from the linked instance.\n * @param key - The key of the header.\n */\n public removeFetchGraphQlHeader(key: string): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).removeFetchGraphQlHeader(key);\n } else {\n // Remove from self\n super.removeFetchGraphQlHeader(key);\n }\n }\n\n /**\n * Gets the value of a specific GraphQL header. When linked to another instance, this gets the header from the linked instance.\n * @param key - The key of the header.\n * @returns The value of the header, or undefined if not found.\n */\n public getFetchGraphQlHeader(key: string): string | null | undefined {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n return (this._source as FetchGraphQL).getFetchGraphQlHeader(key);\n }\n // Get from self\n return super.getFetchGraphQlHeader(key);\n }\n\n /**\n * Adds a before hook. When linked to another instance, this adds the hook to the linked instance.\n * @param hook - The hook function.\n */\n public addBeforeHook(hook: BeforeHook): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).addBeforeHook(hook);\n } else {\n // Add to self\n super.addBeforeHook(hook);\n }\n }\n\n /**\n * Adds an after hook. When linked to another instance, this adds the hook to the linked instance.\n * @param hook - The hook function.\n */\n public addAfterHook(hook: AfterHook): void {\n if (this._mode === 'linked') {\n // Delegate to linked instance\n (this._source as FetchGraphQL).addAfterHook(hook);\n } else {\n // Add to self\n super.addAfterHook(hook);\n }\n }\n\n /**\n * Collects all before hooks. When linked, delegates to the linked instance.\n * @protected\n */\n protected _collectBeforeHooks(): BeforeHook[] {\n if (this._mode === 'linked') {\n return (this._source as FetchGraphQL)._collectBeforeHooks();\n }\n return this._beforeHooks;\n }\n\n /**\n * Collects all after hooks. When linked, delegates to the linked instance.\n * @protected\n */\n protected _collectAfterHooks(): AfterHook[] {\n if (this._mode === 'linked') {\n return (this._source as FetchGraphQL)._collectAfterHooks();\n }\n return this._afterHooks;\n }\n}\n\nfunction minimizeGraphQlQuery(query: string) {\n // Remove comments\n query = query.replace(/#.*/g, '');\n\n // Remove extra spaces, tabs, and line breaks\n query = query.replace(/\\s+/g, ' ');\n\n return query.trim();\n}\n/**\n * Exports several methods from the `mesh` object.\n *\n * @property {Function} setEndpoint - Sets the GraphQL endpoint.\n * @property {Function} setFetchGraphQlHeaders - Sets the GraphQL headers.\n * @property {Function} setFetchGraphQlHeader - Sets a specific GraphQL header.\n * @property {Function} getFetchGraphQlHeader - Gets the value of a specific GraphQL header.\n * @property {Function} removeFetchGraphQlHeader - Removes a specific GraphQL header.\n * @property {Function} fetchGraphQl - Fetches GraphQL data.\n * @property {Function} getConfig - Gets the configuration.\n * @property {Function} addBeforeHook - Adds a hook executed before the GraphQL call.\n * @property {Function} addAfterHook - Adds a hook executed after the GraphQL call.\n */\n\n// Global Mesh instance\nexport const {\n setEndpoint,\n setFetchGraphQlHeaders,\n setFetchGraphQlHeader,\n getFetchGraphQlHeader,\n removeFetchGraphQlHeader,\n fetchGraphQl,\n getConfig,\n addBeforeHook,\n addAfterHook,\n} = mesh.getMethods();\n"],"names":["defaultHeaders","FetchGraphQLMesh","__publicField","endpoint","key","value","header","hook","query","options","fetchGraphQlHeaders","method","cache","signal","body","url","headers","minimizeGraphQlQuery","requestInit","prev","allAfterHooks","r","response","result","mesh","FetchGraphQL","_a","setEndpoint","setFetchGraphQlHeaders","setFetchGraphQlHeader","getFetchGraphQlHeader","removeFetchGraphQlHeader","fetchGraphQl","getConfig","addBeforeHook","addAfterHook"],"mappings":"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"}
package/lib/aem/assets.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /*! Copyright 2026 Adobe
2
2
  All Rights Reserved. */
3
- import{getConfigValue as O}from"./configs.js";import{p as f,I as g}from"../../chunks/Image.js";import"../../chunks/get-path-value.js";import"../../chunks/cjs.js";import"../../chunks/preact-vendor.js";import"../../chunks/vcomponent.js";import"../../chunks/image-params-keymap.js";import"../../signals.js";const b=["gif","jpg","jpeg","png","webp"],v=[90,180,270],U=["h","v","hv"];function l(e){let t=e;if(t.startsWith("//")){const{protocol:s}=window.location;t=s+t}return t}function I(e){return U.includes(e)}function L(e){return v.includes(e)}function y(e){return b.includes(e)}function u(e,t,s){if(e!==void 0&&!t(e))throw new Error(s)}function h(){const e=O("commerce-assets-enabled");return e&&(typeof e=="string"&&e.toLowerCase()==="true"||typeof e=="boolean"&&e===!0)}function R(){return{quality:80,format:"webp"}}function A(e){return!!(typeof e=="string"?new URL(l(e)):e).pathname.startsWith("/adobe/assets/urn:aaid:aem")}function w(e,t,s={}){const r={...R(),...s},{format:i,crop:n,...o}=r;u(i,y,"Invalid format"),u(o.flip,I,"Invalid flip"),u(o.rotate,L,"Invalid rotation");const a=Object.fromEntries(Object.entries(o).map(([p,d])=>[p,String(d)])),c=new URLSearchParams(a);if(n){const[p,d]=[n.xOrigin||0,n.yOrigin||0],[P,E]=[n.width||100,n.height||100],S=`${p}p,${d}p,${P}p,${E}p`;c.set("crop",S)}return`${e}/as/${t}.${i}?${c.toString()}`}function M(e,t,s={}){if(!h())return e;const r=new URL(l(e));if(!A(r))return e;const i=r.origin+r.pathname;return w(i,t,s)}function _(e){return t=>{const{wrapper:s,alias:m,params:r,imageProps:i}=e;if(!i.src)throw new Error("An image source is required. Please provide a `src` or `imageProps.src`.");const n=s??document.createElement("div"),o=w(i.src,m,r),a={width:r.width,height:r.height,crop:void 0,fit:void 0,auto:void 0},c={...i,width:r.width,height:r.height,src:o,params:a};f.render(g,c)(n),t.replaceWith(n)}}function V(e,t){function s(){const i=t.wrapper??document.createElement("div"),{imageProps:n,params:o}=t,a={...n,width:o.width,height:o.height};f.render(g,a)(i),e.replaceWith(i)}if(!h()){s();return}if(!t.imageProps.src)throw new Error("An image source is required. Please provide a `src` or `imageProps.src`.");const r=new URL(l(t.imageProps.src));if(!A(r)){s();return}_(t)(e)}export{w as generateAemAssetsOptimizedUrl,R as getDefaultAemAssetsOptimizationParams,h as isAemAssetsEnabled,A as isAemAssetsUrl,_ as makeAemAssetsImageSlot,M as tryGenerateAemAssetsOptimizedUrl,V as tryRenderAemAssetsImage};
3
+ import{getConfigValue as O}from"./configs.js";import{p as f,I as g}from"../../chunks/Image.js";import"../../chunks/cjs.js";import"../../chunks/get-path-value.js";import"../../chunks/preact-vendor.js";import"../../chunks/vcomponent.js";import"../../chunks/image-params-keymap.js";import"../../signals.js";const b=["gif","jpg","jpeg","png","webp"],v=[90,180,270],U=["h","v","hv"];function l(e){let t=e;if(t.startsWith("//")){const{protocol:s}=window.location;t=s+t}return t}function I(e){return U.includes(e)}function L(e){return v.includes(e)}function y(e){return b.includes(e)}function u(e,t,s){if(e!==void 0&&!t(e))throw new Error(s)}function h(){const e=O("commerce-assets-enabled");return e&&(typeof e=="string"&&e.toLowerCase()==="true"||typeof e=="boolean"&&e===!0)}function R(){return{quality:80,format:"webp"}}function A(e){return!!(typeof e=="string"?new URL(l(e)):e).pathname.startsWith("/adobe/assets/urn:aaid:aem")}function w(e,t,s={}){const r={...R(),...s},{format:i,crop:n,...o}=r;u(i,y,"Invalid format"),u(o.flip,I,"Invalid flip"),u(o.rotate,L,"Invalid rotation");const a=Object.fromEntries(Object.entries(o).map(([p,d])=>[p,String(d)])),c=new URLSearchParams(a);if(n){const[p,d]=[n.xOrigin||0,n.yOrigin||0],[P,E]=[n.width||100,n.height||100],S=`${p}p,${d}p,${P}p,${E}p`;c.set("crop",S)}return`${e}/as/${t}.${i}?${c.toString()}`}function M(e,t,s={}){if(!h())return e;const r=new URL(l(e));if(!A(r))return e;const i=r.origin+r.pathname;return w(i,t,s)}function _(e){return t=>{const{wrapper:s,alias:m,params:r,imageProps:i}=e;if(!i.src)throw new Error("An image source is required. Please provide a `src` or `imageProps.src`.");const n=s??document.createElement("div"),o=w(i.src,m,r),a={width:r.width,height:r.height,crop:void 0,fit:void 0,auto:void 0},c={...i,width:r.width,height:r.height,src:o,params:a};f.render(g,c)(n),t.replaceWith(n)}}function V(e,t){function s(){const i=t.wrapper??document.createElement("div"),{imageProps:n,params:o}=t,a={...n,width:o.width,height:o.height};f.render(g,a)(i),e.replaceWith(i)}if(!h()){s();return}if(!t.imageProps.src)throw new Error("An image source is required. Please provide a `src` or `imageProps.src`.");const r=new URL(l(t.imageProps.src));if(!A(r)){s();return}_(t)(e)}export{w as generateAemAssetsOptimizedUrl,R as getDefaultAemAssetsOptimizationParams,h as isAemAssetsEnabled,A as isAemAssetsUrl,_ as makeAemAssetsImageSlot,M as tryGenerateAemAssetsOptimizedUrl,V as tryRenderAemAssetsImage};
4
4
  //# sourceMappingURL=assets.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sources":["/@dropins/tools/src/lib/aem/assets.ts"],"sourcesContent":["import {\n provider as UI,\n Image,\n type ImageProps,\n} from '@adobe-commerce/elsie/components';\n\nimport { getConfigValue } from '@adobe-commerce/elsie/lib/aem/configs';\nimport type { ResolveImageUrlOptions } from '../resolve-image';\n\nconst AEM_ASSETS_FORMATS = ['gif', 'jpg', 'jpeg', 'png', 'webp'] as const;\nconst AEM_ASSETS_ALLOWED_ROTATIONS = [90, 180, 270] as const;\nconst AEM_ASSETS_ALLOWED_FLIPS = ['h', 'v', 'hv'] as const;\n\n/** The allowed formats for the `AEM Assets` image optimization API. */\nexport type AemAssetsFormat = (typeof AEM_ASSETS_FORMATS)[number];\n\n/** The allowed rotations for the `AEM Assets` image optimization API. */\nexport type AemAssetsRotation = (typeof AEM_ASSETS_ALLOWED_ROTATIONS)[number];\n\n/** The allowed flips for the `AEM Assets` image optimization API. */\nexport type AemAssetsFlip = (typeof AEM_ASSETS_ALLOWED_FLIPS)[number];\n\n/**\n * Defines a crop region of an image.\n * @example\n * ```ts\n * // Crop the image to a 80% width and height, starting at 10% from the top and left.\n * const cropSettings: AemAssetsCropSettings = {\n * xOrigin: 10,\n * yOrigin: 10,\n * width: 80,\n * height: 80,\n * };\n */\nexport interface AemAssetsCropSettings {\n /** The (relative) x origin of the crop (between 0 and 100) */\n xOrigin?: number;\n\n /** The (relative) y origin of the crop (between 0 and 100) */\n yOrigin?: number;\n\n /** The width of the crop (between 0 and 100) */\n width?: number;\n\n /** The height of the crop (between 0 and 100) */\n height?: number;\n}\n\n/**\n * The parameters accepted by the `AEM Assets` image optimization API.\n * @see https://adobe-aem-assets-delivery-experimental.redoc.ly/\n */\nexport interface AemAssetsParams {\n format: AemAssetsFormat;\n rotate?: AemAssetsRotation;\n flip?: AemAssetsFlip;\n crop?: AemAssetsCropSettings;\n\n width?: number;\n height?: number;\n quality?: number;\n\n attachment?: boolean;\n sharpen?: boolean;\n blur?: number;\n dpr?: number;\n smartCrop?: string;\n\n // For future updates we may miss.\n [key: string]: unknown;\n}\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\n/** The parameters to be applied to the asset (known width required when using a slot) */\nexport type AemAssetsImageSlotConfigParams = WithRequired<\n Partial<AemAssetsParams>,\n 'width'\n>;\n\n/** The configuration for an image slot. */\nexport interface AemAssetsImageSlotConfig {\n /** The alias (i.e. seoName) of the image */\n alias: string;\n\n /** The props to be applied to the underlying {@link Image} component */\n imageProps: Partial<Omit<ImageProps, 'params' | 'width' | 'height'>> & {\n src: string;\n };\n\n /** The parameters to be applied to the asset (known width required when using a slot) */\n params: AemAssetsImageSlotConfigParams;\n\n /** The element that will contain the image in the slot */\n wrapper?: HTMLElement;\n}\n\ninterface RenderContext {\n replaceWith: (element: HTMLElement) => void;\n}\n\n/**\n * Normalizes the given URL to ensure it is a valid URL.\n * @param {string} url - The URL to normalize.\n * @returns {string} The normalized URL.\n */\nfunction normalizeUrl(url: string): string {\n let imageUrl = url;\n\n if (imageUrl.startsWith('//')) {\n // Use current window's protocol.\n const { protocol } = window.location;\n imageUrl = protocol + imageUrl;\n }\n\n return imageUrl;\n}\n\n/** Returns whether the given value is a valid flip. */\nfunction isValidFlip(flip: unknown): flip is AemAssetsFlip {\n return AEM_ASSETS_ALLOWED_FLIPS.includes(flip as AemAssetsFlip);\n}\n\n/** Returns whether the given value is a valid rotation. */\nfunction isValidRotation(rotation: unknown): rotation is AemAssetsRotation {\n return AEM_ASSETS_ALLOWED_ROTATIONS.includes(rotation as AemAssetsRotation);\n}\n\n/** Returns whether the given value is a valid format. */\nfunction isValidFormat(format: unknown): format is AemAssetsFormat {\n return AEM_ASSETS_FORMATS.includes(format as AemAssetsFormat);\n}\n\n/** Asserts that the given value is valid. */\nfunction assertUnionParameter(\n value: unknown,\n validator: (value: unknown) => boolean,\n errorMessage: string\n): void {\n if (value !== undefined && !validator(value)) {\n throw new Error(errorMessage);\n }\n}\n\n/** Returns whether AEM Assets is enabled in the Storefront. */\nexport function isAemAssetsEnabled(): boolean {\n const config = getConfigValue('commerce-assets-enabled');\n\n return (\n config &&\n ((typeof config === 'string' && config.toLowerCase() === 'true') ||\n (typeof config === 'boolean' && config === true))\n );\n}\n\n/** The default optimization parameters used globally, unless overriden (per use). */\nexport function getDefaultAemAssetsOptimizationParams(): AemAssetsParams {\n // See: https://adobe-aem-assets-delivery-experimental.redoc.ly/\n return {\n quality: 80,\n format: 'webp',\n };\n}\n\n/** Returns true if the given URL is an AEM Assets URL. */\nexport function isAemAssetsUrl(url: string | URL): boolean {\n const assetsUrl = typeof url === 'string' ? new URL(normalizeUrl(url)) : url;\n\n if (!assetsUrl.pathname.startsWith('/adobe/assets/urn:aaid:aem')) {\n return false;\n }\n\n return true;\n}\n\n/** Generates an optimized URL for AEM Assets. */\nexport function generateAemAssetsOptimizedUrl(\n assetUrl: string,\n alias: string,\n params: Partial<AemAssetsParams> = {}\n): string {\n const defaultParams = getDefaultAemAssetsOptimizationParams();\n const mergedParams: AemAssetsParams = { ...defaultParams, ...params };\n\n // Destructure the ones that need special handling/validation.\n const { format, crop, ...optimizedParams } = mergedParams;\n assertUnionParameter(format, isValidFormat, 'Invalid format');\n assertUnionParameter(optimizedParams.flip, isValidFlip, 'Invalid flip');\n assertUnionParameter(\n optimizedParams.rotate,\n isValidRotation,\n 'Invalid rotation'\n );\n\n const stringifiedParams = Object.fromEntries(\n Object.entries(optimizedParams).map(([key, value]) => [key, String(value)])\n );\n\n const searchParams = new URLSearchParams(stringifiedParams);\n\n if (crop) {\n const [xOrigin, yOrigin] = [crop.xOrigin || 0, crop.yOrigin || 0];\n const [width, height] = [crop.width || 100, crop.height || 100];\n\n const cropTransform = `${xOrigin}p,${yOrigin}p,${width}p,${height}p`;\n searchParams.set('crop', cropTransform);\n }\n\n return `${assetUrl}/as/${alias}.${format}?${searchParams.toString()}`;\n}\n\n/**\n * Tries to generate an optimized URL for AEM Assets. Returns the given\n * url if AEM Assets is not enabled or is not an AEM Assets URL.\n */\nexport function tryGenerateAemAssetsOptimizedUrl(\n assetUrl: string,\n alias: string,\n params: Partial<AemAssetsParams> = {}\n): string {\n const assetsEnabled = isAemAssetsEnabled();\n\n if (!assetsEnabled) {\n // No-op, doesn't do anything.\n return assetUrl;\n }\n\n const assetsUrl = new URL(normalizeUrl(assetUrl));\n\n if (!isAemAssetsUrl(assetsUrl)) {\n // Not an AEM Assets URL, so no-op.\n return assetUrl;\n }\n\n const base = assetsUrl.origin + assetsUrl.pathname;\n return generateAemAssetsOptimizedUrl(base, alias, params);\n}\n\n/** Creates a slot that renders an AEM Assets image. */\nexport function makeAemAssetsImageSlot(config: AemAssetsImageSlotConfig) {\n return (ctx: RenderContext) => {\n const { wrapper, alias, params, imageProps } = config;\n\n if (!imageProps.src) {\n throw new Error(\n 'An image source is required. Please provide a `src` or `imageProps.src`.'\n );\n }\n\n const container = wrapper ?? document.createElement('div');\n const imageSrc = generateAemAssetsOptimizedUrl(\n imageProps.src,\n alias,\n params\n );\n\n const imageComponentParams: ResolveImageUrlOptions = {\n width: params.width,\n height: params.height,\n\n // If this is not done, they will be applied by default.\n // And they are not compatible with the AEM Assets API.\n crop: undefined,\n fit: undefined,\n auto: undefined,\n };\n\n const imageComponentProps: ImageProps = {\n ...imageProps,\n width: params.width,\n height: params.height,\n\n src: imageSrc,\n params: imageComponentParams,\n };\n\n UI.render(Image, imageComponentProps)(container);\n ctx.replaceWith(container);\n };\n}\n\nexport function tryRenderAemAssetsImage(\n ctx: RenderContext,\n config: AemAssetsImageSlotConfig\n): void {\n // Renders an equivalent of the default image.\n function renderDefaultImage(): void {\n const container = config.wrapper ?? document.createElement('div');\n const { imageProps, params } = config;\n const imageComponentProps: ImageProps = {\n ...imageProps,\n width: params.width,\n height: params.height,\n };\n\n UI.render(Image, imageComponentProps)(container);\n ctx.replaceWith(container);\n }\n\n const assetsEnabled = isAemAssetsEnabled();\n\n if (!assetsEnabled) {\n // No-op, render the default image.\n renderDefaultImage();\n return;\n }\n\n if (!config.imageProps.src) {\n throw new Error(\n 'An image source is required. Please provide a `src` or `imageProps.src`.'\n );\n }\n\n const assetsUrl = new URL(normalizeUrl(config.imageProps.src));\n\n if (!isAemAssetsUrl(assetsUrl)) {\n // Not an AEM Assets URL, so render the default image.\n renderDefaultImage();\n return;\n }\n\n makeAemAssetsImageSlot(config)(ctx);\n}\n"],"names":["AEM_ASSETS_FORMATS","AEM_ASSETS_ALLOWED_ROTATIONS","AEM_ASSETS_ALLOWED_FLIPS","normalizeUrl","url","imageUrl","protocol","isValidFlip","flip","isValidRotation","rotation","isValidFormat","format","assertUnionParameter","value","validator","errorMessage","isAemAssetsEnabled","config","getConfigValue","getDefaultAemAssetsOptimizationParams","isAemAssetsUrl","generateAemAssetsOptimizedUrl","assetUrl","alias","params","mergedParams","crop","optimizedParams","stringifiedParams","key","searchParams","xOrigin","yOrigin","width","height","cropTransform","tryGenerateAemAssetsOptimizedUrl","assetsUrl","base","makeAemAssetsImageSlot","ctx","wrapper","imageProps","container","imageSrc","imageComponentParams","imageComponentProps","UI","Image","tryRenderAemAssetsImage","renderDefaultImage"],"mappings":"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"}
1
+ {"version":3,"file":"assets.js","sources":["/@dropins/tools/src/lib/aem/assets.ts"],"sourcesContent":["import {\n provider as UI,\n Image,\n type ImageProps,\n} from '@adobe-commerce/elsie/components';\n\nimport { getConfigValue } from '@adobe-commerce/elsie/lib/aem/configs';\nimport type { ResolveImageUrlOptions } from '../resolve-image';\n\nconst AEM_ASSETS_FORMATS = ['gif', 'jpg', 'jpeg', 'png', 'webp'] as const;\nconst AEM_ASSETS_ALLOWED_ROTATIONS = [90, 180, 270] as const;\nconst AEM_ASSETS_ALLOWED_FLIPS = ['h', 'v', 'hv'] as const;\n\n/** The allowed formats for the `AEM Assets` image optimization API. */\nexport type AemAssetsFormat = (typeof AEM_ASSETS_FORMATS)[number];\n\n/** The allowed rotations for the `AEM Assets` image optimization API. */\nexport type AemAssetsRotation = (typeof AEM_ASSETS_ALLOWED_ROTATIONS)[number];\n\n/** The allowed flips for the `AEM Assets` image optimization API. */\nexport type AemAssetsFlip = (typeof AEM_ASSETS_ALLOWED_FLIPS)[number];\n\n/**\n * Defines a crop region of an image.\n * @example\n * ```ts\n * // Crop the image to a 80% width and height, starting at 10% from the top and left.\n * const cropSettings: AemAssetsCropSettings = {\n * xOrigin: 10,\n * yOrigin: 10,\n * width: 80,\n * height: 80,\n * };\n */\nexport interface AemAssetsCropSettings {\n /** The (relative) x origin of the crop (between 0 and 100) */\n xOrigin?: number;\n\n /** The (relative) y origin of the crop (between 0 and 100) */\n yOrigin?: number;\n\n /** The width of the crop (between 0 and 100) */\n width?: number;\n\n /** The height of the crop (between 0 and 100) */\n height?: number;\n}\n\n/**\n * The parameters accepted by the `AEM Assets` image optimization API.\n * @see https://adobe-aem-assets-delivery-experimental.redoc.ly/\n */\nexport interface AemAssetsParams {\n format: AemAssetsFormat;\n rotate?: AemAssetsRotation;\n flip?: AemAssetsFlip;\n crop?: AemAssetsCropSettings;\n\n width?: number;\n height?: number;\n quality?: number;\n\n attachment?: boolean;\n sharpen?: boolean;\n blur?: number;\n dpr?: number;\n smartCrop?: string;\n\n // For future updates we may miss.\n [key: string]: unknown;\n}\n\ntype WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };\n\n/** The parameters to be applied to the asset (known width required when using a slot) */\nexport type AemAssetsImageSlotConfigParams = WithRequired<\n Partial<AemAssetsParams>,\n 'width'\n>;\n\n/** The configuration for an image slot. */\nexport interface AemAssetsImageSlotConfig {\n /** The alias (i.e. seoName) of the image */\n alias: string;\n\n /** The props to be applied to the underlying {@link Image} component */\n imageProps: Partial<Omit<ImageProps, 'params' | 'width' | 'height'>> & {\n src: string;\n };\n\n /** The parameters to be applied to the asset (known width required when using a slot) */\n params: AemAssetsImageSlotConfigParams;\n\n /** The element that will contain the image in the slot */\n wrapper?: HTMLElement;\n}\n\ninterface RenderContext {\n replaceWith: (element: HTMLElement) => void;\n}\n\n/**\n * Normalizes the given URL to ensure it is a valid URL.\n * @param {string} url - The URL to normalize.\n * @returns {string} The normalized URL.\n */\nfunction normalizeUrl(url: string): string {\n let imageUrl = url;\n\n if (imageUrl.startsWith('//')) {\n // Use current window's protocol.\n const { protocol } = window.location;\n imageUrl = protocol + imageUrl;\n }\n\n return imageUrl;\n}\n\n/** Returns whether the given value is a valid flip. */\nfunction isValidFlip(flip: unknown): flip is AemAssetsFlip {\n return AEM_ASSETS_ALLOWED_FLIPS.includes(flip as AemAssetsFlip);\n}\n\n/** Returns whether the given value is a valid rotation. */\nfunction isValidRotation(rotation: unknown): rotation is AemAssetsRotation {\n return AEM_ASSETS_ALLOWED_ROTATIONS.includes(rotation as AemAssetsRotation);\n}\n\n/** Returns whether the given value is a valid format. */\nfunction isValidFormat(format: unknown): format is AemAssetsFormat {\n return AEM_ASSETS_FORMATS.includes(format as AemAssetsFormat);\n}\n\n/** Asserts that the given value is valid. */\nfunction assertUnionParameter(\n value: unknown,\n validator: (value: unknown) => boolean,\n errorMessage: string,\n): void {\n if (value !== undefined && !validator(value)) {\n throw new Error(errorMessage);\n }\n}\n\n/** Returns whether AEM Assets is enabled in the Storefront. */\nexport function isAemAssetsEnabled(): boolean {\n const config = getConfigValue('commerce-assets-enabled');\n\n return (\n config &&\n ((typeof config === 'string' && config.toLowerCase() === 'true') ||\n (typeof config === 'boolean' && config === true))\n );\n}\n\n/** The default optimization parameters used globally, unless overriden (per use). */\nexport function getDefaultAemAssetsOptimizationParams(): AemAssetsParams {\n // See: https://adobe-aem-assets-delivery-experimental.redoc.ly/\n return {\n quality: 80,\n format: 'webp',\n };\n}\n\n/** Returns true if the given URL is an AEM Assets URL. */\nexport function isAemAssetsUrl(url: string | URL): boolean {\n const assetsUrl = typeof url === 'string' ? new URL(normalizeUrl(url)) : url;\n\n if (!assetsUrl.pathname.startsWith('/adobe/assets/urn:aaid:aem')) {\n return false;\n }\n\n return true;\n}\n\n/** Generates an optimized URL for AEM Assets. */\nexport function generateAemAssetsOptimizedUrl(\n assetUrl: string,\n alias: string,\n params: Partial<AemAssetsParams> = {},\n): string {\n const defaultParams = getDefaultAemAssetsOptimizationParams();\n const mergedParams: AemAssetsParams = { ...defaultParams, ...params };\n\n // Destructure the ones that need special handling/validation.\n const { format, crop, ...optimizedParams } = mergedParams;\n assertUnionParameter(format, isValidFormat, 'Invalid format');\n assertUnionParameter(optimizedParams.flip, isValidFlip, 'Invalid flip');\n assertUnionParameter(\n optimizedParams.rotate,\n isValidRotation,\n 'Invalid rotation',\n );\n\n const stringifiedParams = Object.fromEntries(\n Object.entries(optimizedParams).map(([key, value]) => [key, String(value)]),\n );\n\n const searchParams = new URLSearchParams(stringifiedParams);\n\n if (crop) {\n const [xOrigin, yOrigin] = [crop.xOrigin || 0, crop.yOrigin || 0];\n const [width, height] = [crop.width || 100, crop.height || 100];\n\n const cropTransform = `${xOrigin}p,${yOrigin}p,${width}p,${height}p`;\n searchParams.set('crop', cropTransform);\n }\n\n return `${assetUrl}/as/${alias}.${format}?${searchParams.toString()}`;\n}\n\n/**\n * Tries to generate an optimized URL for AEM Assets. Returns the given\n * url if AEM Assets is not enabled or is not an AEM Assets URL.\n */\nexport function tryGenerateAemAssetsOptimizedUrl(\n assetUrl: string,\n alias: string,\n params: Partial<AemAssetsParams> = {},\n): string {\n const assetsEnabled = isAemAssetsEnabled();\n\n if (!assetsEnabled) {\n // No-op, doesn't do anything.\n return assetUrl;\n }\n\n const assetsUrl = new URL(normalizeUrl(assetUrl));\n\n if (!isAemAssetsUrl(assetsUrl)) {\n // Not an AEM Assets URL, so no-op.\n return assetUrl;\n }\n\n const base = assetsUrl.origin + assetsUrl.pathname;\n return generateAemAssetsOptimizedUrl(base, alias, params);\n}\n\n/** Creates a slot that renders an AEM Assets image. */\nexport function makeAemAssetsImageSlot(config: AemAssetsImageSlotConfig) {\n return (ctx: RenderContext) => {\n const { wrapper, alias, params, imageProps } = config;\n\n if (!imageProps.src) {\n throw new Error(\n 'An image source is required. Please provide a `src` or `imageProps.src`.',\n );\n }\n\n const container = wrapper ?? document.createElement('div');\n const imageSrc = generateAemAssetsOptimizedUrl(\n imageProps.src,\n alias,\n params,\n );\n\n const imageComponentParams: ResolveImageUrlOptions = {\n width: params.width,\n height: params.height,\n\n // If this is not done, they will be applied by default.\n // And they are not compatible with the AEM Assets API.\n crop: undefined,\n fit: undefined,\n auto: undefined,\n };\n\n const imageComponentProps: ImageProps = {\n ...imageProps,\n width: params.width,\n height: params.height,\n\n src: imageSrc,\n params: imageComponentParams,\n };\n\n UI.render(Image, imageComponentProps)(container);\n ctx.replaceWith(container);\n };\n}\n\nexport function tryRenderAemAssetsImage(\n ctx: RenderContext,\n config: AemAssetsImageSlotConfig,\n): void {\n // Renders an equivalent of the default image.\n function renderDefaultImage(): void {\n const container = config.wrapper ?? document.createElement('div');\n const { imageProps, params } = config;\n const imageComponentProps: ImageProps = {\n ...imageProps,\n width: params.width,\n height: params.height,\n };\n\n UI.render(Image, imageComponentProps)(container);\n ctx.replaceWith(container);\n }\n\n const assetsEnabled = isAemAssetsEnabled();\n\n if (!assetsEnabled) {\n // No-op, render the default image.\n renderDefaultImage();\n return;\n }\n\n if (!config.imageProps.src) {\n throw new Error(\n 'An image source is required. Please provide a `src` or `imageProps.src`.',\n );\n }\n\n const assetsUrl = new URL(normalizeUrl(config.imageProps.src));\n\n if (!isAemAssetsUrl(assetsUrl)) {\n // Not an AEM Assets URL, so render the default image.\n renderDefaultImage();\n return;\n }\n\n makeAemAssetsImageSlot(config)(ctx);\n}\n"],"names":["AEM_ASSETS_FORMATS","AEM_ASSETS_ALLOWED_ROTATIONS","AEM_ASSETS_ALLOWED_FLIPS","normalizeUrl","url","imageUrl","protocol","isValidFlip","flip","isValidRotation","rotation","isValidFormat","format","assertUnionParameter","value","validator","errorMessage","isAemAssetsEnabled","config","getConfigValue","getDefaultAemAssetsOptimizationParams","isAemAssetsUrl","generateAemAssetsOptimizedUrl","assetUrl","alias","params","mergedParams","crop","optimizedParams","stringifiedParams","key","searchParams","xOrigin","yOrigin","width","height","cropTransform","tryGenerateAemAssetsOptimizedUrl","assetsUrl","base","makeAemAssetsImageSlot","ctx","wrapper","imageProps","container","imageSrc","imageComponentParams","imageComponentProps","UI","Image","tryRenderAemAssetsImage","renderDefaultImage"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  /*! Copyright 2026 Adobe
2
2
  All Rights Reserved. */
3
- import{g as c}from"../../chunks/get-path-value.js";import{d as s}from"../../chunks/cjs.js";let l=null,f=null,u=null,i=null;function z(){l=null,f=null,u=null,i=null}function g(t=l,e=f){return t?Object.keys(t==null?void 0:t.public).sort((n,r)=>{const o=n.split("/").filter(Boolean).length;return r.split("/").filter(Boolean).length-o}).find(n=>{var r;return window.location.pathname===n||(((r=e==null?void 0:e.match)==null?void 0:r.call(e,n))??window.location.pathname.startsWith(n))})??"/":(console.warn("No config found. Please call initializeConfig() first."),"/")}function h(){return l?Object.keys(l.public).filter(t=>t!=="default"&&t.startsWith("/")):(console.warn("No config found. Please call initializeConfig() first."),[])}function P(){return h().length>=1}function p(t){if(!i)throw new Error("Configuration not initialized. Call initializeConfig() first.");const e=i.headers??{};return{...e.all??{},...e[t]??{}}}function d(t,e){var n;const a=(n=t.public)==null?void 0:n.default;return e==="/"||!t.public[e]?a:s(a,t.public[e])}function v(t,e){return l=t,f=e??null,u=g(l,{match:e==null?void 0:e.match}),i=d(l,u),i}function S(t){if(!i)throw new Error("Configuration not initialized. Call initializeConfig() first.");return c(i,t)}export{S as getConfigValue,p as getHeaders,h as getListOfRootPaths,g as getRootPath,v as initializeConfig,P as isMultistore,z as resetConfig};
3
+ import{d as c}from"../../chunks/cjs.js";import{g as s}from"../../chunks/get-path-value.js";let l=null,f=null,u=null,i=null;function z(){l=null,f=null,u=null,i=null}function g(t=l,e=f){return t?Object.keys(t==null?void 0:t.public).sort((n,r)=>{const o=n.split("/").filter(Boolean).length;return r.split("/").filter(Boolean).length-o}).find(n=>{var r;return window.location.pathname===n||(((r=e==null?void 0:e.match)==null?void 0:r.call(e,n))??window.location.pathname.startsWith(n))})??"/":(console.warn("No config found. Please call initializeConfig() first."),"/")}function h(){return l?Object.keys(l.public).filter(t=>t!=="default"&&t.startsWith("/")):(console.warn("No config found. Please call initializeConfig() first."),[])}function P(){return h().length>=1}function p(t){if(!i)throw new Error("Configuration not initialized. Call initializeConfig() first.");const e=i.headers??{};return{...e.all??{},...e[t]??{}}}function d(t,e){var n;const a=(n=t.public)==null?void 0:n.default;return e==="/"||!t.public[e]?a:c(a,t.public[e])}function v(t,e){return l=t,f=e??null,u=g(l,{match:e==null?void 0:e.match}),i=d(l,u),i}function S(t){if(!i)throw new Error("Configuration not initialized. Call initializeConfig() first.");return s(i,t)}export{S as getConfigValue,p as getHeaders,h as getListOfRootPaths,g as getRootPath,v as initializeConfig,P as isMultistore,z as resetConfig};
4
4
  //# sourceMappingURL=configs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"configs.js","sources":["/@dropins/tools/src/lib/aem/configs.ts"],"sourcesContent":["import { deepmerge } from '../deepmerge';\nimport { getPathValue } from '../get-path-value';\n\ninterface ConfigHeaders {\n all?: Record<string, string>;\n [key: string]: Record<string, string> | undefined;\n}\n\ninterface ConfigPublic {\n default: ConfigRoot;\n [key: string]: ConfigRoot;\n}\n\ninterface ConfigRoot {\n headers?: ConfigHeaders;\n [key: string]: any;\n}\n\ninterface Config {\n public: ConfigPublic;\n [key: string]: any;\n}\n\n// Private state\nlet config: Config | null = null;\nlet options: { match?: (key: string) => boolean } | null = null;\nlet rootPath: string | null = null;\nlet rootConfig: ConfigRoot | null = null;\n\n/**\n * Reset the config state\n */\nfunction resetConfig() {\n config = null;\n options = null;\n rootPath = null;\n rootConfig = null;\n}\n\n/**\n * Get root path\n * @param {Object} [configObj=config] - The config object.\n * @returns {string} - The root path.\n */\nfunction getRootPath(configObj: Config | null = config, optionsObj: { match?: (key: string) => boolean } | null = options): string {\n if (!configObj) {\n console.warn('No config found. Please call initializeConfig() first.');\n return '/';\n }\n\n const value = Object.keys(configObj?.public)\n // Sort by number of non-empty segments to find the deepest path\n .sort((a, b) => {\n const aSegments = a.split('/').filter(Boolean).length;\n const bSegments = b.split('/').filter(Boolean).length;\n return bSegments - aSegments;\n })\n .find(\n (key) =>\n window.location.pathname === key ||\n (optionsObj?.match?.(key) ?? window.location.pathname.startsWith(key))\n );\n\n return value ?? '/';\n}\n\n/**\n * Get list of root paths from public config\n * @returns {Array} - The list of root paths.\n */\nfunction getListOfRootPaths(): string[] {\n if (!config) {\n console.warn('No config found. Please call initializeConfig() first.');\n return [];\n }\n\n return Object.keys(config.public).filter((root) => root !== 'default' && root.startsWith('/'));\n}\n\n/**\n * Checks if the public config contains more than \"default\"\n * @returns {boolean} - true if public config contains more than \"default\"\n */\nfunction isMultistore(): boolean {\n return getListOfRootPaths().length >= 1;\n}\n\n/**\n * Retrieves headers from config entries like commerce.headers.pdp.my-header, etc and\n * returns as object of all headers like { my-header: value, ... }\n * @param {string} scope - The scope of the headers to retrieve.\n * @returns {Object} - The headers.\n */\nfunction getHeaders(scope: string): Record<string, string> {\n if (!rootConfig) {\n throw new Error(\n 'Configuration not initialized. Call initializeConfig() first.'\n );\n }\n const headers = rootConfig.headers ?? {};\n return {\n ...(headers.all ?? {}),\n ...(headers[scope] ?? {}),\n };\n}\n\n/**\n * Applies config overrides from metadata.\n *\n * @param {Object} [configObj] - The base config.\n * @param {string} [root] - The root path.\n * @returns {Object} - The config with overrides applied.\n */\nfunction applyConfigOverrides(\n configObj: Config | null,\n root: string | null\n): ConfigRoot {\n const defaultConfig = configObj!.public?.default;\n\n if (root === '/' || !configObj!.public[root as keyof ConfigPublic])\n return defaultConfig;\n\n return deepmerge(\n defaultConfig,\n configObj!.public[root as keyof ConfigPublic]\n );\n}\n\n/**\n * Initializes the configuration system.\n * @param {Object} configObj - The config object.\n * @param {Object} [options] - The options object.\n * @param {Function} [options.match] - The function to match the path to the config.\n * @returns {Object} The initialized root configuration\n */\nfunction initializeConfig(configObj: Config, optionsObj?: { match?: (key: string) => boolean }): ConfigRoot {\n config = configObj;\n options = optionsObj ?? null;\n rootPath = getRootPath(config, { match: optionsObj?.match });\n rootConfig = applyConfigOverrides(config, rootPath);\n return rootConfig;\n}\n\n/**\n * Retrieves a configuration value.\n *\n * @param {string} configParam - The configuration parameter to retrieve.\n * @returns {string|undefined} - The value of the configuration parameter, or undefined.\n */\nfunction getConfigValue(configParam: string): any {\n if (!rootConfig) {\n throw new Error(\n 'Configuration not initialized. Call initializeConfig() first.'\n );\n }\n return getPathValue(rootConfig, configParam);\n}\n\nexport {\n initializeConfig,\n getRootPath,\n getListOfRootPaths,\n isMultistore,\n getConfigValue,\n getHeaders,\n resetConfig,\n};\n"],"names":["config","options","rootPath","rootConfig","resetConfig","getRootPath","configObj","optionsObj","a","b","aSegments","key","_a","getListOfRootPaths","root","isMultistore","getHeaders","scope","headers","applyConfigOverrides","defaultConfig","deepmerge","initializeConfig","getConfigValue","configParam","getPathValue"],"mappings":"2FAwBA,IAAIA,EAAwB,KACxBC,EAAuD,KACvDC,EAA0B,KAC1BC,EAAgC,KAKpC,SAASC,GAAc,CACrBJ,EAAS,KACTC,EAAU,KACVC,EAAW,KACXC,EAAa,IACf,CAOA,SAASE,EAAYC,EAA2BN,EAAQO,EAA0DN,EAAiB,CACjI,OAAKK,EAKS,OAAO,KAAKA,GAAA,YAAAA,EAAW,MAAM,EAExC,KAAK,CAACE,EAAGC,IAAM,CACd,MAAMC,EAAYF,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,OAE/C,OADkBC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,OAC5BC,CACrB,CAAC,EACA,KACEC,GAAA,OACC,cAAO,SAAS,WAAaA,MAC5BC,EAAAL,GAAA,YAAAA,EAAY,QAAZ,YAAAK,EAAA,KAAAL,EAAoBI,KAAQ,OAAO,SAAS,SAAS,WAAWA,CAAG,GAAA,GAG1D,KAjBd,QAAQ,KAAK,wDAAwD,EAC9D,IAiBX,CAMA,SAASE,GAA+B,CACtC,OAAKb,EAKE,OAAO,KAAKA,EAAO,MAAM,EAAE,OAAQc,GAASA,IAAS,WAAaA,EAAK,WAAW,GAAG,CAAC,GAJ3F,QAAQ,KAAK,wDAAwD,EAC9D,CAAA,EAIX,CAMA,SAASC,GAAwB,CAC/B,OAAOF,EAAA,EAAqB,QAAU,CACxC,CAQA,SAASG,EAAWC,EAAuC,CACzD,GAAI,CAACd,EACH,MAAM,IAAI,MACR,+DAAA,EAGJ,MAAMe,EAAUf,EAAW,SAAW,CAAA,EACtC,MAAO,CACL,GAAIe,EAAQ,KAAO,CAAA,EACnB,GAAIA,EAAQD,CAAK,GAAK,CAAA,CAAC,CAE3B,CASA,SAASE,EACPb,EACAQ,EACY,OACZ,MAAMM,GAAgBR,EAAAN,EAAW,SAAX,YAAAM,EAAmB,QAEzC,OAAIE,IAAS,KAAO,CAACR,EAAW,OAAOQ,CAA0B,EACxDM,EAEFC,EACLD,EACAd,EAAW,OAAOQ,CAA0B,CAAA,CAEhD,CASA,SAASQ,EAAiBhB,EAAmBC,EAA+D,CAC1G,OAAAP,EAASM,EACTL,EAAUM,GAAc,KACxBL,EAAWG,EAAYL,EAAQ,CAAE,MAAOO,GAAA,YAAAA,EAAY,MAAO,EAC3DJ,EAAagB,EAAqBnB,EAAQE,CAAQ,EAC3CC,CACT,CAQA,SAASoB,EAAeC,EAA0B,CAChD,GAAI,CAACrB,EACH,MAAM,IAAI,MACR,+DAAA,EAGJ,OAAOsB,EAAatB,EAAYqB,CAAW,CAC7C"}
1
+ {"version":3,"file":"configs.js","sources":["/@dropins/tools/src/lib/aem/configs.ts"],"sourcesContent":["import { deepmerge } from '../deepmerge';\nimport { getPathValue } from '../get-path-value';\n\ninterface ConfigHeaders {\n all?: Record<string, string>;\n [key: string]: Record<string, string> | undefined;\n}\n\ninterface ConfigPublic {\n default: ConfigRoot;\n [key: string]: ConfigRoot;\n}\n\ninterface ConfigRoot {\n headers?: ConfigHeaders;\n [key: string]: any;\n}\n\ninterface Config {\n public: ConfigPublic;\n [key: string]: any;\n}\n\n// Private state\nlet config: Config | null = null;\nlet options: { match?: (key: string) => boolean } | null = null;\nlet rootPath: string | null = null;\nlet rootConfig: ConfigRoot | null = null;\n\n/**\n * Reset the config state\n */\nfunction resetConfig() {\n config = null;\n options = null;\n rootPath = null;\n rootConfig = null;\n}\n\n/**\n * Get root path\n * @param {Object} [configObj=config] - The config object.\n * @returns {string} - The root path.\n */\nfunction getRootPath(\n configObj: Config | null = config,\n optionsObj: { match?: (key: string) => boolean } | null = options,\n): string {\n if (!configObj) {\n console.warn('No config found. Please call initializeConfig() first.');\n return '/';\n }\n\n const value = Object.keys(configObj?.public)\n // Sort by number of non-empty segments to find the deepest path\n .sort((a, b) => {\n const aSegments = a.split('/').filter(Boolean).length;\n const bSegments = b.split('/').filter(Boolean).length;\n return bSegments - aSegments;\n })\n .find(\n (key) =>\n window.location.pathname === key ||\n (optionsObj?.match?.(key) ?? window.location.pathname.startsWith(key)),\n );\n\n return value ?? '/';\n}\n\n/**\n * Get list of root paths from public config\n * @returns {Array} - The list of root paths.\n */\nfunction getListOfRootPaths(): string[] {\n if (!config) {\n console.warn('No config found. Please call initializeConfig() first.');\n return [];\n }\n\n return Object.keys(config.public).filter(\n (root) => root !== 'default' && root.startsWith('/'),\n );\n}\n\n/**\n * Checks if the public config contains more than \"default\"\n * @returns {boolean} - true if public config contains more than \"default\"\n */\nfunction isMultistore(): boolean {\n return getListOfRootPaths().length >= 1;\n}\n\n/**\n * Retrieves headers from config entries like commerce.headers.pdp.my-header, etc and\n * returns as object of all headers like { my-header: value, ... }\n * @param {string} scope - The scope of the headers to retrieve.\n * @returns {Object} - The headers.\n */\nfunction getHeaders(scope: string): Record<string, string> {\n if (!rootConfig) {\n throw new Error(\n 'Configuration not initialized. Call initializeConfig() first.',\n );\n }\n const headers = rootConfig.headers ?? {};\n return {\n ...(headers.all ?? {}),\n ...(headers[scope] ?? {}),\n };\n}\n\n/**\n * Applies config overrides from metadata.\n *\n * @param {Object} [configObj] - The base config.\n * @param {string} [root] - The root path.\n * @returns {Object} - The config with overrides applied.\n */\nfunction applyConfigOverrides(\n configObj: Config | null,\n root: string | null,\n): ConfigRoot {\n const defaultConfig = configObj!.public?.default;\n\n if (root === '/' || !configObj!.public[root as keyof ConfigPublic])\n return defaultConfig;\n\n return deepmerge(\n defaultConfig,\n configObj!.public[root as keyof ConfigPublic],\n );\n}\n\n/**\n * Initializes the configuration system.\n * @param {Object} configObj - The config object.\n * @param {Object} [options] - The options object.\n * @param {Function} [options.match] - The function to match the path to the config.\n * @returns {Object} The initialized root configuration\n */\nfunction initializeConfig(\n configObj: Config,\n optionsObj?: { match?: (key: string) => boolean },\n): ConfigRoot {\n config = configObj;\n options = optionsObj ?? null;\n rootPath = getRootPath(config, { match: optionsObj?.match });\n rootConfig = applyConfigOverrides(config, rootPath);\n return rootConfig;\n}\n\n/**\n * Retrieves a configuration value.\n *\n * @param {string} configParam - The configuration parameter to retrieve.\n * @returns {string|undefined} - The value of the configuration parameter, or undefined.\n */\nfunction getConfigValue(configParam: string): any {\n if (!rootConfig) {\n throw new Error(\n 'Configuration not initialized. Call initializeConfig() first.',\n );\n }\n return getPathValue(rootConfig, configParam);\n}\n\nexport {\n initializeConfig,\n getRootPath,\n getListOfRootPaths,\n isMultistore,\n getConfigValue,\n getHeaders,\n resetConfig,\n};\n"],"names":["config","options","rootPath","rootConfig","resetConfig","getRootPath","configObj","optionsObj","a","b","aSegments","key","_a","getListOfRootPaths","root","isMultistore","getHeaders","scope","headers","applyConfigOverrides","defaultConfig","deepmerge","initializeConfig","getConfigValue","configParam","getPathValue"],"mappings":"2FAwBA,IAAIA,EAAwB,KACxBC,EAAuD,KACvDC,EAA0B,KAC1BC,EAAgC,KAKpC,SAASC,GAAc,CACrBJ,EAAS,KACTC,EAAU,KACVC,EAAW,KACXC,EAAa,IACf,CAOA,SAASE,EACPC,EAA2BN,EAC3BO,EAA0DN,EAClD,CACR,OAAKK,EAKS,OAAO,KAAKA,GAAA,YAAAA,EAAW,MAAM,EAExC,KAAK,CAACE,EAAGC,IAAM,CACd,MAAMC,EAAYF,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,OAE/C,OADkBC,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,OAC5BC,CACrB,CAAC,EACA,KACEC,GAAA,OACC,cAAO,SAAS,WAAaA,MAC5BC,EAAAL,GAAA,YAAAA,EAAY,QAAZ,YAAAK,EAAA,KAAAL,EAAoBI,KAAQ,OAAO,SAAS,SAAS,WAAWA,CAAG,GAAA,GAG1D,KAjBd,QAAQ,KAAK,wDAAwD,EAC9D,IAiBX,CAMA,SAASE,GAA+B,CACtC,OAAKb,EAKE,OAAO,KAAKA,EAAO,MAAM,EAAE,OAC/Bc,GAASA,IAAS,WAAaA,EAAK,WAAW,GAAG,CAAA,GALnD,QAAQ,KAAK,wDAAwD,EAC9D,CAAA,EAMX,CAMA,SAASC,GAAwB,CAC/B,OAAOF,EAAA,EAAqB,QAAU,CACxC,CAQA,SAASG,EAAWC,EAAuC,CACzD,GAAI,CAACd,EACH,MAAM,IAAI,MACR,+DAAA,EAGJ,MAAMe,EAAUf,EAAW,SAAW,CAAA,EACtC,MAAO,CACL,GAAIe,EAAQ,KAAO,CAAA,EACnB,GAAIA,EAAQD,CAAK,GAAK,CAAA,CAAC,CAE3B,CASA,SAASE,EACPb,EACAQ,EACY,OACZ,MAAMM,GAAgBR,EAAAN,EAAW,SAAX,YAAAM,EAAmB,QAEzC,OAAIE,IAAS,KAAO,CAACR,EAAW,OAAOQ,CAA0B,EACxDM,EAEFC,EACLD,EACAd,EAAW,OAAOQ,CAA0B,CAAA,CAEhD,CASA,SAASQ,EACPhB,EACAC,EACY,CACZ,OAAAP,EAASM,EACTL,EAAUM,GAAc,KACxBL,EAAWG,EAAYL,EAAQ,CAAE,MAAOO,GAAA,YAAAA,EAAY,MAAO,EAC3DJ,EAAagB,EAAqBnB,EAAQE,CAAQ,EAC3CC,CACT,CAQA,SAASoB,EAAeC,EAA0B,CAChD,GAAI,CAACrB,EACH,MAAM,IAAI,MACR,+DAAA,EAGJ,OAAOsB,EAAatB,EAAYqB,CAAW,CAC7C"}
package/lib.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lib.js","sources":["/@dropins/tools/src/lib/form-values.ts","/@dropins/tools/src/lib/deepmerge.ts","/@dropins/tools/src/lib/i18n.ts","/@dropins/tools/src/lib/slot.tsx","/@dropins/tools/src/lib/get-cookie.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const getFormValues = (form: HTMLFormElement) => {\n const formData: any = new FormData(form);\n const result = Object.fromEntries(formData);\n return result;\n};\n\nexport const getFormErrors = (form: HTMLFormElement) => {\n const formData: any = new FormData(form);\n\n const data = Object.fromEntries(formData);\n\n const result = Object.entries(data).reduce((result, [key]) => {\n // @ts-ignore\n const field = form.elements[key];\n\n return field?.validationMessage\n ? { ...result, [key]: field.validationMessage }\n : { ...result };\n }, {});\n\n return result;\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport deepmerge from 'deepmerge';\n\nexport { default as deepmerge } from 'deepmerge';\n\nconst mergeOptions = {\n arrayMerge: (target: any, source: any, options: any) => {\n const destination = target.slice();\n\n source.forEach((item: any, index: number) => {\n if (typeof destination[index] === 'undefined') {\n destination[index] = options.cloneUnlessOtherwiseSpecified(\n item,\n options\n );\n } else if (options.isMergeableObject(item)) {\n destination[index] = deepmerge(target[index], item, options);\n } else if (target.indexOf(item) === -1) {\n destination.push(item);\n }\n });\n return destination;\n },\n};\n\nexport function merge<T>(\n prev: T,\n next?: { [key: string]: any }\n) {\n if (!next) return prev;\n\n return deepmerge<T, { [key: string]: any }>(\n prev,\n next,\n mergeOptions\n );\n}\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\n/**\n * Convert locale from Magento standard to react-intl BCP 47 language tag\n *\n * @param {string} locale - A locale (e.g. `fr_FR`).\n * @returns {string} A BCP 47 language tag (e.g. `fr-FR`).\n */\nexport const toLanguageTag = (locale: string) => {\n return locale.replace('_', '-');\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { IntlContext, Lang } from '@adobe-commerce/elsie/i18n';\nimport {\n cloneElement,\n ComponentChildren,\n createElement,\n RefObject,\n VNode,\n} from 'preact';\nimport { Children, HTMLAttributes, isValidElement } from 'preact/compat';\nimport {\n StateUpdater,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\nimport { SlotQueueContext } from './render';\n\ntype MutateElement = (elem: HTMLElement) => void;\n\ninterface State {\n get: (key: string) => void;\n set: (key: string, value: any) => void;\n}\n\ninterface SlotElement {\n appendChild: MutateElement;\n prependChild: MutateElement;\n appendSibling: MutateElement;\n prependSibling: MutateElement;\n remove: () => void;\n}\n\ninterface PrivateContext<T> {\n _setProps: (s: StateUpdater<{}>) => void;\n _registerMethod: (\n cb: (next: T & DefaultSlotContext<T>, state: State) => void\n ) => void;\n // eslint-disable-next-line no-undef\n _htmlElementToVNode: (element: HTMLElement, tag: keyof HTMLElementTagNameMap) => VNode;\n}\n\ninterface DefaultSlotContext<T> extends PrivateContext<T> {\n dictionary: Lang;\n getSlotElement: (key: string) => SlotElement;\n replaceWith: MutateElement;\n appendChild: MutateElement;\n prependChild: MutateElement;\n appendSibling: MutateElement;\n prependSibling: MutateElement;\n remove: () => void;\n onRender: (cb: (next: T & DefaultSlotContext<T>) => void) => void;\n onChange: (cb: (next: T & DefaultSlotContext<T>) => void) => void;\n}\n\ntype Context<T> = T & ThisType<DefaultSlotContext<T>>; // NOSONAR\n\nexport type SlotProps<T = any> = (\n ctx: T & DefaultSlotContext<T>,\n element: HTMLDivElement | null\n) => Promise<void> | void;\n\nexport type SlotMethod<P = any> = (\n callback: (next: unknown, state: State) => P\n) => void;\n\n// Slot Hook\nexport function useSlot<K, V extends HTMLElement>(\n name: string,\n // @ts-ignore\n context: Context<K> = {},\n callback?: SlotProps<K>,\n children?: ComponentChildren,\n render?: Function,\n // eslint-disable-next-line no-undef\n contentTag: keyof HTMLElementTagNameMap = 'div'\n): [RefObject<V>, Record<string, any>, 'loading' | 'pending' | 'ready'] {\n const slotsQueue = useContext(SlotQueueContext);\n\n // HTML Element\n const elementRef = useRef<V>(null);\n\n const status = useRef<'pending' | 'ready' | 'loading'>('pending');\n\n // Methods\n const methodsRef = useRef<any>([]);\n\n // Children VNodes\n const [props, _setProps] = useState<Record<string, any>>({\n children: [children],\n });\n\n // Attributes\n const [_state, setState] = useState<any>({});\n\n const state = useMemo(\n () => ({\n get: (key: string) => _state[key],\n set: (key: string, value: any) => {\n setState({ ...state, [key]: value });\n },\n }),\n [_state]\n );\n\n /** Internationalization */\n // @ts-ignore\n const { intl }: any = useContext(IntlContext);\n\n // @ts-ignore\n context.dictionary = intl.dictionary;\n\n /** Privates */\n // @ts-ignore\n context._setProps = (next: State<any>) => {\n _setProps((prev) => {\n // next props\n const _next = typeof next === 'function' ? next(prev) : next;\n\n // On render method...\n if (render) {\n const renderNode = cloneElement(render(prev), { key: 'render' });\n\n // find index of existing render node\n const index = prev.children.findIndex((n: any) => n?.key === 'render');\n\n // replace existing render node\n prev.children[index] = renderNode;\n }\n\n return _next;\n });\n };\n\n const _registerMethod = useCallback((cb: Function) => {\n if (typeof cb === 'function') {\n methodsRef.current.push(cb);\n } else {\n console.warn('Skipped: Invalid _registerMethod', cb);\n }\n }, []);\n\n // @ts-ignore\n context._registerMethod = _registerMethod;\n\n const _htmlElementToVNode = useCallback(\n (elem: HTMLElement) => {\n return createElement(\n contentTag,\n {\n 'data-slot-html-element': elem.tagName.toLowerCase(),\n ref: (refElem: HTMLElement | null): void => {\n refElem?.appendChild(elem);\n },\n },\n null\n );\n },\n [contentTag]\n );\n\n // @ts-ignore\n context._htmlElementToVNode = _htmlElementToVNode;\n\n /** Prebuilt Methods */\n // @ts-ignore\n context.getSlotElement = useCallback(\n (key: string) => {\n const element = elementRef.current?.querySelector(\n `[data-slot-key=\"${key}\"]`\n );\n\n log(\n `🟦 \"${name}\" Slot getSlotElement: ${key}`,\n elementRef.current?.cloneNode(true),\n element?.cloneNode(true)\n );\n\n if (!element) return;\n\n return {\n appendChild: (elem: HTMLElement) => {\n element.appendChild(elem);\n },\n\n prependChild: (elem: HTMLElement) => {\n element.insertBefore(elem, element.firstChild);\n },\n\n appendSibling: (elem: HTMLElement) => {\n const parent = element.parentNode;\n parent?.insertBefore(elem, element.nextSibling);\n },\n\n prependSibling: (elem: HTMLElement) => {\n const parent = element.parentNode;\n parent?.insertBefore(elem, element);\n },\n\n remove: () => {\n element.remove();\n },\n };\n },\n [name]\n );\n\n // @ts-ignore\n context.onRender = useCallback((cb: Function) => {\n methodsRef.current.push(cb);\n }, []);\n\n /**\n * @deprecated Use `onRender` instead.\n */\n // @ts-ignore\n context.onChange = context.onRender;\n\n // @ts-ignore\n context.replaceWith = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod((next) => {\n // @ts-ignore\n const children = _htmlElementToVNode(elem);\n\n next._setProps({ children: [children] });\n });\n },\n [_htmlElementToVNode, _registerMethod]\n );\n\n // @ts-ignore\n context.appendChild = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod((next) => {\n // @ts-ignore\n const vnode = _htmlElementToVNode(elem);\n\n next._setProps((prev: any) => {\n return {\n ...prev,\n children: [...prev.children, vnode],\n };\n });\n });\n },\n [_htmlElementToVNode, _registerMethod]\n );\n\n // @ts-ignore\n context.prependChild = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod((next) => {\n // @ts-ignore\n const vnode = _htmlElementToVNode(elem);\n\n next._setProps((prev: any) => {\n return {\n ...prev,\n children: [vnode, ...prev.children],\n };\n });\n });\n },\n [_htmlElementToVNode, _registerMethod]\n );\n\n // @ts-ignore\n context.appendSibling = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod(() => {\n const parent = elementRef.current?.parentNode;\n\n parent?.insertBefore(elem, elementRef.current?.nextSibling ?? null);\n });\n },\n [_registerMethod]\n );\n\n // @ts-ignore\n context.prependSibling = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod(() => {\n const parent = elementRef.current?.parentNode;\n\n parent?.insertBefore(elem, elementRef.current);\n });\n },\n [_registerMethod]\n );\n\n // @ts-ignore\n context.remove = useCallback(() => {\n // @ts-ignore\n _registerMethod(() => {\n elementRef.current?.remove();\n });\n }, [_registerMethod]);\n\n const handleLifeCycleRender = useCallback(async () => {\n if (status.current === 'loading') return;\n\n status.current = 'loading';\n\n log(`🟨 \"${name}\" Slot Rendered`);\n\n // Reset\n const renderNode = render\n ? cloneElement(render(props), { key: 'render' })\n : null;\n _setProps({ children: [renderNode ?? children] });\n\n // Run all registered methods\n methodsRef.current.forEach((method: any) => {\n method(context, state);\n });\n\n status.current = 'ready';\n }, [children, context, name, props, render, state]);\n\n // Initialization\n const handleLifeCycleInit = useCallback(async () => {\n if (!callback) return;\n\n try {\n status.current = 'loading';\n\n log(`🟩 \"${name}\" Slot Initialized`);\n await callback(\n context as K & DefaultSlotContext<K>,\n elementRef.current as HTMLDivElement | null\n );\n } catch (error) {\n console.error(`Error in \"${callback.name}\" Slot callback`, error);\n } finally {\n status.current = 'ready';\n\n // first render\n await handleLifeCycleRender();\n }\n }, [callback, context, handleLifeCycleRender, name]);\n\n // Initialization\n useEffect(() => {\n handleLifeCycleInit().finally(() => {\n if (slotsQueue && slotsQueue.value.has(name)) {\n slotsQueue.value.delete(name);\n slotsQueue.value = new Set(slotsQueue.value);\n }\n });\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Update\n useEffect(() => {\n handleLifeCycleRender();\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [JSON.stringify(context), JSON.stringify(_state)]);\n\n return [elementRef, props, status.current];\n}\n\n/**\n * Recursively processes children elements to conditionally prevent image loading.\n * \n * This function traverses the children tree and modifies img elements to prevent\n * premature loading during slot initialization. When isReady is false, img src\n * attributes are set to empty string to prevent network requests, while preserving\n * the original src in a data attribute for debugging purposes.\n * \n * @param children - The children elements to process (can be any React/Preact children)\n * @param isReady - Whether the slot is ready to load images (true) or should prevent loading (false)\n * @returns Processed children with conditional image src attributes\n */\nconst processChildren = (children: any, isReady: boolean): any => {\n return Children.map(children, child => {\n // Handle text nodes, numbers, etc.\n if (!isValidElement(child)) {\n return child;\n }\n\n // Handle img elements - conditionally set src\n if (child.props.src) {\n return cloneElement(child, {\n ...child.props,\n src: isReady ? child.props.src : \"\",\n // Optionally preserve original src in data attribute for debugging\n 'data-original-src': child.props.src,\n });\n }\n\n // Handle elements with children - recursively process them\n if (child.props && child.props.children) {\n return cloneElement(child, {\n ...child.props,\n children: processChildren(child.props.children, isReady),\n });\n }\n\n // Return other elements as-is\n return child;\n });\n};\n\n// Slot Component\ninterface SlotPropsComponent<T>\n extends Omit<HTMLAttributes<HTMLElement>, 'slot'> {\n name: string;\n lazy?: boolean;\n slot?: SlotProps<T>;\n context?: Context<T>;\n render?: (props: Record<string, any>) => VNode | VNode[];\n // eslint-disable-next-line no-undef\n slotTag?: keyof HTMLElementTagNameMap; // The tag for the slot wrapper itself\n // eslint-disable-next-line no-undef\n contentTag?: keyof HTMLElementTagNameMap; // The tag for dynamically inserted content\n children?: ComponentChildren;\n}\n\nexport function Slot<T>({\n name,\n lazy = false,\n context,\n slot,\n children,\n render,\n slotTag = 'div',\n contentTag = 'div',\n ...props\n}: Readonly<SlotPropsComponent<T>>): VNode<{\n ref: RefObject<HTMLElement>;\n 'data-slot': string;\n [key: string]: any;\n}> {\n const slotsQueue = useContext(SlotQueueContext);\n\n const [elementRef, slotProps, status] = useSlot<T, HTMLElement>(\n name,\n context,\n slot,\n children,\n render,\n contentTag\n );\n\n useMemo(() => {\n if (!name) {\n return console.warn('Slot \"name\" is required');\n }\n\n // add slot to queue\n if (slotsQueue && lazy === false) {\n slotsQueue.value.add(name);\n slotsQueue.value = new Set(slotsQueue.value);\n }\n }, [name, lazy, slotsQueue]);\n\n return createElement(\n slotTag,\n {\n ...props,\n ref: elementRef,\n 'data-slot': name,\n },\n processChildren(slotProps.children, status === 'ready')\n );\n}\n\n// Debugger\n\n// @ts-ignore\nwindow.DROPINS = window.DROPINS || {};\n\n// @ts-ignore\nwindow.DROPINS.showSlots = async (state) => {\n console.warn('[Dropins] DROPINS.showSlots() is deprecated. Use DROPINS.showOverlays() instead.');\n // @ts-ignore\n await window.DROPINS.showOverlays?.(state);\n};\n\nlet log: (...attrs: any) => void = () => {};\n\n// @ts-ignore\nwindow.DROPINS.logSlots = async (state) => {\n // cache state in session storage\n window.sessionStorage.setItem('dropin-debugger--log-slots', state.toString());\n\n log = state ? (...attrs) => console.log(...attrs) : () => {};\n};\n\n/** Persistent Settings */\n\n// @ts-ignore\nwindow.DROPINS.logSlots(\n window.sessionStorage.getItem('dropin-debugger--log-slots') === 'true'\n);\n","/**\n * Get cookie\n * @param {string} cookieName - The name of the cookie to get\n * @returns {string} - The value of the cookie\n */\nexport function getCookie(cookieName: string): string | undefined {\n const cookies = document.cookie.split(';');\n let foundValue;\n\n cookies.forEach((cookie) => {\n const [name, value] = cookie.trim().split('=');\n if (name === cookieName) {\n foundValue = decodeURIComponent(value);\n }\n });\n\n return foundValue;\n}\n"],"names":["getFormValues","form","formData","getFormErrors","data","result","key","field","mergeOptions","target","source","options","destination","item","index","deepmerge","merge","prev","next","toLanguageTag","locale","useSlot","name","context","callback","children","render","contentTag","slotsQueue","useContext","SlotQueueContext","elementRef","useRef","status","methodsRef","props","_setProps","useState","_state","setState","state","useMemo","value","intl","IntlContext","_next","renderNode","cloneElement","n","_registerMethod","useCallback","cb","_htmlElementToVNode","elem","createElement","refElem","element","_a","log","_b","parent","vnode","handleLifeCycleRender","method","handleLifeCycleInit","error","useEffect","processChildren","isReady","Children","child","isValidElement","Slot","lazy","slot","slotTag","slotProps","attrs","getCookie","cookieName","cookies","foundValue","cookie"],"mappings":"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"}
1
+ {"version":3,"file":"lib.js","sources":["/@dropins/tools/src/lib/form-values.ts","/@dropins/tools/src/lib/deepmerge.ts","/@dropins/tools/src/lib/i18n.ts","/@dropins/tools/src/lib/slot.tsx","/@dropins/tools/src/lib/get-cookie.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nexport const getFormValues = (form: HTMLFormElement) => {\n const formData: any = new FormData(form);\n const result = Object.fromEntries(formData);\n return result;\n};\n\nexport const getFormErrors = (form: HTMLFormElement) => {\n const formData: any = new FormData(form);\n\n const data = Object.fromEntries(formData);\n\n const result = Object.entries(data).reduce((result, [key]) => {\n // @ts-ignore\n const field = form.elements[key];\n\n return field?.validationMessage\n ? { ...result, [key]: field.validationMessage }\n : { ...result };\n }, {});\n\n return result;\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport deepmerge from 'deepmerge';\n\nexport { default as deepmerge } from 'deepmerge';\n\nconst mergeOptions = {\n arrayMerge: (target: any, source: any, options: any) => {\n const destination = target.slice();\n\n source.forEach((item: any, index: number) => {\n if (typeof destination[index] === 'undefined') {\n destination[index] = options.cloneUnlessOtherwiseSpecified(\n item,\n options,\n );\n } else if (options.isMergeableObject(item)) {\n destination[index] = deepmerge(target[index], item, options);\n } else if (target.indexOf(item) === -1) {\n destination.push(item);\n }\n });\n return destination;\n },\n};\n\nexport function merge<T>(prev: T, next?: { [key: string]: any }) {\n if (!next) return prev;\n\n return deepmerge<T, { [key: string]: any }>(prev, next, mergeOptions);\n}\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\n/**\n * Convert locale from Magento standard to react-intl BCP 47 language tag\n *\n * @param {string} locale - A locale (e.g. `fr_FR`).\n * @returns {string} A BCP 47 language tag (e.g. `fr-FR`).\n */\nexport const toLanguageTag = (locale: string) => {\n return locale.replace('_', '-');\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { IntlContext, Lang } from '@adobe-commerce/elsie/i18n';\nimport {\n cloneElement,\n ComponentChildren,\n createElement,\n RefObject,\n VNode,\n} from 'preact';\nimport { Children, HTMLAttributes, isValidElement } from 'preact/compat';\nimport {\n StateUpdater,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\nimport { SlotQueueContext } from './render';\n\ntype MutateElement = (elem: HTMLElement) => void;\n\ninterface State {\n get: (key: string) => void;\n set: (key: string, value: any) => void;\n}\n\ninterface SlotElement {\n appendChild: MutateElement;\n prependChild: MutateElement;\n appendSibling: MutateElement;\n prependSibling: MutateElement;\n remove: () => void;\n}\n\ninterface PrivateContext<T> {\n _setProps: (s: StateUpdater<{}>) => void;\n _registerMethod: (\n cb: (next: T & DefaultSlotContext<T>, state: State) => void,\n ) => void;\n // eslint-disable-next-line no-undef\n _htmlElementToVNode: (\n element: HTMLElement,\n tag: keyof HTMLElementTagNameMap,\n ) => VNode;\n}\n\ninterface DefaultSlotContext<T> extends PrivateContext<T> {\n dictionary: Lang;\n getSlotElement: (key: string) => SlotElement;\n replaceWith: MutateElement;\n appendChild: MutateElement;\n prependChild: MutateElement;\n appendSibling: MutateElement;\n prependSibling: MutateElement;\n remove: () => void;\n onRender: (cb: (next: T & DefaultSlotContext<T>) => void) => void;\n onChange: (cb: (next: T & DefaultSlotContext<T>) => void) => void;\n}\n\ntype Context<T> = T & ThisType<DefaultSlotContext<T>>; // NOSONAR\n\nexport type SlotProps<T = any> = (\n ctx: T & DefaultSlotContext<T>,\n element: HTMLDivElement | null,\n) => Promise<void> | void;\n\nexport type SlotMethod<P = any> = (\n callback: (next: unknown, state: State) => P,\n) => void;\n\n// Slot Hook\nexport function useSlot<K, V extends HTMLElement>(\n name: string,\n // @ts-ignore\n context: Context<K> = {},\n callback?: SlotProps<K>,\n children?: ComponentChildren,\n render?: Function,\n // eslint-disable-next-line no-undef\n contentTag: keyof HTMLElementTagNameMap = 'div',\n): [RefObject<V>, Record<string, any>, 'loading' | 'pending' | 'ready'] {\n const slotsQueue = useContext(SlotQueueContext);\n\n // HTML Element\n const elementRef = useRef<V>(null);\n\n const status = useRef<'pending' | 'ready' | 'loading'>('pending');\n\n // Methods\n const methodsRef = useRef<any>([]);\n\n // Children VNodes\n const [props, _setProps] = useState<Record<string, any>>({\n children: [children],\n });\n\n // Attributes\n const [_state, setState] = useState<any>({});\n\n const state = useMemo(\n () => ({\n get: (key: string) => _state[key],\n set: (key: string, value: any) => {\n setState({ ...state, [key]: value });\n },\n }),\n [_state],\n );\n\n /** Internationalization */\n // @ts-ignore\n const { intl }: any = useContext(IntlContext);\n\n // @ts-ignore\n context.dictionary = intl.dictionary;\n\n /** Privates */\n // @ts-ignore\n context._setProps = (next: State<any>) => {\n _setProps((prev) => {\n // next props\n const _next = typeof next === 'function' ? next(prev) : next;\n\n // On render method...\n if (render) {\n const renderNode = cloneElement(render(prev), { key: 'render' });\n\n // find index of existing render node\n const index = prev.children.findIndex((n: any) => n?.key === 'render');\n\n // replace existing render node\n prev.children[index] = renderNode;\n }\n\n return _next;\n });\n };\n\n const _registerMethod = useCallback((cb: Function) => {\n if (typeof cb === 'function') {\n methodsRef.current.push(cb);\n } else {\n console.warn('Skipped: Invalid _registerMethod', cb);\n }\n }, []);\n\n // @ts-ignore\n context._registerMethod = _registerMethod;\n\n const _htmlElementToVNode = useCallback(\n (elem: HTMLElement) => {\n return createElement(\n contentTag,\n {\n 'data-slot-html-element': elem.tagName.toLowerCase(),\n ref: (refElem: HTMLElement | null): void => {\n refElem?.appendChild(elem);\n },\n },\n null,\n );\n },\n [contentTag],\n );\n\n // @ts-ignore\n context._htmlElementToVNode = _htmlElementToVNode;\n\n /** Prebuilt Methods */\n // @ts-ignore\n context.getSlotElement = useCallback(\n (key: string) => {\n const element = elementRef.current?.querySelector(\n `[data-slot-key=\"${key}\"]`,\n );\n\n log(\n `🟦 \"${name}\" Slot getSlotElement: ${key}`,\n elementRef.current?.cloneNode(true),\n element?.cloneNode(true),\n );\n\n if (!element) return;\n\n return {\n appendChild: (elem: HTMLElement) => {\n element.appendChild(elem);\n },\n\n prependChild: (elem: HTMLElement) => {\n element.insertBefore(elem, element.firstChild);\n },\n\n appendSibling: (elem: HTMLElement) => {\n const parent = element.parentNode;\n parent?.insertBefore(elem, element.nextSibling);\n },\n\n prependSibling: (elem: HTMLElement) => {\n const parent = element.parentNode;\n parent?.insertBefore(elem, element);\n },\n\n remove: () => {\n element.remove();\n },\n };\n },\n [name],\n );\n\n // @ts-ignore\n context.onRender = useCallback((cb: Function) => {\n methodsRef.current.push(cb);\n }, []);\n\n /**\n * @deprecated Use `onRender` instead.\n */\n // @ts-ignore\n context.onChange = context.onRender;\n\n // @ts-ignore\n context.replaceWith = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod((next) => {\n // @ts-ignore\n const children = _htmlElementToVNode(elem);\n\n next._setProps({ children: [children] });\n });\n },\n [_htmlElementToVNode, _registerMethod],\n );\n\n // @ts-ignore\n context.appendChild = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod((next) => {\n // @ts-ignore\n const vnode = _htmlElementToVNode(elem);\n\n next._setProps((prev: any) => {\n return {\n ...prev,\n children: [...prev.children, vnode],\n };\n });\n });\n },\n [_htmlElementToVNode, _registerMethod],\n );\n\n // @ts-ignore\n context.prependChild = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod((next) => {\n // @ts-ignore\n const vnode = _htmlElementToVNode(elem);\n\n next._setProps((prev: any) => {\n return {\n ...prev,\n children: [vnode, ...prev.children],\n };\n });\n });\n },\n [_htmlElementToVNode, _registerMethod],\n );\n\n // @ts-ignore\n context.appendSibling = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod(() => {\n const parent = elementRef.current?.parentNode;\n\n parent?.insertBefore(elem, elementRef.current?.nextSibling ?? null);\n });\n },\n [_registerMethod],\n );\n\n // @ts-ignore\n context.prependSibling = useCallback(\n (elem: HTMLElement) => {\n // @ts-ignore\n _registerMethod(() => {\n const parent = elementRef.current?.parentNode;\n\n parent?.insertBefore(elem, elementRef.current);\n });\n },\n [_registerMethod],\n );\n\n // @ts-ignore\n context.remove = useCallback(() => {\n // @ts-ignore\n _registerMethod(() => {\n elementRef.current?.remove();\n });\n }, [_registerMethod]);\n\n const handleLifeCycleRender = useCallback(async () => {\n if (status.current === 'loading') return;\n\n status.current = 'loading';\n\n log(`🟨 \"${name}\" Slot Rendered`);\n\n // Reset\n const renderNode = render\n ? cloneElement(render(props), { key: 'render' })\n : null;\n _setProps({ children: [renderNode ?? children] });\n\n // Run all registered methods\n methodsRef.current.forEach((method: any) => {\n method(context, state);\n });\n\n status.current = 'ready';\n }, [children, context, name, props, render, state]);\n\n // Initialization\n const handleLifeCycleInit = useCallback(async () => {\n if (!callback) return;\n\n try {\n status.current = 'loading';\n\n log(`🟩 \"${name}\" Slot Initialized`);\n await callback(\n context as K & DefaultSlotContext<K>,\n elementRef.current as HTMLDivElement | null,\n );\n } catch (error) {\n console.error(`Error in \"${callback.name}\" Slot callback`, error);\n } finally {\n status.current = 'ready';\n\n // first render\n await handleLifeCycleRender();\n }\n }, [callback, context, handleLifeCycleRender, name]);\n\n // Initialization\n useEffect(() => {\n handleLifeCycleInit().finally(() => {\n if (slotsQueue && slotsQueue.value.has(name)) {\n slotsQueue.value.delete(name);\n slotsQueue.value = new Set(slotsQueue.value);\n }\n });\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Update\n useEffect(() => {\n handleLifeCycleRender();\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [JSON.stringify(context), JSON.stringify(_state)]);\n\n return [elementRef, props, status.current];\n}\n\n/**\n * Recursively processes children elements to conditionally prevent image loading.\n *\n * This function traverses the children tree and modifies img elements to prevent\n * premature loading during slot initialization. When isReady is false, img src\n * attributes are set to empty string to prevent network requests, while preserving\n * the original src in a data attribute for debugging purposes.\n *\n * @param children - The children elements to process (can be any React/Preact children)\n * @param isReady - Whether the slot is ready to load images (true) or should prevent loading (false)\n * @returns Processed children with conditional image src attributes\n */\nconst processChildren = (children: any, isReady: boolean): any => {\n return Children.map(children, (child) => {\n // Handle text nodes, numbers, etc.\n if (!isValidElement(child)) {\n return child;\n }\n\n // Handle img elements - conditionally set src\n if (child.props.src) {\n return cloneElement(child, {\n ...child.props,\n src: isReady ? child.props.src : '',\n // Optionally preserve original src in data attribute for debugging\n 'data-original-src': child.props.src,\n });\n }\n\n // Handle elements with children - recursively process them\n if (child.props && child.props.children) {\n return cloneElement(child, {\n ...child.props,\n children: processChildren(child.props.children, isReady),\n });\n }\n\n // Return other elements as-is\n return child;\n });\n};\n\n// Slot Component\ninterface SlotPropsComponent<T> extends Omit<\n HTMLAttributes<HTMLElement>,\n 'slot'\n> {\n name: string;\n lazy?: boolean;\n slot?: SlotProps<T>;\n context?: Context<T>;\n render?: (props: Record<string, any>) => VNode | VNode[];\n // eslint-disable-next-line no-undef\n slotTag?: keyof HTMLElementTagNameMap; // The tag for the slot wrapper itself\n // eslint-disable-next-line no-undef\n contentTag?: keyof HTMLElementTagNameMap; // The tag for dynamically inserted content\n children?: ComponentChildren;\n}\n\nexport function Slot<T>({\n name,\n lazy = false,\n context,\n slot,\n children,\n render,\n slotTag = 'div',\n contentTag = 'div',\n ...props\n}: Readonly<SlotPropsComponent<T>>): VNode<{\n ref: RefObject<HTMLElement>;\n 'data-slot': string;\n [key: string]: any;\n}> {\n const slotsQueue = useContext(SlotQueueContext);\n\n const [elementRef, slotProps, status] = useSlot<T, HTMLElement>(\n name,\n context,\n slot,\n children,\n render,\n contentTag,\n );\n\n useMemo(() => {\n if (!name) {\n return console.warn('Slot \"name\" is required');\n }\n\n // add slot to queue\n if (slotsQueue && lazy === false) {\n slotsQueue.value.add(name);\n slotsQueue.value = new Set(slotsQueue.value);\n }\n }, [name, lazy, slotsQueue]);\n\n return createElement(\n slotTag,\n {\n ...props,\n ref: elementRef,\n 'data-slot': name,\n },\n processChildren(slotProps.children, status === 'ready'),\n );\n}\n\n// Debugger\n\n// @ts-ignore\nwindow.DROPINS = window.DROPINS || {};\n\n// @ts-ignore\nwindow.DROPINS.showSlots = async (state) => {\n console.warn(\n '[Dropins] DROPINS.showSlots() is deprecated. Use DROPINS.showOverlays() instead.',\n );\n // @ts-ignore\n await window.DROPINS.showOverlays?.(state);\n};\n\nlet log: (...attrs: any) => void = () => {};\n\n// @ts-ignore\nwindow.DROPINS.logSlots = async (state) => {\n // cache state in session storage\n window.sessionStorage.setItem('dropin-debugger--log-slots', state.toString());\n\n log = state ? (...attrs) => console.log(...attrs) : () => {};\n};\n\n/** Persistent Settings */\n\n// @ts-ignore\nwindow.DROPINS.logSlots(\n window.sessionStorage.getItem('dropin-debugger--log-slots') === 'true',\n);\n","/**\n * Get cookie\n * @param {string} cookieName - The name of the cookie to get\n * @returns {string} - The value of the cookie\n */\nexport function getCookie(cookieName: string): string | undefined {\n const cookies = document.cookie.split(';');\n let foundValue;\n\n cookies.forEach((cookie) => {\n const [name, value] = cookie.trim().split('=');\n if (name === cookieName) {\n foundValue = decodeURIComponent(value);\n }\n });\n\n return foundValue;\n}\n"],"names":["getFormValues","form","formData","getFormErrors","data","result","key","field","mergeOptions","target","source","options","destination","item","index","deepmerge","merge","prev","next","toLanguageTag","locale","useSlot","name","context","callback","children","render","contentTag","slotsQueue","useContext","SlotQueueContext","elementRef","useRef","status","methodsRef","props","_setProps","useState","_state","setState","state","useMemo","value","intl","IntlContext","_next","renderNode","cloneElement","n","_registerMethod","useCallback","cb","_htmlElementToVNode","elem","createElement","refElem","element","_a","log","_b","parent","vnode","handleLifeCycleRender","method","handleLifeCycleInit","error","useEffect","processChildren","isReady","Children","child","isValidElement","Slot","lazy","slot","slotTag","slotProps","attrs","getCookie","cookieName","cookies","foundValue","cookie"],"mappings":"2lBASO,MAAMA,EAAiBC,GAA0B,CACtD,MAAMC,EAAgB,IAAI,SAASD,CAAI,EAEvC,OADe,OAAO,YAAYC,CAAQ,CAE5C,EAEaC,EAAiBF,GAA0B,CACtD,MAAMC,EAAgB,IAAI,SAASD,CAAI,EAEjCG,EAAO,OAAO,YAAYF,CAAQ,EAWxC,OATe,OAAO,QAAQE,CAAI,EAAE,OAAO,CAACC,EAAQ,CAACC,CAAG,IAAM,CAE5D,MAAMC,EAAQN,EAAK,SAASK,CAAG,EAE/B,OAAOC,GAAA,MAAAA,EAAO,kBACV,CAAE,GAAGF,EAAQ,CAACC,CAAG,EAAGC,EAAM,iBAAA,EAC1B,CAAE,GAAGF,CAAAA,CACX,EAAG,CAAA,CAAE,CAGP,ECjBMG,EAAe,CACnB,WAAY,CAACC,EAAaC,EAAaC,IAAiB,CACtD,MAAMC,EAAcH,EAAO,MAAA,EAE3B,OAAAC,EAAO,QAAQ,CAACG,EAAWC,IAAkB,CACvC,OAAOF,EAAYE,CAAK,EAAM,IAChCF,EAAYE,CAAK,EAAIH,EAAQ,8BAC3BE,EACAF,CAAA,EAEOA,EAAQ,kBAAkBE,CAAI,EACvCD,EAAYE,CAAK,EAAIC,EAAUN,EAAOK,CAAK,EAAGD,EAAMF,CAAO,EAClDF,EAAO,QAAQI,CAAI,IAAM,IAClCD,EAAY,KAAKC,CAAI,CAEzB,CAAC,EACMD,CACT,CACF,EAEO,SAASI,EAASC,EAASC,EAA+B,CAC/D,OAAKA,EAEEH,EAAqCE,EAAMC,EAAMV,CAAY,EAFlDS,CAGpB,CCtBO,MAAME,EAAiBC,GACrBA,EAAO,QAAQ,IAAK,GAAG,ECiEzB,SAASC,EACdC,EAEAC,EAAsB,CAAA,EACtBC,EACAC,EACAC,EAEAC,EAA0C,MAC4B,CACtE,MAAMC,EAAaC,EAAWC,CAAgB,EAGxCC,EAAaC,EAAU,IAAI,EAE3BC,EAASD,EAAwC,SAAS,EAG1DE,EAAaF,EAAY,EAAE,EAG3B,CAACG,EAAOC,CAAS,EAAIC,EAA8B,CACvD,SAAU,CAACZ,CAAQ,CAAA,CACpB,EAGK,CAACa,EAAQC,CAAQ,EAAIF,EAAc,CAAA,CAAE,EAErCG,EAAQC,EACZ,KAAO,CACL,IAAMnC,GAAgBgC,EAAOhC,CAAG,EAChC,IAAK,CAACA,EAAaoC,IAAe,CAChCH,EAAS,CAAE,GAAGC,EAAO,CAAClC,CAAG,EAAGoC,EAAO,CACrC,CAAA,GAEF,CAACJ,CAAM,CAAA,EAKH,CAAE,KAAAK,CAAA,EAAcd,EAAWe,CAAW,EAG5CrB,EAAQ,WAAaoB,EAAK,WAI1BpB,EAAQ,UAAaL,GAAqB,CACxCkB,EAAWnB,GAAS,CAElB,MAAM4B,EAAQ,OAAO3B,GAAS,WAAaA,EAAKD,CAAI,EAAIC,EAGxD,GAAIQ,EAAQ,CACV,MAAMoB,EAAaC,EAAarB,EAAOT,CAAI,EAAG,CAAE,IAAK,SAAU,EAGzDH,EAAQG,EAAK,SAAS,UAAW+B,IAAWA,GAAA,YAAAA,EAAG,OAAQ,QAAQ,EAGrE/B,EAAK,SAASH,CAAK,EAAIgC,CACzB,CAEA,OAAOD,CACT,CAAC,CACH,EAEA,MAAMI,EAAkBC,EAAaC,GAAiB,CAChD,OAAOA,GAAO,WAChBjB,EAAW,QAAQ,KAAKiB,CAAE,EAE1B,QAAQ,KAAK,mCAAoCA,CAAE,CAEvD,EAAG,CAAA,CAAE,EAGL5B,EAAQ,gBAAkB0B,EAE1B,MAAMG,EAAsBF,EACzBG,GACQC,EACL3B,EACA,CACE,yBAA0B0B,EAAK,QAAQ,YAAA,EACvC,IAAME,GAAsC,CAC1CA,GAAA,MAAAA,EAAS,YAAYF,EACvB,CAAA,EAEF,IAAA,EAGJ,CAAC1B,CAAU,CAAA,EAIbJ,EAAQ,oBAAsB6B,EAI9B7B,EAAQ,eAAiB2B,EACtB5C,GAAgB,SACf,MAAMkD,GAAUC,EAAA1B,EAAW,UAAX,YAAA0B,EAAoB,cAClC,mBAAmBnD,CAAG,MASxB,GANAoD,EACE,OAAOpC,CAAI,0BAA0BhB,CAAG,IACxCqD,EAAA5B,EAAW,UAAX,YAAA4B,EAAoB,UAAU,IAC9BH,GAAA,YAAAA,EAAS,UAAU,GAAI,EAGrB,EAACA,EAEL,MAAO,CACL,YAAcH,GAAsB,CAClCG,EAAQ,YAAYH,CAAI,CAC1B,EAEA,aAAeA,GAAsB,CACnCG,EAAQ,aAAaH,EAAMG,EAAQ,UAAU,CAC/C,EAEA,cAAgBH,GAAsB,CACpC,MAAMO,EAASJ,EAAQ,WACvBI,GAAA,MAAAA,EAAQ,aAAaP,EAAMG,EAAQ,YACrC,EAEA,eAAiBH,GAAsB,CACrC,MAAMO,EAASJ,EAAQ,WACvBI,GAAA,MAAAA,EAAQ,aAAaP,EAAMG,EAC7B,EAEA,OAAQ,IAAM,CACZA,EAAQ,OAAA,CACV,CAAA,CAEJ,EACA,CAAClC,CAAI,CAAA,EAIPC,EAAQ,SAAW2B,EAAaC,GAAiB,CAC/CjB,EAAW,QAAQ,KAAKiB,CAAE,CAC5B,EAAG,CAAA,CAAE,EAML5B,EAAQ,SAAWA,EAAQ,SAG3BA,EAAQ,YAAc2B,EACnBG,GAAsB,CAErBJ,EAAiB/B,GAAS,CAExB,MAAMO,EAAW2B,EAAoBC,CAAI,EAEzCnC,EAAK,UAAU,CAAE,SAAU,CAACO,CAAQ,EAAG,CACzC,CAAC,CACH,EACA,CAAC2B,EAAqBH,CAAe,CAAA,EAIvC1B,EAAQ,YAAc2B,EACnBG,GAAsB,CAErBJ,EAAiB/B,GAAS,CAExB,MAAM2C,EAAQT,EAAoBC,CAAI,EAEtCnC,EAAK,UAAWD,IACP,CACL,GAAGA,EACH,SAAU,CAAC,GAAGA,EAAK,SAAU4C,CAAK,CAAA,EAErC,CACH,CAAC,CACH,EACA,CAACT,EAAqBH,CAAe,CAAA,EAIvC1B,EAAQ,aAAe2B,EACpBG,GAAsB,CAErBJ,EAAiB/B,GAAS,CAExB,MAAM2C,EAAQT,EAAoBC,CAAI,EAEtCnC,EAAK,UAAWD,IACP,CACL,GAAGA,EACH,SAAU,CAAC4C,EAAO,GAAG5C,EAAK,QAAQ,CAAA,EAErC,CACH,CAAC,CACH,EACA,CAACmC,EAAqBH,CAAe,CAAA,EAIvC1B,EAAQ,cAAgB2B,EACrBG,GAAsB,CAErBJ,EAAgB,IAAM,SACpB,MAAMW,GAASH,EAAA1B,EAAW,UAAX,YAAA0B,EAAoB,WAEnCG,GAAA,MAAAA,EAAQ,aAAaP,IAAMM,EAAA5B,EAAW,UAAX,YAAA4B,EAAoB,cAAe,KAChE,CAAC,CACH,EACA,CAACV,CAAe,CAAA,EAIlB1B,EAAQ,eAAiB2B,EACtBG,GAAsB,CAErBJ,EAAgB,IAAM,OACpB,MAAMW,GAASH,EAAA1B,EAAW,UAAX,YAAA0B,EAAoB,WAEnCG,GAAA,MAAAA,EAAQ,aAAaP,EAAMtB,EAAW,QACxC,CAAC,CACH,EACA,CAACkB,CAAe,CAAA,EAIlB1B,EAAQ,OAAS2B,EAAY,IAAM,CAEjCD,EAAgB,IAAM,QACpBQ,EAAA1B,EAAW,UAAX,MAAA0B,EAAoB,QACtB,CAAC,CACH,EAAG,CAACR,CAAe,CAAC,EAEpB,MAAMa,EAAwBZ,EAAY,SAAY,CACpD,GAAIjB,EAAO,UAAY,UAAW,OAElCA,EAAO,QAAU,UAEjByB,EAAI,OAAOpC,CAAI,iBAAiB,EAGhC,MAAMwB,EAAapB,EACfqB,EAAarB,EAAOS,CAAK,EAAG,CAAE,IAAK,QAAA,CAAU,EAC7C,KACJC,EAAU,CAAE,SAAU,CAACU,GAAcrB,CAAQ,EAAG,EAGhDS,EAAW,QAAQ,QAAS6B,GAAgB,CAC1CA,EAAOxC,EAASiB,CAAK,CACvB,CAAC,EAEDP,EAAO,QAAU,OACnB,EAAG,CAACR,EAAUF,EAASD,EAAMa,EAAOT,EAAQc,CAAK,CAAC,EAG5CwB,EAAsBd,EAAY,SAAY,CAClD,GAAK1B,EAEL,GAAI,CACFS,EAAO,QAAU,UAEjByB,EAAI,OAAOpC,CAAI,oBAAoB,EACnC,MAAME,EACJD,EACAQ,EAAW,OAAA,CAEf,OAASkC,EAAO,CACd,QAAQ,MAAM,aAAazC,EAAS,IAAI,kBAAmByC,CAAK,CAClE,QAAA,CACEhC,EAAO,QAAU,QAGjB,MAAM6B,EAAA,CACR,CACF,EAAG,CAACtC,EAAUD,EAASuC,EAAuBxC,CAAI,CAAC,EAGnD4C,OAAAA,EAAU,IAAM,CACdF,EAAA,EAAsB,QAAQ,IAAM,CAC9BpC,GAAcA,EAAW,MAAM,IAAIN,CAAI,IACzCM,EAAW,MAAM,OAAON,CAAI,EAC5BM,EAAW,MAAQ,IAAI,IAAIA,EAAW,KAAK,EAE/C,CAAC,CAGH,EAAG,CAAA,CAAE,EAGLsC,EAAU,IAAM,CACdJ,EAAA,CAGF,EAAG,CAAC,KAAK,UAAUvC,CAAO,EAAG,KAAK,UAAUe,CAAM,CAAC,CAAC,EAE7C,CAACP,EAAYI,EAAOF,EAAO,OAAO,CAC3C,CAcA,MAAMkC,EAAkB,CAAC1C,EAAe2C,IAC/BC,EAAS,IAAI5C,EAAW6C,GAExBC,EAAeD,CAAK,EAKrBA,EAAM,MAAM,IACPvB,EAAauB,EAAO,CACzB,GAAGA,EAAM,MACT,IAAKF,EAAUE,EAAM,MAAM,IAAM,GAEjC,oBAAqBA,EAAM,MAAM,GAAA,CAClC,EAICA,EAAM,OAASA,EAAM,MAAM,SACtBvB,EAAauB,EAAO,CACzB,GAAGA,EAAM,MACT,SAAUH,EAAgBG,EAAM,MAAM,SAAUF,CAAO,CAAA,CACxD,EAIIE,EAtBEA,CAuBV,EAoBI,SAASE,EAAQ,CACtB,KAAAlD,EACA,KAAAmD,EAAO,GACP,QAAAlD,EACA,KAAAmD,EACA,SAAAjD,EACA,OAAAC,EACA,QAAAiD,EAAU,MACV,WAAAhD,EAAa,MACb,GAAGQ,CACL,EAIG,CACD,MAAMP,EAAaC,EAAWC,CAAgB,EAExC,CAACC,EAAY6C,EAAW3C,CAAM,EAAIZ,EACtCC,EACAC,EACAmD,EACAjD,EACAC,EACAC,CAAA,EAGFc,OAAAA,EAAQ,IAAM,CACZ,GAAI,CAACnB,EACH,OAAO,QAAQ,KAAK,yBAAyB,EAI3CM,GAAc6C,IAAS,KACzB7C,EAAW,MAAM,IAAIN,CAAI,EACzBM,EAAW,MAAQ,IAAI,IAAIA,EAAW,KAAK,EAE/C,EAAG,CAACN,EAAMmD,EAAM7C,CAAU,CAAC,EAEpB0B,EACLqB,EACA,CACE,GAAGxC,EACH,IAAKJ,EACL,YAAaT,CAAA,EAEf6C,EAAgBS,EAAU,SAAU3C,IAAW,OAAO,CAAA,CAE1D,CAKA,OAAO,QAAU,OAAO,SAAW,CAAA,EAGnC,OAAO,QAAQ,UAAY,MAAOO,GAAU,SAC1C,QAAQ,KACN,kFAAA,EAGF,OAAMmB,GAAAF,EAAA,OAAO,SAAQ,eAAf,YAAAE,EAAA,KAAAF,EAA8BjB,GACtC,EAEA,IAAIkB,EAA+B,IAAM,CAAC,EAG1C,OAAO,QAAQ,SAAW,MAAOlB,GAAU,CAEzC,OAAO,eAAe,QAAQ,6BAA8BA,EAAM,UAAU,EAE5EkB,EAAMlB,EAAQ,IAAIqC,IAAU,QAAQ,IAAI,GAAGA,CAAK,EAAI,IAAM,CAAC,CAC7D,EAKA,OAAO,QAAQ,SACb,OAAO,eAAe,QAAQ,4BAA4B,IAAM,MAClE,ECngBO,SAASC,EAAUC,EAAwC,CAChE,MAAMC,EAAU,SAAS,OAAO,MAAM,GAAG,EACzC,IAAIC,EAEJ,OAAAD,EAAQ,QAASE,GAAW,CAC1B,KAAM,CAAC5D,EAAMoB,CAAK,EAAIwC,EAAO,KAAA,EAAO,MAAM,GAAG,EACzC5D,IAASyD,IACXE,EAAa,mBAAmBvC,CAAK,EAEzC,CAAC,EAEMuC,CACT"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@dropins/tools",
3
- "version": "2.0.0",
3
+ "version": "2.0.1-alpha-20260728135101",
4
4
  "license": "SEE LICENSE IN LICENSE.md"
5
5
  }
package/recaptcha.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"recaptcha.js","sources":["@dropins/tools/src/recaptcha/configs/message.config.ts","@dropins/tools/src/recaptcha/configs/typeForms.config.ts","@dropins/tools/src/recaptcha/configs/recaptchaBadgeSelector.config.ts","@dropins/tools/src/recaptcha/lib/_extendConfig.ts","@dropins/tools/src/recaptcha/lib/_storageConfig.ts","@dropins/tools/src/recaptcha/lib/_checkRecaptchaBadge.ts","@dropins/tools/src/recaptcha/lib/_convertKeysToCamelCase.ts","@dropins/tools/src/recaptcha/services/recaptcha.service.ts","@dropins/tools/src/recaptcha/graphql/recaptchaConfig.graphql.ts","@dropins/tools/src/recaptcha/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const recaptchaMessage = {\n failedFetch: 'Failed to fetch config from backend with status:',\n failedSetStorageConfig: 'Failed to set storage config',\n failedGetStorageConfig: 'Configuration could not be loaded.',\n failedExecutionRecaptcha: 'Recaptcha execution failed',\n failedInitializing: 'An error occurred while initializing ReCaptcha:',\n mixedTypesWarning:\n 'Multiple reCAPTCHA types detected across forms (both v3 and Enterprise). ' +\n 'This configuration is not supported — all forms must use the same reCAPTCHA type. ' +\n 'Please update your configuration in Commerce Admin '\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const typeDefaultForm: Record<string, string> = {\n PLACE_ORDER: 'placeOrder',\n CONTACT: 'contactUs',\n CUSTOMER_LOGIN: 'generateCustomerToken',\n CUSTOMER_FORGOT_PASSWORD: 'requestPasswordResetEmail',\n CUSTOMER_CREATE: 'createCustomerV2',\n COMPANY_CREATE: 'createCompany',\n CUSTOMER_EDIT: 'updateCustomerV2',\n NEWSLETTER: 'subscribeEmailToNewsletter',\n PRODUCT_REVIEW: 'createProductReview',\n SENDFRIEND: 'SENDFRIEND',\n BRAINTREE: 'BRAINTREE',\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const recaptchaBadgeSelector = '.grecaptcha-badge iframe';","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { ReCaptchaModel } from '../types/recaptcha.types';\nimport { typeDefaultForm } from '../configs/typeForms.config';\n\nexport const extendConfig = (\n config: ReCaptchaModel,\n modifyParams: any[]\n): ReCaptchaModel | undefined => {\n if (config && config.forms) {\n const modifyForm = config.forms.concat(modifyParams).map((el) => {\n if (typeof el !== 'string') return { ...el, enabledBadgePlace: false };\n\n return {\n badgeId: typeDefaultForm[el],\n enabledBadgePlace: false,\n };\n });\n\n return { ...config, forms: [...new Set(modifyForm)] };\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport { ReCaptchaModel } from '../types/recaptcha.types';\n\nconst getConfigStorage = async (\n storageKey: string,\n retries = 1,\n delay = 1000\n): Promise<ReCaptchaModel | null> => {\n const storedConfig = sessionStorage.getItem(storageKey);\n\n if (storedConfig !== null) {\n return JSON.parse(storedConfig);\n } else if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return getConfigStorage(storageKey, retries - 1, delay);\n }\n\n return null;\n};\n\nconst setConfigStorage = (\n storageKey: string,\n config: ReCaptchaModel,\n logger: boolean\n) => {\n if (!storageKey || !config.websiteKey) return null;\n\n try {\n sessionStorage.setItem(storageKey, JSON.stringify(config));\n } catch (error) {\n logger && console.error(recaptchaMessage.failedSetStorageConfig, error);\n return null;\n }\n};\n\nexport { getConfigStorage, setConfigStorage };\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaBadgeSelector } from '../configs';\n\nconst waitForElement = (selector: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n // Check if the element is already in the DOM\n if (document.querySelector(selector)) {\n resolve();\n return;\n }\n\n // Create an observer to watch for changes\n const observer = new MutationObserver(() => {\n if (document.querySelector(selector)) {\n resolve();\n observer.disconnect();\n }\n });\n\n // Start observing the body for child changes only\n observer.observe(document.body, {\n childList: true,\n subtree: false,\n });\n } catch (error) {\n reject(error);\n }\n });\n};\n\nexport const checkRecaptchaBadge = async (): Promise<boolean> => {\n try {\n await waitForElement(recaptchaBadgeSelector);\n return true;\n } catch (error) {\n return false;\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nexport const convertKeysToCamelCase = (obj: {\n [key: string]: any;\n}): { [key: string]: string | number | boolean } => {\n const camelCaseKey = (key: string): string => {\n return key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n };\n\n return Object.keys(obj).reduce((result, key) => {\n const newKey = camelCaseKey(key);\n result[newKey] = obj[key];\n return result;\n }, {} as { [key: string]: any });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport {\n MutationObserverInit,\n ReCaptchaModel,\n} from '../types/recaptcha.types';\n\ndeclare global {\n interface Window {\n grecaptcha?: typeof grecaptcha;\n }\n}\n\nconst { failedExecutionRecaptcha } = recaptchaMessage;\n\nexport const getRecaptchaToken = async (\n websiteKey: string,\n isEnterprise = false\n): Promise<string> => {\n if (!window.grecaptcha) {\n return Promise.reject(failedExecutionRecaptcha);\n }\n\n try {\n const token = isEnterprise\n ? await window.grecaptcha.enterprise.execute(websiteKey, {\n action: 'click',\n })\n : await window.grecaptcha.execute(websiteKey, {\n action: 'click',\n });\n\n return token;\n } catch (error) {\n return Promise.reject(`${failedExecutionRecaptcha} : ${error}`);\n }\n};\n\nexport const waitForReCaptcha = () => {\n return new Promise((resolve) => {\n const observer = new MutationObserver((_, obs) => {\n if (window.grecaptcha) {\n obs.disconnect();\n resolve(true);\n }\n });\n\n const observerOptions: MutationObserverInit = {\n childList: true,\n subtree: true,\n attributes: true,\n };\n\n observer.observe(document.body, observerOptions);\n });\n};\n\nexport const verifyReCaptchaLoad = async (\n badgeId: string,\n config: ReCaptchaModel,\n logger: boolean,\n isEnterprise = false\n): Promise<void> => {\n if (!window.grecaptcha) {\n await waitForReCaptcha();\n }\n\n const api = isEnterprise ? grecaptcha.enterprise : grecaptcha;\n\n return api.ready(() => {\n const badgeContainers = document.querySelectorAll(`#${badgeId}`);\n\n if (!badgeContainers.length) return;\n\n // Handle the case when multiple instances of the drop-in container rendered on the same page\n\n badgeContainers.forEach(\n (element) => (element.id = `${element.id}_${Math.random().toString(36)}`) // NOSONAR\n );\n\n badgeContainers.forEach((element) => {\n if (element.innerHTML === '') {\n try {\n api.render(element.id, {\n sitekey: config.websiteKey as string,\n badge: config.badgePosition as ReCaptchaV2.Badge,\n size: 'invisible',\n theme: (config.theme ?? 'light') as ReCaptchaV2.Theme,\n });\n } catch (error) {\n logger && console.error(error);\n }\n }\n });\n });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this \n * file in accordance with the terms of the Adobe license agreement \n * accompanying it. \n *******************************************************************/\nconst RECAPTCHA_FORM_CONFIG_FIELDS = `\n is_enabled\n configurations {\n website_key\n badge_position\n language_code\n minimum_score\n re_captcha_type\n technical_failure_message\n validation_failure_message\n theme\n }`;\n\nexport const buildRecaptchaFormConfigQuery = (\n formTypes: string[]\n): string => {\n const queries = formTypes\n .map(\n (formType) =>\n ` ${formType}: recaptchaFormConfig(formType: ${formType}) {${RECAPTCHA_FORM_CONFIG_FIELDS}\n }`\n )\n .join('\\n');\n\n return `query {\\n${queries}\\n}`;\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport {\n ReCaptchaResponse,\n PropsFormTypes,\n ReCaptchaModel,\n ReCaptchaFormConfigResult,\n} from './types/recaptcha.types';\nimport {\n recaptchaMessage,\n recaptchaBadgeSelector,\n typeDefaultForm,\n} from './configs';\nimport {\n extendConfig,\n setConfigStorage,\n getConfigStorage,\n checkRecaptchaBadge,\n convertKeysToCamelCase,\n} from './lib';\nimport {\n getRecaptchaToken,\n verifyReCaptchaLoad,\n} from './services/recaptcha.service';\nimport { buildRecaptchaFormConfigQuery } from './graphql/recaptchaConfig.graphql';\n\nimport { FetchGraphQL } from '@adobe-commerce/fetch-graphql';\n\nexport const recaptchaFetchApi = new FetchGraphQL().getMethods();\n\nconst RECAPTCHA_V3_SCRIPT_URL = 'https://www.google.com/recaptcha/api.js';\nconst RECAPTCHA_ENTERPRISE_SCRIPT_URL = 'https://www.google.com/recaptcha/enterprise.js';\n\nconst LOG_PREFIX = '[ReCaptcha]';\n\nexport class RecaptchaModule {\n _enableReCAPTCHA: boolean = false;\n _recaptchaBackendEndpoint: string = recaptchaFetchApi.getConfig()?.endpoint || '';\n _recaptchaScriptUrl: string = RECAPTCHA_V3_SCRIPT_URL;\n _configStorageKey: string = 'recaptchaConfig';\n _logger: boolean = false;\n\n _log(...args: any[]) {\n this._logger && console.log(LOG_PREFIX, ...args);\n }\n\n _normalizeFormConfigResponse(\n response: any,\n formTypes: string[]\n ): ReCaptchaResponse | undefined {\n const data = response?.data;\n if (!data) return undefined;\n\n const enabledForms: string[] = [];\n let globalConfig: ReCaptchaFormConfigResult | null = null;\n const detectedTypes = new Set<string>();\n\n for (const formType of formTypes) {\n const formData = data[formType];\n\n if (!formData?.is_enabled) continue;\n\n // configurations may be an array or a single object\n const config = Array.isArray(formData.configurations)\n ? formData.configurations[0]\n : formData.configurations;\n\n if (!config) continue;\n\n // Track all reCAPTCHA types across enabled forms, regardless of website_key\n if (config.re_captcha_type) {\n detectedTypes.add(config.re_captcha_type);\n }\n\n // Skip forms with empty website_key — enabled but not usable\n if (!config.website_key) {\n this._log(\n `Skipping ${formType}: enabled but missing website_key`\n );\n continue;\n }\n\n enabledForms.push(formType);\n\n if (!globalConfig) {\n globalConfig = config;\n }\n }\n\n // Abort if mixed reCAPTCHA types detected across enabled forms\n if (detectedTypes.size > 1) {\n console.warn(\n LOG_PREFIX,\n recaptchaMessage.mixedTypesWarning,\n `\\nDetected: ${[...detectedTypes].join(', ')}`\n );\n return undefined;\n }\n\n if (!globalConfig || enabledForms.length === 0) {\n this._log('No enabled forms found in recaptchaFormConfig response');\n return undefined;\n }\n\n // Map ReCaptchaConfiguration fields to the existing recaptchaConfig shape\n const isEnterprise =\n globalConfig.re_captcha_type === 'RECAPTCHA_ENTERPRISE';\n\n this._log(\n `Using reCAPTCHA ${isEnterprise ? 'Enterprise' : 'v3'}`,\n `| Enabled forms: ${enabledForms.join(', ')}`\n );\n\n return {\n data: {\n recaptchaConfig: {\n is_enabled: true,\n website_key: globalConfig.website_key,\n badge_position: globalConfig.badge_position,\n language_code: globalConfig.language_code,\n minimum_score: globalConfig.minimum_score,\n failure_message: globalConfig.validation_failure_message,\n theme: globalConfig.theme,\n forms: enabledForms,\n recaptcha_type: isEnterprise ? 'enterprise' : 'v3',\n },\n },\n };\n }\n\n async _updateBadgePosition(\n badgeId: string,\n config: ReCaptchaModel\n ): Promise<void | null> {\n if (!config) return;\n\n if (config?.badgePosition === 'inline') {\n this._log(`Rendering inline badge for: ${badgeId}`);\n await verifyReCaptchaLoad(\n badgeId,\n config,\n this._logger,\n config.recaptchaType === 'enterprise'\n );\n } else {\n const isBadgeLoaded = await checkRecaptchaBadge();\n\n if (!isBadgeLoaded) return;\n\n const recaptchaBadge = document.querySelector(\n recaptchaBadgeSelector\n ) as HTMLIFrameElement;\n\n const shouldUpdateSrc =\n config.theme &&\n recaptchaBadge &&\n !recaptchaBadge.src.includes('theme=dark') &&\n !recaptchaBadge.src.includes('theme=light');\n\n if (shouldUpdateSrc) {\n recaptchaBadge.setAttribute(\n 'src',\n `${recaptchaBadge.src}&theme=${config.theme}`\n );\n }\n }\n }\n\n async _addRecaptchaScript(): Promise<void> {\n const config = await this._loadConfig();\n\n if (!document.getElementById('recaptchaId') && config) {\n const webApiKey = config.websiteKey;\n const isBadgeGlobal = config.badgePosition === 'inline';\n const languageCode = config.languageCode;\n\n if (!webApiKey) {\n this._log('No website key found, skipping script injection');\n return;\n }\n\n const scriptUrl =\n config.recaptchaType === 'enterprise'\n ? RECAPTCHA_ENTERPRISE_SCRIPT_URL\n : this._recaptchaScriptUrl;\n\n const script = document.createElement('script');\n script.setAttribute('id', 'recaptchaId');\n script.defer = true;\n script.src = isBadgeGlobal\n ? `${scriptUrl}?render=${webApiKey}&badge=none&hl=${languageCode}`\n : `${scriptUrl}?render=${webApiKey}&badge=${config.badgePosition}&hl=${languageCode}`;\n\n this._log(`Loading script: ${script.src}`);\n document.head.appendChild(script);\n }\n }\n\n async _fetchStoreConfig(): Promise<ReCaptchaResponse | undefined> {\n try {\n const formTypes = Object.keys(typeDefaultForm);\n const query = buildRecaptchaFormConfigQuery(formTypes);\n\n this._log(`Fetching config for forms: ${formTypes.join(', ')}`);\n\n const response = await recaptchaFetchApi.fetchGraphQl(query, {\n method: 'GET',\n cache: 'force-cache',\n });\n\n if (response?.errors?.length) {\n this._logger && console.error(response.errors[0].message);\n\n return;\n }\n\n return this._normalizeFormConfigResponse(response, formTypes);\n } catch (error) {\n this._logger && console.error(`${recaptchaMessage.failedFetch}:`, error);\n }\n }\n\n async _loadConfig(): Promise<ReCaptchaModel | null> {\n const config = await getConfigStorage(this._configStorageKey);\n\n if (!config) {\n this._logger && console.error(recaptchaMessage.failedGetStorageConfig);\n\n return null;\n }\n\n this._enableReCAPTCHA = !!config.isEnabled;\n\n return config;\n }\n\n setEndpoint(url: string) {\n if (!url) return;\n\n this._recaptchaBackendEndpoint = url;\n recaptchaFetchApi.setEndpoint(url);\n }\n\n async setConfig(configList: PropsFormTypes[]) {\n try {\n const config = await this._fetchStoreConfig();\n\n if (!config?.data?.recaptchaConfig) {\n this._log('No reCAPTCHA config returned, clearing storage');\n sessionStorage.removeItem(this._configStorageKey);\n return;\n }\n\n const transformConfig: ReCaptchaModel = convertKeysToCamelCase(\n config?.data?.recaptchaConfig\n );\n\n const extendedRecaptchaConfig = extendConfig(transformConfig, configList);\n\n if (extendedRecaptchaConfig) {\n this._log('Config stored:', {\n type: extendedRecaptchaConfig.recaptchaType ?? 'v3',\n enabled: extendedRecaptchaConfig.isEnabled,\n badge: extendedRecaptchaConfig.badgePosition,\n forms: extendedRecaptchaConfig.forms,\n });\n setConfigStorage(\n this._configStorageKey,\n extendedRecaptchaConfig,\n this._logger\n );\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedSetStorageConfig, error);\n\n sessionStorage.removeItem(this._configStorageKey);\n }\n }\n\n async initReCaptcha(lazyLoadTimeout = 3000) {\n // IIFE added to fix SonarQube error \"Promise returned in function argument where a void return was expected\"\n setTimeout(() => {\n (async () => {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.isEnabled) {\n this._log('reCAPTCHA disabled or no forms configured, skipping init');\n return;\n }\n\n this._log(\n `Initializing reCAPTCHA (type: ${config.recaptchaType ?? 'v3'}, badge: ${config.badgePosition})`\n );\n\n await this._addRecaptchaScript();\n\n if (config.badgePosition === 'inline') {\n await Promise.all(\n (config.forms as PropsFormTypes[]).map((element) =>\n this._updateBadgePosition(element.badgeId, config)\n )\n );\n } else {\n await this._updateBadgePosition('', config);\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedInitializing, error);\n }\n })();\n }, lazyLoadTimeout);\n }\n\n async verifyReCaptcha(): Promise<string | undefined> {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.websiteKey || !config.isEnabled) {\n this._log('verifyReCaptcha skipped: reCAPTCHA not enabled or missing config');\n return undefined;\n }\n\n this._log(\n `Requesting token (type: ${config.recaptchaType ?? 'v3'})`\n );\n\n const token = await getRecaptchaToken(\n config.websiteKey,\n config.recaptchaType === 'enterprise'\n );\n\n this._log('Token obtained successfully');\n\n return token;\n } catch (error) {\n this._logger && console.error(error);\n }\n }\n\n enableLogger(logger: boolean) {\n this._logger = logger;\n }\n\n getMethods() {\n return {\n enableLogger: this.enableLogger.bind(this),\n setEndpoint: this.setEndpoint.bind(this),\n setConfig: this.setConfig.bind(this),\n initReCaptcha: this.initReCaptcha.bind(this),\n verifyReCaptcha: this.verifyReCaptcha.bind(this),\n };\n }\n}\n\nconst recaptcha = new RecaptchaModule();\n\nconst { initReCaptcha, verifyReCaptcha, setEndpoint, setConfig, enableLogger } =\n recaptcha.getMethods();\n\nexport { setEndpoint, setConfig, initReCaptcha, verifyReCaptcha, enableLogger };\n"],"names":["recaptchaMessage","typeDefaultForm","recaptchaBadgeSelector","extendConfig","config","modifyParams","modifyForm","el","getConfigStorage","storageKey","retries","delay","storedConfig","resolve","setConfigStorage","logger","error","waitForElement","selector","reject","observer","checkRecaptchaBadge","convertKeysToCamelCase","obj","camelCaseKey","key","_","letter","result","newKey","failedExecutionRecaptcha","getRecaptchaToken","websiteKey","isEnterprise","waitForReCaptcha","obs","observerOptions","verifyReCaptchaLoad","badgeId","api","badgeContainers","element","RECAPTCHA_FORM_CONFIG_FIELDS","buildRecaptchaFormConfigQuery","formTypes","formType","recaptchaFetchApi","FetchGraphQL","RECAPTCHA_V3_SCRIPT_URL","RECAPTCHA_ENTERPRISE_SCRIPT_URL","LOG_PREFIX","RecaptchaModule","__publicField","_a","args","response","data","enabledForms","globalConfig","detectedTypes","formData","recaptchaBadge","webApiKey","isBadgeGlobal","languageCode","scriptUrl","script","query","url","configList","transformConfig","_b","extendedRecaptchaConfig","lazyLoadTimeout","token","recaptcha","initReCaptcha","verifyReCaptcha","setEndpoint","setConfig","enableLogger"],"mappings":"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"}
1
+ {"version":3,"file":"recaptcha.js","sources":["@dropins/tools/src/recaptcha/configs/message.config.ts","@dropins/tools/src/recaptcha/configs/typeForms.config.ts","@dropins/tools/src/recaptcha/configs/recaptchaBadgeSelector.config.ts","@dropins/tools/src/recaptcha/lib/_extendConfig.ts","@dropins/tools/src/recaptcha/lib/_storageConfig.ts","@dropins/tools/src/recaptcha/lib/_checkRecaptchaBadge.ts","@dropins/tools/src/recaptcha/lib/_convertKeysToCamelCase.ts","@dropins/tools/src/recaptcha/services/recaptcha.service.ts","@dropins/tools/src/recaptcha/graphql/recaptchaConfig.graphql.ts","@dropins/tools/src/recaptcha/index.ts"],"sourcesContent":["/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nexport const recaptchaMessage = {\n failedFetch: 'Failed to fetch config from backend with status:',\n failedSetStorageConfig: 'Failed to set storage config',\n failedGetStorageConfig: 'Configuration could not be loaded.',\n failedExecutionRecaptcha: 'Recaptcha execution failed',\n failedInitializing: 'An error occurred while initializing ReCaptcha:',\n mixedTypesWarning:\n 'Multiple reCAPTCHA types detected across forms (both v3 and Enterprise). ' +\n 'This configuration is not supported — all forms must use the same reCAPTCHA type. ' +\n 'Please update your configuration in Commerce Admin ',\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nexport const typeDefaultForm: Record<string, string> = {\n PLACE_ORDER: 'placeOrder',\n CONTACT: 'contactUs',\n CUSTOMER_LOGIN: 'generateCustomerToken',\n CUSTOMER_FORGOT_PASSWORD: 'requestPasswordResetEmail',\n CUSTOMER_CREATE: 'createCustomerV2',\n COMPANY_CREATE: 'createCompany',\n CUSTOMER_EDIT: 'updateCustomerV2',\n NEWSLETTER: 'subscribeEmailToNewsletter',\n PRODUCT_REVIEW: 'createProductReview',\n SENDFRIEND: 'SENDFRIEND',\n BRAINTREE: 'BRAINTREE',\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nexport const recaptchaBadgeSelector = '.grecaptcha-badge iframe';\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { ReCaptchaModel } from '../types/recaptcha.types';\nimport { typeDefaultForm } from '../configs/typeForms.config';\n\nexport const extendConfig = (\n config: ReCaptchaModel,\n modifyParams: any[],\n): ReCaptchaModel | undefined => {\n if (config && config.forms) {\n const modifyForm = config.forms.concat(modifyParams).map((el) => {\n if (typeof el !== 'string') return { ...el, enabledBadgePlace: false };\n\n return {\n badgeId: typeDefaultForm[el],\n enabledBadgePlace: false,\n };\n });\n\n return { ...config, forms: [...new Set(modifyForm)] };\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport { ReCaptchaModel } from '../types/recaptcha.types';\n\nconst getConfigStorage = async (\n storageKey: string,\n retries = 1,\n delay = 1000,\n): Promise<ReCaptchaModel | null> => {\n const storedConfig = sessionStorage.getItem(storageKey);\n\n if (storedConfig !== null) {\n return JSON.parse(storedConfig);\n } else if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return getConfigStorage(storageKey, retries - 1, delay);\n }\n\n return null;\n};\n\nconst setConfigStorage = (\n storageKey: string,\n config: ReCaptchaModel,\n logger: boolean,\n) => {\n if (!storageKey || !config.websiteKey) return null;\n\n try {\n sessionStorage.setItem(storageKey, JSON.stringify(config));\n } catch (error) {\n logger && console.error(recaptchaMessage.failedSetStorageConfig, error);\n return null;\n }\n};\n\nexport { getConfigStorage, setConfigStorage };\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { recaptchaBadgeSelector } from '../configs';\n\nconst waitForElement = (selector: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n try {\n // Check if the element is already in the DOM\n if (document.querySelector(selector)) {\n resolve();\n return;\n }\n\n // Create an observer to watch for changes\n const observer = new MutationObserver(() => {\n if (document.querySelector(selector)) {\n resolve();\n observer.disconnect();\n }\n });\n\n // Start observing the body for child changes only\n observer.observe(document.body, {\n childList: true,\n subtree: false,\n });\n } catch (error) {\n reject(error);\n }\n });\n};\n\nexport const checkRecaptchaBadge = async (): Promise<boolean> => {\n try {\n await waitForElement(recaptchaBadgeSelector);\n return true;\n } catch (error) {\n return false;\n }\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nexport const convertKeysToCamelCase = (obj: {\n [key: string]: any;\n}): { [key: string]: string | number | boolean } => {\n const camelCaseKey = (key: string): string => {\n return key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n };\n\n return Object.keys(obj).reduce(\n (result, key) => {\n const newKey = camelCaseKey(key);\n result[newKey] = obj[key];\n return result;\n },\n {} as { [key: string]: any },\n );\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport { recaptchaMessage } from '../configs';\nimport { MutationObserverInit, ReCaptchaModel } from '../types/recaptcha.types';\n\ndeclare global {\n interface Window {\n grecaptcha?: typeof grecaptcha;\n }\n}\n\nconst { failedExecutionRecaptcha } = recaptchaMessage;\n\nexport const getRecaptchaToken = async (\n websiteKey: string,\n isEnterprise = false,\n): Promise<string> => {\n if (!window.grecaptcha) {\n return Promise.reject(failedExecutionRecaptcha);\n }\n\n try {\n const token = isEnterprise\n ? await window.grecaptcha.enterprise.execute(websiteKey, {\n action: 'click',\n })\n : await window.grecaptcha.execute(websiteKey, {\n action: 'click',\n });\n\n return token;\n } catch (error) {\n return Promise.reject(`${failedExecutionRecaptcha} : ${error}`);\n }\n};\n\nexport const waitForReCaptcha = () => {\n return new Promise((resolve) => {\n const observer = new MutationObserver((_, obs) => {\n if (window.grecaptcha) {\n obs.disconnect();\n resolve(true);\n }\n });\n\n const observerOptions: MutationObserverInit = {\n childList: true,\n subtree: true,\n attributes: true,\n };\n\n observer.observe(document.body, observerOptions);\n });\n};\n\nexport const verifyReCaptchaLoad = async (\n badgeId: string,\n config: ReCaptchaModel,\n logger: boolean,\n isEnterprise = false,\n): Promise<void> => {\n if (!window.grecaptcha) {\n await waitForReCaptcha();\n }\n\n const api = isEnterprise ? grecaptcha.enterprise : grecaptcha;\n\n return api.ready(() => {\n const badgeContainers = document.querySelectorAll(`#${badgeId}`);\n\n if (!badgeContainers.length) return;\n\n // Handle the case when multiple instances of the drop-in container rendered on the same page\n\n badgeContainers.forEach(\n (element) => (element.id = `${element.id}_${Math.random().toString(36)}`), // NOSONAR\n );\n\n badgeContainers.forEach((element) => {\n if (element.innerHTML === '') {\n try {\n api.render(element.id, {\n sitekey: config.websiteKey as string,\n badge: config.badgePosition as ReCaptchaV2.Badge,\n size: 'invisible',\n theme: (config.theme ?? 'light') as ReCaptchaV2.Theme,\n });\n } catch (error) {\n logger && console.error(error);\n }\n }\n });\n });\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\nconst RECAPTCHA_FORM_CONFIG_FIELDS = `\n is_enabled\n configurations {\n website_key\n badge_position\n language_code\n minimum_score\n re_captcha_type\n technical_failure_message\n validation_failure_message\n theme\n }`;\n\nexport const buildRecaptchaFormConfigQuery = (formTypes: string[]): string => {\n const queries = formTypes\n .map(\n (formType) =>\n ` ${formType}: recaptchaFormConfig(formType: ${formType}) {${RECAPTCHA_FORM_CONFIG_FIELDS}\n }`,\n )\n .join('\\n');\n\n return `query {\\n${queries}\\n}`;\n};\n","/********************************************************************\n * Copyright 2024 Adobe\n * All Rights Reserved.\n *\n * NOTICE: Adobe permits you to use, modify, and distribute this\n * file in accordance with the terms of the Adobe license agreement\n * accompanying it.\n *******************************************************************/\n\nimport {\n ReCaptchaResponse,\n PropsFormTypes,\n ReCaptchaModel,\n ReCaptchaFormConfigResult,\n} from './types/recaptcha.types';\nimport {\n recaptchaMessage,\n recaptchaBadgeSelector,\n typeDefaultForm,\n} from './configs';\nimport {\n extendConfig,\n setConfigStorage,\n getConfigStorage,\n checkRecaptchaBadge,\n convertKeysToCamelCase,\n} from './lib';\nimport {\n getRecaptchaToken,\n verifyReCaptchaLoad,\n} from './services/recaptcha.service';\nimport { buildRecaptchaFormConfigQuery } from './graphql/recaptchaConfig.graphql';\n\nimport { FetchGraphQL } from '@adobe-commerce/fetch-graphql';\n\nexport const recaptchaFetchApi = new FetchGraphQL().getMethods();\n\nconst RECAPTCHA_V3_SCRIPT_URL = 'https://www.google.com/recaptcha/api.js';\nconst RECAPTCHA_ENTERPRISE_SCRIPT_URL =\n 'https://www.google.com/recaptcha/enterprise.js';\n\nconst LOG_PREFIX = '[ReCaptcha]';\n\nexport class RecaptchaModule {\n _enableReCAPTCHA: boolean = false;\n _recaptchaBackendEndpoint: string =\n recaptchaFetchApi.getConfig()?.endpoint || '';\n _recaptchaScriptUrl: string = RECAPTCHA_V3_SCRIPT_URL;\n _configStorageKey: string = 'recaptchaConfig';\n _logger: boolean = false;\n\n _log(...args: any[]) {\n this._logger && console.log(LOG_PREFIX, ...args);\n }\n\n _normalizeFormConfigResponse(\n response: any,\n formTypes: string[],\n ): ReCaptchaResponse | undefined {\n const data = response?.data;\n if (!data) return undefined;\n\n const enabledForms: string[] = [];\n let globalConfig: ReCaptchaFormConfigResult | null = null;\n const detectedTypes = new Set<string>();\n\n for (const formType of formTypes) {\n const formData = data[formType];\n\n if (!formData?.is_enabled) continue;\n\n // configurations may be an array or a single object\n const config = Array.isArray(formData.configurations)\n ? formData.configurations[0]\n : formData.configurations;\n\n if (!config) continue;\n\n // Track all reCAPTCHA types across enabled forms, regardless of website_key\n if (config.re_captcha_type) {\n detectedTypes.add(config.re_captcha_type);\n }\n\n // Skip forms with empty website_key — enabled but not usable\n if (!config.website_key) {\n this._log(`Skipping ${formType}: enabled but missing website_key`);\n continue;\n }\n\n enabledForms.push(formType);\n\n if (!globalConfig) {\n globalConfig = config;\n }\n }\n\n // Abort if mixed reCAPTCHA types detected across enabled forms\n if (detectedTypes.size > 1) {\n console.warn(\n LOG_PREFIX,\n recaptchaMessage.mixedTypesWarning,\n `\\nDetected: ${[...detectedTypes].join(', ')}`,\n );\n return undefined;\n }\n\n if (!globalConfig || enabledForms.length === 0) {\n this._log('No enabled forms found in recaptchaFormConfig response');\n return undefined;\n }\n\n // Map ReCaptchaConfiguration fields to the existing recaptchaConfig shape\n const isEnterprise =\n globalConfig.re_captcha_type === 'RECAPTCHA_ENTERPRISE';\n\n this._log(\n `Using reCAPTCHA ${isEnterprise ? 'Enterprise' : 'v3'}`,\n `| Enabled forms: ${enabledForms.join(', ')}`,\n );\n\n return {\n data: {\n recaptchaConfig: {\n is_enabled: true,\n website_key: globalConfig.website_key,\n badge_position: globalConfig.badge_position,\n language_code: globalConfig.language_code,\n minimum_score: globalConfig.minimum_score,\n failure_message: globalConfig.validation_failure_message,\n theme: globalConfig.theme,\n forms: enabledForms,\n recaptcha_type: isEnterprise ? 'enterprise' : 'v3',\n },\n },\n };\n }\n\n async _updateBadgePosition(\n badgeId: string,\n config: ReCaptchaModel,\n ): Promise<void | null> {\n if (!config) return;\n\n if (config?.badgePosition === 'inline') {\n this._log(`Rendering inline badge for: ${badgeId}`);\n await verifyReCaptchaLoad(\n badgeId,\n config,\n this._logger,\n config.recaptchaType === 'enterprise',\n );\n } else {\n const isBadgeLoaded = await checkRecaptchaBadge();\n\n if (!isBadgeLoaded) return;\n\n const recaptchaBadge = document.querySelector(\n recaptchaBadgeSelector,\n ) as HTMLIFrameElement;\n\n const shouldUpdateSrc =\n config.theme &&\n recaptchaBadge &&\n !recaptchaBadge.src.includes('theme=dark') &&\n !recaptchaBadge.src.includes('theme=light');\n\n if (shouldUpdateSrc) {\n recaptchaBadge.setAttribute(\n 'src',\n `${recaptchaBadge.src}&theme=${config.theme}`,\n );\n }\n }\n }\n\n async _addRecaptchaScript(): Promise<void> {\n const config = await this._loadConfig();\n\n if (!document.getElementById('recaptchaId') && config) {\n const webApiKey = config.websiteKey;\n const isBadgeGlobal = config.badgePosition === 'inline';\n const languageCode = config.languageCode;\n\n if (!webApiKey) {\n this._log('No website key found, skipping script injection');\n return;\n }\n\n const scriptUrl =\n config.recaptchaType === 'enterprise'\n ? RECAPTCHA_ENTERPRISE_SCRIPT_URL\n : this._recaptchaScriptUrl;\n\n const script = document.createElement('script');\n script.setAttribute('id', 'recaptchaId');\n script.defer = true;\n script.src = isBadgeGlobal\n ? `${scriptUrl}?render=${webApiKey}&badge=none&hl=${languageCode}`\n : `${scriptUrl}?render=${webApiKey}&badge=${config.badgePosition}&hl=${languageCode}`;\n\n this._log(`Loading script: ${script.src}`);\n document.head.appendChild(script);\n }\n }\n\n async _fetchStoreConfig(): Promise<ReCaptchaResponse | undefined> {\n try {\n const formTypes = Object.keys(typeDefaultForm);\n const query = buildRecaptchaFormConfigQuery(formTypes);\n\n this._log(`Fetching config for forms: ${formTypes.join(', ')}`);\n\n const response = await recaptchaFetchApi.fetchGraphQl(query, {\n method: 'GET',\n cache: 'force-cache',\n });\n\n if (response?.errors?.length) {\n this._logger && console.error(response.errors[0].message);\n\n return;\n }\n\n return this._normalizeFormConfigResponse(response, formTypes);\n } catch (error) {\n this._logger && console.error(`${recaptchaMessage.failedFetch}:`, error);\n }\n }\n\n async _loadConfig(): Promise<ReCaptchaModel | null> {\n const config = await getConfigStorage(this._configStorageKey);\n\n if (!config) {\n this._logger && console.error(recaptchaMessage.failedGetStorageConfig);\n\n return null;\n }\n\n this._enableReCAPTCHA = !!config.isEnabled;\n\n return config;\n }\n\n setEndpoint(url: string) {\n if (!url) return;\n\n this._recaptchaBackendEndpoint = url;\n recaptchaFetchApi.setEndpoint(url);\n }\n\n async setConfig(configList: PropsFormTypes[]) {\n try {\n const config = await this._fetchStoreConfig();\n\n if (!config?.data?.recaptchaConfig) {\n this._log('No reCAPTCHA config returned, clearing storage');\n sessionStorage.removeItem(this._configStorageKey);\n return;\n }\n\n const transformConfig: ReCaptchaModel = convertKeysToCamelCase(\n config?.data?.recaptchaConfig,\n );\n\n const extendedRecaptchaConfig = extendConfig(transformConfig, configList);\n\n if (extendedRecaptchaConfig) {\n this._log('Config stored:', {\n type: extendedRecaptchaConfig.recaptchaType ?? 'v3',\n enabled: extendedRecaptchaConfig.isEnabled,\n badge: extendedRecaptchaConfig.badgePosition,\n forms: extendedRecaptchaConfig.forms,\n });\n setConfigStorage(\n this._configStorageKey,\n extendedRecaptchaConfig,\n this._logger,\n );\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedSetStorageConfig, error);\n\n sessionStorage.removeItem(this._configStorageKey);\n }\n }\n\n async initReCaptcha(lazyLoadTimeout = 3000) {\n // IIFE added to fix SonarQube error \"Promise returned in function argument where a void return was expected\"\n setTimeout(() => {\n (async () => {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.isEnabled) {\n this._log(\n 'reCAPTCHA disabled or no forms configured, skipping init',\n );\n return;\n }\n\n this._log(\n `Initializing reCAPTCHA (type: ${config.recaptchaType ?? 'v3'}, badge: ${config.badgePosition})`,\n );\n\n await this._addRecaptchaScript();\n\n if (config.badgePosition === 'inline') {\n await Promise.all(\n (config.forms as PropsFormTypes[]).map((element) =>\n this._updateBadgePosition(element.badgeId, config),\n ),\n );\n } else {\n await this._updateBadgePosition('', config);\n }\n } catch (error) {\n this._logger &&\n console.error(recaptchaMessage.failedInitializing, error);\n }\n })();\n }, lazyLoadTimeout);\n }\n\n async verifyReCaptcha(): Promise<string | undefined> {\n try {\n const config = await this._loadConfig();\n\n if (!config?.forms || !config.websiteKey || !config.isEnabled) {\n this._log(\n 'verifyReCaptcha skipped: reCAPTCHA not enabled or missing config',\n );\n return undefined;\n }\n\n this._log(`Requesting token (type: ${config.recaptchaType ?? 'v3'})`);\n\n const token = await getRecaptchaToken(\n config.websiteKey,\n config.recaptchaType === 'enterprise',\n );\n\n this._log('Token obtained successfully');\n\n return token;\n } catch (error) {\n this._logger && console.error(error);\n }\n }\n\n enableLogger(logger: boolean) {\n this._logger = logger;\n }\n\n getMethods() {\n return {\n enableLogger: this.enableLogger.bind(this),\n setEndpoint: this.setEndpoint.bind(this),\n setConfig: this.setConfig.bind(this),\n initReCaptcha: this.initReCaptcha.bind(this),\n verifyReCaptcha: this.verifyReCaptcha.bind(this),\n };\n }\n}\n\nconst recaptcha = new RecaptchaModule();\n\nconst { initReCaptcha, verifyReCaptcha, setEndpoint, setConfig, enableLogger } =\n recaptcha.getMethods();\n\nexport { setEndpoint, setConfig, initReCaptcha, verifyReCaptcha, enableLogger };\n"],"names":["recaptchaMessage","typeDefaultForm","recaptchaBadgeSelector","extendConfig","config","modifyParams","modifyForm","el","getConfigStorage","storageKey","retries","delay","storedConfig","resolve","setConfigStorage","logger","error","waitForElement","selector","reject","observer","checkRecaptchaBadge","convertKeysToCamelCase","obj","camelCaseKey","key","_","letter","result","newKey","failedExecutionRecaptcha","getRecaptchaToken","websiteKey","isEnterprise","waitForReCaptcha","obs","observerOptions","verifyReCaptchaLoad","badgeId","api","badgeContainers","element","RECAPTCHA_FORM_CONFIG_FIELDS","buildRecaptchaFormConfigQuery","formTypes","formType","recaptchaFetchApi","FetchGraphQL","RECAPTCHA_V3_SCRIPT_URL","RECAPTCHA_ENTERPRISE_SCRIPT_URL","LOG_PREFIX","RecaptchaModule","__publicField","_a","args","response","data","enabledForms","globalConfig","detectedTypes","formData","recaptchaBadge","webApiKey","isBadgeGlobal","languageCode","scriptUrl","script","query","url","configList","transformConfig","_b","extendedRecaptchaConfig","lazyLoadTimeout","token","recaptcha","initReCaptcha","verifyReCaptcha","setEndpoint","setConfig","enableLogger"],"mappings":"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"}