@buildinams/core 0.3.1 → 0.4.0
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/README.md +24 -1
- package/dist/analytics/google/index.d.ts +158 -0
- package/dist/analytics/google/index.js +274 -0
- package/dist/analytics/google/index.js.map +1 -0
- package/dist/analytics/index.d.ts +101 -0
- package/dist/analytics/index.js +384 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/shopify/index.d.ts +186 -0
- package/dist/analytics/shopify/index.js +175 -0
- package/dist/analytics/shopify/index.js.map +1 -0
- package/dist/{chunk-5KDGGGVO.js → chunk-FJ7SNQQI.js} +24 -6
- package/dist/chunk-FJ7SNQQI.js.map +1 -0
- package/dist/chunk-G2BKC4BU.js +8 -0
- package/dist/chunk-G2BKC4BU.js.map +1 -0
- package/dist/chunk-GQVN2ECX.js +14 -0
- package/dist/chunk-GQVN2ECX.js.map +1 -0
- package/dist/chunk-LL3VTFNY.js +22 -0
- package/dist/chunk-LL3VTFNY.js.map +1 -0
- package/dist/chunk-M3HNM5HC.js +48 -0
- package/dist/chunk-M3HNM5HC.js.map +1 -0
- package/dist/chunk-MHFGMH3G.js +11 -0
- package/dist/chunk-MHFGMH3G.js.map +1 -0
- package/dist/chunk-OS2T6P2T.js +50 -0
- package/dist/chunk-OS2T6P2T.js.map +1 -0
- package/dist/chunk-QIJGG2F4.js +51 -0
- package/dist/chunk-QIJGG2F4.js.map +1 -0
- package/dist/consent/cookiebot/index.d.ts +16 -0
- package/dist/consent/cookiebot/index.js +27 -0
- package/dist/consent/cookiebot/index.js.map +1 -0
- package/dist/consent/google/index.d.ts +23 -0
- package/dist/consent/google/index.js +48 -0
- package/dist/consent/google/index.js.map +1 -0
- package/dist/consent/index.d.ts +1 -0
- package/dist/consent/index.js +3 -0
- package/dist/consent/index.js.map +1 -0
- package/dist/consent/onetrust/index.d.ts +23 -0
- package/dist/consent/onetrust/index.js +39 -0
- package/dist/consent/onetrust/index.js.map +1 -0
- package/dist/consent/shopify/index.d.ts +44 -0
- package/dist/consent/shopify/index.js +84 -0
- package/dist/consent/shopify/index.js.map +1 -0
- package/dist/cookies/index.d.ts +230 -0
- package/dist/cookies/index.js +188 -0
- package/dist/cookies/index.js.map +1 -0
- package/dist/define-events-CxZjoUlG.d.ts +255 -0
- package/dist/destination-5KJ5PeR3.d.ts +122 -0
- package/dist/index-Zef1nnTP.d.ts +36 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +64 -1
- package/dist/index.js.map +1 -1
- package/dist/listeners-DkU-vBPa.d.ts +15 -0
- package/dist/navigation/index.js +1 -1
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +1 -1
- package/dist/store/index.js +1 -1
- package/dist/tracking/cart/index.d.ts +74 -0
- package/dist/tracking/cart/index.js +118 -0
- package/dist/tracking/cart/index.js.map +1 -0
- package/dist/tracking/dom/index.d.ts +320 -0
- package/dist/tracking/dom/index.js +1196 -0
- package/dist/tracking/dom/index.js.map +1 -0
- package/docs/analytics.md +883 -0
- package/docs/cookies.md +354 -0
- package/docs/decisions/001-analytics-project-events.md +31 -0
- package/docs/decisions/002-tracking-dom-opt-in.md +29 -0
- package/docs/decisions/003-tracking-element-data.md +27 -0
- package/docs/decisions/004-cookies-explicit-store.md +26 -0
- package/docs/decisions/005-cookies-invalid-reads-fall-back.md +27 -0
- package/docs/decisions/006-cookies-server-only-types.md +19 -0
- package/docs/decisions/007-cookies-options-on-definition.md +25 -0
- package/docs/decisions/008-cookies-in-vertical-slices.md +24 -0
- package/docs/decisions/009-analytics-consent-targets.md +29 -0
- package/docs/decisions/010-analytics-destination-contract.md +29 -0
- package/docs/decisions/011-tracking-decoupled.md +30 -0
- package/docs/tracking.md +221 -0
- package/package.json +83 -2
- package/dist/chunk-5KDGGGVO.js.map +0 -1
- package/dist/chunk-SIU7SKJK.js +0 -139
- package/dist/chunk-SIU7SKJK.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/tracking/dom/roles.ts","../../../src/tracking/dom/attributes.ts","../../../src/tracking/dom/auto-track.ts","../../../src/tracking/dom/plugin.ts","../../../src/tracking/dom/shared.ts","../../../src/tracking/dom/clicks.ts","../../../src/tracking/dom/attach.ts","../../../src/tracking/dom/track.ts","../../../src/tracking/dom/create-dom-watcher.ts","../../../src/tracking/dom/ecommerce.ts","../../../src/tracking/dom/forms.ts","../../../src/tracking/dom/page-views.ts","../../../src/tracking/dom/scroll.ts","../../../src/tracking/dom/videos.ts"],"names":["attributes","listeners","takeChanges","view","videos"],"mappings":"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","file":"index.js","sourcesContent":["export const ROLE = \"data-track\";\n\nexport type AutoTrackKind = \"links\" | \"forms\";\n\ntype Role =\n\t| \"page-view\"\n\t| \"view-item\"\n\t| \"quick-view\"\n\t| \"list\"\n\t| \"item\"\n\t| \"promotion\"\n\t| \"click\"\n\t| \"location\"\n\t| \"video\"\n\t| \"form\"\n\t| \"scroll\"\n\t| `auto-${AutoTrackKind}`\n\t| \"auto-none\";\n\nexport const roleSelector = (role: Role) => `[${ROLE}~=\"${role}\"]`;\n\nexport const hasRole = (element: Element, role: Role) =>\n\t!!element.getAttribute(ROLE)?.split(/\\s+/).includes(role);\n","import { ROLE } from \"./roles\";\n\nexport const toKebabCase = (name: string) =>\n\tname.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n\nexport const toCamelCase = (name: string) =>\n\tname.replace(/-([a-z])/g, (_, letter: string) => letter.toUpperCase());\n\nconst toName = (field: string) => `${ROLE}-${toKebabCase(field)}`;\n\nconst toField = (name: string) => toCamelCase(name.slice(ROLE.length + 1));\n\nexport const getField = (element: Element, field: string) =>\n\telement.getAttribute(toName(field)) || undefined;\n\n// Read by the plugins themselves, so they're written without the type.\nconst BUILT_IN_FIELDS: Record<string, readonly string[] | undefined> = {\n\t\"page-view\": [\"url\", \"title\", \"pageType\"],\n\tclick: [\"id\"],\n\tlocation: [\"name\"],\n\tvideo: [\"title\"],\n\tform: [\"id\"],\n\tscroll: [\"id\"],\n};\n\nconst isBuiltIn = (type: string, field: string) =>\n\t!!BUILT_IN_FIELDS[type]?.includes(field);\n\n/**\n * The project's own fields of a type, e.g. `cta` of `track({ click: { cta } })`, written as\n * `data-track-click-cta`, so the other types on the element don't read them.\n */\nexport const getCustomFields = (element: Element, type: string) => {\n\tconst prefix = `${ROLE}-${type}-`;\n\tconst fields: Record<string, string> = {};\n\tfor (const { name, value } of element.attributes) {\n\t\tif (name.startsWith(prefix) && value) {\n\t\t\tfields[toField(`${ROLE}-${name.slice(prefix.length)}`)] = value;\n\t\t}\n\t}\n\treturn fields;\n};\n\n/** Each string field as `data-track-<field>`, or `data-track-<type>-<field>` for the project's own. */\nexport const toFieldAttributes = (type: string, data: object) =>\n\tObject.fromEntries(\n\t\tObject.entries(data).flatMap(([field, value]) =>\n\t\t\ttypeof value === \"string\"\n\t\t\t\t? [[toName(isBuiltIn(type, field) ? field : `${type}-${field}`), value]]\n\t\t\t\t: [],\n\t\t),\n\t);\n","import { type AutoTrackKind, roleSelector } from \"./roles\";\n\nconst AUTO = [\n\troleSelector(\"auto-links\"),\n\troleSelector(\"auto-forms\"),\n\troleSelector(\"auto-none\"),\n].join(\", \");\n\n/** Whether the nearest `attributes(\"auto\")` tracks this kind. */\nexport const isAutoTracked = (element: Element, kind: AutoTrackKind) =>\n\t!!element.closest(AUTO)?.matches(roleSelector(`auto-${kind}`));\n","import type { TrackRole } from \"./attach\";\nimport type { AutoTrackKind } from \"./roles\";\n\n/**\n * DOM changes in one `MutationObserver` batch, in order, only those matching the plugin's selector, attributes and\n * roles. Data changes come after the batch's DOM changes.\n */\nexport type DomChange =\n\t| { type: \"attribute\"; element: Element; attribute: string }\n\t| { type: \"children\"; added: Element[]; removed: Element[] }\n\t| { type: \"data\"; element: Element; role: TrackRole };\n\nexport type DomContext = {\n\t/** Hands an occurrence to the watcher's listeners. */\n\temit: (name: string, payload: object, element?: Element) => void;\n\troot: Document | Element;\n\t/** Handles DOM and data changes made earlier in this task, e.g. by another click handler, before they're delivered. */\n\ttakeChanges: () => void;\n\t/** Tells every plugin on the root that `pageViews()` reported a page view. */\n\tnewPage: () => void;\n};\n\nexport type DomPluginInstance = {\n\t/** Elements whose additions and removals the plugin receives, also those present at install. */\n\tselector?: string;\n\t/** Attributes whose changes the plugin receives. */\n\tattributes?: readonly string[];\n\t/** Roles whose data changes the plugin receives, for elements in the root. */\n\tdata?: readonly TrackRole[];\n\t/** Capturing listeners on the root. */\n\tlisteners?: readonly (readonly [\n\t\ttype: string,\n\t\tlistener: (event: Event) => void,\n\t])[];\n\tchanged?: (changes: DomChange[]) => void;\n\t/** Before any plugin on the root emits, itself included. */\n\tbeforeEmit?: () => void;\n\t/** On a new page, from `pageViews()` or the watcher's `newPage()`. */\n\tnewPage?: () => void;\n\t/** Emits what the plugin holds back, e.g. batched views. */\n\tflush?: () => void;\n\tstop?: () => void;\n};\n\n// Also the order plugins handle each event in, so a click's `itemSelected` comes before its `clicked` however they're\n// passed.\nexport const PLUGIN_ORDER = [\n\t\"pageViews\",\n\t\"ecommerce\",\n\t\"clicks\",\n\t\"videos\",\n\t\"forms\",\n\t\"scroll\",\n] as const;\n\nexport type PluginName = (typeof PLUGIN_ORDER)[number];\n\n/** What a plugin reports, as the watcher's listeners receive it. */\nexport type DomEvent<\n\tName extends string = string,\n\tPayload extends object = object,\n\tSource extends Element | undefined = Element | undefined,\n> = undefined extends Source\n\t? { name: Name; payload: Payload }\n\t: { name: Name; payload: Payload; element: Source };\n\ndeclare const plugin: unique symbol;\n\n/**\n * Created by `pageViews()`, `ecommerce()`, `clicks()`, `videos()`, `forms()` or `scroll()`, and passed to\n * `createDomWatcher()`. Its type says what it reports, and the fields, data and `auto` kinds `track()` takes.\n */\nexport type DomPlugin<\n\tEvent extends DomEvent = DomEvent,\n\tAttributes extends object = object,\n\tData extends object = object,\n\tAuto extends AutoTrackKind = AutoTrackKind,\n> = {\n\treadonly [plugin]?: {\n\t\tevent: Event;\n\t\tattributes: Attributes;\n\t\tdata: Data;\n\t\tauto: Auto;\n\t};\n};\n\ntype Definition = {\n\tname: PluginName;\n\tinstall: (context: DomContext) => DomPluginInstance;\n\t/** What it reports, by name: when and what it means. */\n\tevents: Record<string, string>;\n\t/** The product an item is, for `track()`. */\n\ttoId?: (item: never) => string;\n};\n\n// Opaque, so projects can't depend on the contract while it's internal.\nexport const definePlugin = <Plugin extends DomPlugin>(\n\tdefinition: Definition,\n) => definition as unknown as Plugin;\n\nexport const toDefinition = (domPlugin: DomPlugin) =>\n\tdomPlugin as unknown as Definition;\n\n/** A plugin's own `data-track-<field>` attributes, each a string. */\nexport type CustomFields = Record<string, string>;\n","import { roleSelector } from \"./roles\";\n\nexport const CLICK = roleSelector(\"click\");\n\nexport const INTERACTIVE = `a[href], button, [role=\"button\"], ${CLICK}`;\nconst MAX_TEXT_LENGTH = 100;\n// Raw text up to this length usually collapses to enough, as a link can wrap a whole product card.\nconst MAX_RAW_TEXT_LENGTH = MAX_TEXT_LENGTH * 10;\n\n// Per event, as `ecommerce()` and `clicks()` both handle each click.\nconst interactions = new WeakMap<Event, Element | null>();\n\n/** The link or button a click is on, unless it's a non-middle `auxclick`. */\nexport const getInteraction = (event: Event) => {\n\tif (interactions.has(event)) return interactions.get(event)!;\n\tconst interaction =\n\t\t// Middle clicks only arrive as `auxclick`.\n\t\t(event.type !== \"auxclick\" || (event as MouseEvent).button === 1) &&\n\t\tevent.target instanceof Element\n\t\t\t? event.target.closest(INTERACTIVE)\n\t\t\t: null;\n\tinteractions.set(event, interaction);\n\treturn interaction;\n};\n\n// Path and query, so each navigation views promotions again but a hash change doesn't.\nexport const getPage = () => window.location.pathname + window.location.search;\n\nexport const isRendered = (element: Element) => {\n\tif (typeof element.checkVisibility === \"function\") {\n\t\treturn element.checkVisibility();\n\t}\n\tfor (let node: Element | null = element; node; node = node.parentElement) {\n\t\tif (getComputedStyle(node).display === \"none\") return false;\n\t}\n\treturn true;\n};\n\nconst getLabelledBy = (element: Element) => {\n\tconst ids = element.getAttribute(\"aria-labelledby\")?.split(/\\s+/);\n\tif (!ids) return null;\n\treturn ids\n\t\t.map((id) => element.ownerDocument.getElementById(id)?.textContent)\n\t\t.join(\" \");\n};\n\nconst collapseWhitespace = (text: string) => text.replace(/\\s+/g, \" \").trim();\n\nexport const getText = (element: Element) => {\n\tconst raw =\n\t\telement.getAttribute(\"aria-label\") ??\n\t\tgetLabelledBy(element) ??\n\t\telement.textContent ??\n\t\t\"\";\n\tlet text = collapseWhitespace(raw.slice(0, MAX_RAW_TEXT_LENGTH));\n\t// Heavily indented markup can collapse to less.\n\tif (text.length < MAX_TEXT_LENGTH && raw.length > MAX_RAW_TEXT_LENGTH) {\n\t\ttext = collapseWhitespace(raw);\n\t}\n\treturn text.slice(0, MAX_TEXT_LENGTH) || undefined;\n};\n","import type { Clicked } from \"../occurrences\";\nimport { getCustomFields, getField } from \"./attributes\";\nimport { isAutoTracked } from \"./auto-track\";\nimport {\n\ttype CustomFields,\n\tdefinePlugin,\n\ttype DomEvent,\n\ttype DomPlugin,\n} from \"./plugin\";\nimport { roleSelector } from \"./roles\";\nimport { CLICK, getInteraction, getText } from \"./shared\";\n\nconst LOCATION = roleSelector(\"location\");\n\n// The nearest with data, as one written in plain HTML has none.\nconst getLocation = (element: Element): string | undefined => {\n\tconst area = element.closest(LOCATION);\n\tif (!area) return undefined;\n\treturn (\n\t\tgetField(area, \"name\") ||\n\t\t(area.parentElement ? getLocation(area.parentElement) : undefined)\n\t);\n};\n\n/**\n * Plugin for `createDomWatcher()`: `clicked` for links and buttons with `track({ click })`, and links inside\n * `track({ auto: \"links\" })`, with `location` from the nearest `track({ location })`. `Fields` are the project's own\n * fields of `click`, also in the payload.\n *\n * @example\n * ```ts\n * clicks<{ cta: string }>();\n * ```\n */\nexport const clicks = <Fields extends CustomFields = Record<never, never>>() =>\n\tdefinePlugin<\n\t\tDomPlugin<\n\t\t\tDomEvent<\"clicked\", Clicked & Partial<Fields>, Element>,\n\t\t\t{ click: { id?: string } & Fields; location: { name: string } },\n\t\t\tRecord<never, never>,\n\t\t\t\"links\"\n\t\t>\n\t>({\n\t\tname: \"clicks\",\n\t\tevents: { clicked: \"A tracked link or button was clicked.\" },\n\t\tinstall: ({ emit }) => {\n\t\t\tconst onClick = (event: Event) => {\n\t\t\t\tconst element = getInteraction(event);\n\t\t\t\tif (!element) return;\n\n\t\t\t\tconst isLink = element instanceof HTMLAnchorElement;\n\t\t\t\tif (\n\t\t\t\t\t!element.matches(CLICK) &&\n\t\t\t\t\t!(isLink && isAutoTracked(element, \"links\"))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\temit(\n\t\t\t\t\t\"clicked\",\n\t\t\t\t\t{\n\t\t\t\t\t\t...getCustomFields(element, \"click\"),\n\t\t\t\t\t\telementType: isLink ? \"link\" : \"button\",\n\t\t\t\t\t\telementId: getField(element, \"id\") || element.id || undefined,\n\t\t\t\t\t\ttext: getText(element),\n\t\t\t\t\t\turl: isLink ? element.href : undefined,\n\t\t\t\t\t\toutbound:\n\t\t\t\t\t\t\tisLink && element.protocol.startsWith(\"http\")\n\t\t\t\t\t\t\t\t? element.origin !== window.location.origin\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tlocation: getLocation(element),\n\t\t\t\t\t},\n\t\t\t\t\telement,\n\t\t\t\t);\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tlisteners: [\n\t\t\t\t\t[\"click\", onClick],\n\t\t\t\t\t[\"auxclick\", onClick],\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t});\n","import { shallowEqual } from \"../../functions/shallow-equal\";\nimport { hasRole } from \"./roles\";\n\n/** The types that take the project's item, list or promotion as data. */\nexport type TrackRole =\n\t| \"view-item\"\n\t| \"quick-view\"\n\t| \"list\"\n\t| \"item\"\n\t| \"promotion\";\n\nexport const TRACK_ROLES = new Set<string>([\n\t\"view-item\",\n\t\"quick-view\",\n\t\"list\",\n\t\"item\",\n\t\"promotion\",\n] satisfies TrackRole[]);\n\n/** The data, or a function that builds it when a plugin first reads it, e.g. when the element becomes visible. */\nexport type TrackValue<Data> = Data | (() => Data);\n\nexport const ITEM_ROLES = new Set<TrackRole>([\n\t\"item\",\n\t\"view-item\",\n\t\"quick-view\",\n]);\n\n// `Symbol.for`, so two copies of the package in one bundle share the data.\nconst DATA = Symbol.for(\"@buildinams/core/tracking/dom\");\n\ntype Stored = {\n\tvalue: unknown;\n\tresolved?: { value: unknown };\n\t// JSON of the data, to compare it with new data and key views by it.\n\tkey?: string;\n\ttoId?: (data: never) => string;\n\tid?: string;\n\t// By a plugin, so a new function only needs building to compare it when one has.\n\tread?: boolean;\n};\ntype Holder = Element & { [DATA]?: Map<TrackRole, Stored> };\n\ntype Listener = (element: Element, role: TrackRole) => void;\nconst listeners = new Set<Listener>();\n\n/** For `createDomWatcher()`, as a `MutationObserver` doesn't see properties. */\nexport const onTrackData = (listener: Listener) => {\n\tlisteners.add(listener);\n\treturn () => {\n\t\tlisteners.delete(listener);\n\t};\n};\n\n// Only for roles the element has, so data left behind when a render drops its role isn't read.\nconst getStored = (element: Element, role: TrackRole) =>\n\thasRole(element, role) ? (element as Holder)[DATA]?.get(role) : undefined;\n\nconst readStored = (element: Element, role: TrackRole) => {\n\tconst stored = getStored(element, role);\n\tif (stored) stored.read = true;\n\treturn stored;\n};\n\nconst resolve = (stored: Stored) => {\n\tstored.resolved ??= {\n\t\tvalue: typeof stored.value === \"function\" ? stored.value() : stored.value,\n\t};\n\treturn stored.resolved.value;\n};\n\nconst getKey = (stored: Stored) =>\n\t(stored.key ??= JSON.stringify(resolve(stored)));\n\nconst isLazy = (stored: Stored) => typeof stored.value === \"function\";\n\nconst isSame = (current: Stored, next: Stored) => {\n\t// Building lazy data only to compare it would defeat it.\n\tif (isLazy(current) && !current.read) return false;\n\t// E.g. `{ product }` again with the same `product`, without serializing it.\n\tif (\n\t\t!isLazy(current) &&\n\t\t!isLazy(next) &&\n\t\tshallowEqual(current.value as object, next.value as object)\n\t) {\n\t\treturn true;\n\t}\n\ttry {\n\t\treturn getKey(current) === getKey(next);\n\t} catch {\n\t\t// Reported when a plugin reads it.\n\t\treturn false;\n\t}\n};\n\n// Ignores data equal to the current data, so it can be set on every render. Only read while the element has the role.\nexport const setTrackData = (\n\telement: Element,\n\trole: TrackRole,\n\tvalue: unknown,\n\ttoId?: Stored[\"toId\"],\n) => {\n\tconst holder = element as Holder;\n\tconst data = (holder[DATA] ??= new Map());\n\tconst current = data.get(role);\n\tif (value === undefined) {\n\t\tif (!current) return;\n\t\tdata.delete(role);\n\t} else if (current?.value === value) {\n\t\treturn;\n\t} else {\n\t\tconst next: Stored = { value, toId };\n\t\t// Not read yet, so plugins read the new function without being told, as a render passes a new one each time.\n\t\tif (current && !current.read && isLazy(next)) {\n\t\t\tdata.set(role, next);\n\t\t\treturn;\n\t\t}\n\t\tif (current && isSame(current, next)) return;\n\t\tdata.set(role, next);\n\t}\n\tlisteners.forEach((listener) => listener(element, role));\n};\n\n/** The data a role reads on an element. Builds lazy data. */\nexport const getTrackData = (element: Element, role: TrackRole): unknown => {\n\tconst stored = readStored(element, role);\n\treturn stored && resolve(stored);\n};\n\n/** Without building lazy data. */\nexport const hasTrackData = (element: Element, role: TrackRole) =>\n\t!!getStored(element, role);\n\n/** The data as JSON, or `\"\"` without it, to key views by. Builds lazy data. */\nexport const getTrackKey = (element: Element, role: TrackRole) => {\n\tconst stored = readStored(element, role);\n\treturn stored ? getKey(stored) : \"\";\n};\n\n/** The product an item role's data is, by `ecommerce()`'s `id`, or `\"\"` without data. Builds lazy data. */\nexport const getTrackId = (element: Element, role: TrackRole) => {\n\tconst stored = readStored(element, role);\n\tif (!stored) return \"\";\n\tif (stored.id === undefined) {\n\t\tconst toId = stored.toId as ((data: unknown) => string) | undefined;\n\t\ttry {\n\t\t\tstored.id = toId ? toId(resolve(stored)) : getTrackKey(element, role);\n\t\t} catch (error) {\n\t\t\t// The project's `id` must not break tracking of the other elements in the same handler.\n\t\t\tconsole.error(\"[analytics] ecommerce id\", error);\n\t\t\tstored.id = getTrackKey(element, role);\n\t\t}\n\t}\n\treturn stored.id;\n};\n","import { setTrackData, TRACK_ROLES, type TrackRole } from \"./attach\";\nimport { toFieldAttributes, toKebabCase } from \"./attributes\";\nimport { ROLE } from \"./roles\";\n\n/** What `track()` returns to spread on the element. */\nexport type TrackProps = { [ROLE]?: string } & {\n\t[name: `${typeof ROLE}-${string}`]: string;\n};\n\ntype Ref = { ref: (element: Element | null) => void };\n\nconst getTypes = (element: Element) =>\n\telement.getAttribute(ROLE)?.split(/\\s+/).filter(Boolean) ?? [];\n\nconst setTypes = (element: Element, types: string[]) => {\n\tif (types.length > 0) element.setAttribute(ROLE, types.join(\" \"));\n\telse element.removeAttribute(ROLE);\n};\n\nexport const toTrackProps = (\n\tspec: Record<string, unknown>,\n\tidFor: (role: TrackRole) => ((data: never) => string) | undefined,\n): TrackProps | (TrackProps & Ref) => {\n\tconst types: string[] = [];\n\tconst fields: Record<string, string> = {};\n\tconst data: [TrackRole, unknown][] = [];\n\n\tfor (const [key, value] of Object.entries(spec)) {\n\t\tconst type = toKebabCase(key);\n\t\tif (TRACK_ROLES.has(type)) {\n\t\t\tdata.push([type as TrackRole, value]);\n\t\t\tif (value !== undefined) types.push(type);\n\t\t} else if (type === \"auto\") {\n\t\t\tif (value === false) types.push(\"auto-none\");\n\t\t\telse if (value !== undefined) {\n\t\t\t\tfor (const kind of [value].flat()) types.push(`auto-${kind}`);\n\t\t\t}\n\t\t} else if (value !== undefined && value !== false) {\n\t\t\ttypes.push(type);\n\t\t\tObject.assign(\n\t\t\t\tfields,\n\t\t\t\ttoFieldAttributes(type, value === true ? {} : (value as object)),\n\t\t\t);\n\t\t}\n\t}\n\n\tconst props: TrackProps = {\n\t\t...fields,\n\t\t...(types.length > 0 && { [ROLE]: types.join(\" \") }),\n\t};\n\tif (data.length === 0) return props;\n\n\treturn {\n\t\t...props,\n\t\t// Also adds or removes the types, for an element rendered without spreading the props.\n\t\tref: (element) => {\n\t\t\tif (!element) return;\n\t\t\tfor (const [role, value] of data) {\n\t\t\t\tconst current = getTypes(element);\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tif (current.includes(role)) {\n\t\t\t\t\t\tsetTypes(\n\t\t\t\t\t\t\telement,\n\t\t\t\t\t\t\tcurrent.filter((type) => type !== role),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tsetTrackData(element, role, undefined);\n\t\t\t\t} else {\n\t\t\t\t\tsetTrackData(element, role, value, idFor(role));\n\t\t\t\t\tif (!current.includes(role)) setTypes(element, [...current, role]);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n};\n","import { type EventCatalog, shape } from \"../../analytics/define-events\";\nimport { createListeners, type Subscribe } from \"../listeners\";\nimport { onTrackData, type TrackRole, type TrackValue } from \"./attach\";\nimport {\n\ttype DomChange,\n\ttype DomContext,\n\ttype DomPlugin,\n\ttype DomPluginInstance,\n\tPLUGIN_ORDER,\n\ttype PluginName,\n\ttoDefinition,\n} from \"./plugin\";\nimport { toTrackProps, type TrackProps } from \"./track\";\n\nexport type DomWatcherOptions = {\n\t/** Where the plugins watch for markup and events. Defaults to `document`. */\n\troot?: Document | Element;\n};\n\ntype RootState = {\n\tinstances: Map<PluginName, DomPluginInstance>;\n\tordered: DomPluginInstance[];\n\tselector: string;\n\tobserver: MutationObserver;\n\thandlers: Map<string, ((event: Event) => void)[]>;\n\tdispatchers: Map<string, (event: Event) => void>;\n\tdata: Map<Element, Set<TrackRole>>;\n\tstopData: () => void;\n\t/**\n\t * What watchers' plugins reported while starting, delivered in a microtask or before anything reported after, so\n\t * every subscription made in the same task receives it, and in order across the root's watchers.\n\t */\n\theld: (() => void)[];\n};\n\nconst elementsIn = (node: Node, selector: string) =>\n\tnode instanceof Element\n\t\t? [\n\t\t\t\t...(node.matches(selector) ? [node] : []),\n\t\t\t\t...node.querySelectorAll(selector),\n\t\t\t]\n\t\t: [];\n\n// Shared by every watcher on a root, with one plugin of each kind, so a module re-evaluated by HMR replaces its\n// plugins instead of tracking twice, while watchers with other plugins keep theirs.\nconst roots = new WeakMap<Document | Element, RootState>();\n\nconst notify = (state: RootState, mutations: MutationRecord[]) => {\n\tif (mutations.length === 0) return;\n\t// One query per added or removed subtree for all plugins, as React can replace large parts of the page at once.\n\tconst found = mutations.map((mutation) => {\n\t\tif (mutation.type !== \"childList\" || !state.selector) return undefined;\n\t\tconst added = [...mutation.addedNodes].flatMap((node) =>\n\t\t\telementsIn(node, state.selector),\n\t\t);\n\t\tconst removed = [...mutation.removedNodes].flatMap((node) =>\n\t\t\telementsIn(node, state.selector),\n\t\t);\n\t\t// Most of a page's renders touch no tracked element, so plugins aren't woken for them.\n\t\treturn added.length > 0 || removed.length > 0\n\t\t\t? { added, removed }\n\t\t\t: undefined;\n\t});\n\tfor (const instance of state.ordered) {\n\t\tif (!instance.changed) continue;\n\t\tconst { selector, attributes = [] } = instance;\n\t\tconst changes = mutations.flatMap((mutation, index): DomChange[] => {\n\t\t\tif (mutation.type === \"attributes\") {\n\t\t\t\treturn attributes.includes(mutation.attributeName!)\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"attribute\",\n\t\t\t\t\t\t\t\telement: mutation.target as Element,\n\t\t\t\t\t\t\t\tattribute: mutation.attributeName!,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\t}\n\t\t\tconst children = found[index];\n\t\t\tif (!selector || !children) return [];\n\t\t\tconst matches = (element: Element) => element.matches(selector);\n\t\t\tconst added = children.added.filter(matches);\n\t\t\tconst removed = children.removed.filter(matches);\n\t\t\treturn added.length > 0 || removed.length > 0\n\t\t\t\t? [{ type: \"children\", added, removed }]\n\t\t\t\t: [];\n\t\t});\n\t\tif (changes.length > 0) instance.changed(changes);\n\t}\n};\n\nconst notifyData = (state: RootState) => {\n\tif (state.data.size === 0) return;\n\tconst changed = [...state.data];\n\tstate.data.clear();\n\tfor (const instance of state.ordered) {\n\t\tconst { data: roles = [] } = instance;\n\t\tif (!instance.changed || roles.length === 0) continue;\n\t\t// Removed in the meantime, and already handled as such.\n\t\tconst changes = changed.flatMap(([element, elementRoles]) =>\n\t\t\t!element.isConnected\n\t\t\t\t? []\n\t\t\t\t: [...elementRoles]\n\t\t\t\t\t\t.filter((role) => roles.includes(role))\n\t\t\t\t\t\t.map((role): DomChange => ({ type: \"data\", element, role })),\n\t\t);\n\t\tif (changes.length > 0) instance.changed(changes);\n\t}\n};\n\nconst release = (state: RootState) => {\n\tconst held = state.held;\n\tstate.held = [];\n\theld.forEach((deliver) => deliver());\n};\n\n// DOM changes first, so plugins already know about the elements whose data changed.\nconst takeChanges = (state: RootState) => {\n\tnotify(state, state.observer.takeRecords());\n\tnotifyData(state);\n};\n\nconst createState = (root: Document | Element): RootState => {\n\tconst state: RootState = {\n\t\tinstances: new Map(),\n\t\tordered: [],\n\t\tselector: \"\",\n\t\tobserver: new MutationObserver((mutations) => notify(state, mutations)),\n\t\thandlers: new Map(),\n\t\tdispatchers: new Map(),\n\t\tdata: new Map(),\n\t\theld: [],\n\t\t// After the task's other data, as React sets children's refs before their parents': an item handled straight away\n\t\t// would miss its list's data.\n\t\tstopData: onTrackData((element, role) => {\n\t\t\tif (!root.contains(element)) return;\n\t\t\tif (state.data.size === 0) queueMicrotask(() => takeChanges(state));\n\t\t\tconst roles = state.data.get(element) ?? new Set();\n\t\t\tstate.data.set(element, roles.add(role));\n\t\t}),\n\t};\n\troots.set(root, state);\n\treturn state;\n};\n\n// After installs and removals, with pending changes already handled, as `disconnect()` drops them.\nconst configure = (root: Document | Element, state: RootState) => {\n\tstate.ordered = PLUGIN_ORDER.flatMap((name) => {\n\t\tconst instance = state.instances.get(name);\n\t\treturn instance ? [instance] : [];\n\t});\n\tstate.selector = state.ordered\n\t\t.flatMap(({ selector }) => (selector ? [selector] : []))\n\t\t.join(\", \");\n\tconst attributes = [\n\t\t...new Set(state.ordered.flatMap(({ attributes = [] }) => attributes)),\n\t];\n\n\tstate.observer.disconnect();\n\tif (state.selector || attributes.length > 0) {\n\t\tstate.observer.observe(root, {\n\t\t\tchildList: !!state.selector,\n\t\t\tsubtree: true,\n\t\t\t...(attributes.length > 0 && {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: attributes,\n\t\t\t}),\n\t\t});\n\t}\n\n\tstate.handlers = new Map();\n\tfor (const { listeners = [] } of state.ordered) {\n\t\tfor (const [type, listener] of listeners) {\n\t\t\tstate.handlers.set(type, [...(state.handlers.get(type) ?? []), listener]);\n\t\t}\n\t}\n\t// Capturing, as media events don't bubble.\n\tfor (const [type, dispatcher] of state.dispatchers) {\n\t\tif (state.handlers.has(type)) continue;\n\t\troot.removeEventListener(type, dispatcher, true);\n\t\tstate.dispatchers.delete(type);\n\t}\n\tfor (const type of state.handlers.keys()) {\n\t\tif (state.dispatchers.has(type)) continue;\n\t\tconst dispatcher = (event: Event) =>\n\t\t\tstate.handlers.get(type)?.forEach((handler) => handler(event));\n\t\troot.addEventListener(type, dispatcher, true);\n\t\tstate.dispatchers.set(type, dispatcher);\n\t}\n\n\tif (state.instances.size === 0) {\n\t\tstate.stopData();\n\t\troots.delete(root);\n\t}\n};\n\nconst remove = (state: RootState, name: PluginName) => {\n\tconst instance = state.instances.get(name);\n\tif (!instance) return;\n\tstate.instances.delete(name);\n\tinstance.stop?.();\n};\n\ntype UnionToIntersection<Union> = (\n\tUnion extends unknown ? (value: Union) => void : never\n) extends (value: infer Intersection) => void\n\t? Intersection\n\t: never;\n\ntype Brand<Plugin> = NonNullable<\n\tPlugin extends DomPlugin ? Plugin[keyof Plugin] : never\n>;\n\n/** What the plugins report, as the watcher's listeners receive it. */\nexport type DomEventOf<Plugins extends readonly DomPlugin[]> = Brand<\n\tPlugins[number]\n>[\"event\"];\n\ntype AttributesOf<Plugins extends readonly DomPlugin[]> = UnionToIntersection<\n\tBrand<Plugins[number]>[\"attributes\"]\n>;\n\ntype DataOf<Plugins extends readonly DomPlugin[]> = UnionToIntersection<\n\tBrand<Plugins[number]>[\"data\"]\n>;\n\ntype AutoOf<Plugins extends readonly DomPlugin[]> = Brand<\n\tPlugins[number]\n>[\"auto\"];\n\n/** Payloads of the plugins' events, by name. */\ntype EventMapOf<Event extends { name: string; payload: object }> = {\n\t[E in Event as E[\"name\"]]: E[\"payload\"];\n};\n\n/** What `track()` takes: per type, its fields, or `true` when they're all optional, and data for `ecommerce()`. */\nexport type TrackSpec<Plugins extends readonly DomPlugin[]> = {\n\t[T in keyof AttributesOf<Plugins>]?: Record<\n\t\tnever,\n\t\tnever\n\t> extends AttributesOf<Plugins>[T]\n\t\t? AttributesOf<Plugins>[T] | true\n\t\t: AttributesOf<Plugins>[T];\n} & {\n\t[R in keyof DataOf<Plugins>]?: TrackValue<DataOf<Plugins>[R]> | undefined;\n} & ([AutoOf<Plugins>] extends [never]\n\t\t? unknown\n\t\t: {\n\t\t\t\tauto?:\n\t\t\t\t\t| AutoOf<Plugins>\n\t\t\t\t\t| readonly [AutoOf<Plugins>, ...AutoOf<Plugins>[]]\n\t\t\t\t\t| false;\n\t\t\t});\n\ntype Tracked<Spec, Data> = [keyof Spec & keyof Data] extends [never]\n\t? TrackProps\n\t: TrackProps & { ref: (element: Element | null) => void };\n\nexport type DomWatcher<Plugins extends readonly DomPlugin[]> = {\n\t/**\n\t * Props to spread on an element, so the plugins track it. Each key is a type, written in `data-track`, with its fields\n\t * as `data-track-<field>` attributes, so server components and CMS markup can write them too. Only the types of the\n\t * watcher's plugins:\n\t *\n\t * - `pageView`: `pageViewed` when the element appears, with `pageViews()`. Put it on each page's root.\n\t * - `click`: `clicked` for this button or link, with `clicks()`. Buttons always need it.\n\t * - `location`: `location` on every `clicked` inside it, with `clicks()`. Reports nothing by itself.\n\t * - `auto`: tracks every link (`\"links\"`) or form (`\"forms\"`) inside it, with `clicks()` and `forms()`; `false` turns\n\t * it off for a subtree. The nearest one decides.\n\t * - `video`: video events for this `<video>` or the videos inside it, with `videos()`.\n\t * - `form`: `formStarted` and `formSubmitted` for this form, with `forms()`.\n\t * - `scroll`: `scrolled` as the visitor scrolls through this element, with `scroll()`.\n\t *\n\t * The project's item, list or promotion, for `ecommerce()`, come with a `ref`, which sets the data on the element\n\t * once it mounts, so it stays out of the HTML. Without data, e.g. while a quick view is closed, the element isn't\n\t * tracked as one.\n\t *\n\t * - `viewItem`: `itemViewed` when visible, once per URL for each product. On a product page.\n\t * - `quickView`: `itemViewed` each time it becomes visible. On a quick view.\n\t * - `promotion`: `promotionViewed` when visible, `promotionSelected` for clicks inside it.\n\t * - `list`: places the items inside it in the list.\n\t * - `item`: `itemsViewed` when visible, batched per list, `itemSelected` for clicks inside it.\n\t *\n\t * Data can be a function, built when the plugin first reads it, e.g. when the element becomes visible; once read, a\n\t * new function from a later render is built to compare it, so keep it stable where building is costly. An element\n\t * with its own ref needs a ref that calls both. Without a framework, call `ref` with the element: it also adds or\n\t * removes the data's types.\n\t *\n\t * @example\n\t * ```tsx\n\t * <main {...track({ pageView: { pageType: \"product\" } })}>\n\t * <footer {...track({ auto: \"links\", location: { name: \"footer\" } })}>\n\t * <section {...track({ promotion: { id: \"summer\" }, location: { name: \"hero\" } })}>\n\t * ```\n\t */\n\ttrack: <Spec extends TrackSpec<Plugins>>(\n\t\tspec: Spec & Record<Exclude<keyof Spec, keyof TrackSpec<Plugins>>, never>,\n\t) => Tracked<Spec, DataOf<Plugins>>;\n\t/**\n\t * Hands what the plugins report to `listener`: every event, or only those named. Pass the watcher to\n\t * `createAnalytics()`'s `sources` instead to track them. The first subscription starts the plugins in the browser,\n\t * and the last one to unsubscribe stops them. What they report while starting, e.g. a server-rendered page's view,\n\t * reaches every subscription made in the same task.\n\t */\n\tsubscribe: Subscribe<DomEventOf<Plugins>>;\n\t/** Catalog entries for what the plugins report, to spread into `defineEvents()`. */\n\tevents: EventCatalog<EventMapOf<DomEventOf<Plugins>>>;\n\t/**\n\t * Tells the plugins a new page is shown, for a router that tracks page views itself instead of `pageViews()`. Views\n\t * pending from the previous page are emitted, and what stays in view counts again.\n\t */\n\tnewPage: () => void;\n\t/** Emits the views `ecommerce()` batches, e.g. right before tracking an event that must come after them. */\n\tflush: () => void;\n};\n\n/**\n * Watches markup with the plugins you pass and reports what happens, so call sites only need the watcher's `track()`.\n * Creating it does nothing, so server components can import it; the first `subscribe()` starts it in the browser:\n *\n * - `pageViews()`: `pageViewed` for `track({ pageView })`.\n * - `ecommerce()`: `itemViewed`, `itemsViewed`, `itemSelected`, `promotionViewed` and `promotionSelected` for\n * `track({ viewItem | quickView | list | item | promotion })`.\n * - `clicks()`: `clicked` for links and buttons with `track({ click })`, and links inside `track({ auto: \"links\" })`.\n * - `videos()`: `videoStarted`, `videoProgressed` and `videoCompleted` for `track({ video })`.\n * - `forms()`: `formStarted` and `formSubmitted` for `track({ form })`, and forms inside `track({ auto: \"forms\" })`.\n * - `scroll()`: `scrolled` as `track({ scroll })` is scrolled into view, by default at 25, 50, 75 and 90%.\n *\n * The plugins decide which types `track()` takes, and with which fields and data. Nothing is tracked without its type\n * in `data-track`, so a project decides what reaches analytics. Works with server-rendered and CMS markup, as it\n * listens on the root instead of the elements.\n *\n * @example\n * ```ts\n * export const domWatcher = createDomWatcher([pageViews(), clicks<{ cta: string }>(), ecommerce<{ item: Item }>()]);\n * export const { track } = domWatcher;\n *\n * export const events = defineEvents({ ...domWatcher.events });\n * export const analytics = createAnalytics<EventsOf<typeof events>>({ events, sources: [domWatcher], consent });\n * ```\n */\nexport const createDomWatcher = <const Plugins extends readonly DomPlugin[]>(\n\tplugins: Plugins,\n\t{ root: rootOption }: DomWatcherOptions = {},\n): DomWatcher<Plugins> => {\n\tconst definitions = plugins.map(toDefinition);\n\t// The last, as it replaces the others when installed.\n\tconst toId = [...definitions]\n\t\t.reverse()\n\t\t.find(({ name }) => name === \"ecommerce\")?.toId;\n\tconst idFor = (type: TrackRole) =>\n\t\ttype === \"list\" || type === \"promotion\" ? undefined : toId;\n\tlet running:\n\t\t| {\n\t\t\t\troot: Document | Element;\n\t\t\t\tstate: RootState;\n\t\t\t\tinstalled: Map<PluginName, DomPluginInstance>;\n\t\t }\n\t\t| undefined;\n\tconst isCurrent = ({ state, installed }: NonNullable<typeof running>) =>\n\t\t[...installed].some(\n\t\t\t([name, instance]) => state.instances.get(name) === instance,\n\t\t);\n\tconst eachInstance = (method: \"newPage\" | \"flush\") => {\n\t\t// Replaced by another watcher on the root, e.g. after HMR, which handles its own.\n\t\tif (!running || !isCurrent(running)) return;\n\t\tconst { state } = running;\n\t\ttakeChanges(state);\n\t\tstate.ordered.forEach((instance) => instance[method]?.());\n\t};\n\n\tlet isStarting = false;\n\n\tconst start = () => {\n\t\tconst root = rootOption ?? document;\n\t\tconst state = roots.get(root) ?? createState(root);\n\t\ttakeChanges(state);\n\t\tisStarting = true;\n\n\t\tconst context: DomContext = {\n\t\t\temit: (name, payload, element) => {\n\t\t\t\t// Read when emitting, as a plugin from another watcher can join the root.\n\t\t\t\tfor (const instance of state.ordered) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinstance.beforeEmit?.();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(\"[analytics] beforeEmit\", error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst event = (\n\t\t\t\t\telement ? { name, payload, element } : { name, payload }\n\t\t\t\t) as DomEventOf<Plugins>;\n\t\t\t\tif (isStarting) {\n\t\t\t\t\tstate.held.push(() => listeners.emit(event));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\trelease(state);\n\t\t\t\tlisteners.emit(event);\n\t\t\t},\n\t\t\troot,\n\t\t\ttakeChanges: () => takeChanges(state),\n\t\t\tnewPage: () => state.ordered.forEach((instance) => instance.newPage?.()),\n\t\t};\n\t\tconst installed = new Map<PluginName, DomPluginInstance>();\n\t\tfor (const { name, install } of definitions) {\n\t\t\tremove(state, name);\n\t\t\tconst instance = install(context);\n\t\t\tstate.instances.set(name, instance);\n\t\t\tinstalled.set(name, instance);\n\t\t}\n\t\tconfigure(root, state);\n\n\t\tconst rootElement = root instanceof Document ? root.documentElement : root;\n\t\tfor (const name of PLUGIN_ORDER) {\n\t\t\tconst instance = installed.get(name);\n\t\t\tif (!instance?.selector || !instance.changed) continue;\n\t\t\tinstance.changed([\n\t\t\t\t{\n\t\t\t\t\ttype: \"children\",\n\t\t\t\t\tadded: elementsIn(rootElement, instance.selector),\n\t\t\t\t\tremoved: [],\n\t\t\t\t},\n\t\t\t]);\n\t\t}\n\n\t\tisStarting = false;\n\t\trunning = { root, state, installed };\n\t\tqueueMicrotask(() => release(state));\n\t};\n\n\tconst listeners = createListeners<DomEventOf<Plugins>>({\n\t\tstart: () => {\n\t\t\ttry {\n\t\t\t\tstart();\n\t\t\t} finally {\n\t\t\t\tisStarting = false;\n\t\t\t}\n\t\t},\n\t\tstop: () => {\n\t\t\tif (!running) return;\n\t\t\tconst { root, state, installed } = running;\n\t\t\trunning = undefined;\n\t\t\ttakeChanges(state);\n\t\t\trelease(state);\n\t\t\tfor (const [name, instance] of installed) {\n\t\t\t\tif (state.instances.get(name) === instance) remove(state, name);\n\t\t\t}\n\t\t\tconfigure(root, state);\n\t\t},\n\t});\n\n\treturn {\n\t\ttrack: ((spec: Record<string, unknown>) =>\n\t\t\ttoTrackProps(spec, idFor)) as DomWatcher<Plugins>[\"track\"],\n\t\tsubscribe: listeners.subscribe,\n\t\tevents: Object.fromEntries(\n\t\t\tdefinitions.flatMap(({ events }) =>\n\t\t\t\tObject.entries(events).map(([name, description]) => [\n\t\t\t\t\tname,\n\t\t\t\t\t{ description, payload: shape() },\n\t\t\t\t]),\n\t\t\t),\n\t\t) as DomWatcher<Plugins>[\"events\"],\n\t\tnewPage: () => eachInstance(\"newPage\"),\n\t\tflush: () => eachInstance(\"flush\"),\n\t};\n};\n","import { IS_DEVELOPMENT } from \"../../config\";\nimport type {\n\tEcommerceOccurrences,\n\tEcommerceShapes,\n\tShapeLeaf,\n} from \"../occurrences\";\nimport {\n\tgetTrackData,\n\tgetTrackId,\n\tgetTrackKey,\n\thasTrackData,\n\ttype TrackRole,\n} from \"./attach\";\nimport { toCamelCase } from \"./attributes\";\nimport { definePlugin, type DomEvent, type DomPlugin } from \"./plugin\";\nimport { hasRole, ROLE, roleSelector } from \"./roles\";\nimport { getInteraction, getPage, isRendered } from \"./shared\";\n\n// The project's data, which this plugin only passes on.\ntype Data = object;\n\n// Where an item is: its list, its position in it, and the promotion around it.\ntype Placement = { list?: Data; index?: number; promotion?: Data };\n\ntype Placed = { item: Data } & Omit<Placement, \"list\">;\n\ntype Occurrences = EcommerceOccurrences<EcommerceShapes>;\n\nconst PROMOTION = roleSelector(\"promotion\");\nconst QUICK_VIEW = roleSelector(\"quick-view\");\nconst VIEW_ITEM = `${roleSelector(\"view-item\")}, ${QUICK_VIEW}`;\nconst ITEM_LIST = roleSelector(\"list\");\nconst ITEM = roleSelector(\"item\");\nconst ROLES = [\"promotion\", \"view-item\", \"quick-view\", \"item\", \"list\"] as const;\n\n// Keeps each dataLayer push small; GA4 accepts up to 200 items per event.\nconst MAX_BATCH_SIZE = 30;\n// Hydration sets data sooner, so an element still without it most likely misses its ref.\nconst MISSING_DATA_DELAY = 2000;\n// After a URL change, for the page to render with it, e.g. a variant picker that changes the URL before the data.\nconst URL_CHANGE_DELAY = 100;\n\nconst OBSERVED = `${PROMOTION}, ${ITEM}, ${VIEW_ITEM}`;\n// Share of the viewport.\nconst LINE_HEIGHT = 0.001;\n// Placements kept for the tab, the most recently selected products'.\nconst MAX_STORED_PLACEMENTS = 50;\n\n/** The project's item, and its list and promotion when it has them. */\nexport type EcommerceInput = {\n\titem: object;\n\tlist?: object;\n\tpromotion?: object;\n};\n\ntype Complete<Shapes extends EcommerceInput> = {\n\titem: Shapes[\"item\"];\n\tlist: ShapeLeaf<Shapes, \"list\">;\n\tpromotion: ShapeLeaf<Shapes, \"promotion\">;\n};\n\ntype EcommerceEvent<Shapes extends EcommerceInput> = {\n\t[K in keyof Occurrences]: DomEvent<\n\t\tK,\n\t\tEcommerceOccurrences<Complete<Shapes>>[K],\n\t\tundefined\n\t>;\n}[keyof Occurrences];\n\n// Without keys for a list or promotion the project doesn't have.\ntype EcommerceData<Shapes extends EcommerceInput> = {\n\tviewItem: Shapes[\"item\"];\n\tquickView: Shapes[\"item\"];\n\titem: Shapes[\"item\"];\n} & Pick<Complete<Shapes>, Extract<keyof Shapes, \"list\" | \"promotion\">>;\n\nexport type EcommerceOptions<Item = object> = {\n\t/**\n\t * Which product an item is, e.g. `({ product }) => product.id`, so a product page's `{ product, variant }` matches\n\t * the `{ product }` of the card it was selected on, and counts as one view per product. Defaults to the item's JSON.\n\t */\n\tid?: (item: Item) => string;\n\t/** Share of a promotion or item, or of the viewport for those taller than it, that counts as viewed. */\n\tthreshold?: number;\n\t/**\n\t * Milliseconds that views are collected for before they're tracked in the order they happened, with one\n\t * `itemsViewed` per list.\n\t */\n\tbatchDelay?: number;\n\t/**\n\t * Where the tab keeps the placements of the products last selected, so a product page loaded in full, e.g. on a\n\t * multi-page site, gets the list it was selected from. Change it when the list's or promotion's shape changes. Default\n\t * `\"analytics-placements\"`.\n\t */\n\tstorageKey?: string;\n};\n\nconst getListElement = (itemElement: Element) =>\n\titemElement.parentElement?.closest(ITEM_LIST) ?? null;\n\n// A product in a promotion without a list in between is part of the promotion's creative.\nconst getFeaturedIn = (itemElement: Element, listElement: Element | null) => {\n\tconst promotionElement = itemElement.closest(PROMOTION);\n\treturn promotionElement &&\n\t\t!(listElement && promotionElement.contains(listElement))\n\t\t? promotionElement\n\t\t: null;\n};\n\n// Without the fields it doesn't have, so payloads only hold what the markup says.\nconst definedFields = <T extends object>(fields: T) =>\n\tObject.fromEntries(\n\t\tObject.entries(fields).filter(([, value]) => value !== undefined),\n\t) as T;\n\n/**\n * The band of the viewport, as shares of its height from its top and bottom, that an element must reach to cover\n * `threshold` of the viewport: any of it up to half, and both its edges above. Cut off at its top or bottom, an\n * element reaching it covers that much; otherwise it's in view whole, and its own share counts.\n */\nconst toLines = (threshold: number) => {\n\tconst lines: [top: number, bottom: number][] =\n\t\tthreshold <= 0.5\n\t\t\t? [[threshold, threshold]]\n\t\t\t: [\n\t\t\t\t\t[1 - threshold, threshold],\n\t\t\t\t\t[threshold, 1 - threshold],\n\t\t\t\t];\n\t// About a pixel tall, as a root without height only meets targets by touching its edge.\n\treturn lines.map(([top, bottom]): [top: number, bottom: number] =>\n\t\ttop + bottom >= 1\n\t\t\t? [top - LINE_HEIGHT / 2, bottom - LINE_HEIGHT / 2]\n\t\t\t: [top, bottom],\n\t);\n};\n\nconst toMargin = (share: number) => `${-Math.round(share * 10_000) / 100}%`;\n\nconst isItem = (element: Element) => element.matches(ITEM);\n\nconst isPlacement = (entry: unknown): entry is [string, Placement] => {\n\tif (!Array.isArray(entry) || typeof entry[0] !== \"string\") return false;\n\tconst placement: unknown = entry[1];\n\tif (\n\t\ttypeof placement !== \"object\" ||\n\t\tplacement === null ||\n\t\tArray.isArray(placement)\n\t) {\n\t\treturn false;\n\t}\n\tconst { index } = placement as Placement;\n\treturn index === undefined || typeof index === \"number\";\n};\n\n// Written by an earlier deploy too, so entries in another shape are ignored.\nconst readPlacements = (key: string) => {\n\ttry {\n\t\tconst value = sessionStorage.getItem(key);\n\t\tconst entries: unknown = value ? JSON.parse(value) : [];\n\t\treturn new Map(\n\t\t\tArray.isArray(entries)\n\t\t\t\t? entries.filter(isPlacement).slice(-MAX_STORED_PLACEMENTS)\n\t\t\t\t: [],\n\t\t);\n\t} catch {\n\t\treturn new Map<string, Placement>();\n\t}\n};\n\nconst writePlacements = (key: string, placements: Map<string, Placement>) => {\n\ttry {\n\t\tsessionStorage.setItem(key, JSON.stringify([...placements]));\n\t} catch {\n\t\t// Storage blocked or full: placements only last until the next page load.\n\t}\n};\n\n/**\n * Plugin for `createDomWatcher()`: views and selections of products, lists and promotions, with the data passed to the\n * watcher's `track()`, placed by the markup around it:\n *\n * - `itemViewed` for `track({ viewItem })` when it becomes visible, and `track({ quickView })` each time it does.\n * - `promotionViewed` and `promotionSelected` for `track({ promotion })`.\n * - `itemsViewed` and `itemSelected` for `track({ item })`, inside `track({ list })`.\n *\n * Views are batched, and emitted before anything else the watcher emits. Leave out `list` or `promotion` when the\n * project has none.\n *\n * @example\n * ```ts\n * ecommerce<{ item: { product: ProductFragment; variant?: VariantFragment }; list: List }>({\n * id: ({ product }) => product.id,\n * });\n * ```\n */\nexport const ecommerce = <Shapes extends EcommerceInput>({\n\tid,\n\tthreshold = 0.5,\n\tbatchDelay = 500,\n\tstorageKey = \"analytics-placements\",\n}: EcommerceOptions<Shapes[\"item\"]> = {}) =>\n\tdefinePlugin<\n\t\tDomPlugin<\n\t\t\tEcommerceEvent<Shapes>,\n\t\t\tRecord<never, never>,\n\t\t\tEcommerceData<Shapes>,\n\t\t\tnever\n\t\t>\n\t>({\n\t\tname: \"ecommerce\",\n\t\tevents: {\n\t\t\titemViewed:\n\t\t\t\t\"A product was viewed on its page or in a quick view, placed where it was last selected.\",\n\t\t\titemSelected: \"A product in a list was clicked.\",\n\t\t\titemsViewed: \"Products in a list came into view, batched per list.\",\n\t\t\tpromotionViewed: \"A promotion came into view.\",\n\t\t\tpromotionSelected: \"A promotion was clicked.\",\n\t\t},\n\t\ttoId: id as ((item: never) => string) | undefined,\n\t\tinstall: (context) => {\n\t\t\tconst { takeChanges } = context;\n\t\t\t// Set while emitting its own views, which flush nothing.\n\t\t\tlet isTrackingViews = false;\n\t\t\tconst emit = <K extends keyof Occurrences>(\n\t\t\t\tkey: K,\n\t\t\t\toccurrence: Occurrences[K],\n\t\t\t) => {\n\t\t\t\tconst wasTracking = isTrackingViews;\n\t\t\t\tisTrackingViews = key === \"itemsViewed\" || key === \"promotionViewed\";\n\t\t\t\ttry {\n\t\t\t\t\tcontext.emit(key, occurrence);\n\t\t\t\t} finally {\n\t\t\t\t\tisTrackingViews = wasTracking;\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst checked = new WeakSet<Element>();\n\t\t\tconst warnWithoutData = (element: Element, type: TrackRole) => {\n\t\t\t\tif (!IS_DEVELOPMENT || checked.has(element)) return;\n\t\t\t\tchecked.add(element);\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (\n\t\t\t\t\t\telement.isConnected &&\n\t\t\t\t\t\thasRole(element, type) &&\n\t\t\t\t\t\t!hasTrackData(element, type)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[analytics] data-track=\"${type}\" has no data. Set the ref from track({ ${toCamelCase(type)} }) on it.`,\n\t\t\t\t\t\t\telement,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}, MISSING_DATA_DELAY);\n\t\t\t};\n\n\t\t\t// Per page, so a promotion or item that stays mounted across navigations is viewed once per page.\n\t\t\tconst viewed = new Set<string>();\n\t\t\tlet viewedPage: string | undefined;\n\t\t\tconst visible = new Set<Element>();\n\t\t\t// Views waiting to be tracked, in the order they happened: items per list element, promotions per view.\n\t\t\tconst pending = new Map<\n\t\t\t\tobject | null,\n\t\t\t\t{ list?: Data; items: Placed[] } | { promotion: Data; items: Data[] }\n\t\t\t>();\n\t\t\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\n\t\t\tconst flushViews = () => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\ttimeout = undefined;\n\t\t\t\tconst views = [...pending.values()];\n\t\t\t\tpending.clear();\n\t\t\t\tfor (const view of views) {\n\t\t\t\t\tif (\"promotion\" in view) {\n\t\t\t\t\t\temit(\"promotionViewed\", view);\n\t\t\t\t\t} else {\n\t\t\t\t\t\temit(\"itemsViewed\", definedFields(view));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleFlush = () => {\n\t\t\t\ttimeout ??= setTimeout(flushViews, batchDelay);\n\t\t\t};\n\n\t\t\tconst viewedOnPage = () => {\n\t\t\t\tif (viewedPage !== getPage()) {\n\t\t\t\t\tviewed.clear();\n\t\t\t\t\tviewedPage = getPage();\n\t\t\t\t}\n\t\t\t\treturn viewed;\n\t\t\t};\n\n\t\t\tconst isNewView = (key: string) => {\n\t\t\t\tif (viewedOnPage().has(key)) return false;\n\t\t\t\tviewed.add(key);\n\t\t\t\treturn true;\n\t\t\t};\n\n\t\t\t// Where each product was last selected, for an `itemViewed` it opens outside the list, e.g. a quick view or the next page.\n\t\t\tconst selectedFrom = readPlacements(storageKey);\n\t\t\tconst setSelectedFrom = (product: string, placement: Placement) => {\n\t\t\t\t// Reinserted, so the map stays ordered by selection.\n\t\t\t\tselectedFrom.delete(product);\n\t\t\t\tselectedFrom.set(product, placement);\n\t\t\t\tfor (const oldest of selectedFrom.keys()) {\n\t\t\t\t\tif (selectedFrom.size <= MAX_STORED_PLACEMENTS) break;\n\t\t\t\t\tselectedFrom.delete(oldest);\n\t\t\t\t}\n\t\t\t\twritePlacements(storageKey, selectedFrom);\n\t\t\t};\n\n\t\t\t// Positions of the items in each list, until items or lists are added, removed or changed.\n\t\t\tlet indexes = new WeakMap<Element, Map<Element, number>>();\n\n\t\t\tconst getIndex = (listElement: Element, itemElement: Element) => {\n\t\t\t\tlet positions = indexes.get(listElement);\n\t\t\t\tif (!positions) {\n\t\t\t\t\tpositions = new Map();\n\t\t\t\t\tfor (const other of listElement.querySelectorAll(ITEM)) {\n\t\t\t\t\t\tif (getListElement(other) === listElement) {\n\t\t\t\t\t\t\tpositions.set(other, positions.size);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tindexes.set(listElement, positions);\n\t\t\t\t}\n\t\t\t\treturn positions.get(itemElement) ?? -1;\n\t\t\t};\n\n\t\t\tconst toItem = (\n\t\t\t\telement: Element,\n\t\t\t\tlistElement = getListElement(element),\n\t\t\t) => {\n\t\t\t\tconst item = getTrackData(element, \"item\") as Data | undefined;\n\t\t\t\tif (!item) {\n\t\t\t\t\twarnWithoutData(element, \"item\");\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst list =\n\t\t\t\t\t(listElement && (getTrackData(listElement, \"list\") as Data)) ||\n\t\t\t\t\tundefined;\n\t\t\t\tif (listElement && !list) warnWithoutData(listElement, \"list\");\n\t\t\t\tconst promotionElement = element.closest(PROMOTION);\n\t\t\t\tconst promotion =\n\t\t\t\t\t(promotionElement &&\n\t\t\t\t\t\t(getTrackData(promotionElement, \"promotion\") as Data)) ||\n\t\t\t\t\tundefined;\n\n\t\t\t\treturn {\n\t\t\t\t\tlist,\n\t\t\t\t\tfeaturedIn: getFeaturedIn(element, listElement),\n\t\t\t\t\tplaced: definedFields<Placed>({\n\t\t\t\t\t\titem,\n\t\t\t\t\t\tindex: listElement ? getIndex(listElement, element) : undefined,\n\t\t\t\t\t\tpromotion,\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t};\n\n\t\t\t// The URL and products each visible quick view was shown with, so a variant picked in it doesn't\n\t\t\t// count again.\n\t\t\tconst shownItems = new WeakMap<Element, string>();\n\n\t\t\tconst trackViewItem = (element: Element) => {\n\t\t\t\tconst isQuickView = element.matches(QUICK_VIEW);\n\t\t\t\tconst type = isQuickView ? \"quick-view\" : \"view-item\";\n\t\t\t\tconst item = getTrackData(element, type) as Data | undefined;\n\t\t\t\tif (!item) {\n\t\t\t\t\twarnWithoutData(element, type);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Products, not variants, like GA4's one view per item details screen.\n\t\t\t\tconst product = getTrackId(element, type);\n\t\t\t\tif (isQuickView) {\n\t\t\t\t\tconst key = `${getPage()}${product}`;\n\t\t\t\t\tif (shownItems.get(element) === key) return;\n\t\t\t\t\tshownItems.set(element, key);\n\t\t\t\t} else if (!isNewView(`${VIEW_ITEM}${product}`)) {\n\t\t\t\t\t// Per page, so a product page that scrolls back into view or remounts without navigating counts once.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\temit(\"itemViewed\", { ...selectedFrom.get(product), item });\n\t\t\t};\n\n\t\t\tconst viewItem = (element: Element) => {\n\t\t\t\tconst listElement = getListElement(element);\n\t\t\t\t// Featured products are viewed with their promotion.\n\t\t\t\tif (getFeaturedIn(element, listElement)) return;\n\t\t\t\tconst key = `${ITEM}${listElement ? getTrackKey(listElement, \"list\") : \"\"}${getTrackId(element, \"item\")}`;\n\t\t\t\t// Checked before resolving, as items are viewed in bulk while scrolling.\n\t\t\t\tif (viewedOnPage().has(key)) return;\n\t\t\t\tconst resolved = toItem(element, listElement);\n\t\t\t\tif (!resolved) return;\n\t\t\t\tviewed.add(key);\n\t\t\t\tconst { list, placed } = resolved;\n\n\t\t\t\tconst batch = pending.get(listElement);\n\t\t\t\tif (batch && !(\"promotion\" in batch)) {\n\t\t\t\t\tbatch.items.push(placed);\n\t\t\t\t\tif (batch.items.length >= MAX_BATCH_SIZE) flushViews();\n\t\t\t\t} else {\n\t\t\t\t\tpending.set(listElement, { list, items: [placed] });\n\t\t\t\t}\n\t\t\t\tscheduleFlush();\n\t\t\t};\n\n\t\t\tconst view = (element: Element) => {\n\t\t\t\tif (!element.isConnected) return;\n\t\t\t\tif (element.matches(VIEW_ITEM)) trackViewItem(element);\n\t\t\t\tif (element.matches(ITEM)) viewItem(element);\n\n\t\t\t\tconst key = `${PROMOTION}${getTrackKey(element, \"promotion\")}`;\n\t\t\t\tif (!element.matches(PROMOTION) || viewedOnPage().has(key)) return;\n\t\t\t\tconst promotion = getTrackData(element, \"promotion\") as\n\t\t\t\t\t| Data\n\t\t\t\t\t| undefined;\n\t\t\t\tif (!promotion) {\n\t\t\t\t\twarnWithoutData(element, \"promotion\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tviewed.add(key);\n\t\t\t\tconst items = [...element.querySelectorAll(ITEM)].flatMap(\n\t\t\t\t\t(itemElement) => {\n\t\t\t\t\t\tconst listElement = getListElement(itemElement);\n\t\t\t\t\t\t// Before reading the data, as the items of a list inside the promotion aren't featured.\n\t\t\t\t\t\tif (getFeaturedIn(itemElement, listElement) !== element) return [];\n\t\t\t\t\t\tif (listElement && !hasTrackData(listElement, \"list\")) {\n\t\t\t\t\t\t\twarnWithoutData(listElement, \"list\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst item = getTrackData(itemElement, \"item\") as Data | undefined;\n\t\t\t\t\t\tif (!item) warnWithoutData(itemElement, \"item\");\n\t\t\t\t\t\treturn item ? [item] : [];\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst promotionView = { promotion, items };\n\t\t\t\tpending.set(promotionView, promotionView);\n\t\t\t\tscheduleFlush();\n\t\t\t};\n\n\t\t\tconst onClick = (event: Event) => {\n\t\t\t\tconst element = getInteraction(event);\n\t\t\t\tif (!element) return;\n\t\t\t\t// So positions are current.\n\t\t\t\ttakeChanges();\n\n\t\t\t\tconst promotionElement = element.closest(PROMOTION);\n\t\t\t\tconst promotion =\n\t\t\t\t\tpromotionElement &&\n\t\t\t\t\t(getTrackData(promotionElement, \"promotion\") as Data | undefined);\n\t\t\t\tconst itemElement = element.closest(ITEM);\n\t\t\t\tconst resolved = itemElement && toItem(itemElement);\n\n\t\t\t\tconst isFeatured = !!resolved?.featuredIn;\n\t\t\t\t// A product in a list in a promotion carries the promotion in `itemSelected` instead.\n\t\t\t\tconst isInPromotedList =\n\t\t\t\t\t!!resolved &&\n\t\t\t\t\t!isFeatured &&\n\t\t\t\t\t!!promotionElement?.contains(itemElement);\n\n\t\t\t\t// The observer can lag behind a fast click.\n\t\t\t\tif (promotion) view(promotionElement);\n\t\t\t\tif (resolved) view(itemElement);\n\t\t\t\tif (promotion && !isInPromotedList) {\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"promotionSelected\",\n\t\t\t\t\t\tdefinedFields({\n\t\t\t\t\t\t\tpromotion,\n\t\t\t\t\t\t\titem: isFeatured ? resolved.placed.item : undefined,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!resolved) return;\n\t\t\t\tconst { list, placed } = resolved;\n\t\t\t\tsetSelectedFrom(\n\t\t\t\t\tgetTrackId(itemElement, \"item\"),\n\t\t\t\t\tdefinedFields({\n\t\t\t\t\t\tlist,\n\t\t\t\t\t\tindex: placed.index,\n\t\t\t\t\t\tpromotion: placed.promotion,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tif (!isFeatured) {\n\t\t\t\t\temit(\"itemSelected\", definedFields({ list, ...placed }));\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst setInView = (target: Element, isInView: boolean) => {\n\t\t\t\tif (isInView && visible.has(target)) return;\n\t\t\t\t// An entry can be queued before a navigation hid its target, e.g. the previous page in Next.js's <Activity>.\n\t\t\t\tif (isInView && isRendered(target)) {\n\t\t\t\t\tvisible.add(target);\n\t\t\t\t\tview(target);\n\t\t\t\t} else {\n\t\t\t\t\tvisible.delete(target);\n\t\t\t\t\t// Hidden, e.g. a closed quick view, so it counts again when shown.\n\t\t\t\t\tshownItems.delete(target);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Undefined until each observer reported since `observe()`, so one isn't read without the others.\n\t\t\ttype Reports = { ratio?: boolean; lines: (boolean | undefined)[] };\n\t\t\tconst reports = new WeakMap<Element, Reports>();\n\t\t\tconst report = (target: Element, update: (state: Reports) => void) => {\n\t\t\t\tconst state = reports.get(target);\n\t\t\t\tif (!state) return;\n\t\t\t\tupdate(state);\n\t\t\t\tif (state.ratio === undefined || state.lines.includes(undefined))\n\t\t\t\t\treturn;\n\t\t\t\tsetInView(target, state.ratio || state.lines.every(Boolean));\n\t\t\t};\n\n\t\t\tconst ratioObserver = new IntersectionObserver(\n\t\t\t\t(entries) => {\n\t\t\t\t\tfor (const { target, isIntersecting, intersectionRatio } of entries) {\n\t\t\t\t\t\treport(target, (state) => {\n\t\t\t\t\t\t\tstate.ratio = isIntersecting && intersectionRatio >= threshold;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ threshold },\n\t\t\t);\n\t\t\tconst lineObservers = toLines(threshold).map(\n\t\t\t\t([top, bottom], index) =>\n\t\t\t\t\tnew IntersectionObserver(\n\t\t\t\t\t\t(entries) => {\n\t\t\t\t\t\t\tfor (const { target, isIntersecting } of entries) {\n\t\t\t\t\t\t\t\treport(target, (state) => {\n\t\t\t\t\t\t\t\t\tstate.lines[index] = isIntersecting;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The document, not the implicit root, as that ignores the margin in a cross-origin iframe.\n\t\t\t\t\t\t\troot: document,\n\t\t\t\t\t\t\trootMargin: `${toMargin(top)} 0px ${toMargin(bottom)} 0px`,\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tconst observe = (element: Element) => {\n\t\t\t\treports.set(element, { lines: lineObservers.map(() => undefined) });\n\t\t\t\tratioObserver.observe(element);\n\t\t\t\tlineObservers.forEach((observer) => observer.observe(element));\n\t\t\t};\n\t\t\tconst unobserve = (element: Element) => {\n\t\t\t\treports.delete(element);\n\t\t\t\tratioObserver.unobserve(element);\n\t\t\t\tlineObservers.forEach((observer) => observer.unobserve(element));\n\t\t\t};\n\n\t\t\t// What stays in view across a client-side navigation doesn't intersect again, so it's observed anew. The navigation\n\t\t\t// can hide what was visible before the observer reports it.\n\t\t\tlet observedPath = window.location.pathname;\n\t\t\t// Once page views are reported, by `pageViews()` or the watcher's `newPage()`, a new path alone isn't one yet.\n\t\t\tlet hasPageViews = false;\n\t\t\tconst observeAnew = () => {\n\t\t\t\tobservedPath = window.location.pathname;\n\t\t\t\tflushViews();\n\t\t\t\tvisible.forEach((element) => {\n\t\t\t\t\tunobserve(element);\n\t\t\t\t\tobserve(element);\n\t\t\t\t});\n\t\t\t\tvisible.clear();\n\t\t\t};\n\n\t\t\t// Pending views would be lost when the visitor leaves.\n\t\t\tconst onHide = () => {\n\t\t\t\tif (document.visibilityState === \"hidden\") flushViews();\n\t\t\t};\n\t\t\twindow.addEventListener(\"pagehide\", flushViews);\n\t\t\tdocument.addEventListener(\"visibilitychange\", onHide);\n\n\t\t\t// A variant picker can change the URL after the data, in a later task and without remounting the page.\n\t\t\tlet urlChange: ReturnType<typeof setTimeout> | undefined;\n\t\t\tconst onUrlChange = () => {\n\t\t\t\tclearTimeout(urlChange);\n\t\t\t\turlChange = setTimeout(() => {\n\t\t\t\t\tvisible.forEach((element) => {\n\t\t\t\t\t\tif (element.isConnected) trackViewItem(element);\n\t\t\t\t\t});\n\t\t\t\t}, URL_CHANGE_DELAY);\n\t\t\t};\n\t\t\tconst navigation = (window as { navigation?: EventTarget }).navigation;\n\t\t\t// Covers `history.replaceState`, unlike `popstate`, which is for browsers without it.\n\t\t\tnavigation?.addEventListener(\"currententrychange\", onUrlChange);\n\t\t\twindow.addEventListener(\"popstate\", onUrlChange);\n\n\t\t\t// New data or roles for the same element, e.g. a rerendered carousel slide, or data set after it mounted.\n\t\t\tconst dataChanged = (element: Element) => {\n\t\t\t\tconst wasVisible = visible.has(element);\n\t\t\t\tunobserve(element);\n\t\t\t\tvisible.delete(element);\n\t\t\t\tif (\n\t\t\t\t\t!hasTrackData(element, \"view-item\") &&\n\t\t\t\t\t!hasTrackData(element, \"quick-view\")\n\t\t\t\t) {\n\t\t\t\t\tshownItems.delete(element);\n\t\t\t\t}\n\t\t\t\tif (!element.matches(OBSERVED)) return;\n\t\t\t\tobserve(element);\n\t\t\t\t// Without waiting for the observer, which is a frame late and paused in background tabs.\n\t\t\t\tif (wasVisible) {\n\t\t\t\t\tvisible.add(element);\n\t\t\t\t\tview(element);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tselector: OBSERVED,\n\t\t\t\tattributes: [ROLE],\n\t\t\t\tdata: ROLES,\n\t\t\t\tlisteners: [\n\t\t\t\t\t[\"click\", onClick],\n\t\t\t\t\t[\"auxclick\", onClick],\n\t\t\t\t],\n\t\t\t\t// So pending views come before any interaction or page view. Without page views, a new path means the router\n\t\t\t\t// shows a page the project tracks itself.\n\t\t\t\tbeforeEmit: () => {\n\t\t\t\t\tif (isTrackingViews) return;\n\t\t\t\t\tif (hasPageViews || window.location.pathname === observedPath) {\n\t\t\t\t\t\tflushViews();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tobserveAnew();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tnewPage: () => {\n\t\t\t\t\thasPageViews = true;\n\t\t\t\t\tobserveAnew();\n\t\t\t\t},\n\t\t\t\tflush: flushViews,\n\t\t\t\tchanged: (changes) => {\n\t\t\t\t\tconst movesItems = changes.some((change) =>\n\t\t\t\t\t\tchange.type === \"children\"\n\t\t\t\t\t\t\t? change.added.some(isItem) || change.removed.some(isItem)\n\t\t\t\t\t\t\t: change.type === \"attribute\" ||\n\t\t\t\t\t\t\t\tchange.role === \"item\" ||\n\t\t\t\t\t\t\t\tchange.role === \"list\",\n\t\t\t\t\t);\n\t\t\t\t\tif (movesItems) indexes = new WeakMap();\n\n\t\t\t\t\tfor (const change of changes) {\n\t\t\t\t\t\tif (change.type === \"children\") {\n\t\t\t\t\t\t\tchange.removed.forEach((element) => {\n\t\t\t\t\t\t\t\tunobserve(element);\n\t\t\t\t\t\t\t\tvisible.delete(element);\n\t\t\t\t\t\t\t\tshownItems.delete(element);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tchange.added.forEach(observe);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdataChanged(change.element);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\tflushViews();\n\t\t\t\t\twindow.removeEventListener(\"pagehide\", flushViews);\n\t\t\t\t\tdocument.removeEventListener(\"visibilitychange\", onHide);\n\t\t\t\t\tnavigation?.removeEventListener(\"currententrychange\", onUrlChange);\n\t\t\t\t\twindow.removeEventListener(\"popstate\", onUrlChange);\n\t\t\t\t\tclearTimeout(urlChange);\n\t\t\t\t\tratioObserver.disconnect();\n\t\t\t\t\tlineObservers.forEach((observer) => observer.disconnect());\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n","import type { DomOccurrences } from \"../occurrences\";\nimport { getCustomFields, getField } from \"./attributes\";\nimport { isAutoTracked } from \"./auto-track\";\nimport {\n\ttype CustomFields,\n\tdefinePlugin,\n\ttype DomEvent,\n\ttype DomPlugin,\n} from \"./plugin\";\nimport { roleSelector } from \"./roles\";\nimport { getPage, getText } from \"./shared\";\n\ntype Form = DomOccurrences[\"formStarted\"];\n\nconst FORM = roleSelector(\"form\");\n\nconst isTracked = (form: HTMLFormElement) =>\n\tform.matches(FORM) || isAutoTracked(form, \"forms\");\n\n// Attributes, not properties: `form.id` and `form.action` return a field when one is named `id` or `action`.\nconst toForm = (form: HTMLFormElement): Form => {\n\tconst action = form.getAttribute(\"action\");\n\treturn {\n\t\t...getCustomFields(form, \"form\"),\n\t\tformId: getField(form, \"id\") || form.getAttribute(\"id\") || undefined,\n\t\tformName: form.getAttribute(\"name\") || undefined,\n\t\tformDestination: action\n\t\t\t? new URL(action, window.location.href).href\n\t\t\t: window.location.href,\n\t};\n};\n\ntype FormEvent<\n\tName extends \"formStarted\" | \"formSubmitted\",\n\tFields extends CustomFields,\n> = DomEvent<Name, DomOccurrences[Name] & Partial<Fields>, HTMLFormElement>;\n\n/**\n * Plugin for `createDomWatcher()`: `formStarted` and `formSubmitted` for forms with `track({ form })` or inside\n * `track({ auto: \"forms\" })`. Never field values. `Fields` are the project's own fields of `form`, also in\n * the payload.\n */\nexport const forms = <Fields extends CustomFields = Record<never, never>>() =>\n\tdefinePlugin<\n\t\tDomPlugin<\n\t\t\tFormEvent<\"formStarted\", Fields> | FormEvent<\"formSubmitted\", Fields>,\n\t\t\t{ form: { id?: string } & Fields },\n\t\t\tRecord<never, never>,\n\t\t\t\"forms\"\n\t\t>\n\t>({\n\t\tname: \"forms\",\n\t\tevents: {\n\t\t\tformStarted: \"A tracked form was first interacted with on this page.\",\n\t\t\tformSubmitted: \"A tracked form was submitted.\",\n\t\t},\n\t\tinstall: ({ emit }) => {\n\t\t\t// Per page, like GA4, so a form filled in again after a navigation starts again. Also untracked forms, so their\n\t\t\t// ancestors aren't searched on every keystroke.\n\t\t\tconst seenForms = new WeakMap<HTMLFormElement, string>();\n\n\t\t\tconst onFormInput = (event: Event) => {\n\t\t\t\tif (!(event.target instanceof Element)) return;\n\t\t\t\tconst form =\n\t\t\t\t\tevent.target instanceof HTMLFormElement\n\t\t\t\t\t\t? event.target\n\t\t\t\t\t\t: event.target.closest(\"form\");\n\t\t\t\tif (!form || seenForms.get(form) === getPage()) return;\n\t\t\t\tseenForms.set(form, getPage());\n\t\t\t\tif (isTracked(form)) {\n\t\t\t\t\temit(\"formStarted\", toForm(form), form);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst onSubmit = (event: Event) => {\n\t\t\t\tconst form = event.target;\n\t\t\t\tif (!(form instanceof HTMLFormElement && isTracked(form))) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst { submitter } = event as SubmitEvent;\n\t\t\t\temit(\n\t\t\t\t\t\"formSubmitted\",\n\t\t\t\t\t{\n\t\t\t\t\t\t...toForm(form),\n\t\t\t\t\t\tformSubmitText: submitter ? getText(submitter) : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tform,\n\t\t\t\t);\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tlisteners: [\n\t\t\t\t\t[\"input\", onFormInput],\n\t\t\t\t\t[\"change\", onFormInput],\n\t\t\t\t\t[\"submit\", onSubmit],\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t});\n","import type { PageViewed } from \"../occurrences\";\nimport { getCustomFields, getField } from \"./attributes\";\nimport {\n\ttype CustomFields,\n\tdefinePlugin,\n\ttype DomEvent,\n\ttype DomPlugin,\n} from \"./plugin\";\nimport { ROLE, roleSelector } from \"./roles\";\nimport { getPage, isRendered } from \"./shared\";\n\nconst PAGE_VIEW = roleSelector(\"page-view\");\nconst PAGE_FIELDS = [\"url\", \"title\", \"pageType\"] as const;\n\n/**\n * Plugin for `createDomWatcher()`: `pageViewed` for elements with `track({ pageView })` when they appear or are shown\n * again, once per URL. `Fields` are the project's own fields of `pageView`, also in the payload.\n *\n * @example\n * ```ts\n * pageViews<{ section: string }>();\n * ```\n */\nexport const pageViews = <\n\tFields extends CustomFields = Record<never, never>,\n>() =>\n\tdefinePlugin<\n\t\tDomPlugin<\n\t\t\tDomEvent<\"pageViewed\", PageViewed & Partial<Fields>, Element>,\n\t\t\t{ pageView: PageViewed & Fields },\n\t\t\tRecord<never, never>,\n\t\t\tnever\n\t\t>\n\t>({\n\t\tname: \"pageViews\",\n\t\tevents: {\n\t\t\tpageViewed:\n\t\t\t\t\"A page was shown: on load, after a client-side navigation, and when a hidden page is shown again.\",\n\t\t},\n\t\tinstall: ({ emit, newPage }) => {\n\t\t\tlet lastPageView: string | undefined;\n\n\t\t\tconst trackPageView = (element: Element) => {\n\t\t\t\t// Also skips a page that remounts without navigating, e.g. after a Suspense fallback.\n\t\t\t\tif (lastPageView === getPage() || !element.matches(PAGE_VIEW)) return;\n\t\t\t\tif (!isRendered(element)) return;\n\t\t\t\tlastPageView = getPage();\n\t\t\t\tnewPage();\n\t\t\t\temit(\n\t\t\t\t\t\"pageViewed\",\n\t\t\t\t\t{\n\t\t\t\t\t\t...getCustomFields(element, \"page-view\"),\n\t\t\t\t\t\t...Object.fromEntries(\n\t\t\t\t\t\t\tPAGE_FIELDS.flatMap((field) => {\n\t\t\t\t\t\t\t\tconst value = getField(element, field);\n\t\t\t\t\t\t\t\treturn value ? [[field, value]] : [];\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\telement,\n\t\t\t\t);\n\t\t\t};\n\n\t\t\t// Showing a hidden page changes its size, e.g. React's <Activity>, which Next.js uses to keep visited pages\n\t\t\t// mounted. Observing `style` instead would wake every plugin for each animation frame.\n\t\t\tconst resizes =\n\t\t\t\ttypeof ResizeObserver === \"undefined\"\n\t\t\t\t\t? undefined\n\t\t\t\t\t: new ResizeObserver((entries) =>\n\t\t\t\t\t\t\tentries.forEach(({ target }) => trackPageView(target)),\n\t\t\t\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tselector: PAGE_VIEW,\n\t\t\t\tattributes: [ROLE, `${ROLE}-page-type`, `${ROLE}-url`, `${ROLE}-title`],\n\t\t\t\tchanged: (changes) => {\n\t\t\t\t\tfor (const change of changes) {\n\t\t\t\t\t\tif (change.type === \"children\") {\n\t\t\t\t\t\t\tchange.removed.forEach((element) => resizes?.unobserve(element));\n\t\t\t\t\t\t\tchange.added.forEach((element) => {\n\t\t\t\t\t\t\t\tresizes?.observe(element);\n\t\t\t\t\t\t\t\ttrackPageView(element);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (change.type === \"attribute\") {\n\t\t\t\t\t\t\tif (change.element.matches(PAGE_VIEW)) {\n\t\t\t\t\t\t\t\tresizes?.observe(change.element);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttrackPageView(change.element);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstop: () => resizes?.disconnect(),\n\t\t\t};\n\t\t},\n\t});\n","import type { Scrolled } from \"../occurrences\";\nimport { getCustomFields, getField } from \"./attributes\";\nimport {\n\ttype CustomFields,\n\tdefinePlugin,\n\ttype DomEvent,\n\ttype DomPlugin,\n} from \"./plugin\";\nimport { ROLE, roleSelector } from \"./roles\";\nimport { getPage, isRendered } from \"./shared\";\n\nconst SCROLL = roleSelector(\"scroll\");\n\ntype ScrollOptions = {\n\t/** Percentages of the element scrolled into view that each report `scrolled` once per URL. */\n\tthresholds?: readonly number[];\n};\n\n// How much of the element is above the viewport's bottom edge.\nconst getPercent = (element: Element) => {\n\tconst { top, height } = element.getBoundingClientRect();\n\t// Hidden, e.g. a page React's <Activity> keeps mounted.\n\tif (height === 0 || !isRendered(element)) return 0;\n\tconst percent = ((window.innerHeight - top) / height) * 100;\n\treturn Math.min(Math.max(percent, 0), 100);\n};\n\n/**\n * Plugin for `createDomWatcher()`: `scrolled` for elements with `track({ scroll })`, once per URL for each threshold\n * (25, 50, 75 and 90%) of the element scrolled into view. Only after a scroll, also a restored scroll position, so an\n * element that fits the viewport isn't tracked on load. Put it on the page's root for scroll depth, or on an article.\n * `Fields` are the project's own fields of `scroll`, also in the payload.\n */\nexport const scroll = <Fields extends CustomFields = Record<never, never>>({\n\tthresholds = [25, 50, 75, 90],\n}: ScrollOptions = {}) =>\n\tdefinePlugin<\n\t\tDomPlugin<\n\t\t\tDomEvent<\"scrolled\", Scrolled & Partial<Fields>, Element>,\n\t\t\t{ scroll: { id?: string } & Fields },\n\t\t\tRecord<never, never>,\n\t\t\tnever\n\t\t>\n\t>({\n\t\tname: \"scroll\",\n\t\tevents: {\n\t\t\tscrolled:\n\t\t\t\t\"A tracked element was scrolled through to a threshold, once per page.\",\n\t\t},\n\t\tinstall: ({ emit }) => {\n\t\t\tconst ascending = [...thresholds].sort((a, b) => a - b);\n\t\t\tconst elements = new Set<Element>();\n\t\t\tconst reached = new WeakMap<\n\t\t\t\tElement,\n\t\t\t\t{ page: string; percents: Set<number> }\n\t\t\t>();\n\t\t\tlet frame: number | undefined;\n\n\t\t\tconst check = () => {\n\t\t\t\tframe = undefined;\n\t\t\t\tconst page = getPage();\n\t\t\t\tfor (const element of elements) {\n\t\t\t\t\tconst percent = getPercent(element);\n\t\t\t\t\tlet state = reached.get(element);\n\t\t\t\t\tif (state?.page !== page) {\n\t\t\t\t\t\tstate = { page, percents: new Set() };\n\t\t\t\t\t\treached.set(element, state);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const threshold of ascending) {\n\t\t\t\t\t\tif (percent < threshold || state.percents.has(threshold)) continue;\n\t\t\t\t\t\tstate.percents.add(threshold);\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"scrolled\",\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t...getCustomFields(element, \"scroll\"),\n\t\t\t\t\t\t\t\tpercentScrolled: threshold,\n\t\t\t\t\t\t\t\telementId: getField(element, \"id\") || element.id || undefined,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\telement,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Once per frame, as scroll events can fire more often.\n\t\t\tconst onScroll = () => {\n\t\t\t\tif (elements.size > 0) frame ??= requestAnimationFrame(check);\n\t\t\t};\n\t\t\t// On the window, not the root, as the page's scroll events target the document. Capturing, as they don't bubble.\n\t\t\twindow.addEventListener(\"scroll\", onScroll, {\n\t\t\t\tcapture: true,\n\t\t\t\tpassive: true,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tselector: SCROLL,\n\t\t\t\tattributes: [ROLE],\n\t\t\t\tchanged: (changes) => {\n\t\t\t\t\tfor (const change of changes) {\n\t\t\t\t\t\tif (change.type === \"children\") {\n\t\t\t\t\t\t\tchange.removed.forEach((element) => elements.delete(element));\n\t\t\t\t\t\t\tchange.added.forEach((element) => elements.add(element));\n\t\t\t\t\t\t} else if (change.type === \"attribute\") {\n\t\t\t\t\t\t\tif (change.element.matches(SCROLL)) elements.add(change.element);\n\t\t\t\t\t\t\telse elements.delete(change.element);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tstop: () => {\n\t\t\t\t\twindow.removeEventListener(\"scroll\", onScroll, { capture: true });\n\t\t\t\t\tif (frame !== undefined) cancelAnimationFrame(frame);\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n","import type { DomOccurrences } from \"../occurrences\";\nimport { getCustomFields, getField } from \"./attributes\";\nimport {\n\ttype CustomFields,\n\tdefinePlugin,\n\ttype DomEvent,\n\ttype DomPlugin,\n} from \"./plugin\";\nimport { roleSelector } from \"./roles\";\n\ntype Video = DomOccurrences[\"videoStarted\"];\n\nconst VIDEO = roleSelector(\"video\");\n// GA4's enhanced measurement milestones.\nconst VIDEO_MILESTONES = [10, 25, 50, 75];\n\nconst toSeconds = (seconds: number) =>\n\tNumber.isFinite(seconds) ? Math.round(seconds) : undefined;\n\nconst toVideo = (video: HTMLMediaElement, container: Element): Video => ({\n\t...getCustomFields(container, \"video\"),\n\tvideoTitle:\n\t\tgetField(container, \"title\") ||\n\t\tvideo.title ||\n\t\tvideo.getAttribute(\"aria-label\") ||\n\t\tundefined,\n\tvideoUrl: video.currentSrc || undefined,\n\tvideoProvider: \"html5\",\n\tvideoDuration: toSeconds(video.duration),\n\tvideoCurrentTime: toSeconds(video.currentTime),\n});\n\ntype VideoEvent<\n\tName extends \"videoStarted\" | \"videoProgressed\" | \"videoCompleted\",\n\tFields extends CustomFields,\n> = DomEvent<Name, DomOccurrences[Name] & Partial<Fields>, HTMLVideoElement>;\n\n/**\n * Plugin for `createDomWatcher()`: `videoStarted`, `videoProgressed` (10, 25, 50 and 75%) and `videoCompleted` for\n * `<video>` elements with, or inside, `track({ video })`, so decorative loops aren't tracked. `Fields` are the\n * project's own fields of `video`, also in the payload.\n */\nexport const videos = <Fields extends CustomFields = Record<never, never>>() =>\n\tdefinePlugin<\n\t\tDomPlugin<\n\t\t\t| VideoEvent<\"videoStarted\", Fields>\n\t\t\t| VideoEvent<\"videoProgressed\", Fields>\n\t\t\t| VideoEvent<\"videoCompleted\", Fields>,\n\t\t\t{ video: { title?: string } & Fields },\n\t\t\tRecord<never, never>,\n\t\t\tnever\n\t\t>\n\t>({\n\t\tname: \"videos\",\n\t\tevents: {\n\t\t\tvideoStarted: \"A tracked video started playing.\",\n\t\t\tvideoProgressed:\n\t\t\t\t\"A tracked video passed 10, 25, 50 or 75% of its duration.\",\n\t\t\tvideoCompleted: \"A tracked video played to its end.\",\n\t\t},\n\t\tinstall: ({ emit }) => {\n\t\t\t// Per play-through, so replaying after the end starts again.\n\t\t\tconst videos = new WeakMap<HTMLMediaElement, Set<number>>();\n\n\t\t\tconst onMedia = (event: Event) => {\n\t\t\t\tconst target = event.target;\n\t\t\t\tif (!(target instanceof HTMLVideoElement)) return;\n\t\t\t\t// `timeupdate` fires several times a second, mostly for videos that aren't tracked.\n\t\t\t\tif (event.type !== \"play\" && !videos.has(target)) return;\n\t\t\t\tconst container = target.closest(VIDEO);\n\t\t\t\tif (!container) return;\n\n\t\t\t\tconst reached = videos.get(target);\n\t\t\t\tif (event.type === \"emptied\") {\n\t\t\t\t\tvideos.delete(target);\n\t\t\t\t} else if (event.type === \"play\" && !reached) {\n\t\t\t\t\tvideos.set(target, new Set());\n\t\t\t\t\temit(\"videoStarted\", toVideo(target, container), target);\n\t\t\t\t} else if (event.type === \"timeupdate\" && reached && target.duration) {\n\t\t\t\t\tconst percent = (target.currentTime / target.duration) * 100;\n\t\t\t\t\tfor (const milestone of VIDEO_MILESTONES) {\n\t\t\t\t\t\tif (percent < milestone || reached.has(milestone)) continue;\n\t\t\t\t\t\treached.add(milestone);\n\t\t\t\t\t\temit(\n\t\t\t\t\t\t\t\"videoProgressed\",\n\t\t\t\t\t\t\t{ ...toVideo(target, container), videoPercent: milestone },\n\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"ended\" && reached) {\n\t\t\t\t\tvideos.delete(target);\n\t\t\t\t\temit(\n\t\t\t\t\t\t\"videoCompleted\",\n\t\t\t\t\t\t{ ...toVideo(target, container), videoPercent: 100 },\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tlisteners: [\n\t\t\t\t\t[\"play\", onMedia],\n\t\t\t\t\t[\"timeupdate\", onMedia],\n\t\t\t\t\t[\"ended\", onMedia],\n\t\t\t\t\t[\"emptied\", onMedia],\n\t\t\t\t],\n\t\t\t};\n\t\t},\n\t});\n"]}
|