@pierre/diffs 1.2.10 → 1.2.11
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 +6 -6
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +6 -6
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +6 -1
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +1 -1
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.js +4 -2
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +6 -2
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +82 -21
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +7 -2
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +77 -15
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/managers/InteractionManager.js +1 -1
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/ResizeManager.js +1 -1
- package/dist/managers/ResizeManager.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +3 -2
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +49 -2
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.js +12 -0
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/includesFileAnnotations.d.ts +17 -0
- package/dist/utils/includesFileAnnotations.d.ts.map +1 -0
- package/dist/utils/includesFileAnnotations.js +19 -0
- package/dist/utils/includesFileAnnotations.js.map +1 -0
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +4 -2
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +4 -2
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/worker/worker-portable.js +8 -4
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +8 -4
- package/dist/worker/worker.js.map +1 -1
- package/package.json +2 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractionManager.js","names":["mode: TMode","options: InteractionManagerOptions<TMode>","reasons: string[]","start: SelectionPoint","end: SelectionPoint","nextRange: SelectedLineRange | null","lineType: LineTypes | undefined","codeElement: HTMLElement | undefined","lineElement: HTMLElement | undefined","lineIndexValue: string | undefined","numberElement: HTMLElement | undefined","tokenElement: HTMLElement | undefined","tokenInfo: TokenCache | undefined","expandInfo: ExpandCache | undefined","lineNumber: number | undefined","mergeConflictActionTarget: MergeConflictActionTarget | undefined","path: EventTarget[]","current: Node | null"],"sources":["../../src/managers/InteractionManager.ts"],"sourcesContent":["import { toHtml } from 'hast-util-to-html';\n\nimport type {\n AnnotationSide,\n DiffLineEventBaseProps,\n DiffTokenEventBaseProps,\n ExpansionDirections,\n LineEventBaseProps,\n LineTypes,\n MergeConflictResolution,\n SelectedLineRange,\n SelectionPoint,\n SelectionSide,\n TokenEventBase,\n} from '../types';\nimport { areSelectionPointsEqual } from '../utils/areSelectionPointsEqual';\nimport { areSelectionsEqual } from '../utils/areSelectionsEqual';\nimport { createGutterUtilityElement } from '../utils/createGutterUtilityElement';\n\ninterface TokenCache {\n tokenElement: HTMLElement;\n lineCharStart: number;\n lineCharEnd: number;\n tokenText: string;\n}\n\ninterface ExpandCache {\n hunkIndex: number | undefined;\n direction: ExpansionDirections;\n all: boolean;\n}\n\nexport type LogTypes = 'click' | 'move' | 'both' | 'none';\n\nexport type InteractionManagerMode = 'file' | 'diff';\n\nexport interface OnLineClickProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnLineEnterLeaveProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineClickProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineEnterLeaveProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface SelectionWriteOptions {\n notify?: boolean;\n}\n\nexport type GetLineIndexUtility = (\n lineNumber: number,\n side?: SelectionSide\n) => [number, number] | undefined;\n\ntype EventClickProps<TMode extends InteractionManagerMode> =\n TMode extends 'file' ? OnLineClickProps : OnDiffLineClickProps;\n\ntype PointerEventEnterLeaveProps<TMode extends InteractionManagerMode> =\n TMode extends 'file' ? OnLineEnterLeaveProps : OnDiffLineEnterLeaveProps;\n\ntype EventBaseProps<TMode extends InteractionManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\nexport type OnTokenEventProps<TMode extends InteractionManagerMode> =\n TMode extends 'file' ? TokenEventBase : DiffTokenEventBaseProps;\n\ninterface ExpandoEventProps {\n type: 'line-info';\n hunkIndex: number;\n direction: ExpansionDirections;\n all: boolean;\n}\n\nexport type GetHoveredLineResult<TMode extends InteractionManagerMode> =\n TMode extends 'file'\n ? { lineNumber: number }\n : { lineNumber: number; side: AnnotationSide };\n\ninterface SelectionInfo {\n lineNumber: number;\n eventSide: SelectionSide | undefined;\n lineIndex: number;\n}\n\ntype SelectionHitSource = 'event-path' | 'coordinates-first';\n\ninterface SelectionHitOptions {\n source: SelectionHitSource;\n excludeUtility?: boolean;\n}\n\ninterface SelectionInfoOptions extends SelectionHitOptions {\n requireNumberColumn: boolean;\n}\n\ninterface SelectionEnds {\n top: SelectionPoint;\n bottom: SelectionPoint;\n}\n\ninterface ResolvedLineTarget<TMode extends InteractionManagerMode> {\n kind: 'line';\n lineType: LineTypes;\n lineElement: HTMLElement;\n lineNumber: number;\n numberColumn: boolean;\n numberElement: HTMLElement;\n side: TMode extends 'diff' ? AnnotationSide : undefined;\n splitLineIndex: number | undefined;\n}\n\ninterface ResolvedTokenTarget<TMode extends InteractionManagerMode> {\n kind: 'token';\n lineType: LineTypes;\n lineElement: HTMLElement;\n lineNumber: number;\n numberColumn: boolean;\n numberElement: HTMLElement;\n side: TMode extends 'diff' ? AnnotationSide : undefined;\n splitLineIndex: number | undefined;\n tokenElement: HTMLElement;\n tokenText: string;\n lineCharStart: number;\n lineCharEnd: number;\n}\n\nexport interface MergeConflictActionTarget {\n kind: 'merge-conflict-action';\n resolution: MergeConflictResolution;\n conflictIndex: number;\n}\n\ntype ResolvedPointerTarget<TMode extends InteractionManagerMode> =\n | ResolvedLineTarget<TMode>\n | ResolvedTokenTarget<TMode>\n | ExpandoEventProps\n | MergeConflictActionTarget;\n\ntype LinePointerTarget<TMode extends InteractionManagerMode> =\n ResolvedLineTarget<TMode>;\n\ntype TokenPointerTarget<TMode extends InteractionManagerMode> =\n ResolvedTokenTarget<TMode>;\n\ntype HoverableLinePointerTarget<TMode extends InteractionManagerMode> =\n | LinePointerTarget<TMode>\n | TokenPointerTarget<TMode>;\n\ninterface SessionIdle {\n mode: 'idle';\n}\n\ninterface SessionSelecting {\n mode: 'selecting';\n pointerId: number;\n}\n\ninterface SessionPendingSingleLineUnselect {\n mode: 'pendingSingleLineUnselect';\n pointerId: number;\n anchor: SelectionPoint;\n pending: SelectionPoint;\n}\n\ninterface SessionGutterSelecting {\n mode: 'gutterSelecting';\n pointerId: number;\n anchor: SelectionPoint;\n current: SelectionPoint;\n}\n\ntype PointerSession =\n | SessionIdle\n | SessionSelecting\n | SessionPendingSingleLineUnselect\n | SessionGutterSelecting;\n\nexport interface InteractionManagerBaseOptions<\n TMode extends InteractionManagerMode,\n> {\n lineHoverHighlight?: 'disabled' | 'both' | 'number' | 'line';\n enableTokenInteractionsOnWhitespace?: boolean;\n enableGutterUtility?: boolean;\n onGutterUtilityClick?(range: SelectedLineRange): unknown;\n onLineClick?(props: EventClickProps<TMode>): unknown;\n onLineNumberClick?(props: EventClickProps<TMode>): unknown;\n onLineEnter?(props: PointerEventEnterLeaveProps<TMode>): unknown;\n onLineLeave?(props: PointerEventEnterLeaveProps<TMode>): unknown;\n onTokenClick?(props: OnTokenEventProps<TMode>, event: MouseEvent): unknown;\n onTokenEnter?(props: OnTokenEventProps<TMode>, event: PointerEvent): unknown;\n onTokenLeave?(props: OnTokenEventProps<TMode>, event: PointerEvent): unknown;\n __debugPointerEvents?: LogTypes;\n enableLineSelection?: boolean;\n controlledSelection?: boolean;\n onLineSelected?: (range: SelectedLineRange | null) => void;\n onLineSelectionStart?: (range: SelectedLineRange | null) => void;\n onLineSelectionChange?: (range: SelectedLineRange | null) => void;\n onLineSelectionEnd?: (range: SelectedLineRange | null) => void;\n getLineIndex?: GetLineIndexUtility;\n}\n\nexport interface InteractionManagerOptions<\n TMode extends InteractionManagerMode,\n> extends InteractionManagerBaseOptions<TMode> {\n usesCustomGutterUtility?: boolean;\n onHunkExpand?(\n hunkIndex: number,\n direction: ExpansionDirections,\n expansionLineCountOverride?: number\n ): unknown;\n onMergeConflictActionClick?(target: MergeConflictActionTarget): void;\n}\n\ninterface HandlePointerEventProps {\n eventType: 'click' | 'move';\n event: PointerEvent | MouseEvent;\n}\n\nexport class InteractionManager<TMode extends InteractionManagerMode> {\n private hoveredLine: EventBaseProps<TMode> | undefined;\n private hoveredToken: OnTokenEventProps<TMode> | undefined;\n private pre: HTMLPreElement | undefined;\n\n private gutterUtilityLine: EventBaseProps<TMode> | undefined;\n private gutterUtilityContainer: HTMLDivElement | undefined;\n private gutterUtilityButton: HTMLButtonElement | undefined;\n private gutterUtilitySlot: HTMLSlotElement | undefined;\n\n private interactiveLinesAttr = false;\n private interactiveLineNumbersAttr = false;\n\n private hasPointerListeners = false;\n private hasDocumentPointerListeners = false;\n\n private selectedRange: SelectedLineRange | null = null;\n private proposedSelectedRange: SelectedLineRange | null | undefined;\n private renderedSelectionRange: SelectedLineRange | null | undefined;\n private selectionAnchor: SelectionPoint | undefined;\n private queuedSelectionRender: number | undefined;\n private pointerSession: PointerSession = { mode: 'idle' };\n\n constructor(\n private mode: TMode,\n private options: InteractionManagerOptions<TMode>\n ) {}\n\n setOptions(options: InteractionManagerOptions<TMode>): void {\n this.options = options;\n }\n\n cleanUp(): void {\n this.pre?.removeEventListener('click', this.handlePointerClick);\n this.pre?.removeEventListener('pointerdown', this.handlePointerDown);\n this.pre?.removeEventListener('pointermove', this.handlePointerMove);\n this.pre?.removeEventListener('pointerleave', this.handlePointerLeave);\n this.pre?.removeAttribute('data-interactive-lines');\n this.pre?.removeAttribute('data-interactive-line-numbers');\n this.pre = undefined;\n this.gutterUtilityContainer?.remove();\n this.gutterUtilityLine = undefined;\n this.gutterUtilityContainer = undefined;\n this.gutterUtilityButton = undefined;\n this.gutterUtilitySlot = undefined;\n this.clearHoveredLine();\n this.clearHoveredToken();\n this.detachDocumentPointerListeners();\n this.clearPointerSession();\n if (this.queuedSelectionRender != null) {\n cancelAnimationFrame(this.queuedSelectionRender);\n this.queuedSelectionRender = undefined;\n }\n this.interactiveLinesAttr = false;\n this.interactiveLineNumbersAttr = false;\n this.hasPointerListeners = false;\n }\n\n setup(pre: HTMLPreElement): void {\n this.setSelectionDirty();\n const { usesCustomGutterUtility = false, enableGutterUtility = false } =\n this.options;\n\n const newContainer = this.pre !== pre;\n if (newContainer) {\n this.cleanUp();\n this.pre = pre;\n }\n\n if (enableGutterUtility) {\n this.ensureGutterUtilityNode(usesCustomGutterUtility);\n } else if (this.gutterUtilityContainer != null) {\n this.gutterUtilityContainer.remove();\n this.gutterUtilityLine = undefined;\n this.gutterUtilityContainer = undefined;\n this.gutterUtilityButton = undefined;\n this.gutterUtilitySlot = undefined;\n if (this.pointerSession.mode === 'gutterSelecting') {\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n }\n }\n\n this.syncPointerListeners(pre);\n this.updateInteractiveLineAttributes();\n this.renderSelection();\n this.placeUtility();\n }\n\n setSelectionDirty(): void {\n this.renderedSelectionRange = undefined;\n }\n\n isSelectionDirty(): boolean {\n return this.renderedSelectionRange === null;\n }\n\n setSelection(\n range: SelectedLineRange | null,\n options?: SelectionWriteOptions\n ): void {\n const isRangeChange = !(\n range === this.selectedRange ||\n areSelectionsEqual(range ?? undefined, this.selectedRange ?? undefined)\n );\n if (!this.isSelectionDirty() && !isRangeChange) {\n return;\n }\n this.proposedSelectedRange = undefined;\n this.selectedRange = range;\n this.renderSelection();\n this.placeUtility();\n if (isRangeChange && options?.notify !== false) {\n this.notifySelectionCommitted();\n }\n }\n\n getSelection(): SelectedLineRange | null {\n return this.selectedRange;\n }\n\n getHoveredLine = (): GetHoveredLineResult<TMode> | undefined => {\n const gutterUtilityLine = this.gutterUtilityLine ?? this.hoveredLine;\n if (gutterUtilityLine != null) {\n if (this.mode === 'diff' && gutterUtilityLine.type === 'diff-line') {\n return {\n lineNumber: gutterUtilityLine.lineNumber,\n side: gutterUtilityLine.annotationSide,\n } as GetHoveredLineResult<TMode>;\n }\n if (this.mode === 'file' && gutterUtilityLine.type === 'line') {\n return {\n lineNumber: gutterUtilityLine.lineNumber,\n } as GetHoveredLineResult<TMode>;\n }\n }\n return undefined;\n };\n\n handlePointerClick = (event: MouseEvent): void => {\n const {\n onHunkExpand,\n onLineClick,\n onLineNumberClick,\n onTokenClick,\n onMergeConflictActionClick,\n } = this.options;\n if (\n onHunkExpand == null &&\n onLineClick == null &&\n onLineNumberClick == null &&\n onMergeConflictActionClick == null &&\n onTokenClick == null\n ) {\n return;\n }\n if (\n this.options.onGutterUtilityClick != null &&\n isGutterUtilityPath(event.composedPath())\n ) {\n return;\n }\n debugLogIfEnabled(\n this.options.__debugPointerEvents,\n 'click',\n 'FileDiff.DEBUG.handlePointerClick:',\n event\n );\n this.handlePointerEvent({ eventType: 'click', event });\n };\n\n handlePointerMove = (event: PointerEvent): void => {\n // Touch and pen moves are active drag/scroll gestures, not hover. Keeping\n // hover mouse-only prevents content scrolls from leaving stale utilities.\n if (event.pointerType !== 'mouse') {\n return;\n }\n\n const {\n lineHoverHighlight = 'disabled',\n onLineEnter,\n onLineLeave,\n onTokenEnter,\n onTokenLeave,\n enableGutterUtility = false,\n } = this.options;\n if (\n lineHoverHighlight === 'disabled' &&\n !enableGutterUtility &&\n onLineEnter == null &&\n onLineLeave == null &&\n onTokenEnter == null &&\n onTokenLeave == null\n ) {\n return;\n }\n debugLogIfEnabled(\n this.options.__debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.handlePointerMove:',\n event\n );\n // should we perhaps throttle this a bit because move can be fast as fuk\n // boiiii\n this.handlePointerEvent({ eventType: 'move', event });\n };\n\n handlePointerLeave = (event: PointerEvent): void => {\n const { __debugPointerEvents } = this.options;\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.handlePointerLeave: no event'\n );\n if (this.hoveredLine == null && this.hoveredToken == null) {\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.handlePointerLeave: returned early, no hovered line or token'\n );\n return;\n }\n if (this.hoveredToken != null) {\n this.options.onTokenLeave?.(this.hoveredToken, event);\n this.clearHoveredToken();\n }\n\n if (this.hoveredLine != null) {\n this.options.onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as PointerEventEnterLeaveProps<TMode>);\n this.clearHoveredLine();\n }\n this.placeUtility();\n };\n\n private handlePointerEvent({ eventType, event }: HandlePointerEventProps) {\n const { __debugPointerEvents } = this.options;\n const composedPath = event.composedPath();\n debugLogIfEnabled(\n __debugPointerEvents,\n eventType,\n 'FileDiff.DEBUG.handlePointerEvent:',\n { eventType, composedPath }\n );\n const target = this.resolvePointerTarget(composedPath);\n debugLogIfEnabled(\n __debugPointerEvents,\n eventType,\n 'FileDiff.DEBUG.handlePointerEvent: resolvePointerTarget result:',\n target\n );\n\n const {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n onHunkExpand,\n onMergeConflictActionClick,\n } = this.options;\n\n switch (eventType) {\n case 'move': {\n const sameLine =\n isHoverableLinePointerTarget(target) &&\n this.hoveredLine?.lineElement === target.lineElement;\n const sameToken =\n isTokenPointerTarget(target) &&\n this.hoveredToken?.tokenElement === target.tokenElement;\n\n // Handle token transitions\n if (!sameToken) {\n if (this.hoveredToken != null) {\n onTokenLeave?.(this.hoveredToken, event as PointerEvent);\n this.clearHoveredToken();\n }\n if (isTokenPointerTarget(target)) {\n this.setHoveredToken(this.toTokenEventBaseProps(target));\n onTokenEnter?.(\n this.hoveredToken as OnTokenEventProps<TMode>,\n event as PointerEvent\n );\n }\n }\n\n // Handle line transitions\n if (!sameLine) {\n if (this.hoveredLine != null) {\n onLineLeave?.({\n ...this.hoveredLine,\n event: event as PointerEvent,\n } as PointerEventEnterLeaveProps<TMode>);\n this.clearHoveredLine();\n }\n if (isHoverableLinePointerTarget(target)) {\n this.setHoveredLine(this.toEventBaseProps(target));\n this.placeUtility();\n onLineEnter?.({\n ...this.hoveredLine,\n event: event as PointerEvent,\n } as PointerEventEnterLeaveProps<TMode>);\n } else {\n this.placeUtility();\n }\n }\n break;\n }\n case 'click': {\n if (target == null) {\n break;\n }\n if (\n isMergeConflictActionPointerTarget(target) &&\n onMergeConflictActionClick != null\n ) {\n onMergeConflictActionClick(target);\n break;\n }\n if (isExpandoPointerTarget(target) && onHunkExpand != null) {\n onHunkExpand(\n target.hunkIndex,\n target.all || event.shiftKey ? 'both' : target.direction,\n target.all || event.shiftKey ? Number.POSITIVE_INFINITY : undefined\n );\n break;\n }\n\n if (!isHoverableLinePointerTarget(target)) {\n break;\n }\n\n if (isTokenPointerTarget(target) && onTokenClick != null) {\n onTokenClick(this.toTokenEventBaseProps(target), event as MouseEvent);\n }\n\n const eventBase = this.toEventBaseProps(target);\n if (onLineNumberClick != null && target.numberColumn) {\n onLineNumberClick({\n ...eventBase,\n event: event as PointerEvent,\n } as EventClickProps<TMode>);\n } else if (onLineClick != null) {\n onLineClick({\n ...eventBase,\n event: event as PointerEvent,\n } as EventClickProps<TMode>);\n }\n break;\n }\n }\n }\n\n private syncPointerListeners(pre: HTMLPreElement): void {\n const {\n __debugPointerEvents,\n lineHoverHighlight = 'disabled',\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n onHunkExpand,\n onMergeConflictActionClick,\n enableGutterUtility = false,\n enableLineSelection = false,\n onGutterUtilityClick,\n } = this.options;\n const enableGutterSelection = onGutterUtilityClick != null;\n const shouldAttachPointerListeners =\n lineHoverHighlight !== 'disabled' ||\n onLineClick != null ||\n onLineNumberClick != null ||\n onLineEnter != null ||\n onLineLeave != null ||\n onTokenClick != null ||\n onTokenEnter != null ||\n onTokenLeave != null ||\n onHunkExpand != null ||\n onMergeConflictActionClick != null ||\n enableGutterUtility ||\n enableLineSelection ||\n enableGutterSelection;\n\n if (shouldAttachPointerListeners && !this.hasPointerListeners) {\n pre.addEventListener('click', this.handlePointerClick);\n pre.addEventListener('pointerdown', this.handlePointerDown);\n pre.addEventListener('pointermove', this.handlePointerMove);\n pre.addEventListener('pointerleave', this.handlePointerLeave);\n this.hasPointerListeners = true;\n\n debugLogIfEnabled(\n __debugPointerEvents,\n 'click',\n 'FileDiff.DEBUG.attachEventListeners: Attaching click events for:',\n (() => {\n const reasons: string[] = [];\n if (\n __debugPointerEvents === 'both' ||\n __debugPointerEvents === 'click'\n ) {\n if (onLineClick != null) {\n reasons.push('onLineClick');\n }\n if (onLineNumberClick != null) {\n reasons.push('onLineNumberClick');\n }\n if (onHunkExpand != null) {\n reasons.push('expandable hunk separators');\n }\n if (onMergeConflictActionClick != null) {\n reasons.push('merge conflict actions');\n }\n }\n return reasons;\n })()\n );\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer move event'\n );\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event'\n );\n } else if (!shouldAttachPointerListeners && this.hasPointerListeners) {\n pre.removeEventListener('click', this.handlePointerClick);\n pre.removeEventListener('pointerdown', this.handlePointerDown);\n pre.removeEventListener('pointermove', this.handlePointerMove);\n pre.removeEventListener('pointerleave', this.handlePointerLeave);\n this.hasPointerListeners = false;\n }\n\n const hasActiveLineSelectionSession =\n this.pointerSession.mode === 'selecting' ||\n this.pointerSession.mode === 'pendingSingleLineUnselect';\n const hasActiveGutterSelectionSession =\n this.pointerSession.mode === 'gutterSelecting';\n if (\n (!enableLineSelection && hasActiveLineSelectionSession) ||\n (!enableGutterSelection && hasActiveGutterSelectionSession)\n ) {\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n this.selectionAnchor = undefined;\n this.clearPendingSingleLineState();\n }\n }\n\n private updateInteractiveLineAttributes(): void {\n if (this.pre == null) {\n return;\n }\n\n const {\n onLineClick,\n onLineNumberClick,\n enableLineSelection = false,\n } = this.options;\n\n const shouldHaveInteractiveLines = onLineClick != null;\n const shouldHaveInteractiveLineNumbers =\n onLineNumberClick != null || enableLineSelection;\n\n if (shouldHaveInteractiveLines && !this.interactiveLinesAttr) {\n this.pre.setAttribute('data-interactive-lines', '');\n this.interactiveLinesAttr = true;\n } else if (!shouldHaveInteractiveLines && this.interactiveLinesAttr) {\n this.pre.removeAttribute('data-interactive-lines');\n this.interactiveLinesAttr = false;\n }\n\n if (shouldHaveInteractiveLineNumbers && !this.interactiveLineNumbersAttr) {\n this.pre.setAttribute('data-interactive-line-numbers', '');\n this.interactiveLineNumbersAttr = true;\n } else if (\n !shouldHaveInteractiveLineNumbers &&\n this.interactiveLineNumbersAttr\n ) {\n this.pre.removeAttribute('data-interactive-line-numbers');\n this.interactiveLineNumbersAttr = false;\n }\n }\n\n private handlePointerDown = (event: PointerEvent): void => {\n if (\n (event.pointerType === 'mouse' && event.button !== 0) ||\n this.pre == null ||\n this.pointerSession.mode !== 'idle'\n ) {\n return;\n }\n\n const path = event.composedPath();\n if (\n isGutterUtilityPath(path) &&\n this.options.onGutterUtilityClick != null\n ) {\n this.startGutterSelectionFromPointerDown(event);\n } else {\n if (event.pointerType !== 'mouse') {\n this.revealUtilityFromGutterPath(path);\n }\n this.startLineSelectionFromPointerDown(event);\n }\n };\n\n private startLineSelectionFromPointerDown(event: PointerEvent): void {\n const { enableLineSelection = false } = this.options;\n if (!enableLineSelection) {\n return;\n }\n\n const pointerInfo = this.resolveSelectionInfo(event, {\n source: 'event-path',\n requireNumberColumn: true,\n });\n if (pointerInfo == null) {\n return;\n }\n\n const { pre } = this;\n if (pre == null) {\n return;\n }\n\n event.preventDefault();\n const { lineNumber, eventSide, lineIndex } = pointerInfo;\n\n if (event.shiftKey && this.selectedRange != null) {\n const rowRange = this.getIndexesFromSelection(\n this.selectedRange,\n pre.getAttribute('data-diff-type') === 'split'\n );\n if (rowRange == null) {\n return;\n }\n const useStart =\n rowRange.start <= rowRange.end\n ? lineIndex >= rowRange.start\n : lineIndex <= rowRange.end;\n this.selectionAnchor = {\n lineNumber: useStart\n ? this.selectedRange.start\n : this.selectedRange.end,\n side: useStart\n ? this.selectedRange.side\n : (this.selectedRange.endSide ?? this.selectedRange.side),\n };\n this.updateSelection(lineNumber, eventSide, false);\n this.notifySelectionStart(this.getCurrentSelectionRange());\n this.pointerSession = { mode: 'selecting', pointerId: event.pointerId };\n this.attachDocumentPointerListeners();\n return;\n }\n\n if (\n this.selectedRange?.start === lineNumber &&\n this.selectedRange?.end === lineNumber\n ) {\n const point = { lineNumber, side: eventSide };\n this.selectionAnchor = point;\n this.pointerSession = {\n mode: 'pendingSingleLineUnselect',\n pointerId: event.pointerId,\n anchor: point,\n pending: point,\n };\n this.attachDocumentPointerListeners();\n return;\n }\n\n if (this.options.controlledSelection === true) {\n this.proposedSelectedRange = null;\n } else {\n this.selectedRange = null;\n }\n this.placeUtility();\n this.selectionAnchor = { lineNumber, side: eventSide };\n this.updateSelection(lineNumber, eventSide, false);\n this.notifySelectionStart(this.getCurrentSelectionRange());\n this.pointerSession = { mode: 'selecting', pointerId: event.pointerId };\n this.attachDocumentPointerListeners();\n }\n\n private startGutterSelectionFromPointerDown(event: PointerEvent): void {\n const { enableLineSelection = false, onGutterUtilityClick } = this.options;\n if (onGutterUtilityClick == null) {\n return;\n }\n // If a selection already exists, the utility represents that whole range.\n // Dragging should start from the visual top and extend from the visual\n // bottom, regardless of the direction the range was originally created.\n const selectedEndpoints = this.currentSelectionEnds();\n const point =\n selectedEndpoints?.bottom ??\n this.resolveSelectionPoint(event, {\n source: 'event-path',\n excludeUtility: false,\n });\n const anchor = selectedEndpoints?.top ?? point;\n if (point == null || anchor == null) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n this.pointerSession = {\n mode: 'gutterSelecting',\n pointerId: event.pointerId,\n anchor,\n current: point,\n };\n if (enableLineSelection) {\n this.selectionAnchor = {\n lineNumber: anchor.lineNumber,\n side: anchor.side,\n };\n this.updateSelection(point.lineNumber, point.side, false);\n this.notifySelectionStart(this.getCurrentSelectionRange());\n }\n this.attachDocumentPointerListeners();\n }\n\n private handleDocumentPointerMove = (event: PointerEvent): void => {\n const { enableLineSelection = false } = this.options;\n switch (this.pointerSession.mode) {\n case 'idle':\n return;\n case 'gutterSelecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const point = this.resolveSelectionPoint(event, {\n source: 'coordinates-first',\n });\n if (point == null) {\n return;\n }\n this.pointerSession.current = point;\n if (enableLineSelection === true) {\n this.updateSelection(point.lineNumber, point.side);\n }\n return;\n }\n case 'selecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const pointerInfo = this.resolveSelectionInfo(event, {\n source: 'coordinates-first',\n requireNumberColumn: false,\n });\n if (pointerInfo == null || this.selectionAnchor == null) {\n return;\n }\n this.updateSelection(pointerInfo.lineNumber, pointerInfo.eventSide);\n return;\n }\n case 'pendingSingleLineUnselect': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const pointerInfo = this.resolveSelectionInfo(event, {\n source: 'coordinates-first',\n requireNumberColumn: false,\n });\n if (pointerInfo == null || this.selectionAnchor == null) {\n return;\n }\n const point = {\n lineNumber: pointerInfo.lineNumber,\n side: pointerInfo.eventSide,\n };\n if (areSelectionPointsEqual(this.pointerSession.pending, point)) {\n return;\n }\n this.updateSelection(\n pointerInfo.lineNumber,\n pointerInfo.eventSide,\n false\n );\n this.notifySelectionStart(this.getCurrentSelectionRange());\n this.notifySelectionChangeDelta();\n this.pointerSession = {\n mode: 'selecting',\n pointerId: event.pointerId,\n };\n return;\n }\n }\n };\n\n private handleDocumentPointerUp = (event: PointerEvent): void => {\n const { enableLineSelection = false, onGutterUtilityClick } = this.options;\n switch (this.pointerSession.mode) {\n case 'idle':\n return;\n case 'gutterSelecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const point = this.resolveSelectionPoint(event, {\n source: 'coordinates-first',\n });\n if (point != null) {\n this.pointerSession.current = point;\n if (enableLineSelection) {\n this.updateSelection(point.lineNumber, point.side);\n }\n }\n onGutterUtilityClick?.(\n this.buildSelectedLineRange(\n this.pointerSession.anchor,\n this.pointerSession.current\n )\n );\n this.selectionAnchor = undefined;\n if (enableLineSelection) {\n this.notifySelectionEnd(this.getCurrentSelectionRange());\n this.notifySelectionCommitted();\n this.clearProposedSelection();\n }\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n return;\n }\n case 'pendingSingleLineUnselect': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n this.updateSelection(null, undefined, false);\n this.selectionAnchor = undefined;\n this.clearPendingSingleLineState();\n this.detachDocumentPointerListeners();\n this.notifySelectionEnd(this.getCurrentSelectionRange());\n this.notifySelectionCommitted();\n this.clearProposedSelection();\n return;\n }\n case 'selecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n this.selectionAnchor = undefined;\n this.detachDocumentPointerListeners();\n this.clearPointerSession();\n this.notifySelectionEnd(this.getCurrentSelectionRange());\n this.notifySelectionCommitted();\n this.clearProposedSelection();\n }\n }\n };\n\n private handleDocumentPointerCancel = (event: PointerEvent): void => {\n switch (this.pointerSession.mode) {\n case 'idle':\n return;\n case 'gutterSelecting':\n case 'selecting':\n case 'pendingSingleLineUnselect': {\n if ('pointerId' in this.pointerSession) {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n }\n this.selectionAnchor = undefined;\n this.clearProposedSelection();\n this.clearPendingSingleLineState();\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n }\n }\n };\n\n private clearHoveredLine() {\n if (this.hoveredLine == null) {\n return;\n }\n this.hoveredLine.lineElement.removeAttribute('data-hovered');\n this.hoveredLine.numberElement.removeAttribute('data-hovered');\n this.hoveredLine = undefined;\n }\n\n private setHoveredLine(hoveredLine: EventBaseProps<TMode>) {\n const { lineHoverHighlight = 'disabled' } = this.options;\n if (this.hoveredLine != null) {\n this.clearHoveredLine();\n }\n this.hoveredLine = hoveredLine;\n if (lineHoverHighlight !== 'disabled') {\n if (lineHoverHighlight === 'both' || lineHoverHighlight === 'line') {\n this.hoveredLine.lineElement.setAttribute('data-hovered', '');\n }\n if (lineHoverHighlight === 'both' || lineHoverHighlight === 'number') {\n this.hoveredLine.numberElement.setAttribute('data-hovered', '');\n }\n }\n }\n\n private clearHoveredToken() {\n if (this.hoveredToken == null) {\n return;\n }\n this.hoveredToken = undefined;\n }\n\n private setHoveredToken(hoveredToken: OnTokenEventProps<TMode>) {\n if (this.hoveredToken != null) {\n this.clearHoveredToken();\n }\n this.hoveredToken = hoveredToken;\n }\n\n private ensureGutterUtilityNode(useCustomGutterUtility: boolean): void {\n if (this.gutterUtilityContainer == null) {\n this.gutterUtilityContainer = document.createElement('div');\n this.gutterUtilityContainer.setAttribute('data-gutter-utility-slot', '');\n }\n if (useCustomGutterUtility) {\n if (this.gutterUtilityButton != null) {\n this.gutterUtilityButton.remove();\n this.gutterUtilityButton = undefined;\n }\n if (this.gutterUtilitySlot == null) {\n this.gutterUtilitySlot = document.createElement('slot');\n this.gutterUtilitySlot.name = 'gutter-utility-slot';\n }\n if (this.gutterUtilitySlot.parentNode !== this.gutterUtilityContainer) {\n this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);\n }\n } else {\n this.gutterUtilitySlot?.remove();\n this.gutterUtilitySlot = undefined;\n if (this.gutterUtilityButton == null) {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = toHtml(createGutterUtilityElement());\n const utilityButton = tempDiv.firstElementChild;\n if (!(utilityButton instanceof HTMLButtonElement)) {\n throw new Error(\n 'InteractionManager.ensureGutterUtilityNode: Node element should be a button'\n );\n }\n utilityButton.remove();\n this.gutterUtilityButton = utilityButton;\n }\n if (this.gutterUtilityButton.parentNode !== this.gutterUtilityContainer) {\n this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton);\n }\n }\n }\n\n private revealUtilityFromGutterPath(path: (EventTarget | undefined)[]): void {\n if (this.placeUtilityFromSelection()) {\n return;\n }\n const target = this.resolvePointerTarget(path);\n if (isLinePointerTarget(target) && target.numberColumn) {\n this.showUtilityOnLine(this.toEventBaseProps(target));\n }\n }\n\n // The gutter utility follows the active selection first because a selected\n // range is more stable than transient hover/touch state. Without a\n // selection, desktop hover and mobile tap reveal can still place it on a\n // single row.\n private placeUtility(): void {\n if (this.placeUtilityFromSelection()) {\n return;\n }\n if (this.hoveredLine != null) {\n this.showUtilityOnLine(this.hoveredLine);\n return;\n }\n this.hideUtility();\n }\n\n private placeUtilityFromSelection(): boolean {\n const endpoints = this.currentSelectionEnds();\n if (endpoints == null) {\n return false;\n }\n const target = this.targetForSelectionPoint(endpoints.bottom);\n if (target == null) {\n this.hideUtility();\n } else {\n this.showUtilityOnLine(this.toEventBaseProps(target));\n }\n return true;\n }\n\n private showUtilityOnLine(line: EventBaseProps<TMode>): void {\n if (this.gutterUtilityContainer == null) {\n return;\n }\n this.gutterUtilityLine = line;\n line.numberElement.appendChild(this.gutterUtilityContainer);\n }\n\n private hideUtility(): void {\n this.gutterUtilityContainer?.remove();\n this.gutterUtilityLine = undefined;\n }\n\n // Selection ranges preserve drag direction, so compare rendered row indexes to\n // find the visually top-most and bottom-most endpoints.\n private currentSelectionEnds(): SelectionEnds | undefined {\n const range = this.getCurrentSelectionRange();\n return range == null ? undefined : this.selectionEnds(range);\n }\n\n private selectionEnds(range: SelectedLineRange): SelectionEnds | undefined {\n const start: SelectionPoint = {\n lineNumber: range.start,\n side: range.side,\n };\n const end: SelectionPoint = {\n lineNumber: range.end,\n side: range.endSide ?? range.side,\n };\n const startIndex = this.selectionPointRowIndex(start);\n const endIndex = this.selectionPointRowIndex(end);\n if (startIndex == null || endIndex == null) {\n return undefined;\n }\n return startIndex > endIndex\n ? { top: end, bottom: start }\n : { top: start, bottom: end };\n }\n\n private selectionPointRowIndex(point: SelectionPoint): number | undefined {\n const indexes = this.getLineIndex(point.lineNumber, point.side);\n if (indexes == null) {\n return undefined;\n }\n return this.isSplitDiff() ? indexes[1] : indexes[0];\n }\n\n private targetForSelectionPoint(\n point: SelectionPoint\n ): LinePointerTarget<TMode> | undefined {\n if (this.pre == null) {\n return undefined;\n }\n const indexes = this.getLineIndex(point.lineNumber, point.side);\n if (indexes == null) {\n return undefined;\n }\n const lineIndex =\n this.mode === 'diff' ? `${indexes[0]},${indexes[1]}` : `${indexes[0]}`;\n // Rebuild the real gutter-row target from the selection point so the\n // utility can anchor to the visible row even when the point came from\n // controlled state rather than a pointer event.\n const candidates = this.pre.querySelectorAll(\n `[data-column-number=\"${point.lineNumber}\"][data-line-index=\"${lineIndex}\"]`\n );\n for (const element of candidates) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const target = this.resolvePointerTarget(getElementPath(element));\n if (!isLinePointerTarget(target)) {\n continue;\n }\n if (\n this.mode === 'diff' &&\n point.side != null &&\n target.side !== point.side\n ) {\n continue;\n }\n return target;\n }\n return undefined;\n }\n\n private attachDocumentPointerListeners(): void {\n if (this.hasDocumentPointerListeners) {\n return;\n }\n document.addEventListener('pointermove', this.handleDocumentPointerMove);\n document.addEventListener('pointerup', this.handleDocumentPointerUp);\n document.addEventListener(\n 'pointercancel',\n this.handleDocumentPointerCancel\n );\n this.hasDocumentPointerListeners = true;\n }\n\n private detachDocumentPointerListeners(): void {\n if (!this.hasDocumentPointerListeners) {\n return;\n }\n document.removeEventListener('pointermove', this.handleDocumentPointerMove);\n document.removeEventListener('pointerup', this.handleDocumentPointerUp);\n document.removeEventListener(\n 'pointercancel',\n this.handleDocumentPointerCancel\n );\n this.hasDocumentPointerListeners = false;\n }\n\n private clearPointerSession(): void {\n this.pointerSession = { mode: 'idle' };\n }\n\n private clearPendingSingleLineState(): void {\n if (this.pointerSession.mode === 'pendingSingleLineUnselect') {\n this.pointerSession = { mode: 'idle' };\n }\n }\n\n private selectionInfoFromPath(\n path: (EventTarget | undefined)[],\n requireNumberColumn: boolean\n ): SelectionInfo | undefined {\n const target = this.resolvePointerTarget(path);\n if (!isLinePointerTarget(target)) {\n return undefined;\n }\n if (requireNumberColumn && !target.numberColumn) {\n return undefined;\n }\n if (target.splitLineIndex == null) {\n return undefined;\n }\n\n return {\n lineIndex: target.splitLineIndex,\n lineNumber: target.lineNumber,\n eventSide: this.mode === 'diff' ? target.side : undefined,\n };\n }\n\n private resolveSelectionInfo(\n event: PointerEvent,\n options: SelectionInfoOptions\n ): SelectionInfo | undefined {\n const path = this.resolveSelectionPath(event, options);\n return path != null\n ? this.selectionInfoFromPath(path, options.requireNumberColumn)\n : undefined;\n }\n\n private selectionPointFromPath(\n path: (EventTarget | undefined)[]\n ): SelectionPoint | undefined {\n const target = this.resolvePointerTarget(path);\n if (!isLinePointerTarget(target)) {\n return undefined;\n }\n return {\n lineNumber: target.lineNumber,\n side: this.mode === 'diff' ? target.side : undefined,\n };\n }\n\n private resolveSelectionPoint(\n event: PointerEvent,\n options: SelectionHitOptions\n ): SelectionPoint | undefined {\n const path = this.resolveSelectionPath(event, options);\n return path != null ? this.selectionPointFromPath(path) : undefined;\n }\n\n private resolveSelectionPath(\n event: PointerEvent,\n options: SelectionHitOptions\n ): (EventTarget | undefined)[] | undefined {\n const excludeUtility = options.excludeUtility !== false;\n switch (options.source) {\n case 'event-path':\n return this.pathFromEventPath(event.composedPath(), excludeUtility);\n case 'coordinates-first': {\n // Touch pointers can keep dispatching move/up events to the element\n // where the drag began. Prefer the row currently under the finger,\n // then fall back only when coordinate hit-testing is unavailable.\n const coordinatePath = this.pathFromCoordinates(event, excludeUtility);\n if (coordinatePath !== undefined) {\n return coordinatePath ?? undefined;\n }\n return this.pathFromEventPath(event.composedPath(), excludeUtility);\n }\n }\n }\n\n private pathFromCoordinates(\n event: PointerEvent,\n excludeUtility: boolean\n ): (EventTarget | undefined)[] | null | undefined {\n const coordinateTarget = this.hitTest(event);\n if (coordinateTarget === undefined) {\n return undefined;\n }\n if (coordinateTarget === null) {\n return null;\n }\n // A coordinate hit can be a token span, line-number span, utility overlay,\n // or separator. Normalize valid descendants back to their row; invalid\n // hits intentionally return null so the last selected row stays sticky.\n return this.pathFromElement(coordinateTarget, excludeUtility) ?? null;\n }\n\n private pathFromEventPath(\n path: (EventTarget | undefined)[],\n excludeUtility: boolean\n ): (EventTarget | undefined)[] | undefined {\n if (excludeUtility && isGutterUtilityPath(path)) {\n return undefined;\n }\n for (const element of path) {\n if (element instanceof Element) {\n return this.pathFromElement(element, excludeUtility);\n }\n }\n return undefined;\n }\n\n private pathFromElement(\n element: Element,\n excludeUtility: boolean\n ): (EventTarget | undefined)[] | undefined {\n const path = getElementPath(element);\n if (excludeUtility && isGutterUtilityPath(path)) {\n return undefined;\n }\n // Selection is row-based, not child-element-based. Lateral movement over\n // tokens, annotations, or line-number text should still update to the\n // nearest content or gutter row; anything else is ignored by returning\n // undefined.\n const row = closestSelectableRow(element);\n if (row != null) {\n return getElementPath(row);\n }\n return this.pathFromAnnotationSlot(element);\n }\n\n private pathFromAnnotationSlot(\n element: Element\n ): (EventTarget | undefined)[] | undefined {\n const point = selectionPointFromAnnotationSlotName(\n getAnnotationSlotName(element)\n );\n if (point == null) {\n return undefined;\n }\n const target = this.targetForSelectionPoint(point);\n return target != null ? getElementPath(target.lineElement) : undefined;\n }\n\n private hitTest(event: PointerEvent): Element | null | undefined {\n // Return undefined when coordinate hit-testing cannot run at all, which\n // allows callers to fall back to the event path for tests and older DOMs.\n // Return null when hit-testing ran but found no element, so active drags\n // keep their previous endpoint instead of using a stale captured target.\n if (!Number.isFinite(event.clientX) || !Number.isFinite(event.clientY)) {\n return undefined;\n }\n const root = this.pre?.getRootNode();\n const elementFromPointRoot = hasElementFromPoint(root)\n ? root\n : hasElementFromPoint(document)\n ? document\n : undefined;\n if (elementFromPointRoot == null) {\n return undefined;\n }\n const element = elementFromPointRoot.elementFromPoint(\n event.clientX,\n event.clientY\n );\n return element;\n }\n\n private getLineIndex(\n lineNumber: number,\n side?: SelectionSide\n ): [number, number] | undefined {\n const { getLineIndex } = this.options;\n return getLineIndex != null\n ? getLineIndex(lineNumber, side)\n : [lineNumber - 1, lineNumber - 1];\n }\n\n private getCurrentSelectionRange(): SelectedLineRange | null {\n return this.proposedSelectedRange !== undefined\n ? this.proposedSelectedRange\n : this.selectedRange;\n }\n\n private clearProposedSelection(): void {\n this.proposedSelectedRange = undefined;\n }\n\n private updateSelection(\n currentLine: number | null,\n side?: SelectionSide,\n emitChange = true\n ): void {\n const previousRange = this.getCurrentSelectionRange();\n let nextRange: SelectedLineRange | null;\n if (currentLine == null) {\n nextRange = null;\n } else {\n const anchorSide = this.selectionAnchor?.side ?? side;\n const anchorLine = this.selectionAnchor?.lineNumber ?? currentLine;\n nextRange = this.buildSelectionRange(\n anchorLine,\n currentLine,\n anchorSide,\n side\n );\n }\n if (\n areSelectionsEqual(previousRange ?? undefined, nextRange ?? undefined)\n ) {\n return;\n }\n if (this.options.controlledSelection === true) {\n this.proposedSelectedRange = nextRange;\n } else {\n this.selectedRange = nextRange;\n this.queuedSelectionRender ??= requestAnimationFrame(\n this.renderSelection\n );\n }\n this.placeUtility();\n if (emitChange) {\n this.notifySelectionChangeDelta();\n }\n }\n\n private getIndexesFromSelection(\n selectedRange: SelectedLineRange,\n split: boolean\n ): { start: number; end: number } | undefined {\n if (this.pre == null) {\n return undefined;\n }\n const startIndexes = this.getLineIndex(\n selectedRange.start,\n selectedRange.side\n );\n const finalIndexes = this.getLineIndex(\n selectedRange.end,\n selectedRange.endSide ?? selectedRange.side\n );\n\n return startIndexes != null && finalIndexes != null\n ? {\n start: split ? startIndexes[1] : startIndexes[0],\n end: split ? finalIndexes[1] : finalIndexes[0],\n }\n : undefined;\n }\n\n private renderSelection = (): void => {\n if (this.queuedSelectionRender != null) {\n cancelAnimationFrame(this.queuedSelectionRender);\n this.queuedSelectionRender = undefined;\n }\n if (\n this.pre == null ||\n this.renderedSelectionRange === this.selectedRange\n ) {\n return;\n }\n\n const allSelected = this.pre.querySelectorAll('[data-selected-line]');\n for (const element of allSelected) {\n element.removeAttribute('data-selected-line');\n }\n\n this.renderedSelectionRange = this.selectedRange;\n if (this.selectedRange == null) {\n return;\n }\n\n const { children: codeElements } = this.pre;\n if (codeElements.length === 0) {\n return;\n }\n if (codeElements.length > 2) {\n console.error(codeElements);\n throw new Error(\n 'InteractionManager.renderSelection: Somehow there are more than 2 code elements...'\n );\n }\n const split = this.pre.getAttribute('data-diff-type') === 'split';\n const rowRange = this.getIndexesFromSelection(this.selectedRange, split);\n if (rowRange == null) {\n console.error({ rowRange, selectedRange: this.selectedRange });\n throw new Error('InteractionManager.renderSelection: No valid rowRange');\n }\n const isSingle = rowRange.start === rowRange.end;\n const first = Math.min(rowRange.start, rowRange.end);\n const last = Math.max(rowRange.start, rowRange.end);\n for (const code of codeElements) {\n const [gutter, content] = code.children;\n const len = content.children.length;\n if (len !== gutter.children.length) {\n throw new Error(\n 'InteractionManager.renderSelection: gutter and content children dont match, something is wrong'\n );\n }\n for (let i = 0; i < len; i++) {\n const contentElement = content.children[i];\n const gutterElement = gutter.children[i];\n if (\n !(contentElement instanceof HTMLElement) ||\n !(gutterElement instanceof HTMLElement)\n ) {\n continue;\n }\n\n const lineIndex = this.parseLineIndex(contentElement, split);\n if ((lineIndex ?? 0) > last) {\n break;\n }\n if (lineIndex == null || lineIndex < first) {\n continue;\n }\n let attributeValue = isSingle\n ? 'single'\n : lineIndex === first\n ? 'first'\n : lineIndex === last\n ? 'last'\n : '';\n contentElement.setAttribute('data-selected-line', attributeValue);\n gutterElement.setAttribute('data-selected-line', attributeValue);\n if (\n gutterElement.nextSibling instanceof HTMLElement &&\n contentElement.nextSibling instanceof HTMLElement &&\n (contentElement.nextSibling.hasAttribute('data-line-annotation') ||\n contentElement.nextSibling.hasAttribute(\n 'data-merge-conflict-actions'\n ))\n ) {\n if (isSingle) {\n attributeValue = 'last';\n contentElement.setAttribute('data-selected-line', 'first');\n } else if (lineIndex === first) {\n attributeValue = '';\n } else if (lineIndex === last) {\n contentElement.setAttribute('data-selected-line', '');\n }\n contentElement.nextSibling.setAttribute(\n 'data-selected-line',\n attributeValue\n );\n gutterElement.nextSibling.setAttribute(\n 'data-selected-line',\n attributeValue\n );\n }\n }\n }\n };\n\n private notifySelectionCommitted(): void {\n this.options.onLineSelected?.(this.getCurrentSelectionRange() ?? null);\n }\n\n private notifySelectionChangeDelta(): void {\n this.options.onLineSelectionChange?.(\n this.getCurrentSelectionRange() ?? null\n );\n }\n\n private notifySelectionStart(range: SelectedLineRange | null): void {\n this.options.onLineSelectionStart?.(range);\n }\n\n private notifySelectionEnd(range: SelectedLineRange | null): void {\n this.options.onLineSelectionEnd?.(range);\n }\n\n private toEventBaseProps(\n target: HoverableLinePointerTarget<TMode>\n ): EventBaseProps<TMode> {\n if (this.mode === 'file') {\n return {\n type: 'line',\n lineElement: target.lineElement,\n lineNumber: target.lineNumber,\n numberColumn: target.numberColumn,\n numberElement: target.numberElement,\n } as EventBaseProps<TMode>;\n }\n\n return {\n type: 'diff-line',\n annotationSide: target.side as AnnotationSide,\n lineType: target.lineType,\n lineElement: target.lineElement,\n numberElement: target.numberElement,\n lineNumber: target.lineNumber,\n numberColumn: target.numberColumn,\n } as EventBaseProps<TMode>;\n }\n\n private toTokenEventBaseProps({\n lineCharEnd,\n lineCharStart,\n lineNumber,\n side,\n tokenElement,\n tokenText,\n }: TokenPointerTarget<TMode>): OnTokenEventProps<TMode> {\n if (this.mode === 'file') {\n return {\n type: 'token',\n lineCharEnd,\n lineCharStart,\n lineNumber,\n tokenElement,\n tokenText,\n } as OnTokenEventProps<TMode>;\n }\n\n return {\n type: 'token',\n lineCharEnd,\n lineCharStart,\n lineNumber,\n side,\n tokenElement,\n tokenText,\n } as OnTokenEventProps<TMode>;\n }\n\n private buildSelectedLineRange(\n anchor: SelectionPoint,\n current: SelectionPoint\n ): SelectedLineRange {\n return this.buildSelectionRange(\n anchor.lineNumber,\n current.lineNumber,\n anchor.side,\n current.side\n );\n }\n\n private buildSelectionRange(\n start: number,\n end: number,\n side?: SelectionSide,\n endSide?: SelectionSide\n ): SelectedLineRange {\n return {\n start,\n end,\n ...(side != null ? { side } : {}),\n ...(side !== endSide && endSide != null ? { endSide } : {}),\n };\n }\n\n private resolvePointerTarget(\n path: (EventTarget | undefined)[]\n ): ResolvedPointerTarget<TMode> | undefined {\n let numberColumn = false;\n let lineType: LineTypes | undefined;\n let codeElement: HTMLElement | undefined;\n let lineElement: HTMLElement | undefined;\n let lineIndexValue: string | undefined;\n let numberElement: HTMLElement | undefined;\n let tokenElement: HTMLElement | undefined;\n let tokenInfo: TokenCache | undefined;\n let expandInfo: ExpandCache | undefined;\n let lineNumber: number | undefined;\n let mergeConflictActionTarget: MergeConflictActionTarget | undefined;\n\n for (const element of path) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n\n if (\n mergeConflictActionTarget == null &&\n element.hasAttribute('data-merge-conflict-action')\n ) {\n const resolutionValue =\n element.getAttribute('data-merge-conflict-action') ?? undefined;\n const conflictIndexValue =\n element.getAttribute('data-merge-conflict-conflict-index') ??\n undefined;\n const conflictIndex =\n conflictIndexValue != null\n ? Number.parseInt(conflictIndexValue, 10)\n : Number.NaN;\n if (\n isMergeConflictResolution(resolutionValue) &&\n Number.isFinite(conflictIndex)\n ) {\n mergeConflictActionTarget = {\n kind: 'merge-conflict-action',\n resolution: resolutionValue,\n conflictIndex,\n };\n }\n }\n\n if (tokenElement == null && element.hasAttribute('data-char')) {\n tokenElement = element;\n const startAttr = element.getAttribute('data-char');\n\n if (startAttr != null) {\n const lineCharStart = Number.parseInt(startAttr, 10);\n if (!Number.isNaN(lineCharStart)) {\n const tokenText = element.textContent ?? '';\n const lineCharEnd = lineCharStart + tokenText.length;\n if (\n tokenText.trim() !== '' ||\n this.options.enableTokenInteractionsOnWhitespace === true\n ) {\n tokenInfo = {\n tokenElement,\n lineCharStart,\n lineCharEnd,\n tokenText,\n };\n }\n continue;\n }\n }\n }\n\n const columnNumber =\n numberElement == null\n ? (element.getAttribute('data-column-number') ?? undefined)\n : undefined;\n if (columnNumber != null) {\n numberElement = element;\n lineNumber = Number.parseInt(columnNumber, 10);\n numberColumn = true;\n lineType = getLineTypeFromElement(element);\n lineIndexValue = element.getAttribute('data-line-index') ?? undefined;\n continue;\n }\n\n const lineAttr =\n lineElement == null\n ? (element.getAttribute('data-line') ?? undefined)\n : undefined;\n if (lineAttr != null) {\n lineElement = element;\n lineNumber = Number.parseInt(lineAttr, 10);\n lineType = getLineTypeFromElement(element);\n lineIndexValue = element.getAttribute('data-line-index') ?? undefined;\n continue;\n }\n\n if (\n expandInfo == null &&\n (element.hasAttribute('data-expand-button') ||\n element.hasAttribute('data-unmodified-lines'))\n ) {\n expandInfo = {\n hunkIndex: undefined,\n direction: (() => {\n if (element.hasAttribute('data-expand-up')) {\n return 'up';\n }\n if (element.hasAttribute('data-expand-down')) {\n return 'down';\n }\n return 'both';\n })(),\n all: element.hasAttribute('data-expand-all-button'),\n };\n continue;\n }\n\n const expandIndexValue =\n expandInfo != null\n ? (element.getAttribute('data-expand-index') ?? undefined)\n : undefined;\n if (expandInfo != null && expandIndexValue != null) {\n const expandIndex = Number.parseInt(expandIndexValue, 10);\n if (!Number.isNaN(expandIndex)) {\n expandInfo.hunkIndex = expandIndex;\n }\n continue;\n }\n\n if (codeElement == null && element.hasAttribute('data-code')) {\n codeElement = element;\n break;\n }\n }\n\n if (mergeConflictActionTarget != null) {\n return mergeConflictActionTarget as ResolvedPointerTarget<TMode>;\n }\n\n if (expandInfo?.hunkIndex != null) {\n return {\n type: 'line-info',\n hunkIndex: expandInfo.hunkIndex,\n direction: expandInfo.direction,\n all: expandInfo.all,\n } as ResolvedPointerTarget<TMode>;\n }\n\n lineElement ??=\n lineIndexValue != null\n ? queryHTMLElement(\n codeElement,\n `[data-line][data-line-index=\"${lineIndexValue}\"]`\n )\n : undefined;\n numberElement ??=\n lineIndexValue != null\n ? queryHTMLElement(\n codeElement,\n `[data-column-number][data-line-index=\"${lineIndexValue}\"]`\n )\n : undefined;\n\n if (\n codeElement == null ||\n lineElement == null ||\n numberElement == null ||\n lineType == null ||\n lineNumber == null ||\n Number.isNaN(lineNumber)\n ) {\n return undefined;\n }\n\n const splitLineIndex = this.parseLineIndex(lineElement, this.isSplitDiff());\n\n if (tokenInfo != null) {\n if (this.mode === 'file') {\n return {\n kind: 'token',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: undefined,\n splitLineIndex,\n ...tokenInfo,\n } as ResolvedPointerTarget<TMode>;\n }\n\n return {\n kind: 'token',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: getAnnotationSide(lineType, codeElement),\n splitLineIndex,\n ...tokenInfo,\n } as ResolvedPointerTarget<TMode>;\n }\n\n // Otherwise return line target\n if (this.mode === 'file') {\n return {\n kind: 'line',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: undefined,\n splitLineIndex,\n } as ResolvedPointerTarget<TMode>;\n }\n\n return {\n kind: 'line',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: getAnnotationSide(lineType, codeElement),\n splitLineIndex,\n } as ResolvedPointerTarget<TMode>;\n }\n\n private isSplitDiff(): boolean {\n return this.pre?.getAttribute('data-diff-type') === 'split';\n }\n\n private parseLineIndex(\n element: HTMLElement,\n split: boolean\n ): number | undefined {\n const lineIndexes = (element.getAttribute('data-line-index') ?? '')\n .split(',')\n .map((value) => Number.parseInt(value, 10))\n .filter((value) => !Number.isNaN(value));\n\n if (split && lineIndexes.length === 2) {\n return lineIndexes[1];\n }\n if (!split) {\n return lineIndexes[0];\n }\n return undefined;\n }\n}\n\ntype InteractionPluckOptions<TMode extends InteractionManagerMode> =\n InteractionManagerBaseOptions<TMode> & {\n renderGutterUtility?(\n getHoveredRow: () => GetHoveredLineResult<TMode> | undefined\n ): HTMLElement | null | undefined;\n };\n\nexport function pluckInteractionOptions<TMode extends InteractionManagerMode>(\n {\n enableTokenInteractionsOnWhitespace,\n enableGutterUtility,\n lineHoverHighlight,\n onGutterUtilityClick,\n onLineClick,\n onLineEnter,\n onLineLeave,\n onLineNumberClick,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n renderGutterUtility,\n __debugPointerEvents,\n enableLineSelection,\n controlledSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionChange,\n onLineSelectionEnd,\n }: InteractionPluckOptions<TMode>,\n onHunkExpand?: (\n hunkIndex: number,\n direction: ExpansionDirections,\n expansionLineCountOverride?: number\n ) => unknown,\n getLineIndex?: GetLineIndexUtility,\n onMergeConflictActionClick?: (target: MergeConflictActionTarget) => void\n): InteractionManagerOptions<TMode> {\n return {\n enableTokenInteractionsOnWhitespace,\n enableGutterUtility: resolveEnableGutterUtilityOption({\n enableGutterUtility,\n renderGutterUtility,\n onGutterUtilityClick,\n }),\n usesCustomGutterUtility: renderGutterUtility != null,\n lineHoverHighlight,\n\n onGutterUtilityClick,\n onHunkExpand,\n onMergeConflictActionClick,\n onLineClick,\n onLineEnter,\n onLineLeave,\n onLineNumberClick,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n __debugPointerEvents,\n\n enableLineSelection,\n controlledSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionChange,\n onLineSelectionEnd,\n\n getLineIndex,\n };\n}\n\nfunction resolveEnableGutterUtilityOption<\n TMode extends InteractionManagerMode,\n>({\n enableGutterUtility,\n renderGutterUtility,\n onGutterUtilityClick,\n}: Pick<\n InteractionPluckOptions<TMode>,\n 'enableGutterUtility' | 'renderGutterUtility' | 'onGutterUtilityClick'\n>): boolean {\n if (onGutterUtilityClick != null && renderGutterUtility != null) {\n throw new Error(\n \"Cannot use both 'onGutterUtilityClick' and 'renderGutterUtility'. Use only one gutter utility API.\"\n );\n }\n return enableGutterUtility ?? false;\n}\n\nfunction isLinePointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode> | undefined\n): target is LinePointerTarget<TMode> {\n return target != null && 'kind' in target && target.kind === 'line';\n}\n\nfunction isTokenPointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode> | undefined\n): target is TokenPointerTarget<TMode> {\n return target != null && 'kind' in target && target.kind === 'token';\n}\n\nfunction isHoverableLinePointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode> | undefined\n): target is HoverableLinePointerTarget<TMode> {\n return isLinePointerTarget(target) || isTokenPointerTarget(target);\n}\n\nfunction isExpandoPointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode>\n): target is ExpandoEventProps {\n return 'type' in target && target.type === 'line-info';\n}\n\nfunction isMergeConflictActionPointerTarget<\n TMode extends InteractionManagerMode,\n>(target: ResolvedPointerTarget<TMode>): target is MergeConflictActionTarget {\n return 'kind' in target && target.kind === 'merge-conflict-action';\n}\n\nfunction isMergeConflictResolution(\n value: string | undefined\n): value is MergeConflictResolution {\n return value === 'current' || value === 'incoming' || value === 'both';\n}\n\nfunction queryHTMLElement(\n parent: HTMLElement | undefined,\n query: string\n): HTMLElement | undefined {\n const element = parent?.querySelector(query);\n return element instanceof HTMLElement ? element : undefined;\n}\n\nfunction getElementPath(element: Node): EventTarget[] {\n const path: EventTarget[] = [];\n let current: Node | null = element;\n while (current != null) {\n path.push(current);\n current = current.parentNode;\n }\n return path;\n}\n\n// Pointer hits often land on text/token descendants. This normalizes those\n// hits back to the row elements InteractionManager knows how to resolve.\nfunction closestSelectableRow(element: Element): HTMLElement | undefined {\n const row = element.closest('[data-line], [data-column-number]');\n if (row instanceof HTMLElement) {\n return row;\n }\n\n const annotationRow = element.closest(\n '[data-line-annotation], [data-gutter-buffer=\"annotation\"]'\n );\n if (!(annotationRow instanceof HTMLElement)) {\n return undefined;\n }\n\n const previousRow = annotationRow.previousElementSibling;\n return previousRow instanceof HTMLElement &&\n (previousRow.hasAttribute('data-line') ||\n previousRow.hasAttribute('data-column-number'))\n ? previousRow\n : undefined;\n}\n\nfunction getAnnotationSlotName(element: Element): string | undefined {\n const slottedElement = element.closest('[slot^=\"annotation-\"]');\n if (slottedElement instanceof HTMLElement) {\n return slottedElement.getAttribute('slot') ?? undefined;\n }\n\n if (element instanceof HTMLElement) {\n const slotName = element.getAttribute('name') ?? undefined;\n return slotName != null && slotName.startsWith('annotation-')\n ? slotName\n : undefined;\n }\n\n return undefined;\n}\n\nfunction selectionPointFromAnnotationSlotName(\n slotName: string | undefined\n): SelectionPoint | undefined {\n if (slotName == null) {\n return undefined;\n }\n\n const match = /^annotation-(?:(additions|deletions)-)?(\\d+)$/.exec(slotName);\n if (match == null) {\n return undefined;\n }\n\n const lineNumber = Number.parseInt(match[2], 10);\n if (!Number.isFinite(lineNumber)) {\n return undefined;\n }\n\n const side = match[1] as SelectionSide | undefined;\n return { lineNumber, side };\n}\n\ninterface ElementFromPointRoot {\n elementFromPoint(x: number, y: number): Element | null;\n}\n\nfunction hasElementFromPoint(\n value: Node | undefined\n): value is Node & ElementFromPointRoot {\n return (\n value != null &&\n typeof (value as Partial<ElementFromPointRoot>).elementFromPoint ===\n 'function'\n );\n}\n\nfunction getAnnotationSide(\n lineType: LineTypes,\n codeElement: HTMLElement\n): AnnotationSide {\n switch (lineType) {\n case 'change-deletion':\n return 'deletions';\n case 'change-addition':\n return 'additions';\n default:\n return codeElement.hasAttribute('data-deletions')\n ? 'deletions'\n : 'additions';\n }\n}\n\nfunction getLineTypeFromElement(element: HTMLElement): LineTypes | undefined {\n const lineType = element.getAttribute('data-line-type');\n if (lineType == null) {\n return undefined;\n }\n switch (lineType) {\n case 'change-deletion':\n case 'change-addition':\n case 'context':\n case 'context-expanded':\n return lineType;\n default:\n return undefined;\n }\n}\n\nfunction isGutterUtilityPath(path: (EventTarget | undefined)[]): boolean {\n for (const element of path) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n if (\n element.hasAttribute('data-utility-button') ||\n element.hasAttribute('data-gutter-utility-slot') ||\n // Custom React/DOM utilities are slotted into the same utility surface,\n // so treat both the assigned content and the slot node itself as\n // utility hits.\n element.getAttribute('slot') === 'gutter-utility-slot' ||\n element.getAttribute('name') === 'gutter-utility-slot'\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction debugLogIfEnabled(\n debugLogType: LogTypes | undefined = 'none',\n logIfType: 'move' | 'click',\n ...args: unknown[]\n) {\n switch (debugLogType) {\n case 'none':\n return;\n case 'both':\n break;\n case 'click':\n if (logIfType !== 'click') {\n return;\n }\n break;\n case 'move':\n if (logIfType !== 'move') {\n return;\n }\n break;\n }\n console.log(...args);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InteractionManager.js","names":["mode: TMode","options: InteractionManagerOptions<TMode>","reasons: string[]","start: SelectionPoint","end: SelectionPoint","nextRange: SelectedLineRange | null","lineType: LineTypes | undefined","codeElement: HTMLElement | undefined","lineElement: HTMLElement | undefined","lineIndexValue: string | undefined","numberElement: HTMLElement | undefined","tokenElement: HTMLElement | undefined","tokenInfo: TokenCache | undefined","expandInfo: ExpandCache | undefined","lineNumber: number | undefined","mergeConflictActionTarget: MergeConflictActionTarget | undefined","path: EventTarget[]","current: Node | null"],"sources":["../../src/managers/InteractionManager.ts"],"sourcesContent":["import { toHtml } from 'hast-util-to-html';\n\nimport type {\n AnnotationSide,\n DiffLineEventBaseProps,\n DiffTokenEventBaseProps,\n ExpansionDirections,\n LineEventBaseProps,\n LineTypes,\n MergeConflictResolution,\n SelectedLineRange,\n SelectionPoint,\n SelectionSide,\n TokenEventBase,\n} from '../types';\nimport { areSelectionPointsEqual } from '../utils/areSelectionPointsEqual';\nimport { areSelectionsEqual } from '../utils/areSelectionsEqual';\nimport { createGutterUtilityElement } from '../utils/createGutterUtilityElement';\n\ninterface TokenCache {\n tokenElement: HTMLElement;\n lineCharStart: number;\n lineCharEnd: number;\n tokenText: string;\n}\n\ninterface ExpandCache {\n hunkIndex: number | undefined;\n direction: ExpansionDirections;\n all: boolean;\n}\n\nexport type LogTypes = 'click' | 'move' | 'both' | 'none';\n\nexport type InteractionManagerMode = 'file' | 'diff';\n\nexport interface OnLineClickProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnLineEnterLeaveProps extends LineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineClickProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface OnDiffLineEnterLeaveProps extends DiffLineEventBaseProps {\n event: PointerEvent;\n}\n\nexport interface SelectionWriteOptions {\n notify?: boolean;\n}\n\nexport type GetLineIndexUtility = (\n lineNumber: number,\n side?: SelectionSide\n) => [number, number] | undefined;\n\ntype EventClickProps<TMode extends InteractionManagerMode> =\n TMode extends 'file' ? OnLineClickProps : OnDiffLineClickProps;\n\ntype PointerEventEnterLeaveProps<TMode extends InteractionManagerMode> =\n TMode extends 'file' ? OnLineEnterLeaveProps : OnDiffLineEnterLeaveProps;\n\ntype EventBaseProps<TMode extends InteractionManagerMode> = TMode extends 'file'\n ? LineEventBaseProps\n : DiffLineEventBaseProps;\n\nexport type OnTokenEventProps<TMode extends InteractionManagerMode> =\n TMode extends 'file' ? TokenEventBase : DiffTokenEventBaseProps;\n\ninterface ExpandoEventProps {\n type: 'line-info';\n hunkIndex: number;\n direction: ExpansionDirections;\n all: boolean;\n}\n\nexport type GetHoveredLineResult<TMode extends InteractionManagerMode> =\n TMode extends 'file'\n ? { lineNumber: number }\n : { lineNumber: number; side: AnnotationSide };\n\ninterface SelectionInfo {\n lineNumber: number;\n eventSide: SelectionSide | undefined;\n lineIndex: number;\n}\n\ntype SelectionHitSource = 'event-path' | 'coordinates-first';\n\ninterface SelectionHitOptions {\n source: SelectionHitSource;\n excludeUtility?: boolean;\n}\n\ninterface SelectionInfoOptions extends SelectionHitOptions {\n requireNumberColumn: boolean;\n}\n\ninterface SelectionEnds {\n top: SelectionPoint;\n bottom: SelectionPoint;\n}\n\ninterface ResolvedLineTarget<TMode extends InteractionManagerMode> {\n kind: 'line';\n lineType: LineTypes;\n lineElement: HTMLElement;\n lineNumber: number;\n numberColumn: boolean;\n numberElement: HTMLElement;\n side: TMode extends 'diff' ? AnnotationSide : undefined;\n splitLineIndex: number | undefined;\n}\n\ninterface ResolvedTokenTarget<TMode extends InteractionManagerMode> {\n kind: 'token';\n lineType: LineTypes;\n lineElement: HTMLElement;\n lineNumber: number;\n numberColumn: boolean;\n numberElement: HTMLElement;\n side: TMode extends 'diff' ? AnnotationSide : undefined;\n splitLineIndex: number | undefined;\n tokenElement: HTMLElement;\n tokenText: string;\n lineCharStart: number;\n lineCharEnd: number;\n}\n\nexport interface MergeConflictActionTarget {\n kind: 'merge-conflict-action';\n resolution: MergeConflictResolution;\n conflictIndex: number;\n}\n\ntype ResolvedPointerTarget<TMode extends InteractionManagerMode> =\n | ResolvedLineTarget<TMode>\n | ResolvedTokenTarget<TMode>\n | ExpandoEventProps\n | MergeConflictActionTarget;\n\ntype LinePointerTarget<TMode extends InteractionManagerMode> =\n ResolvedLineTarget<TMode>;\n\ntype TokenPointerTarget<TMode extends InteractionManagerMode> =\n ResolvedTokenTarget<TMode>;\n\ntype HoverableLinePointerTarget<TMode extends InteractionManagerMode> =\n | LinePointerTarget<TMode>\n | TokenPointerTarget<TMode>;\n\ninterface SessionIdle {\n mode: 'idle';\n}\n\ninterface SessionSelecting {\n mode: 'selecting';\n pointerId: number;\n}\n\ninterface SessionPendingSingleLineUnselect {\n mode: 'pendingSingleLineUnselect';\n pointerId: number;\n anchor: SelectionPoint;\n pending: SelectionPoint;\n}\n\ninterface SessionGutterSelecting {\n mode: 'gutterSelecting';\n pointerId: number;\n anchor: SelectionPoint;\n current: SelectionPoint;\n}\n\ntype PointerSession =\n | SessionIdle\n | SessionSelecting\n | SessionPendingSingleLineUnselect\n | SessionGutterSelecting;\n\nexport interface InteractionManagerBaseOptions<\n TMode extends InteractionManagerMode,\n> {\n lineHoverHighlight?: 'disabled' | 'both' | 'number' | 'line';\n enableTokenInteractionsOnWhitespace?: boolean;\n enableGutterUtility?: boolean;\n onGutterUtilityClick?(range: SelectedLineRange): unknown;\n onLineClick?(props: EventClickProps<TMode>): unknown;\n onLineNumberClick?(props: EventClickProps<TMode>): unknown;\n onLineEnter?(props: PointerEventEnterLeaveProps<TMode>): unknown;\n onLineLeave?(props: PointerEventEnterLeaveProps<TMode>): unknown;\n onTokenClick?(props: OnTokenEventProps<TMode>, event: MouseEvent): unknown;\n onTokenEnter?(props: OnTokenEventProps<TMode>, event: PointerEvent): unknown;\n onTokenLeave?(props: OnTokenEventProps<TMode>, event: PointerEvent): unknown;\n __debugPointerEvents?: LogTypes;\n enableLineSelection?: boolean;\n controlledSelection?: boolean;\n onLineSelected?: (range: SelectedLineRange | null) => void;\n onLineSelectionStart?: (range: SelectedLineRange | null) => void;\n onLineSelectionChange?: (range: SelectedLineRange | null) => void;\n onLineSelectionEnd?: (range: SelectedLineRange | null) => void;\n getLineIndex?: GetLineIndexUtility;\n}\n\nexport interface InteractionManagerOptions<\n TMode extends InteractionManagerMode,\n> extends InteractionManagerBaseOptions<TMode> {\n usesCustomGutterUtility?: boolean;\n onHunkExpand?(\n hunkIndex: number,\n direction: ExpansionDirections,\n expansionLineCountOverride?: number\n ): unknown;\n onMergeConflictActionClick?(target: MergeConflictActionTarget): void;\n}\n\ninterface HandlePointerEventProps {\n eventType: 'click' | 'move';\n event: PointerEvent | MouseEvent;\n}\n\nexport class InteractionManager<TMode extends InteractionManagerMode> {\n private hoveredLine: EventBaseProps<TMode> | undefined;\n private hoveredToken: OnTokenEventProps<TMode> | undefined;\n private pre: HTMLPreElement | undefined;\n\n private gutterUtilityLine: EventBaseProps<TMode> | undefined;\n private gutterUtilityContainer: HTMLDivElement | undefined;\n private gutterUtilityButton: HTMLButtonElement | undefined;\n private gutterUtilitySlot: HTMLSlotElement | undefined;\n\n private interactiveLinesAttr = false;\n private interactiveLineNumbersAttr = false;\n\n private hasPointerListeners = false;\n private hasDocumentPointerListeners = false;\n\n private selectedRange: SelectedLineRange | null = null;\n private proposedSelectedRange: SelectedLineRange | null | undefined;\n private renderedSelectionRange: SelectedLineRange | null | undefined;\n private selectionAnchor: SelectionPoint | undefined;\n private queuedSelectionRender: number | undefined;\n private pointerSession: PointerSession = { mode: 'idle' };\n\n constructor(\n private mode: TMode,\n private options: InteractionManagerOptions<TMode>\n ) {}\n\n setOptions(options: InteractionManagerOptions<TMode>): void {\n this.options = options;\n }\n\n cleanUp(): void {\n this.pre?.removeEventListener('click', this.handlePointerClick);\n this.pre?.removeEventListener('pointerdown', this.handlePointerDown);\n this.pre?.removeEventListener('pointermove', this.handlePointerMove);\n this.pre?.removeEventListener('pointerleave', this.handlePointerLeave);\n this.pre?.removeAttribute('data-interactive-lines');\n this.pre?.removeAttribute('data-interactive-line-numbers');\n this.pre = undefined;\n this.gutterUtilityContainer?.remove();\n this.gutterUtilityLine = undefined;\n this.gutterUtilityContainer = undefined;\n this.gutterUtilityButton = undefined;\n this.gutterUtilitySlot = undefined;\n this.clearHoveredLine();\n this.clearHoveredToken();\n this.detachDocumentPointerListeners();\n this.clearPointerSession();\n if (this.queuedSelectionRender != null) {\n cancelAnimationFrame(this.queuedSelectionRender);\n this.queuedSelectionRender = undefined;\n }\n this.interactiveLinesAttr = false;\n this.interactiveLineNumbersAttr = false;\n this.hasPointerListeners = false;\n }\n\n setup(pre: HTMLPreElement): void {\n this.setSelectionDirty();\n const { usesCustomGutterUtility = false, enableGutterUtility = false } =\n this.options;\n\n const newContainer = this.pre !== pre;\n if (newContainer) {\n this.cleanUp();\n this.pre = pre;\n }\n\n if (enableGutterUtility) {\n this.ensureGutterUtilityNode(usesCustomGutterUtility);\n } else if (this.gutterUtilityContainer != null) {\n this.gutterUtilityContainer.remove();\n this.gutterUtilityLine = undefined;\n this.gutterUtilityContainer = undefined;\n this.gutterUtilityButton = undefined;\n this.gutterUtilitySlot = undefined;\n if (this.pointerSession.mode === 'gutterSelecting') {\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n }\n }\n\n this.syncPointerListeners(pre);\n this.updateInteractiveLineAttributes();\n this.renderSelection();\n this.placeUtility();\n }\n\n setSelectionDirty(): void {\n this.renderedSelectionRange = undefined;\n }\n\n isSelectionDirty(): boolean {\n return this.renderedSelectionRange === null;\n }\n\n setSelection(\n range: SelectedLineRange | null,\n options?: SelectionWriteOptions\n ): void {\n const isRangeChange = !(\n range === this.selectedRange ||\n areSelectionsEqual(range ?? undefined, this.selectedRange ?? undefined)\n );\n if (!this.isSelectionDirty() && !isRangeChange) {\n return;\n }\n this.proposedSelectedRange = undefined;\n this.selectedRange = range;\n this.renderSelection();\n this.placeUtility();\n if (isRangeChange && options?.notify !== false) {\n this.notifySelectionCommitted();\n }\n }\n\n getSelection(): SelectedLineRange | null {\n return this.selectedRange;\n }\n\n getHoveredLine = (): GetHoveredLineResult<TMode> | undefined => {\n const gutterUtilityLine = this.gutterUtilityLine ?? this.hoveredLine;\n if (gutterUtilityLine != null) {\n if (this.mode === 'diff' && gutterUtilityLine.type === 'diff-line') {\n return {\n lineNumber: gutterUtilityLine.lineNumber,\n side: gutterUtilityLine.annotationSide,\n } as GetHoveredLineResult<TMode>;\n }\n if (this.mode === 'file' && gutterUtilityLine.type === 'line') {\n return {\n lineNumber: gutterUtilityLine.lineNumber,\n } as GetHoveredLineResult<TMode>;\n }\n }\n return undefined;\n };\n\n handlePointerClick = (event: MouseEvent): void => {\n const {\n onHunkExpand,\n onLineClick,\n onLineNumberClick,\n onTokenClick,\n onMergeConflictActionClick,\n } = this.options;\n if (\n onHunkExpand == null &&\n onLineClick == null &&\n onLineNumberClick == null &&\n onMergeConflictActionClick == null &&\n onTokenClick == null\n ) {\n return;\n }\n if (\n this.options.onGutterUtilityClick != null &&\n isGutterUtilityPath(event.composedPath())\n ) {\n return;\n }\n debugLogIfEnabled(\n this.options.__debugPointerEvents,\n 'click',\n 'FileDiff.DEBUG.handlePointerClick:',\n event\n );\n this.handlePointerEvent({ eventType: 'click', event });\n };\n\n handlePointerMove = (event: PointerEvent): void => {\n // Touch and pen moves are active drag/scroll gestures, not hover. Keeping\n // hover mouse-only prevents content scrolls from leaving stale utilities.\n if (event.pointerType !== 'mouse') {\n return;\n }\n\n const {\n lineHoverHighlight = 'disabled',\n onLineEnter,\n onLineLeave,\n onTokenEnter,\n onTokenLeave,\n enableGutterUtility = false,\n } = this.options;\n if (\n lineHoverHighlight === 'disabled' &&\n !enableGutterUtility &&\n onLineEnter == null &&\n onLineLeave == null &&\n onTokenEnter == null &&\n onTokenLeave == null\n ) {\n return;\n }\n debugLogIfEnabled(\n this.options.__debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.handlePointerMove:',\n event\n );\n // should we perhaps throttle this a bit because move can be fast as fuk\n // boiiii\n this.handlePointerEvent({ eventType: 'move', event });\n };\n\n handlePointerLeave = (event: PointerEvent): void => {\n const { __debugPointerEvents } = this.options;\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.handlePointerLeave: no event'\n );\n if (this.hoveredLine == null && this.hoveredToken == null) {\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.handlePointerLeave: returned early, no hovered line or token'\n );\n return;\n }\n if (this.hoveredToken != null) {\n this.options.onTokenLeave?.(this.hoveredToken, event);\n this.clearHoveredToken();\n }\n\n if (this.hoveredLine != null) {\n this.options.onLineLeave?.({\n ...this.hoveredLine,\n event,\n } as PointerEventEnterLeaveProps<TMode>);\n this.clearHoveredLine();\n }\n this.placeUtility();\n };\n\n private handlePointerEvent({ eventType, event }: HandlePointerEventProps) {\n const { __debugPointerEvents } = this.options;\n const composedPath = event.composedPath();\n debugLogIfEnabled(\n __debugPointerEvents,\n eventType,\n 'FileDiff.DEBUG.handlePointerEvent:',\n { eventType, composedPath }\n );\n const target = this.resolvePointerTarget(composedPath);\n debugLogIfEnabled(\n __debugPointerEvents,\n eventType,\n 'FileDiff.DEBUG.handlePointerEvent: resolvePointerTarget result:',\n target\n );\n\n const {\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n onHunkExpand,\n onMergeConflictActionClick,\n } = this.options;\n\n switch (eventType) {\n case 'move': {\n const sameLine =\n isHoverableLinePointerTarget(target) &&\n this.hoveredLine?.lineElement === target.lineElement;\n const sameToken =\n isTokenPointerTarget(target) &&\n this.hoveredToken?.tokenElement === target.tokenElement;\n\n // Handle token transitions\n if (!sameToken) {\n if (this.hoveredToken != null) {\n onTokenLeave?.(this.hoveredToken, event as PointerEvent);\n this.clearHoveredToken();\n }\n if (isTokenPointerTarget(target)) {\n this.setHoveredToken(this.toTokenEventBaseProps(target));\n onTokenEnter?.(\n this.hoveredToken as OnTokenEventProps<TMode>,\n event as PointerEvent\n );\n }\n }\n\n // Handle line transitions\n if (!sameLine) {\n if (this.hoveredLine != null) {\n onLineLeave?.({\n ...this.hoveredLine,\n event: event as PointerEvent,\n } as PointerEventEnterLeaveProps<TMode>);\n this.clearHoveredLine();\n }\n if (isHoverableLinePointerTarget(target)) {\n this.setHoveredLine(this.toEventBaseProps(target));\n this.placeUtility();\n onLineEnter?.({\n ...this.hoveredLine,\n event: event as PointerEvent,\n } as PointerEventEnterLeaveProps<TMode>);\n } else {\n this.placeUtility();\n }\n }\n break;\n }\n case 'click': {\n if (target == null) {\n break;\n }\n if (\n isMergeConflictActionPointerTarget(target) &&\n onMergeConflictActionClick != null\n ) {\n onMergeConflictActionClick(target);\n break;\n }\n if (isExpandoPointerTarget(target) && onHunkExpand != null) {\n onHunkExpand(\n target.hunkIndex,\n target.all || event.shiftKey ? 'both' : target.direction,\n target.all || event.shiftKey ? Number.POSITIVE_INFINITY : undefined\n );\n break;\n }\n\n if (!isHoverableLinePointerTarget(target)) {\n break;\n }\n\n if (isTokenPointerTarget(target) && onTokenClick != null) {\n onTokenClick(this.toTokenEventBaseProps(target), event as MouseEvent);\n }\n\n const eventBase = this.toEventBaseProps(target);\n if (onLineNumberClick != null && target.numberColumn) {\n onLineNumberClick({\n ...eventBase,\n event: event as PointerEvent,\n } as EventClickProps<TMode>);\n } else if (onLineClick != null) {\n onLineClick({\n ...eventBase,\n event: event as PointerEvent,\n } as EventClickProps<TMode>);\n }\n break;\n }\n }\n }\n\n private syncPointerListeners(pre: HTMLPreElement): void {\n const {\n __debugPointerEvents,\n lineHoverHighlight = 'disabled',\n onLineClick,\n onLineNumberClick,\n onLineEnter,\n onLineLeave,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n onHunkExpand,\n onMergeConflictActionClick,\n enableGutterUtility = false,\n enableLineSelection = false,\n onGutterUtilityClick,\n } = this.options;\n const enableGutterSelection = onGutterUtilityClick != null;\n const shouldAttachPointerListeners =\n lineHoverHighlight !== 'disabled' ||\n onLineClick != null ||\n onLineNumberClick != null ||\n onLineEnter != null ||\n onLineLeave != null ||\n onTokenClick != null ||\n onTokenEnter != null ||\n onTokenLeave != null ||\n onHunkExpand != null ||\n onMergeConflictActionClick != null ||\n enableGutterUtility ||\n enableLineSelection ||\n enableGutterSelection;\n\n if (shouldAttachPointerListeners && !this.hasPointerListeners) {\n pre.addEventListener('click', this.handlePointerClick);\n pre.addEventListener('pointerdown', this.handlePointerDown);\n pre.addEventListener('pointermove', this.handlePointerMove);\n pre.addEventListener('pointerleave', this.handlePointerLeave);\n this.hasPointerListeners = true;\n\n debugLogIfEnabled(\n __debugPointerEvents,\n 'click',\n 'FileDiff.DEBUG.attachEventListeners: Attaching click events for:',\n (() => {\n const reasons: string[] = [];\n if (\n __debugPointerEvents === 'both' ||\n __debugPointerEvents === 'click'\n ) {\n if (onLineClick != null) {\n reasons.push('onLineClick');\n }\n if (onLineNumberClick != null) {\n reasons.push('onLineNumberClick');\n }\n if (onHunkExpand != null) {\n reasons.push('expandable hunk separators');\n }\n if (onMergeConflictActionClick != null) {\n reasons.push('merge conflict actions');\n }\n }\n return reasons;\n })()\n );\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer move event'\n );\n debugLogIfEnabled(\n __debugPointerEvents,\n 'move',\n 'FileDiff.DEBUG.attachEventListeners: Attaching pointer leave event'\n );\n } else if (!shouldAttachPointerListeners && this.hasPointerListeners) {\n pre.removeEventListener('click', this.handlePointerClick);\n pre.removeEventListener('pointerdown', this.handlePointerDown);\n pre.removeEventListener('pointermove', this.handlePointerMove);\n pre.removeEventListener('pointerleave', this.handlePointerLeave);\n this.hasPointerListeners = false;\n }\n\n const hasActiveLineSelectionSession =\n this.pointerSession.mode === 'selecting' ||\n this.pointerSession.mode === 'pendingSingleLineUnselect';\n const hasActiveGutterSelectionSession =\n this.pointerSession.mode === 'gutterSelecting';\n if (\n (!enableLineSelection && hasActiveLineSelectionSession) ||\n (!enableGutterSelection && hasActiveGutterSelectionSession)\n ) {\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n this.selectionAnchor = undefined;\n this.clearPendingSingleLineState();\n }\n }\n\n private updateInteractiveLineAttributes(): void {\n if (this.pre == null) {\n return;\n }\n\n const {\n onLineClick,\n onLineNumberClick,\n enableLineSelection = false,\n } = this.options;\n\n const shouldHaveInteractiveLines = onLineClick != null;\n const shouldHaveInteractiveLineNumbers =\n onLineNumberClick != null || enableLineSelection;\n\n if (shouldHaveInteractiveLines && !this.interactiveLinesAttr) {\n this.pre.setAttribute('data-interactive-lines', '');\n this.interactiveLinesAttr = true;\n } else if (!shouldHaveInteractiveLines && this.interactiveLinesAttr) {\n this.pre.removeAttribute('data-interactive-lines');\n this.interactiveLinesAttr = false;\n }\n\n if (shouldHaveInteractiveLineNumbers && !this.interactiveLineNumbersAttr) {\n this.pre.setAttribute('data-interactive-line-numbers', '');\n this.interactiveLineNumbersAttr = true;\n } else if (\n !shouldHaveInteractiveLineNumbers &&\n this.interactiveLineNumbersAttr\n ) {\n this.pre.removeAttribute('data-interactive-line-numbers');\n this.interactiveLineNumbersAttr = false;\n }\n }\n\n private handlePointerDown = (event: PointerEvent): void => {\n if (\n (event.pointerType === 'mouse' && event.button !== 0) ||\n this.pre == null ||\n this.pointerSession.mode !== 'idle'\n ) {\n return;\n }\n\n const path = event.composedPath();\n if (\n isGutterUtilityPath(path) &&\n this.options.onGutterUtilityClick != null\n ) {\n this.startGutterSelectionFromPointerDown(event);\n } else {\n if (event.pointerType !== 'mouse') {\n this.revealUtilityFromGutterPath(path);\n }\n this.startLineSelectionFromPointerDown(event);\n }\n };\n\n private startLineSelectionFromPointerDown(event: PointerEvent): void {\n const { enableLineSelection = false } = this.options;\n if (!enableLineSelection) {\n return;\n }\n\n const pointerInfo = this.resolveSelectionInfo(event, {\n source: 'event-path',\n requireNumberColumn: true,\n });\n if (pointerInfo == null) {\n return;\n }\n\n const { pre } = this;\n if (pre == null) {\n return;\n }\n\n event.preventDefault();\n const { lineNumber, eventSide, lineIndex } = pointerInfo;\n\n if (event.shiftKey && this.selectedRange != null) {\n const rowRange = this.getIndexesFromSelection(\n this.selectedRange,\n pre.getAttribute('data-diff-type') === 'split'\n );\n if (rowRange == null) {\n return;\n }\n const useStart =\n rowRange.start <= rowRange.end\n ? lineIndex >= rowRange.start\n : lineIndex <= rowRange.end;\n this.selectionAnchor = {\n lineNumber: useStart\n ? this.selectedRange.start\n : this.selectedRange.end,\n side: useStart\n ? this.selectedRange.side\n : (this.selectedRange.endSide ?? this.selectedRange.side),\n };\n this.updateSelection(lineNumber, eventSide, false);\n this.notifySelectionStart(this.getCurrentSelectionRange());\n this.pointerSession = { mode: 'selecting', pointerId: event.pointerId };\n this.attachDocumentPointerListeners();\n return;\n }\n\n if (\n this.selectedRange?.start === lineNumber &&\n this.selectedRange?.end === lineNumber\n ) {\n const point = { lineNumber, side: eventSide };\n this.selectionAnchor = point;\n this.pointerSession = {\n mode: 'pendingSingleLineUnselect',\n pointerId: event.pointerId,\n anchor: point,\n pending: point,\n };\n this.attachDocumentPointerListeners();\n return;\n }\n\n if (this.options.controlledSelection === true) {\n this.proposedSelectedRange = null;\n } else {\n this.selectedRange = null;\n }\n this.placeUtility();\n this.selectionAnchor = { lineNumber, side: eventSide };\n this.updateSelection(lineNumber, eventSide, false);\n this.notifySelectionStart(this.getCurrentSelectionRange());\n this.pointerSession = { mode: 'selecting', pointerId: event.pointerId };\n this.attachDocumentPointerListeners();\n }\n\n private startGutterSelectionFromPointerDown(event: PointerEvent): void {\n const { enableLineSelection = false, onGutterUtilityClick } = this.options;\n if (onGutterUtilityClick == null) {\n return;\n }\n // If a selection already exists, the utility represents that whole range.\n // Dragging should start from the visual top and extend from the visual\n // bottom, regardless of the direction the range was originally created.\n const selectedEndpoints = this.currentSelectionEnds();\n const point =\n selectedEndpoints?.bottom ??\n this.resolveSelectionPoint(event, {\n source: 'event-path',\n excludeUtility: false,\n });\n const anchor = selectedEndpoints?.top ?? point;\n if (point == null || anchor == null) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n this.pointerSession = {\n mode: 'gutterSelecting',\n pointerId: event.pointerId,\n anchor,\n current: point,\n };\n if (enableLineSelection) {\n this.selectionAnchor = {\n lineNumber: anchor.lineNumber,\n side: anchor.side,\n };\n this.updateSelection(point.lineNumber, point.side, false);\n this.notifySelectionStart(this.getCurrentSelectionRange());\n }\n this.attachDocumentPointerListeners();\n }\n\n private handleDocumentPointerMove = (event: PointerEvent): void => {\n const { enableLineSelection = false } = this.options;\n switch (this.pointerSession.mode) {\n case 'idle':\n return;\n case 'gutterSelecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const point = this.resolveSelectionPoint(event, {\n source: 'coordinates-first',\n });\n if (point == null) {\n return;\n }\n this.pointerSession.current = point;\n if (enableLineSelection === true) {\n this.updateSelection(point.lineNumber, point.side);\n }\n return;\n }\n case 'selecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const pointerInfo = this.resolveSelectionInfo(event, {\n source: 'coordinates-first',\n requireNumberColumn: false,\n });\n if (pointerInfo == null || this.selectionAnchor == null) {\n return;\n }\n this.updateSelection(pointerInfo.lineNumber, pointerInfo.eventSide);\n return;\n }\n case 'pendingSingleLineUnselect': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const pointerInfo = this.resolveSelectionInfo(event, {\n source: 'coordinates-first',\n requireNumberColumn: false,\n });\n if (pointerInfo == null || this.selectionAnchor == null) {\n return;\n }\n const point = {\n lineNumber: pointerInfo.lineNumber,\n side: pointerInfo.eventSide,\n };\n if (areSelectionPointsEqual(this.pointerSession.pending, point)) {\n return;\n }\n this.updateSelection(\n pointerInfo.lineNumber,\n pointerInfo.eventSide,\n false\n );\n this.notifySelectionStart(this.getCurrentSelectionRange());\n this.notifySelectionChangeDelta();\n this.pointerSession = {\n mode: 'selecting',\n pointerId: event.pointerId,\n };\n return;\n }\n }\n };\n\n private handleDocumentPointerUp = (event: PointerEvent): void => {\n const { enableLineSelection = false, onGutterUtilityClick } = this.options;\n switch (this.pointerSession.mode) {\n case 'idle':\n return;\n case 'gutterSelecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n const point = this.resolveSelectionPoint(event, {\n source: 'coordinates-first',\n });\n if (point != null) {\n this.pointerSession.current = point;\n if (enableLineSelection) {\n this.updateSelection(point.lineNumber, point.side);\n }\n }\n onGutterUtilityClick?.(\n this.buildSelectedLineRange(\n this.pointerSession.anchor,\n this.pointerSession.current\n )\n );\n this.selectionAnchor = undefined;\n if (enableLineSelection) {\n this.notifySelectionEnd(this.getCurrentSelectionRange());\n this.notifySelectionCommitted();\n this.clearProposedSelection();\n }\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n return;\n }\n case 'pendingSingleLineUnselect': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n this.updateSelection(null, undefined, false);\n this.selectionAnchor = undefined;\n this.clearPendingSingleLineState();\n this.detachDocumentPointerListeners();\n this.notifySelectionEnd(this.getCurrentSelectionRange());\n this.notifySelectionCommitted();\n this.clearProposedSelection();\n return;\n }\n case 'selecting': {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n event.preventDefault();\n this.selectionAnchor = undefined;\n this.detachDocumentPointerListeners();\n this.clearPointerSession();\n this.notifySelectionEnd(this.getCurrentSelectionRange());\n this.notifySelectionCommitted();\n this.clearProposedSelection();\n }\n }\n };\n\n private handleDocumentPointerCancel = (event: PointerEvent): void => {\n switch (this.pointerSession.mode) {\n case 'idle':\n return;\n case 'gutterSelecting':\n case 'selecting':\n case 'pendingSingleLineUnselect': {\n if ('pointerId' in this.pointerSession) {\n if (event.pointerId !== this.pointerSession.pointerId) {\n return;\n }\n }\n this.selectionAnchor = undefined;\n this.clearProposedSelection();\n this.clearPendingSingleLineState();\n this.clearPointerSession();\n this.detachDocumentPointerListeners();\n }\n }\n };\n\n private clearHoveredLine() {\n if (this.hoveredLine == null) {\n return;\n }\n this.hoveredLine.lineElement.removeAttribute('data-hovered');\n this.hoveredLine.numberElement.removeAttribute('data-hovered');\n this.hoveredLine = undefined;\n }\n\n private setHoveredLine(hoveredLine: EventBaseProps<TMode>) {\n const { lineHoverHighlight = 'disabled' } = this.options;\n if (this.hoveredLine != null) {\n this.clearHoveredLine();\n }\n this.hoveredLine = hoveredLine;\n if (lineHoverHighlight !== 'disabled') {\n if (lineHoverHighlight === 'both' || lineHoverHighlight === 'line') {\n this.hoveredLine.lineElement.setAttribute('data-hovered', '');\n }\n if (lineHoverHighlight === 'both' || lineHoverHighlight === 'number') {\n this.hoveredLine.numberElement.setAttribute('data-hovered', '');\n }\n }\n }\n\n private clearHoveredToken() {\n if (this.hoveredToken == null) {\n return;\n }\n this.hoveredToken = undefined;\n }\n\n private setHoveredToken(hoveredToken: OnTokenEventProps<TMode>) {\n if (this.hoveredToken != null) {\n this.clearHoveredToken();\n }\n this.hoveredToken = hoveredToken;\n }\n\n private ensureGutterUtilityNode(useCustomGutterUtility: boolean): void {\n if (this.gutterUtilityContainer == null) {\n this.gutterUtilityContainer = document.createElement('div');\n this.gutterUtilityContainer.setAttribute('data-gutter-utility-slot', '');\n }\n if (useCustomGutterUtility) {\n if (this.gutterUtilityButton != null) {\n this.gutterUtilityButton.remove();\n this.gutterUtilityButton = undefined;\n }\n if (this.gutterUtilitySlot == null) {\n this.gutterUtilitySlot = document.createElement('slot');\n this.gutterUtilitySlot.name = 'gutter-utility-slot';\n }\n if (this.gutterUtilitySlot.parentNode !== this.gutterUtilityContainer) {\n this.gutterUtilityContainer.replaceChildren(this.gutterUtilitySlot);\n }\n } else {\n this.gutterUtilitySlot?.remove();\n this.gutterUtilitySlot = undefined;\n if (this.gutterUtilityButton == null) {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = toHtml(createGutterUtilityElement());\n const utilityButton = tempDiv.firstElementChild;\n if (!(utilityButton instanceof HTMLButtonElement)) {\n throw new Error(\n 'InteractionManager.ensureGutterUtilityNode: Node element should be a button'\n );\n }\n utilityButton.remove();\n this.gutterUtilityButton = utilityButton;\n }\n if (this.gutterUtilityButton.parentNode !== this.gutterUtilityContainer) {\n this.gutterUtilityContainer.replaceChildren(this.gutterUtilityButton);\n }\n }\n }\n\n private revealUtilityFromGutterPath(path: (EventTarget | undefined)[]): void {\n if (this.placeUtilityFromSelection()) {\n return;\n }\n const target = this.resolvePointerTarget(path);\n if (isLinePointerTarget(target) && target.numberColumn) {\n this.showUtilityOnLine(this.toEventBaseProps(target));\n }\n }\n\n // The gutter utility follows the active selection first because a selected\n // range is more stable than transient hover/touch state. Without a\n // selection, desktop hover and mobile tap reveal can still place it on a\n // single row.\n private placeUtility(): void {\n if (this.placeUtilityFromSelection()) {\n return;\n }\n if (this.hoveredLine != null) {\n this.showUtilityOnLine(this.hoveredLine);\n return;\n }\n this.hideUtility();\n }\n\n private placeUtilityFromSelection(): boolean {\n const endpoints = this.currentSelectionEnds();\n if (endpoints == null) {\n return false;\n }\n const target = this.targetForSelectionPoint(endpoints.bottom);\n if (target == null) {\n this.hideUtility();\n } else {\n this.showUtilityOnLine(this.toEventBaseProps(target));\n }\n return true;\n }\n\n private showUtilityOnLine(line: EventBaseProps<TMode>): void {\n if (this.gutterUtilityContainer == null) {\n return;\n }\n this.gutterUtilityLine = line;\n line.numberElement.appendChild(this.gutterUtilityContainer);\n }\n\n private hideUtility(): void {\n this.gutterUtilityContainer?.remove();\n this.gutterUtilityLine = undefined;\n }\n\n // Selection ranges preserve drag direction, so compare rendered row indexes to\n // find the visually top-most and bottom-most endpoints.\n private currentSelectionEnds(): SelectionEnds | undefined {\n const range = this.getCurrentSelectionRange();\n return range == null ? undefined : this.selectionEnds(range);\n }\n\n private selectionEnds(range: SelectedLineRange): SelectionEnds | undefined {\n const start: SelectionPoint = {\n lineNumber: range.start,\n side: range.side,\n };\n const end: SelectionPoint = {\n lineNumber: range.end,\n side: range.endSide ?? range.side,\n };\n const startIndex = this.selectionPointRowIndex(start);\n const endIndex = this.selectionPointRowIndex(end);\n if (startIndex == null || endIndex == null) {\n return undefined;\n }\n return startIndex > endIndex\n ? { top: end, bottom: start }\n : { top: start, bottom: end };\n }\n\n private selectionPointRowIndex(point: SelectionPoint): number | undefined {\n const indexes = this.getLineIndex(point.lineNumber, point.side);\n if (indexes == null) {\n return undefined;\n }\n return this.isSplitDiff() ? indexes[1] : indexes[0];\n }\n\n private targetForSelectionPoint(\n point: SelectionPoint\n ): LinePointerTarget<TMode> | undefined {\n if (this.pre == null) {\n return undefined;\n }\n const indexes = this.getLineIndex(point.lineNumber, point.side);\n if (indexes == null) {\n return undefined;\n }\n const lineIndex =\n this.mode === 'diff' ? `${indexes[0]},${indexes[1]}` : `${indexes[0]}`;\n // Rebuild the real gutter-row target from the selection point so the\n // utility can anchor to the visible row even when the point came from\n // controlled state rather than a pointer event.\n const candidates = this.pre.querySelectorAll(\n `[data-column-number=\"${point.lineNumber}\"][data-line-index=\"${lineIndex}\"]`\n );\n for (const element of candidates) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const target = this.resolvePointerTarget(getElementPath(element));\n if (!isLinePointerTarget(target)) {\n continue;\n }\n if (\n this.mode === 'diff' &&\n point.side != null &&\n target.side !== point.side\n ) {\n continue;\n }\n return target;\n }\n return undefined;\n }\n\n private attachDocumentPointerListeners(): void {\n if (this.hasDocumentPointerListeners) {\n return;\n }\n document.addEventListener('pointermove', this.handleDocumentPointerMove);\n document.addEventListener('pointerup', this.handleDocumentPointerUp);\n document.addEventListener(\n 'pointercancel',\n this.handleDocumentPointerCancel\n );\n this.hasDocumentPointerListeners = true;\n }\n\n private detachDocumentPointerListeners(): void {\n if (!this.hasDocumentPointerListeners) {\n return;\n }\n document.removeEventListener('pointermove', this.handleDocumentPointerMove);\n document.removeEventListener('pointerup', this.handleDocumentPointerUp);\n document.removeEventListener(\n 'pointercancel',\n this.handleDocumentPointerCancel\n );\n this.hasDocumentPointerListeners = false;\n }\n\n private clearPointerSession(): void {\n this.pointerSession = { mode: 'idle' };\n }\n\n private clearPendingSingleLineState(): void {\n if (this.pointerSession.mode === 'pendingSingleLineUnselect') {\n this.pointerSession = { mode: 'idle' };\n }\n }\n\n private selectionInfoFromPath(\n path: (EventTarget | undefined)[],\n requireNumberColumn: boolean\n ): SelectionInfo | undefined {\n const target = this.resolvePointerTarget(path);\n if (!isLinePointerTarget(target)) {\n return undefined;\n }\n if (requireNumberColumn && !target.numberColumn) {\n return undefined;\n }\n if (target.splitLineIndex == null) {\n return undefined;\n }\n\n return {\n lineIndex: target.splitLineIndex,\n lineNumber: target.lineNumber,\n eventSide: this.mode === 'diff' ? target.side : undefined,\n };\n }\n\n private resolveSelectionInfo(\n event: PointerEvent,\n options: SelectionInfoOptions\n ): SelectionInfo | undefined {\n const path = this.resolveSelectionPath(event, options);\n return path != null\n ? this.selectionInfoFromPath(path, options.requireNumberColumn)\n : undefined;\n }\n\n private selectionPointFromPath(\n path: (EventTarget | undefined)[]\n ): SelectionPoint | undefined {\n const target = this.resolvePointerTarget(path);\n if (!isLinePointerTarget(target)) {\n return undefined;\n }\n return {\n lineNumber: target.lineNumber,\n side: this.mode === 'diff' ? target.side : undefined,\n };\n }\n\n private resolveSelectionPoint(\n event: PointerEvent,\n options: SelectionHitOptions\n ): SelectionPoint | undefined {\n const path = this.resolveSelectionPath(event, options);\n return path != null ? this.selectionPointFromPath(path) : undefined;\n }\n\n private resolveSelectionPath(\n event: PointerEvent,\n options: SelectionHitOptions\n ): (EventTarget | undefined)[] | undefined {\n const excludeUtility = options.excludeUtility !== false;\n switch (options.source) {\n case 'event-path':\n return this.pathFromEventPath(event.composedPath(), excludeUtility);\n case 'coordinates-first': {\n // Touch pointers can keep dispatching move/up events to the element\n // where the drag began. Prefer the row currently under the finger,\n // then fall back only when coordinate hit-testing is unavailable.\n const coordinatePath = this.pathFromCoordinates(event, excludeUtility);\n if (coordinatePath !== undefined) {\n return coordinatePath ?? undefined;\n }\n return this.pathFromEventPath(event.composedPath(), excludeUtility);\n }\n }\n }\n\n private pathFromCoordinates(\n event: PointerEvent,\n excludeUtility: boolean\n ): (EventTarget | undefined)[] | null | undefined {\n const coordinateTarget = this.hitTest(event);\n if (coordinateTarget === undefined) {\n return undefined;\n }\n if (coordinateTarget === null) {\n return null;\n }\n // A coordinate hit can be a token span, line-number span, utility overlay,\n // or separator. Normalize valid descendants back to their row; invalid\n // hits intentionally return null so the last selected row stays sticky.\n return this.pathFromElement(coordinateTarget, excludeUtility) ?? null;\n }\n\n private pathFromEventPath(\n path: (EventTarget | undefined)[],\n excludeUtility: boolean\n ): (EventTarget | undefined)[] | undefined {\n if (excludeUtility && isGutterUtilityPath(path)) {\n return undefined;\n }\n for (const element of path) {\n if (element instanceof Element) {\n return this.pathFromElement(element, excludeUtility);\n }\n }\n return undefined;\n }\n\n private pathFromElement(\n element: Element,\n excludeUtility: boolean\n ): (EventTarget | undefined)[] | undefined {\n const path = getElementPath(element);\n if (excludeUtility && isGutterUtilityPath(path)) {\n return undefined;\n }\n // Selection is row-based, not child-element-based. Lateral movement over\n // tokens, annotations, or line-number text should still update to the\n // nearest content or gutter row; anything else is ignored by returning\n // undefined.\n const row = closestSelectableRow(element);\n if (row != null) {\n return getElementPath(row);\n }\n return this.pathFromAnnotationSlot(element);\n }\n\n private pathFromAnnotationSlot(\n element: Element\n ): (EventTarget | undefined)[] | undefined {\n const point = selectionPointFromAnnotationSlotName(\n getAnnotationSlotName(element)\n );\n if (point == null) {\n return undefined;\n }\n const target = this.targetForSelectionPoint(point);\n return target != null ? getElementPath(target.lineElement) : undefined;\n }\n\n private hitTest(event: PointerEvent): Element | null | undefined {\n // Return undefined when coordinate hit-testing cannot run at all, which\n // allows callers to fall back to the event path for tests and older DOMs.\n // Return null when hit-testing ran but found no element, so active drags\n // keep their previous endpoint instead of using a stale captured target.\n if (!Number.isFinite(event.clientX) || !Number.isFinite(event.clientY)) {\n return undefined;\n }\n const root = this.pre?.getRootNode();\n const elementFromPointRoot = hasElementFromPoint(root)\n ? root\n : hasElementFromPoint(document)\n ? document\n : undefined;\n if (elementFromPointRoot == null) {\n return undefined;\n }\n const element = elementFromPointRoot.elementFromPoint(\n event.clientX,\n event.clientY\n );\n return element;\n }\n\n private getLineIndex(\n lineNumber: number,\n side?: SelectionSide\n ): [number, number] | undefined {\n const { getLineIndex } = this.options;\n return getLineIndex != null\n ? getLineIndex(lineNumber, side)\n : [lineNumber - 1, lineNumber - 1];\n }\n\n private getCurrentSelectionRange(): SelectedLineRange | null {\n return this.proposedSelectedRange !== undefined\n ? this.proposedSelectedRange\n : this.selectedRange;\n }\n\n private clearProposedSelection(): void {\n this.proposedSelectedRange = undefined;\n }\n\n private updateSelection(\n currentLine: number | null,\n side?: SelectionSide,\n emitChange = true\n ): void {\n const previousRange = this.getCurrentSelectionRange();\n let nextRange: SelectedLineRange | null;\n if (currentLine == null) {\n nextRange = null;\n } else {\n const anchorSide = this.selectionAnchor?.side ?? side;\n const anchorLine = this.selectionAnchor?.lineNumber ?? currentLine;\n nextRange = this.buildSelectionRange(\n anchorLine,\n currentLine,\n anchorSide,\n side\n );\n }\n if (\n areSelectionsEqual(previousRange ?? undefined, nextRange ?? undefined)\n ) {\n return;\n }\n if (this.options.controlledSelection === true) {\n this.proposedSelectedRange = nextRange;\n } else {\n this.selectedRange = nextRange;\n this.queuedSelectionRender ??= requestAnimationFrame(\n this.renderSelection\n );\n }\n this.placeUtility();\n if (emitChange) {\n this.notifySelectionChangeDelta();\n }\n }\n\n private getIndexesFromSelection(\n selectedRange: SelectedLineRange,\n split: boolean\n ): { start: number; end: number } | undefined {\n if (this.pre == null) {\n return undefined;\n }\n const startIndexes = this.getLineIndex(\n selectedRange.start,\n selectedRange.side\n );\n const finalIndexes = this.getLineIndex(\n selectedRange.end,\n selectedRange.endSide ?? selectedRange.side\n );\n\n return startIndexes != null && finalIndexes != null\n ? {\n start: split ? startIndexes[1] : startIndexes[0],\n end: split ? finalIndexes[1] : finalIndexes[0],\n }\n : undefined;\n }\n\n private renderSelection = (): void => {\n if (this.queuedSelectionRender != null) {\n cancelAnimationFrame(this.queuedSelectionRender);\n this.queuedSelectionRender = undefined;\n }\n if (\n this.pre == null ||\n this.renderedSelectionRange === this.selectedRange\n ) {\n return;\n }\n\n const allSelected = this.pre.querySelectorAll('[data-selected-line]');\n for (const element of allSelected) {\n element.removeAttribute('data-selected-line');\n }\n\n this.renderedSelectionRange = this.selectedRange;\n if (this.selectedRange == null) {\n return;\n }\n\n const { children: codeElements } = this.pre;\n if (codeElements.length === 0) {\n return;\n }\n if (codeElements.length > 2) {\n console.error(codeElements);\n throw new Error(\n 'InteractionManager.renderSelection: Somehow there are more than 2 code elements...'\n );\n }\n const split = this.pre.getAttribute('data-diff-type') === 'split';\n const rowRange = this.getIndexesFromSelection(this.selectedRange, split);\n if (rowRange == null) {\n console.error({ rowRange, selectedRange: this.selectedRange });\n throw new Error('InteractionManager.renderSelection: No valid rowRange');\n }\n const isSingle = rowRange.start === rowRange.end;\n const first = Math.min(rowRange.start, rowRange.end);\n const last = Math.max(rowRange.start, rowRange.end);\n for (const code of codeElements) {\n const [gutter, content] = code.children;\n const len = content.children.length;\n if (len !== gutter.children.length) {\n throw new Error(\n 'InteractionManager.renderSelection: gutter and content children dont match, something is wrong'\n );\n }\n for (let i = 0; i < len; i++) {\n const contentElement = content.children[i];\n const gutterElement = gutter.children[i];\n if (\n !(contentElement instanceof HTMLElement) ||\n !(gutterElement instanceof HTMLElement)\n ) {\n continue;\n }\n\n const lineIndex = this.parseLineIndex(contentElement, split);\n if ((lineIndex ?? 0) > last) {\n break;\n }\n if (lineIndex == null || lineIndex < first) {\n continue;\n }\n let attributeValue = isSingle\n ? 'single'\n : lineIndex === first\n ? 'first'\n : lineIndex === last\n ? 'last'\n : '';\n contentElement.setAttribute('data-selected-line', attributeValue);\n gutterElement.setAttribute('data-selected-line', attributeValue);\n if (\n gutterElement.nextSibling instanceof HTMLElement &&\n contentElement.nextSibling instanceof HTMLElement &&\n (contentElement.nextSibling.hasAttribute('data-line-annotation') ||\n contentElement.nextSibling.hasAttribute(\n 'data-merge-conflict-actions'\n ))\n ) {\n if (isSingle) {\n attributeValue = 'last';\n contentElement.setAttribute('data-selected-line', 'first');\n } else if (lineIndex === first) {\n attributeValue = '';\n } else if (lineIndex === last) {\n contentElement.setAttribute('data-selected-line', '');\n }\n contentElement.nextSibling.setAttribute(\n 'data-selected-line',\n attributeValue\n );\n gutterElement.nextSibling.setAttribute(\n 'data-selected-line',\n attributeValue\n );\n }\n }\n }\n };\n\n private notifySelectionCommitted(): void {\n this.options.onLineSelected?.(this.getCurrentSelectionRange() ?? null);\n }\n\n private notifySelectionChangeDelta(): void {\n this.options.onLineSelectionChange?.(\n this.getCurrentSelectionRange() ?? null\n );\n }\n\n private notifySelectionStart(range: SelectedLineRange | null): void {\n this.options.onLineSelectionStart?.(range);\n }\n\n private notifySelectionEnd(range: SelectedLineRange | null): void {\n this.options.onLineSelectionEnd?.(range);\n }\n\n private toEventBaseProps(\n target: HoverableLinePointerTarget<TMode>\n ): EventBaseProps<TMode> {\n if (this.mode === 'file') {\n return {\n type: 'line',\n lineElement: target.lineElement,\n lineNumber: target.lineNumber,\n numberColumn: target.numberColumn,\n numberElement: target.numberElement,\n } as EventBaseProps<TMode>;\n }\n\n return {\n type: 'diff-line',\n annotationSide: target.side as AnnotationSide,\n lineType: target.lineType,\n lineElement: target.lineElement,\n numberElement: target.numberElement,\n lineNumber: target.lineNumber,\n numberColumn: target.numberColumn,\n } as EventBaseProps<TMode>;\n }\n\n private toTokenEventBaseProps({\n lineCharEnd,\n lineCharStart,\n lineNumber,\n side,\n tokenElement,\n tokenText,\n }: TokenPointerTarget<TMode>): OnTokenEventProps<TMode> {\n if (this.mode === 'file') {\n return {\n type: 'token',\n lineCharEnd,\n lineCharStart,\n lineNumber,\n tokenElement,\n tokenText,\n } as OnTokenEventProps<TMode>;\n }\n\n return {\n type: 'token',\n lineCharEnd,\n lineCharStart,\n lineNumber,\n side,\n tokenElement,\n tokenText,\n } as OnTokenEventProps<TMode>;\n }\n\n private buildSelectedLineRange(\n anchor: SelectionPoint,\n current: SelectionPoint\n ): SelectedLineRange {\n return this.buildSelectionRange(\n anchor.lineNumber,\n current.lineNumber,\n anchor.side,\n current.side\n );\n }\n\n private buildSelectionRange(\n start: number,\n end: number,\n side?: SelectionSide,\n endSide?: SelectionSide\n ): SelectedLineRange {\n return {\n start,\n end,\n ...(side != null ? { side } : {}),\n ...(side !== endSide && endSide != null ? { endSide } : {}),\n };\n }\n\n private resolvePointerTarget(\n path: (EventTarget | undefined)[]\n ): ResolvedPointerTarget<TMode> | undefined {\n let numberColumn = false;\n let lineType: LineTypes | undefined;\n let codeElement: HTMLElement | undefined;\n let lineElement: HTMLElement | undefined;\n let lineIndexValue: string | undefined;\n let numberElement: HTMLElement | undefined;\n let tokenElement: HTMLElement | undefined;\n let tokenInfo: TokenCache | undefined;\n let expandInfo: ExpandCache | undefined;\n let lineNumber: number | undefined;\n let mergeConflictActionTarget: MergeConflictActionTarget | undefined;\n\n for (const element of path) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n\n if (\n mergeConflictActionTarget == null &&\n element.hasAttribute('data-merge-conflict-action')\n ) {\n const resolutionValue =\n element.getAttribute('data-merge-conflict-action') ?? undefined;\n const conflictIndexValue =\n element.getAttribute('data-merge-conflict-conflict-index') ??\n undefined;\n const conflictIndex =\n conflictIndexValue != null\n ? Number.parseInt(conflictIndexValue, 10)\n : Number.NaN;\n if (\n isMergeConflictResolution(resolutionValue) &&\n Number.isFinite(conflictIndex)\n ) {\n mergeConflictActionTarget = {\n kind: 'merge-conflict-action',\n resolution: resolutionValue,\n conflictIndex,\n };\n }\n }\n\n if (tokenElement == null && element.hasAttribute('data-char')) {\n tokenElement = element;\n const startAttr = element.getAttribute('data-char');\n\n if (startAttr != null) {\n const lineCharStart = Number.parseInt(startAttr, 10);\n if (!Number.isNaN(lineCharStart)) {\n const tokenText = element.textContent ?? '';\n const lineCharEnd = lineCharStart + tokenText.length;\n if (\n tokenText.trim() !== '' ||\n this.options.enableTokenInteractionsOnWhitespace === true\n ) {\n tokenInfo = {\n tokenElement,\n lineCharStart,\n lineCharEnd,\n tokenText,\n };\n }\n continue;\n }\n }\n }\n\n const columnNumber =\n numberElement == null\n ? (element.getAttribute('data-column-number') ?? undefined)\n : undefined;\n if (columnNumber != null) {\n numberElement = element;\n lineNumber = Number.parseInt(columnNumber, 10);\n numberColumn = true;\n lineType = getLineTypeFromElement(element);\n lineIndexValue = element.getAttribute('data-line-index') ?? undefined;\n continue;\n }\n\n const lineAttr =\n lineElement == null\n ? (element.getAttribute('data-line') ?? undefined)\n : undefined;\n if (lineAttr != null) {\n lineElement = element;\n lineNumber = Number.parseInt(lineAttr, 10);\n lineType = getLineTypeFromElement(element);\n lineIndexValue = element.getAttribute('data-line-index') ?? undefined;\n continue;\n }\n\n if (\n expandInfo == null &&\n (element.hasAttribute('data-expand-button') ||\n element.hasAttribute('data-unmodified-lines'))\n ) {\n expandInfo = {\n hunkIndex: undefined,\n direction: (() => {\n if (element.hasAttribute('data-expand-up')) {\n return 'up';\n }\n if (element.hasAttribute('data-expand-down')) {\n return 'down';\n }\n return 'both';\n })(),\n all: element.hasAttribute('data-expand-all-button'),\n };\n continue;\n }\n\n const expandIndexValue =\n expandInfo != null\n ? (element.getAttribute('data-expand-index') ?? undefined)\n : undefined;\n if (expandInfo != null && expandIndexValue != null) {\n const expandIndex = Number.parseInt(expandIndexValue, 10);\n if (!Number.isNaN(expandIndex)) {\n expandInfo.hunkIndex = expandIndex;\n }\n continue;\n }\n\n if (codeElement == null && element.hasAttribute('data-code')) {\n codeElement = element;\n break;\n }\n }\n\n if (mergeConflictActionTarget != null) {\n return mergeConflictActionTarget as ResolvedPointerTarget<TMode>;\n }\n\n if (expandInfo?.hunkIndex != null) {\n return {\n type: 'line-info',\n hunkIndex: expandInfo.hunkIndex,\n direction: expandInfo.direction,\n all: expandInfo.all,\n } as ResolvedPointerTarget<TMode>;\n }\n\n lineElement ??=\n lineIndexValue != null\n ? queryHTMLElement(\n codeElement,\n `[data-line][data-line-index=\"${lineIndexValue}\"]`\n )\n : undefined;\n numberElement ??=\n lineIndexValue != null\n ? queryHTMLElement(\n codeElement,\n `[data-column-number][data-line-index=\"${lineIndexValue}\"]`\n )\n : undefined;\n\n if (\n codeElement == null ||\n lineElement == null ||\n numberElement == null ||\n lineType == null ||\n lineNumber == null ||\n Number.isNaN(lineNumber)\n ) {\n return undefined;\n }\n\n const splitLineIndex = this.parseLineIndex(lineElement, this.isSplitDiff());\n\n if (tokenInfo != null) {\n if (this.mode === 'file') {\n return {\n kind: 'token',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: undefined,\n splitLineIndex,\n ...tokenInfo,\n } as ResolvedPointerTarget<TMode>;\n }\n\n return {\n kind: 'token',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: getAnnotationSide(lineType, codeElement),\n splitLineIndex,\n ...tokenInfo,\n } as ResolvedPointerTarget<TMode>;\n }\n\n // Otherwise return line target\n if (this.mode === 'file') {\n return {\n kind: 'line',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: undefined,\n splitLineIndex,\n } as ResolvedPointerTarget<TMode>;\n }\n\n return {\n kind: 'line',\n lineType,\n lineElement,\n lineNumber,\n numberColumn,\n numberElement,\n side: getAnnotationSide(lineType, codeElement),\n splitLineIndex,\n } as ResolvedPointerTarget<TMode>;\n }\n\n private isSplitDiff(): boolean {\n return this.pre?.getAttribute('data-diff-type') === 'split';\n }\n\n private parseLineIndex(\n element: HTMLElement,\n split: boolean\n ): number | undefined {\n const lineIndexes = (element.getAttribute('data-line-index') ?? '')\n .split(',')\n .map((value) => Number.parseInt(value, 10))\n .filter((value) => !Number.isNaN(value));\n\n if (split && lineIndexes.length === 2) {\n return lineIndexes[1];\n }\n if (!split) {\n return lineIndexes[0];\n }\n return undefined;\n }\n}\n\ntype InteractionPluckOptions<TMode extends InteractionManagerMode> =\n InteractionManagerBaseOptions<TMode> & {\n renderGutterUtility?(\n getHoveredRow: () => GetHoveredLineResult<TMode> | undefined\n ): HTMLElement | null | undefined;\n };\n\nexport function pluckInteractionOptions<TMode extends InteractionManagerMode>(\n {\n enableTokenInteractionsOnWhitespace,\n enableGutterUtility,\n lineHoverHighlight,\n onGutterUtilityClick,\n onLineClick,\n onLineEnter,\n onLineLeave,\n onLineNumberClick,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n renderGutterUtility,\n __debugPointerEvents,\n enableLineSelection,\n controlledSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionChange,\n onLineSelectionEnd,\n }: InteractionPluckOptions<TMode>,\n onHunkExpand?: (\n hunkIndex: number,\n direction: ExpansionDirections,\n expansionLineCountOverride?: number\n ) => unknown,\n getLineIndex?: GetLineIndexUtility,\n onMergeConflictActionClick?: (target: MergeConflictActionTarget) => void\n): InteractionManagerOptions<TMode> {\n return {\n enableTokenInteractionsOnWhitespace,\n enableGutterUtility: resolveEnableGutterUtilityOption({\n enableGutterUtility,\n renderGutterUtility,\n onGutterUtilityClick,\n }),\n usesCustomGutterUtility: renderGutterUtility != null,\n lineHoverHighlight,\n\n onGutterUtilityClick,\n onHunkExpand,\n onMergeConflictActionClick,\n onLineClick,\n onLineEnter,\n onLineLeave,\n onLineNumberClick,\n onTokenClick,\n onTokenEnter,\n onTokenLeave,\n __debugPointerEvents,\n\n enableLineSelection,\n controlledSelection,\n onLineSelected,\n onLineSelectionStart,\n onLineSelectionChange,\n onLineSelectionEnd,\n\n getLineIndex,\n };\n}\n\nfunction resolveEnableGutterUtilityOption<\n TMode extends InteractionManagerMode,\n>({\n enableGutterUtility,\n renderGutterUtility,\n onGutterUtilityClick,\n}: Pick<\n InteractionPluckOptions<TMode>,\n 'enableGutterUtility' | 'renderGutterUtility' | 'onGutterUtilityClick'\n>): boolean {\n if (onGutterUtilityClick != null && renderGutterUtility != null) {\n throw new Error(\n \"Cannot use both 'onGutterUtilityClick' and 'renderGutterUtility'. Use only one gutter utility API.\"\n );\n }\n return enableGutterUtility ?? false;\n}\n\nfunction isLinePointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode> | undefined\n): target is LinePointerTarget<TMode> {\n return target != null && 'kind' in target && target.kind === 'line';\n}\n\nfunction isTokenPointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode> | undefined\n): target is TokenPointerTarget<TMode> {\n return target != null && 'kind' in target && target.kind === 'token';\n}\n\nfunction isHoverableLinePointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode> | undefined\n): target is HoverableLinePointerTarget<TMode> {\n return isLinePointerTarget(target) || isTokenPointerTarget(target);\n}\n\nfunction isExpandoPointerTarget<TMode extends InteractionManagerMode>(\n target: ResolvedPointerTarget<TMode>\n): target is ExpandoEventProps {\n return 'type' in target && target.type === 'line-info';\n}\n\nfunction isMergeConflictActionPointerTarget<\n TMode extends InteractionManagerMode,\n>(target: ResolvedPointerTarget<TMode>): target is MergeConflictActionTarget {\n return 'kind' in target && target.kind === 'merge-conflict-action';\n}\n\nfunction isMergeConflictResolution(\n value: string | undefined\n): value is MergeConflictResolution {\n return value === 'current' || value === 'incoming' || value === 'both';\n}\n\nfunction queryHTMLElement(\n parent: HTMLElement | undefined,\n query: string\n): HTMLElement | undefined {\n const element = parent?.querySelector(query);\n return element instanceof HTMLElement ? element : undefined;\n}\n\nfunction getElementPath(element: Node): EventTarget[] {\n const path: EventTarget[] = [];\n let current: Node | null = element;\n while (current != null) {\n path.push(current);\n current = current.parentNode;\n }\n return path;\n}\n\n// Pointer hits often land on text/token descendants. This normalizes those\n// hits back to the row elements InteractionManager knows how to resolve.\nfunction closestSelectableRow(element: Element): HTMLElement | undefined {\n const row = element.closest('[data-line], [data-column-number]');\n if (row instanceof HTMLElement) {\n return row;\n }\n\n const annotationRow = element.closest(\n '[data-line-annotation], [data-gutter-buffer=\"annotation\"]'\n );\n if (!(annotationRow instanceof HTMLElement)) {\n return undefined;\n }\n\n const previousRow = annotationRow.previousElementSibling;\n return previousRow instanceof HTMLElement &&\n (previousRow.hasAttribute('data-line') ||\n previousRow.hasAttribute('data-column-number'))\n ? previousRow\n : undefined;\n}\n\nfunction getAnnotationSlotName(element: Element): string | undefined {\n const slottedElement = element.closest('[slot^=\"annotation-\"]');\n if (slottedElement instanceof HTMLElement) {\n return slottedElement.getAttribute('slot') ?? undefined;\n }\n\n if (element instanceof HTMLElement) {\n const slotName = element.getAttribute('name') ?? undefined;\n return slotName != null && slotName.startsWith('annotation-')\n ? slotName\n : undefined;\n }\n\n return undefined;\n}\n\nfunction selectionPointFromAnnotationSlotName(\n slotName: string | undefined\n): SelectionPoint | undefined {\n if (slotName == null) {\n return undefined;\n }\n\n const match = /^annotation-(?:(additions|deletions)-)?(\\d+)$/.exec(slotName);\n if (match == null) {\n return undefined;\n }\n\n const lineNumber = Number.parseInt(match[2], 10);\n if (!Number.isFinite(lineNumber) || lineNumber <= 0) {\n return undefined;\n }\n\n const side = match[1] as SelectionSide | undefined;\n return { lineNumber, side };\n}\n\ninterface ElementFromPointRoot {\n elementFromPoint(x: number, y: number): Element | null;\n}\n\nfunction hasElementFromPoint(\n value: Node | undefined\n): value is Node & ElementFromPointRoot {\n return (\n value != null &&\n typeof (value as Partial<ElementFromPointRoot>).elementFromPoint ===\n 'function'\n );\n}\n\nfunction getAnnotationSide(\n lineType: LineTypes,\n codeElement: HTMLElement\n): AnnotationSide {\n switch (lineType) {\n case 'change-deletion':\n return 'deletions';\n case 'change-addition':\n return 'additions';\n default:\n return codeElement.hasAttribute('data-deletions')\n ? 'deletions'\n : 'additions';\n }\n}\n\nfunction getLineTypeFromElement(element: HTMLElement): LineTypes | undefined {\n const lineType = element.getAttribute('data-line-type');\n if (lineType == null) {\n return undefined;\n }\n switch (lineType) {\n case 'change-deletion':\n case 'change-addition':\n case 'context':\n case 'context-expanded':\n return lineType;\n default:\n return undefined;\n }\n}\n\nfunction isGutterUtilityPath(path: (EventTarget | undefined)[]): boolean {\n for (const element of path) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n if (\n element.hasAttribute('data-utility-button') ||\n element.hasAttribute('data-gutter-utility-slot') ||\n // Custom React/DOM utilities are slotted into the same utility surface,\n // so treat both the assigned content and the slot node itself as\n // utility hits.\n element.getAttribute('slot') === 'gutter-utility-slot' ||\n element.getAttribute('name') === 'gutter-utility-slot'\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction debugLogIfEnabled(\n debugLogType: LogTypes | undefined = 'none',\n logIfType: 'move' | 'click',\n ...args: unknown[]\n) {\n switch (debugLogType) {\n case 'none':\n return;\n case 'both':\n break;\n case 'click':\n if (logIfType !== 'click') {\n return;\n }\n break;\n case 'move':\n if (logIfType !== 'move') {\n return;\n }\n break;\n }\n console.log(...args);\n}\n"],"mappings":"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"}
|
|
@@ -76,7 +76,7 @@ var ResizeManager = class ResizeManager {
|
|
|
76
76
|
for (const element of annotationElements) {
|
|
77
77
|
if (!(element instanceof HTMLElement)) continue;
|
|
78
78
|
const lineAnnotation = element.getAttribute("data-line-annotation") ?? "";
|
|
79
|
-
if (
|
|
79
|
+
if (!/^-?\d+,-?\d+$/.test(lineAnnotation)) {
|
|
80
80
|
console.error("DiffFileRenderer.setupResizeObserver: Invalid element or annotation", {
|
|
81
81
|
lineAnnotation,
|
|
82
82
|
element
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResizeManager.js","names":["codeElement: HTMLElement | undefined","item: ObservedGridNodes | ObservedAnnotationNodes | undefined","codeUpdates: CodeUpdateMap","annotationUpdates: Set<ObservedAnnotationNodes>"],"sources":["../../src/managers/ResizeManager.ts"],"sourcesContent":["import type { ObservedAnnotationNodes, ObservedGridNodes } from '../types';\n\ninterface CodeColumnUpdate {\n codeInlineSize?: number;\n numberInlineSize?: number;\n measuredNumberInlineSize?: number;\n}\n\ntype CodeUpdateMap = Map<ObservedGridNodes, CodeColumnUpdate>;\n\ninterface AnnotationSetup {\n child1: HTMLElement;\n child2: HTMLElement;\n item: ObservedAnnotationNodes;\n newHeight: number;\n}\n\nexport class ResizeManager {\n // Shared static resizeObserver that all ResizeManagers use\n private static resizeObserver: ResizeObserver | undefined;\n private static managersByElement = new Map<Element, ResizeManager>();\n\n private static getResizeObserver(): ResizeObserver {\n const resizeObserver =\n ResizeManager.resizeObserver ??\n new ResizeObserver(ResizeManager.handleSharedResizeEntries);\n ResizeManager.resizeObserver = resizeObserver;\n return resizeObserver;\n }\n\n private static handleSharedResizeEntries(entries: ResizeObserverEntry[]) {\n // First we need to batch all elements by manager, so callbacks are\n // properly aligned with a per-instance ResizeManager\n const entriesByManager = new Map<ResizeManager, ResizeObserverEntry[]>();\n for (const entry of entries) {\n const manager = ResizeManager.managersByElement.get(entry.target);\n if (manager == null) {\n continue;\n }\n const managerEntries = entriesByManager.get(manager);\n if (managerEntries == null) {\n entriesByManager.set(manager, [entry]);\n } else {\n managerEntries.push(entry);\n }\n }\n\n for (const [manager, managerEntries] of entriesByManager) {\n manager.handleResizeEntries(managerEntries);\n }\n }\n\n private observedNodes = new Map<\n HTMLElement,\n ObservedAnnotationNodes | ObservedGridNodes\n >();\n\n setup(pre: HTMLPreElement, disableAnnotations: boolean): void {\n const annotationUpdates = new Set<AnnotationSetup>();\n let columnCount = 0;\n const observedNodes = new Map(this.observedNodes);\n this.observedNodes.clear();\n\n for (const element of pre.children) {\n if (columnCount === 2) {\n break;\n }\n const codeElement: HTMLElement | undefined = (() => {\n if (element instanceof HTMLElement && element.tagName === 'CODE') {\n return element;\n }\n return undefined;\n })();\n if (codeElement == null) {\n continue;\n }\n columnCount++;\n let item: ObservedGridNodes | ObservedAnnotationNodes | undefined =\n observedNodes.get(codeElement);\n if (item != null && item.type !== 'code') {\n throw new Error(\n 'ResizeManager.setup: somehow a code node is being used for an annotation, should be impossible'\n );\n }\n\n let numberElement = codeElement.firstElementChild;\n if (!(numberElement instanceof HTMLElement)) {\n numberElement = null;\n }\n if (item != null) {\n this.observedNodes.set(codeElement, item);\n observedNodes.delete(codeElement);\n if (item.numberElement !== numberElement) {\n if (item.numberElement != null) {\n this.unobserve(item.numberElement);\n observedNodes.delete(item.numberElement);\n }\n if (numberElement != null) {\n this.observe(numberElement);\n observedNodes.delete(numberElement);\n this.observedNodes.set(numberElement, item);\n }\n item.numberElement = numberElement;\n item.numberWidth = 0;\n } else if (item.numberElement != null) {\n observedNodes.delete(item.numberElement);\n this.observedNodes.set(item.numberElement, item);\n // If there is a resize, let the resize handler handle it...\n } else {\n item.numberWidth = 0;\n }\n } else {\n item = {\n type: 'code',\n codeElement,\n numberElement,\n codeWidth: 'auto',\n numberWidth: 0,\n };\n this.observedNodes.set(codeElement, item);\n this.observe(codeElement);\n if (numberElement != null) {\n this.observedNodes.set(numberElement, item);\n this.observe(numberElement);\n }\n }\n }\n\n if (columnCount > 1 && !disableAnnotations) {\n const annotationElements = pre.querySelectorAll(\n '[data-line-annotation*=\",\"]'\n );\n\n const elementMap = new Map<string, HTMLElement[]>();\n // Iterate through all the matched elements and organize them into pairs\n // based on the data-line-annotation attribute\n for (const element of annotationElements) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const lineAnnotation =\n element.getAttribute('data-line-annotation') ?? '';\n if (!/^\\d+,\\d+$/.test(lineAnnotation)) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Invalid element or annotation',\n { lineAnnotation, element }\n );\n continue;\n }\n let pairs = elementMap.get(lineAnnotation);\n if (pairs == null) {\n pairs = [];\n elementMap.set(lineAnnotation, pairs);\n }\n pairs.push(element);\n }\n\n for (const [key, pair] of elementMap) {\n if (pair.length !== 2) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Bad Pair',\n key,\n pair\n );\n continue;\n }\n const [container1, container2] = pair;\n const child1 = container1.firstElementChild;\n const child2 = container2.firstElementChild;\n if (\n !(container1 instanceof HTMLElement) ||\n !(container2 instanceof HTMLElement) ||\n !(child1 instanceof HTMLElement) ||\n !(child2 instanceof HTMLElement)\n ) {\n continue;\n }\n\n let item = observedNodes.get(child1);\n\n if (item != null) {\n this.observedNodes.set(child1, item);\n this.observedNodes.set(child2, item);\n observedNodes.delete(child1);\n observedNodes.delete(child2);\n continue;\n }\n\n const child1Height = child1.getBoundingClientRect().height;\n const child2Height = child2.getBoundingClientRect().height;\n item = {\n type: 'annotations',\n column1: {\n container: container1,\n child: child1,\n childHeight: child1Height,\n },\n column2: {\n container: container2,\n child: child2,\n childHeight: child2Height,\n },\n currentHeight: 'auto',\n };\n annotationUpdates.add({\n child1,\n child2,\n item,\n newHeight: Math.max(child1Height, child2Height),\n });\n }\n\n // Measure all annotation heights first, then apply the paired min-height\n // styles after the read phase so setup does not bounce between layout\n // reads and writes for every annotation pair.\n for (const pendingUpdate of annotationUpdates) {\n this.applyNewHeight(pendingUpdate.item, pendingUpdate.newHeight);\n this.observedNodes.set(pendingUpdate.child1, pendingUpdate.item);\n this.observedNodes.set(pendingUpdate.child2, pendingUpdate.item);\n this.observe(pendingUpdate.child1);\n this.observe(pendingUpdate.child2);\n }\n annotationUpdates.clear();\n }\n\n // Cleanup any old nodes that might still be observed\n for (const [element, item] of observedNodes) {\n this.unobserve(element);\n if (item.type === 'code') {\n cleanupStaleCodeItem(item);\n } else {\n cleanupStaleAnnotationItem(item);\n }\n }\n observedNodes.clear();\n }\n\n cleanUp(): void {\n for (const element of this.observedNodes.keys()) {\n this.unobserve(element);\n }\n this.observedNodes.clear();\n }\n\n private observe(element: HTMLElement): void {\n const { managersByElement } = ResizeManager;\n const owner = managersByElement.get(element);\n // Already registered\n if (owner === this) {\n return;\n }\n // If we've already somehow registered with another manager, we in for a\n // world of pain, so complain loudly\n else if (owner != null && owner !== this) {\n throw new Error(\n 'ResizeManager.observe: element is already owned by another ResizeManager'\n );\n }\n managersByElement.set(element, this);\n ResizeManager.getResizeObserver().observe(element);\n }\n\n private unobserve(element: HTMLElement): void {\n const { managersByElement, resizeObserver } = ResizeManager;\n const owner = managersByElement.get(element);\n if (owner == null) {\n return;\n } else if (owner !== this) {\n throw new Error(\n 'ResizeManager.unobserve: element is owned by another ResizeManager'\n );\n }\n\n managersByElement.delete(element);\n resizeObserver?.unobserve(element);\n if (resizeObserver != null && managersByElement.size === 0) {\n resizeObserver.disconnect();\n ResizeManager.resizeObserver = undefined;\n }\n }\n\n private handleResizeEntries(entries: ResizeObserverEntry[]) {\n const codeUpdates: CodeUpdateMap = new Map();\n const annotationUpdates: Set<ObservedAnnotationNodes> = new Set();\n for (const entry of entries) {\n const { target, borderBoxSize, contentBoxSize } = entry;\n if (!(target instanceof HTMLElement)) {\n console.error(\n 'ResizeManager.handleResizeEntries: Invalid element for ResizeObserver',\n entry\n );\n continue;\n }\n const item = this.observedNodes.get(target);\n if (item == null) {\n console.error(\n 'ResizeManager.handleResizeEntries: Not a valid observed node',\n entry\n );\n continue;\n }\n if (item.type === 'annotations') {\n const column = (() => {\n if (target === item.column1.child) {\n return item.column1;\n }\n if (target === item.column2.child) {\n return item.column2;\n }\n return undefined;\n })();\n\n if (column == null) {\n console.error(\n `ResizeManager.handleResizeEntries: Couldn't find a column for`,\n { item, target }\n );\n continue;\n }\n\n column.childHeight = borderBoxSize[0].blockSize;\n annotationUpdates.add(item);\n } else if (item.type === 'code') {\n const update = codeUpdates.get(item) ?? {};\n const inlineSize = contentBoxSize[0].inlineSize;\n if (target === item.codeElement) {\n update.codeInlineSize = inlineSize;\n } else if (target === item.numberElement) {\n update.numberInlineSize = inlineSize;\n }\n codeUpdates.set(item, update);\n }\n }\n this.applyAnnotationUpdates(annotationUpdates);\n annotationUpdates.clear();\n this.applyColumnUpdates(codeUpdates);\n codeUpdates.clear();\n }\n\n private applyAnnotationUpdates(\n annotationUpdates: Set<ObservedAnnotationNodes>\n ) {\n for (const item of annotationUpdates) {\n this.applyNewHeight(\n item,\n Math.max(item.column1.childHeight, item.column2.childHeight)\n );\n }\n }\n\n private applyColumnUpdates = (queuedUpdates: CodeUpdateMap) => {\n for (const [item, update] of queuedUpdates) {\n const nextCodeWidth =\n update.codeInlineSize != null\n ? resolveCodeWidth(update.codeInlineSize)\n : item.codeWidth;\n const nextNumberWidth =\n update.numberInlineSize != null\n ? resolveNumberWidth(update.numberInlineSize)\n : item.numberWidth;\n const codeWidthChanged = nextCodeWidth !== item.codeWidth;\n const numberWidthChanged = nextNumberWidth !== item.numberWidth;\n\n if (!codeWidthChanged && !numberWidthChanged) {\n continue;\n }\n\n item.codeWidth = nextCodeWidth;\n item.numberWidth = nextNumberWidth;\n\n if (codeWidthChanged) {\n item.codeElement.style.setProperty(\n '--diffs-column-width',\n `${typeof nextCodeWidth === 'number' ? `${nextCodeWidth}px` : 'auto'}`\n );\n }\n\n if (numberWidthChanged) {\n item.codeElement.style.setProperty(\n '--diffs-column-number-width',\n `${nextNumberWidth === 0 ? 'auto' : `${nextNumberWidth}px`}`\n );\n }\n\n if (\n codeWidthChanged ||\n (numberWidthChanged && nextCodeWidth !== 'auto')\n ) {\n const targetWidth =\n typeof nextCodeWidth === 'number'\n ? Math.max(nextCodeWidth - nextNumberWidth, 0)\n : 0;\n item.codeElement.style.setProperty(\n '--diffs-column-content-width',\n `${targetWidth > 0 ? `${targetWidth}px` : 'auto'}`\n );\n }\n }\n };\n\n private applyNewHeight(item: ObservedAnnotationNodes, newHeight: number) {\n if (newHeight !== item.currentHeight) {\n item.currentHeight = Math.max(newHeight, 0);\n item.column1.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n item.column2.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n }\n }\n}\n\nfunction resolveCodeWidth(inlineSize: number): number | 'auto' {\n const width = Math.max(Math.floor(inlineSize), 0);\n return width === 0 ? 'auto' : width;\n}\n\nfunction resolveNumberWidth(inlineSize: number): number {\n return Math.max(Math.ceil(inlineSize), 0);\n}\n\nfunction cleanupStaleCodeItem(item: ObservedGridNodes): void {\n if (item.codeElement.isConnected) {\n item.codeElement.style.removeProperty('--diffs-column-content-width');\n item.codeElement.style.removeProperty('--diffs-column-number-width');\n item.codeElement.style.removeProperty('--diffs-column-width');\n }\n}\n\nfunction cleanupStaleAnnotationItem(item: ObservedAnnotationNodes): void {\n if (item.column1.container.isConnected) {\n item.column1.container.style.removeProperty(\n '--diffs-annotation-min-height'\n );\n }\n if (item.column2.container.isConnected) {\n item.column2.container.style.removeProperty(\n '--diffs-annotation-min-height'\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ResizeManager.js","names":["codeElement: HTMLElement | undefined","item: ObservedGridNodes | ObservedAnnotationNodes | undefined","codeUpdates: CodeUpdateMap","annotationUpdates: Set<ObservedAnnotationNodes>"],"sources":["../../src/managers/ResizeManager.ts"],"sourcesContent":["import type { ObservedAnnotationNodes, ObservedGridNodes } from '../types';\n\ninterface CodeColumnUpdate {\n codeInlineSize?: number;\n numberInlineSize?: number;\n measuredNumberInlineSize?: number;\n}\n\ntype CodeUpdateMap = Map<ObservedGridNodes, CodeColumnUpdate>;\n\ninterface AnnotationSetup {\n child1: HTMLElement;\n child2: HTMLElement;\n item: ObservedAnnotationNodes;\n newHeight: number;\n}\n\nexport class ResizeManager {\n // Shared static resizeObserver that all ResizeManagers use\n private static resizeObserver: ResizeObserver | undefined;\n private static managersByElement = new Map<Element, ResizeManager>();\n\n private static getResizeObserver(): ResizeObserver {\n const resizeObserver =\n ResizeManager.resizeObserver ??\n new ResizeObserver(ResizeManager.handleSharedResizeEntries);\n ResizeManager.resizeObserver = resizeObserver;\n return resizeObserver;\n }\n\n private static handleSharedResizeEntries(entries: ResizeObserverEntry[]) {\n // First we need to batch all elements by manager, so callbacks are\n // properly aligned with a per-instance ResizeManager\n const entriesByManager = new Map<ResizeManager, ResizeObserverEntry[]>();\n for (const entry of entries) {\n const manager = ResizeManager.managersByElement.get(entry.target);\n if (manager == null) {\n continue;\n }\n const managerEntries = entriesByManager.get(manager);\n if (managerEntries == null) {\n entriesByManager.set(manager, [entry]);\n } else {\n managerEntries.push(entry);\n }\n }\n\n for (const [manager, managerEntries] of entriesByManager) {\n manager.handleResizeEntries(managerEntries);\n }\n }\n\n private observedNodes = new Map<\n HTMLElement,\n ObservedAnnotationNodes | ObservedGridNodes\n >();\n\n setup(pre: HTMLPreElement, disableAnnotations: boolean): void {\n const annotationUpdates = new Set<AnnotationSetup>();\n let columnCount = 0;\n const observedNodes = new Map(this.observedNodes);\n this.observedNodes.clear();\n\n for (const element of pre.children) {\n if (columnCount === 2) {\n break;\n }\n const codeElement: HTMLElement | undefined = (() => {\n if (element instanceof HTMLElement && element.tagName === 'CODE') {\n return element;\n }\n return undefined;\n })();\n if (codeElement == null) {\n continue;\n }\n columnCount++;\n let item: ObservedGridNodes | ObservedAnnotationNodes | undefined =\n observedNodes.get(codeElement);\n if (item != null && item.type !== 'code') {\n throw new Error(\n 'ResizeManager.setup: somehow a code node is being used for an annotation, should be impossible'\n );\n }\n\n let numberElement = codeElement.firstElementChild;\n if (!(numberElement instanceof HTMLElement)) {\n numberElement = null;\n }\n if (item != null) {\n this.observedNodes.set(codeElement, item);\n observedNodes.delete(codeElement);\n if (item.numberElement !== numberElement) {\n if (item.numberElement != null) {\n this.unobserve(item.numberElement);\n observedNodes.delete(item.numberElement);\n }\n if (numberElement != null) {\n this.observe(numberElement);\n observedNodes.delete(numberElement);\n this.observedNodes.set(numberElement, item);\n }\n item.numberElement = numberElement;\n item.numberWidth = 0;\n } else if (item.numberElement != null) {\n observedNodes.delete(item.numberElement);\n this.observedNodes.set(item.numberElement, item);\n // If there is a resize, let the resize handler handle it...\n } else {\n item.numberWidth = 0;\n }\n } else {\n item = {\n type: 'code',\n codeElement,\n numberElement,\n codeWidth: 'auto',\n numberWidth: 0,\n };\n this.observedNodes.set(codeElement, item);\n this.observe(codeElement);\n if (numberElement != null) {\n this.observedNodes.set(numberElement, item);\n this.observe(numberElement);\n }\n }\n }\n\n if (columnCount > 1 && !disableAnnotations) {\n const annotationElements = pre.querySelectorAll(\n '[data-line-annotation*=\",\"]'\n );\n\n const elementMap = new Map<string, HTMLElement[]>();\n // Iterate through all the matched elements and organize them into pairs\n // based on the data-line-annotation attribute\n for (const element of annotationElements) {\n if (!(element instanceof HTMLElement)) {\n continue;\n }\n const lineAnnotation =\n element.getAttribute('data-line-annotation') ?? '';\n if (!/^-?\\d+,-?\\d+$/.test(lineAnnotation)) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Invalid element or annotation',\n { lineAnnotation, element }\n );\n continue;\n }\n let pairs = elementMap.get(lineAnnotation);\n if (pairs == null) {\n pairs = [];\n elementMap.set(lineAnnotation, pairs);\n }\n pairs.push(element);\n }\n\n for (const [key, pair] of elementMap) {\n if (pair.length !== 2) {\n console.error(\n 'DiffFileRenderer.setupResizeObserver: Bad Pair',\n key,\n pair\n );\n continue;\n }\n const [container1, container2] = pair;\n const child1 = container1.firstElementChild;\n const child2 = container2.firstElementChild;\n if (\n !(container1 instanceof HTMLElement) ||\n !(container2 instanceof HTMLElement) ||\n !(child1 instanceof HTMLElement) ||\n !(child2 instanceof HTMLElement)\n ) {\n continue;\n }\n\n let item = observedNodes.get(child1);\n\n if (item != null) {\n this.observedNodes.set(child1, item);\n this.observedNodes.set(child2, item);\n observedNodes.delete(child1);\n observedNodes.delete(child2);\n continue;\n }\n\n const child1Height = child1.getBoundingClientRect().height;\n const child2Height = child2.getBoundingClientRect().height;\n item = {\n type: 'annotations',\n column1: {\n container: container1,\n child: child1,\n childHeight: child1Height,\n },\n column2: {\n container: container2,\n child: child2,\n childHeight: child2Height,\n },\n currentHeight: 'auto',\n };\n annotationUpdates.add({\n child1,\n child2,\n item,\n newHeight: Math.max(child1Height, child2Height),\n });\n }\n\n // Measure all annotation heights first, then apply the paired min-height\n // styles after the read phase so setup does not bounce between layout\n // reads and writes for every annotation pair.\n for (const pendingUpdate of annotationUpdates) {\n this.applyNewHeight(pendingUpdate.item, pendingUpdate.newHeight);\n this.observedNodes.set(pendingUpdate.child1, pendingUpdate.item);\n this.observedNodes.set(pendingUpdate.child2, pendingUpdate.item);\n this.observe(pendingUpdate.child1);\n this.observe(pendingUpdate.child2);\n }\n annotationUpdates.clear();\n }\n\n // Cleanup any old nodes that might still be observed\n for (const [element, item] of observedNodes) {\n this.unobserve(element);\n if (item.type === 'code') {\n cleanupStaleCodeItem(item);\n } else {\n cleanupStaleAnnotationItem(item);\n }\n }\n observedNodes.clear();\n }\n\n cleanUp(): void {\n for (const element of this.observedNodes.keys()) {\n this.unobserve(element);\n }\n this.observedNodes.clear();\n }\n\n private observe(element: HTMLElement): void {\n const { managersByElement } = ResizeManager;\n const owner = managersByElement.get(element);\n // Already registered\n if (owner === this) {\n return;\n }\n // If we've already somehow registered with another manager, we in for a\n // world of pain, so complain loudly\n else if (owner != null && owner !== this) {\n throw new Error(\n 'ResizeManager.observe: element is already owned by another ResizeManager'\n );\n }\n managersByElement.set(element, this);\n ResizeManager.getResizeObserver().observe(element);\n }\n\n private unobserve(element: HTMLElement): void {\n const { managersByElement, resizeObserver } = ResizeManager;\n const owner = managersByElement.get(element);\n if (owner == null) {\n return;\n } else if (owner !== this) {\n throw new Error(\n 'ResizeManager.unobserve: element is owned by another ResizeManager'\n );\n }\n\n managersByElement.delete(element);\n resizeObserver?.unobserve(element);\n if (resizeObserver != null && managersByElement.size === 0) {\n resizeObserver.disconnect();\n ResizeManager.resizeObserver = undefined;\n }\n }\n\n private handleResizeEntries(entries: ResizeObserverEntry[]) {\n const codeUpdates: CodeUpdateMap = new Map();\n const annotationUpdates: Set<ObservedAnnotationNodes> = new Set();\n for (const entry of entries) {\n const { target, borderBoxSize, contentBoxSize } = entry;\n if (!(target instanceof HTMLElement)) {\n console.error(\n 'ResizeManager.handleResizeEntries: Invalid element for ResizeObserver',\n entry\n );\n continue;\n }\n const item = this.observedNodes.get(target);\n if (item == null) {\n console.error(\n 'ResizeManager.handleResizeEntries: Not a valid observed node',\n entry\n );\n continue;\n }\n if (item.type === 'annotations') {\n const column = (() => {\n if (target === item.column1.child) {\n return item.column1;\n }\n if (target === item.column2.child) {\n return item.column2;\n }\n return undefined;\n })();\n\n if (column == null) {\n console.error(\n `ResizeManager.handleResizeEntries: Couldn't find a column for`,\n { item, target }\n );\n continue;\n }\n\n column.childHeight = borderBoxSize[0].blockSize;\n annotationUpdates.add(item);\n } else if (item.type === 'code') {\n const update = codeUpdates.get(item) ?? {};\n const inlineSize = contentBoxSize[0].inlineSize;\n if (target === item.codeElement) {\n update.codeInlineSize = inlineSize;\n } else if (target === item.numberElement) {\n update.numberInlineSize = inlineSize;\n }\n codeUpdates.set(item, update);\n }\n }\n this.applyAnnotationUpdates(annotationUpdates);\n annotationUpdates.clear();\n this.applyColumnUpdates(codeUpdates);\n codeUpdates.clear();\n }\n\n private applyAnnotationUpdates(\n annotationUpdates: Set<ObservedAnnotationNodes>\n ) {\n for (const item of annotationUpdates) {\n this.applyNewHeight(\n item,\n Math.max(item.column1.childHeight, item.column2.childHeight)\n );\n }\n }\n\n private applyColumnUpdates = (queuedUpdates: CodeUpdateMap) => {\n for (const [item, update] of queuedUpdates) {\n const nextCodeWidth =\n update.codeInlineSize != null\n ? resolveCodeWidth(update.codeInlineSize)\n : item.codeWidth;\n const nextNumberWidth =\n update.numberInlineSize != null\n ? resolveNumberWidth(update.numberInlineSize)\n : item.numberWidth;\n const codeWidthChanged = nextCodeWidth !== item.codeWidth;\n const numberWidthChanged = nextNumberWidth !== item.numberWidth;\n\n if (!codeWidthChanged && !numberWidthChanged) {\n continue;\n }\n\n item.codeWidth = nextCodeWidth;\n item.numberWidth = nextNumberWidth;\n\n if (codeWidthChanged) {\n item.codeElement.style.setProperty(\n '--diffs-column-width',\n `${typeof nextCodeWidth === 'number' ? `${nextCodeWidth}px` : 'auto'}`\n );\n }\n\n if (numberWidthChanged) {\n item.codeElement.style.setProperty(\n '--diffs-column-number-width',\n `${nextNumberWidth === 0 ? 'auto' : `${nextNumberWidth}px`}`\n );\n }\n\n if (\n codeWidthChanged ||\n (numberWidthChanged && nextCodeWidth !== 'auto')\n ) {\n const targetWidth =\n typeof nextCodeWidth === 'number'\n ? Math.max(nextCodeWidth - nextNumberWidth, 0)\n : 0;\n item.codeElement.style.setProperty(\n '--diffs-column-content-width',\n `${targetWidth > 0 ? `${targetWidth}px` : 'auto'}`\n );\n }\n }\n };\n\n private applyNewHeight(item: ObservedAnnotationNodes, newHeight: number) {\n if (newHeight !== item.currentHeight) {\n item.currentHeight = Math.max(newHeight, 0);\n item.column1.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n item.column2.container.style.setProperty(\n '--diffs-annotation-min-height',\n `${item.currentHeight}px`\n );\n }\n }\n}\n\nfunction resolveCodeWidth(inlineSize: number): number | 'auto' {\n const width = Math.max(Math.floor(inlineSize), 0);\n return width === 0 ? 'auto' : width;\n}\n\nfunction resolveNumberWidth(inlineSize: number): number {\n return Math.max(Math.ceil(inlineSize), 0);\n}\n\nfunction cleanupStaleCodeItem(item: ObservedGridNodes): void {\n if (item.codeElement.isConnected) {\n item.codeElement.style.removeProperty('--diffs-column-content-width');\n item.codeElement.style.removeProperty('--diffs-column-number-width');\n item.codeElement.style.removeProperty('--diffs-column-width');\n }\n}\n\nfunction cleanupStaleAnnotationItem(item: ObservedAnnotationNodes): void {\n if (item.column1.container.isConnected) {\n item.column1.container.style.removeProperty(\n '--diffs-annotation-min-height'\n );\n }\n if (item.column2.container.isConnected) {\n item.column2.container.style.removeProperty(\n '--diffs-annotation-min-height'\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseDiffOptions, BaseDiffOptionsWithDefaults, CustomPreProperties, DiffLineAnnotation, ExpansionDirections, FileDiffMetadata, FileHeaderRenderMode, HunkData, HunkExpansionRegion, LineTypes, RenderDiffOptions, RenderRange, ThemedDiffResult } from "../types.js";
|
|
2
2
|
import { WorkerPoolManager } from "../worker/WorkerPoolManager.js";
|
|
3
3
|
import "../worker/index.js";
|
|
4
4
|
import { DiffLineMetadata } from "../utils/iterateOverDiff.js";
|
|
@@ -99,7 +99,7 @@ declare class DiffHunksRenderer<LAnnotation = undefined> {
|
|
|
99
99
|
side,
|
|
100
100
|
type
|
|
101
101
|
}: SplitLineDecorationProps): LineDecoration;
|
|
102
|
-
|
|
102
|
+
private createAnnotationElement;
|
|
103
103
|
protected getUnifiedInjectedRowsForLine?: (ctx: RenderedLineContext) => UnifiedInjectedRowPlacement | undefined;
|
|
104
104
|
protected getSplitInjectedRowsForLine?: (ctx: RenderedLineContext) => SplitInjectedRowPlacement | undefined;
|
|
105
105
|
protected getOptionsWithDefaults(): DiffHunksRendererOptionsWithDefaults;
|
|
@@ -121,6 +121,7 @@ declare class DiffHunksRenderer<LAnnotation = undefined> {
|
|
|
121
121
|
renderFullAST(result: HunksRenderResult, children?: ElementContent[]): Element;
|
|
122
122
|
renderFullHTML(result: HunksRenderResult, tempChildren?: ElementContent[]): string;
|
|
123
123
|
renderPartialHTML(children: ElementContent[], columnType?: 'unified' | 'deletions' | 'additions'): string;
|
|
124
|
+
private pushFileLevelAnnotations;
|
|
124
125
|
private getAnnotations;
|
|
125
126
|
private renderHeader;
|
|
126
127
|
}
|