diff --git a/packages/signals/signals-runtime/src/web/web-signals-types.ts b/packages/signals/signals-runtime/src/web/web-signals-types.ts index 4c3944310..37baf42b4 100644 --- a/packages/signals/signals-runtime/src/web/web-signals-types.ts +++ b/packages/signals/signals-runtime/src/web/web-signals-types.ts @@ -7,28 +7,50 @@ export interface RawSignal extends BaseSignal { data: Data metadata?: Record } - export type InteractionData = ClickData | SubmitData | ChangeData -interface SerializedTarget { +export type ParsedAttributes = { [attributeName: string]: string | null } + +export interface TargetedHTMLElement { + id: string + attributes: ParsedAttributes [key: string]: any } type ClickData = { eventType: 'click' - target: SerializedTarget + target: TargetedHTMLElement } type SubmitData = { eventType: 'submit' - submitter?: SerializedTarget - target: SerializedTarget + submitter?: TargetedHTMLElement + target: TargetedHTMLElement } export type ChangeData = { eventType: 'change' - target: SerializedTarget + /** + * The target element that changed. + */ + target: TargetedHTMLElement + /** + * The name/type of "listener" that triggered the change. + * Elements can change due to a variety of reasons, such as a mutation, a change event, or a contenteditable change + */ listener: 'contenteditable' | 'onchange' | 'mutation' + /** + * The change that occurred -- this is a key-value object of the change that occurred + * For mutation listeners, this is the attributes that changed + * For contenteditable listeners, this is the text that changed + * @example + * ```ts + * { checked: true } // onchange + * { value: 'new value' } // onchange / mutation + * {'aria-selected': 'true' } // mutation + * { textContent: 'Sentence1\nSentence2\n' } // contenteditable + * ``` + */ change: JSONValue } diff --git a/packages/signals/signals/src/core/signal-generators/dom-gen/dom-gen.ts b/packages/signals/signals/src/core/signal-generators/dom-gen/dom-gen.ts index 18611ab6a..742c7a130 100644 --- a/packages/signals/signals/src/core/signal-generators/dom-gen/dom-gen.ts +++ b/packages/signals/signals/src/core/signal-generators/dom-gen/dom-gen.ts @@ -6,6 +6,10 @@ import { import { SignalEmitter } from '../../emitter' import { SignalGenerator } from '../types' import { cleanText } from './helpers' +import type { + ParsedAttributes, + TargetedHTMLElement, +} from '@segment/analytics-signals-runtime' interface Label { textContent: string @@ -38,11 +42,11 @@ const parseToLabel = (label: HTMLElement): Label => { } } -const parseNodeMap = (nodeMap: NamedNodeMap): Record => { - return Array.from(nodeMap).reduce((acc, attr) => { +const parseNodeMap = (nodeMap: NamedNodeMap): ParsedAttributes => { + return Array.from(nodeMap).reduce((acc, attr) => { acc[attr.name] = attr.value return acc - }, {} as Record) + }, {}) } interface ParsedElementBase {