react-diff-viewer-continued 4.2.0 → 4.2.2

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.
@@ -1,12 +1,3 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
2
  import cn from "classnames";
12
3
  import * as React from "react";
@@ -21,12 +12,13 @@ import { Fold } from "./fold.js";
21
12
  * the HTML and wrapping text portions based on character positions in the diff.
22
13
  */
23
14
  function applyDiffToHighlightedHtml(html, diffArray, styles) {
15
+ var _a;
24
16
  const ranges = [];
25
17
  let pos = 0;
26
18
  for (const diff of diffArray) {
27
19
  const value = typeof diff.value === "string" ? diff.value : "";
28
20
  if (value.length > 0) {
29
- ranges.push({ start: pos, end: pos + value.length, type: diff.type });
21
+ ranges.push({ start: pos, end: pos + value.length, type: (_a = diff.type) !== null && _a !== void 0 ? _a : DiffType.DEFAULT });
30
22
  pos += value.length;
31
23
  }
32
24
  }
@@ -60,6 +52,7 @@ function applyDiffToHighlightedHtml(html, diffArray, styles) {
60
52
  .replace(/&/g, "&")
61
53
  .replace(/"/g, '"')
62
54
  .replace(/'/g, "'")
55
+ .replace(/'/g, "'")
63
56
  .replace(/ /g, "\u00A0");
64
57
  }
65
58
  // Helper to get the wrapper tag for a diff type
@@ -166,32 +159,28 @@ class DiffViewer extends React.Component {
166
159
  this.charMeasureRef = React.createRef();
167
160
  this.stickyHeaderRef = React.createRef();
168
161
  this.resizeObserver = null;
162
+ this.scrollDebounceTimer = null;
163
+ this.lastRenderedRange = { start: 0, end: Infinity };
169
164
  /**
170
165
  * Computes word diff on-demand for a line, with caching.
171
166
  * This is used when word diff was deferred during initial computation.
172
167
  */
173
168
  this.getWordDiffValues = (left, right, lineIndex) => {
174
- // Handle empty left/right
169
+ var _a, _b;
175
170
  if (!left || !right) {
176
171
  return { leftValue: left === null || left === void 0 ? void 0 : left.value, rightValue: right === null || right === void 0 ? void 0 : right.value };
177
172
  }
178
- // If no raw values, word diff was already computed or disabled
179
- // Use explicit undefined check since empty string is a valid raw value
180
173
  if (left.rawValue === undefined || right.rawValue === undefined) {
181
174
  return { leftValue: left.value, rightValue: right.value };
182
175
  }
183
- // Check cache
184
176
  const cacheKey = `${lineIndex}-${left.rawValue}-${right.rawValue}`;
185
177
  let cached = this.wordDiffCache.get(cacheKey);
186
178
  if (!cached) {
187
- // Compute word diff on-demand
188
- // Use CHARS method for on-demand computation since rawValue is always a string
189
- // (JSON/YAML methods only work with objects, not the string lines we have here)
190
179
  const compareMethod = (this.props.compareMethod === DiffMethod.JSON || this.props.compareMethod === DiffMethod.YAML)
191
180
  ? DiffMethod.CHARS
192
181
  : this.props.compareMethod;
193
182
  const computed = computeDiff(left.rawValue, right.rawValue, compareMethod);
194
- cached = { left: computed.left, right: computed.right };
183
+ cached = { left: (_a = computed.left) !== null && _a !== void 0 ? _a : [], right: (_b = computed.right) !== null && _b !== void 0 ? _b : [] };
195
184
  this.wordDiffCache.set(cacheKey, cached);
196
185
  }
197
186
  return { leftValue: cached.left, rightValue: cached.right };
@@ -223,7 +212,7 @@ class DiffViewer extends React.Component {
223
212
  * Called on resize and when blocks are expanded/collapsed.
224
213
  */
225
214
  this.recalculateOffsets = () => {
226
- var _a;
215
+ var _a, _b, _c;
227
216
  if (!this.props.infiniteLoading)
228
217
  return;
229
218
  const columnWidth = this.measureContentColumnWidth();
@@ -234,7 +223,7 @@ class DiffViewer extends React.Component {
234
223
  const { lineInformation, lineBlocks, blocks } = (_a = this.state.computedDiffResult[cacheKey]) !== null && _a !== void 0 ? _a : {};
235
224
  if (!lineInformation)
236
225
  return;
237
- const offsets = this.buildCumulativeOffsets(lineInformation, lineBlocks, blocks, this.state.expandedBlocks, this.props.showDiffOnly, charWidth, columnWidth, this.props.splitView);
226
+ const offsets = this.buildCumulativeOffsets(lineInformation, lineBlocks, blocks, this.state.expandedBlocks, (_b = this.props.showDiffOnly) !== null && _b !== void 0 ? _b : true, charWidth, columnWidth, (_c = this.props.splitView) !== null && _c !== void 0 ? _c : true);
238
227
  this.setState({ cumulativeOffsets: offsets, contentColumnWidth: columnWidth, charWidth }, () => {
239
228
  // Force a scroll position update to recalculate visible rows with new offsets
240
229
  this.onScroll();
@@ -322,7 +311,6 @@ class DiffViewer extends React.Component {
322
311
  content = wordDiff.value;
323
312
  }
324
313
  else {
325
- // If wordDiff.value is DiffInformation[], we don't handle it. See c0c99f5712.
326
314
  content = undefined;
327
315
  }
328
316
  return wordDiff.type === DiffType.ADDED ? (_jsx("ins", { className: cn(this.styles.wordDiff, {
@@ -346,10 +334,12 @@ class DiffViewer extends React.Component {
346
334
  * @param additionalPrefix Similar to prefix but for additional line number.
347
335
  */
348
336
  this.renderLine = (lineNumber, type, prefix, value, additionalLineNumber, additionalPrefix) => {
337
+ var _a;
349
338
  const lineNumberTemplate = `${prefix}-${lineNumber}`;
350
339
  const additionalLineNumberTemplate = `${additionalPrefix}-${additionalLineNumber}`;
351
- const highlightLine = this.props.highlightLines.includes(lineNumberTemplate) ||
352
- this.props.highlightLines.includes(additionalLineNumberTemplate);
340
+ const highlightLines = (_a = this.props.highlightLines) !== null && _a !== void 0 ? _a : [];
341
+ const highlightLine = highlightLines.includes(lineNumberTemplate) ||
342
+ highlightLines.includes(additionalLineNumberTemplate);
353
343
  const added = type === DiffType.ADDED;
354
344
  const removed = type === DiffType.REMOVED;
355
345
  const changed = type === DiffType.CHANGED;
@@ -358,7 +348,7 @@ class DiffViewer extends React.Component {
358
348
  if (hasWordDiff) {
359
349
  content = this.renderWordDiff(value, this.props.renderContent);
360
350
  }
361
- else if (this.props.renderContent) {
351
+ else if (this.props.renderContent && typeof value === "string") {
362
352
  content = this.props.renderContent(value);
363
353
  }
364
354
  else {
@@ -386,11 +376,11 @@ class DiffViewer extends React.Component {
386
376
  [this.styles.highlightedGutter]: highlightLine,
387
377
  }), children: _jsx("pre", { className: this.styles.lineNumber, children: additionalLineNumber }) })), this.props.renderGutter
388
378
  ? this.props.renderGutter({
389
- lineNumber,
390
- type,
379
+ lineNumber: lineNumber !== null && lineNumber !== void 0 ? lineNumber : 0,
380
+ type: type !== null && type !== void 0 ? type : DiffType.DEFAULT,
391
381
  prefix,
392
- value,
393
- additionalLineNumber,
382
+ value: value !== null && value !== void 0 ? value : "",
383
+ additionalLineNumber: additionalLineNumber !== null && additionalLineNumber !== void 0 ? additionalLineNumber : undefined,
394
384
  additionalPrefix,
395
385
  styles: this.styles,
396
386
  })
@@ -409,10 +399,18 @@ class DiffViewer extends React.Component {
409
399
  left: prefix === LineNumberPrefix.LEFT,
410
400
  right: prefix === LineNumberPrefix.RIGHT,
411
401
  }), onMouseDown: () => {
412
- const elements = document.getElementsByClassName(prefix === LineNumberPrefix.LEFT ? "right" : "left");
413
- for (let i = 0; i < elements.length; i++) {
414
- const element = elements.item(i);
415
- element.classList.add(this.styles.noSelect);
402
+ var _a, _b, _c;
403
+ const rightElements = document.getElementsByClassName("right");
404
+ for (let i = 0; i < rightElements.length; i++) {
405
+ (_a = rightElements[i]) === null || _a === void 0 ? void 0 : _a.classList.remove(this.styles.noSelect);
406
+ }
407
+ const leftElements = document.getElementsByClassName("left");
408
+ for (let i = 0; i < leftElements.length; i++) {
409
+ (_b = leftElements[i]) === null || _b === void 0 ? void 0 : _b.classList.remove(this.styles.noSelect);
410
+ }
411
+ const opposite = document.getElementsByClassName(prefix === LineNumberPrefix.LEFT ? "right" : "left");
412
+ for (let i = 0; i < opposite.length; i++) {
413
+ (_c = opposite[i]) === null || _c === void 0 ? void 0 : _c.classList.add(this.styles.noSelect);
416
414
  }
417
415
  }, title: added && !hasWordDiff
418
416
  ? "Added line"
@@ -512,8 +510,8 @@ class DiffViewer extends React.Component {
512
510
  * It also computes hidden line blocks for collapsing unchanged sections,
513
511
  * and stores the result in the local component state.
514
512
  */
515
- this.memoisedCompute = () => __awaiter(this, void 0, void 0, function* () {
516
- var _a;
513
+ this.memoisedCompute = async () => {
514
+ var _a, _b;
517
515
  const { oldValue, newValue, disableWordDiff, compareMethod, linesOffset } = this.props;
518
516
  const cacheKey = this.getMemoisedKey();
519
517
  if (!!this.state.computedDiffResult[cacheKey]) {
@@ -532,10 +530,9 @@ class DiffViewer extends React.Component {
532
530
  !!this.props.infiniteLoading &&
533
531
  containerHeightPx > 0 &&
534
532
  containerHeightPx < 2000;
535
- const { lineInformation, diffLines } = yield computeLineInformationWorker(oldValue, newValue, disableWordDiff, compareMethod, linesOffset, this.props.alwaysShowLines, shouldDeferWordDiff);
536
- const extraLines = this.props.extraLinesSurroundingDiff < 0
537
- ? 0
538
- : Math.round(this.props.extraLinesSurroundingDiff);
533
+ const { lineInformation, diffLines } = await computeLineInformationWorker(oldValue, newValue, disableWordDiff, compareMethod, linesOffset, this.props.alwaysShowLines, shouldDeferWordDiff, this.props.disableWorker);
534
+ const rawExtraLines = (_b = this.props.extraLinesSurroundingDiff) !== null && _b !== void 0 ? _b : 3;
535
+ const extraLines = rawExtraLines < 0 ? 0 : Math.round(rawExtraLines);
539
536
  const { lineBlocks, blocks } = computeHiddenBlocks(lineInformation, diffLines, extraLines);
540
537
  this.state.computedDiffResult[cacheKey] = { lineInformation, lineBlocks, blocks };
541
538
  this.setState((prev) => (Object.assign(Object.assign({}, prev), { computedDiffResult: this.state.computedDiffResult, isLoading: false })), () => {
@@ -545,7 +542,7 @@ class DiffViewer extends React.Component {
545
542
  requestAnimationFrame(() => this.recalculateOffsets());
546
543
  }
547
544
  });
548
- });
545
+ };
549
546
  /**
550
547
  * Handles scroll events on the scrollable container.
551
548
  *
@@ -562,16 +559,33 @@ class DiffViewer extends React.Component {
562
559
  const newStartRow = cumulativeOffsets
563
560
  ? this.findLineAtOffset(contentScrollTop, cumulativeOffsets)
564
561
  : Math.floor(contentScrollTop / DiffViewer.ESTIMATED_ROW_HEIGHT);
565
- // Only update state if the start row changed (avoid unnecessary re-renders)
562
+ const viewportRows = Math.ceil(container.clientHeight / DiffViewer.ESTIMATED_ROW_HEIGHT);
563
+ const newEndRow = newStartRow + viewportRows;
564
+ const leavesRenderedRange = newStartRow < this.lastRenderedRange.start || newEndRow > this.lastRenderedRange.end;
565
+ if (this.scrollDebounceTimer) {
566
+ clearTimeout(this.scrollDebounceTimer);
567
+ }
568
+ const stateUpdate = {};
566
569
  if (newStartRow !== this.state.visibleStartRow) {
567
- this.setState({ visibleStartRow: newStartRow });
570
+ stateUpdate.visibleStartRow = newStartRow;
571
+ }
572
+ if (leavesRenderedRange && !this.state.isScrolling) {
573
+ stateUpdate.isScrolling = true;
574
+ }
575
+ if (Object.keys(stateUpdate).length > 0) {
576
+ this.setState(stateUpdate);
577
+ }
578
+ if (this.state.isScrolling || leavesRenderedRange) {
579
+ this.scrollDebounceTimer = setTimeout(() => {
580
+ this.setState({ isScrolling: false });
581
+ }, 150);
568
582
  }
569
583
  };
570
584
  /**
571
585
  * Generates the entire diff view with virtualization support.
572
586
  */
573
587
  this.renderDiff = () => {
574
- var _a, _b, _c, _d, _e, _f;
588
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
575
589
  const { splitView, infiniteLoading, showDiffOnly } = this.props;
576
590
  const { computedDiffResult, expandedBlocks, visibleStartRow, scrollableContainerRef, cumulativeOffsets } = this.state;
577
591
  const cacheKey = this.getMemoisedKey();
@@ -579,7 +593,7 @@ class DiffViewer extends React.Component {
579
593
  // Calculate visible range for virtualization
580
594
  let visibleRowStart = 0;
581
595
  let visibleRowEnd = Infinity;
582
- const buffer = 5; // render extra rows above/below viewport
596
+ const buffer = (_b = infiniteLoading === null || infiniteLoading === void 0 ? void 0 : infiniteLoading.overscan) !== null && _b !== void 0 ? _b : 20;
583
597
  if (infiniteLoading && scrollableContainerRef.current) {
584
598
  const container = scrollableContainerRef.current;
585
599
  // Account for sticky header height in scroll calculations
@@ -677,7 +691,7 @@ class DiffViewer extends React.Component {
677
691
  const lastLineOfBlock = blocks[blockIndex].endLine === lineIndex;
678
692
  if (!expandedBlocks.includes(blockIndex) &&
679
693
  lastLineOfBlock) {
680
- diffNodes.push(_jsx(React.Fragment, { children: this.renderSkippedLineIndicator(blocks[blockIndex].lines, blockIndex, line.left.lineNumber, line.right.lineNumber) }, lineIndex));
694
+ diffNodes.push(_jsx(React.Fragment, { children: this.renderSkippedLineIndicator(blocks[blockIndex].lines, blockIndex, (_c = line.left.lineNumber) !== null && _c !== void 0 ? _c : 0, (_d = line.right.lineNumber) !== null && _d !== void 0 ? _d : 0) }, lineIndex));
681
695
  continue;
682
696
  }
683
697
  if (!expandedBlocks.includes(blockIndex)) {
@@ -697,6 +711,7 @@ class DiffViewer extends React.Component {
697
711
  const bottomPadding = cumulativeOffsets && lastRenderedRowIndex >= 0
698
712
  ? totalContentHeight - (cumulativeOffsets[lastRenderedRowIndex + 1] || totalContentHeight)
699
713
  : 0;
714
+ this.lastRenderedRange = { start: visibleRowStart, end: visibleRowEnd };
700
715
  return {
701
716
  diffNodes,
702
717
  blocks,
@@ -706,24 +721,23 @@ class DiffViewer extends React.Component {
706
721
  bottomPadding,
707
722
  totalContentHeight,
708
723
  renderedCount: diffNodes.length,
709
- // Debug info
710
724
  debug: {
711
725
  visibleRowStart,
712
726
  visibleRowEnd,
713
727
  totalRows: totalRenderedRows,
714
- offsetsLength: (_b = cumulativeOffsets === null || cumulativeOffsets === void 0 ? void 0 : cumulativeOffsets.length) !== null && _b !== void 0 ? _b : 0,
728
+ offsetsLength: (_e = cumulativeOffsets === null || cumulativeOffsets === void 0 ? void 0 : cumulativeOffsets.length) !== null && _e !== void 0 ? _e : 0,
715
729
  renderedCount: diffNodes.length,
716
- scrollTop: (_d = (_c = scrollableContainerRef.current) === null || _c === void 0 ? void 0 : _c.scrollTop) !== null && _d !== void 0 ? _d : 0,
730
+ scrollTop: (_g = (_f = scrollableContainerRef.current) === null || _f === void 0 ? void 0 : _f.scrollTop) !== null && _g !== void 0 ? _g : 0,
717
731
  headerHeight: this.getStickyHeaderHeight(),
718
732
  contentScrollTop: scrollableContainerRef.current
719
733
  ? Math.max(0, scrollableContainerRef.current.scrollTop - this.getStickyHeaderHeight())
720
734
  : 0,
721
- clientHeight: (_f = (_e = scrollableContainerRef.current) === null || _e === void 0 ? void 0 : _e.clientHeight) !== null && _f !== void 0 ? _f : 0,
735
+ clientHeight: (_j = (_h = scrollableContainerRef.current) === null || _h === void 0 ? void 0 : _h.clientHeight) !== null && _j !== void 0 ? _j : 0,
722
736
  }
723
737
  };
724
738
  };
725
739
  this.render = () => {
726
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
740
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
727
741
  const { oldValue, newValue, useDarkTheme, leftTitle, rightTitle, splitView, compareMethod, hideLineNumbers, nonce, } = this.props;
728
742
  if (typeof compareMethod === "string" &&
729
743
  compareMethod !== DiffMethod.JSON) {
@@ -731,7 +745,7 @@ class DiffViewer extends React.Component {
731
745
  throw Error('"oldValue" and "newValue" should be strings');
732
746
  }
733
747
  }
734
- this.styles = this.computeStyles(this.props.styles, useDarkTheme, nonce);
748
+ this.styles = this.computeStyles((_a = this.props.styles) !== null && _a !== void 0 ? _a : {}, useDarkTheme !== null && useDarkTheme !== void 0 ? useDarkTheme : false, nonce !== null && nonce !== void 0 ? nonce : "");
735
749
  const nodes = this.renderDiff();
736
750
  let colSpanOnSplitView = 3;
737
751
  let colSpanOnInlineView = 4;
@@ -783,54 +797,52 @@ class DiffViewer extends React.Component {
783
797
  const tableElement = (_jsxs("table", { className: cn(this.styles.diffContainer, {
784
798
  [this.styles.splitView]: splitView,
785
799
  [this.styles.noWrap]: shouldNoWrap,
786
- }), onMouseUp: () => {
787
- const elements = document.getElementsByClassName("right");
788
- for (let i = 0; i < elements.length; i++) {
789
- const element = elements.item(i);
790
- element.classList.remove(this.styles.noSelect);
791
- }
792
- const elementsLeft = document.getElementsByClassName("left");
793
- for (let i = 0; i < elementsLeft.length; i++) {
794
- const element = elementsLeft.item(i);
795
- element.classList.remove(this.styles.noSelect);
796
- }
797
- }, children: [_jsxs("colgroup", { children: [!this.props.hideLineNumbers && _jsx("col", { width: "50px" }), !splitView && !this.props.hideLineNumbers && _jsx("col", { width: "50px" }), this.props.renderGutter && _jsx("col", { width: "50px" }), _jsx("col", { width: "28px" }), _jsx("col", { width: "auto" }), splitView && (_jsxs(_Fragment, { children: [!this.props.hideLineNumbers && _jsx("col", { width: "50px" }), this.props.renderGutter && _jsx("col", { width: "50px" }), _jsx("col", { width: "28px" }), _jsx("col", { width: "auto" })] }))] }), _jsx("tbody", { children: nodes.diffNodes })] }));
798
- return (_jsxs("div", { style: Object.assign(Object.assign({}, scrollDivStyle), { position: 'relative' }), onScroll: this.onScroll, ref: this.state.scrollableContainerRef, children: [(!this.props.hideSummary || leftTitle || rightTitle) && (_jsxs("div", { ref: this.stickyHeaderRef, className: this.styles.stickyHeader, children: [!this.props.hideSummary && (_jsxs("div", { className: this.styles.summary, role: "banner", children: [_jsx("button", { type: "button", className: this.styles.allExpandButton, onClick: () => {
799
- this.setState({
800
- expandedBlocks: allExpanded
801
- ? []
802
- : nodes.blocks.map((b) => b.index),
803
- }, () => this.recalculateOffsets());
804
- }, children: allExpanded ? _jsx(Fold, {}) : _jsx(Expand, {}) }), " ", totalChanges, _jsx("div", { style: { display: "flex", gap: "1px" }, children: blocks }), this.props.summary ? _jsx("span", { children: this.props.summary }) : null] })), (leftTitle || rightTitle) && (_jsxs("div", { className: this.styles.columnHeaders, children: [_jsx("div", { className: this.styles.titleBlock, children: leftTitle ? (_jsx("pre", { className: this.styles.contentText, children: leftTitle })) : null }), splitView && (_jsx("div", { className: this.styles.titleBlock, children: rightTitle ? (_jsx("pre", { className: this.styles.contentText, children: rightTitle })) : null }))] }))] })), this.state.isLoading && LoadingElement && _jsx(LoadingElement, {}), this.props.infiniteLoading ? (_jsx("div", { style: {
805
- height: nodes.totalContentHeight,
806
- position: 'relative',
807
- }, children: _jsx("div", { style: {
808
- position: 'absolute',
809
- top: nodes.topPadding,
810
- left: 0,
811
- right: 0,
812
- }, children: tableElement }) })) : (tableElement), _jsx("span", { ref: this.charMeasureRef, style: {
800
+ }), onMouseUp: () => { }, children: [_jsxs("colgroup", { children: [!this.props.hideLineNumbers && _jsx("col", { width: "50px" }), !splitView && !this.props.hideLineNumbers && _jsx("col", { width: "50px" }), this.props.renderGutter && _jsx("col", { width: "50px" }), _jsx("col", { width: "28px" }), _jsx("col", { width: "auto" }), splitView && (_jsxs(_Fragment, { children: [!this.props.hideLineNumbers && _jsx("col", { width: "50px" }), this.props.renderGutter && _jsx("col", { width: "50px" }), _jsx("col", { width: "28px" }), _jsx("col", { width: "auto" })] }))] }), _jsx("tbody", { children: nodes.diffNodes })] }));
801
+ const showLoadingOverlay = (this.state.isLoading || this.state.isScrolling) && !!LoadingElement;
802
+ return (_jsxs("div", { style: { position: 'relative' }, children: [showLoadingOverlay && (_jsx("div", { style: {
813
803
  position: 'absolute',
814
804
  top: 0,
815
- left: '-9999px',
816
- visibility: 'hidden',
817
- whiteSpace: 'pre',
818
- fontFamily: 'monospace',
819
- fontSize: 12,
820
- }, "aria-hidden": "true", children: "M" }), this.props.infiniteLoading && this.props.showDebugInfo && (_jsxs("div", { style: {
821
- position: 'fixed',
822
- top: 10,
823
- right: 10,
824
- background: 'rgba(0,0,0,0.85)',
825
- color: '#0f0',
826
- padding: '10px',
827
- fontFamily: 'monospace',
828
- fontSize: '11px',
829
- zIndex: 9999,
830
- borderRadius: '4px',
831
- maxWidth: '300px',
832
- lineHeight: 1.4,
833
- }, children: [_jsx("div", { style: { fontWeight: 'bold', marginBottom: '5px', color: '#fff' }, children: "Debug Info" }), _jsxs("div", { children: ["scrollTop: ", nodes.debug.scrollTop] }), _jsxs("div", { children: ["headerHeight: ", nodes.debug.headerHeight] }), _jsxs("div", { children: ["contentScrollTop: ", nodes.debug.contentScrollTop] }), _jsxs("div", { children: ["clientHeight: ", nodes.debug.clientHeight] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px' }, children: [_jsxs("div", { children: ["visibleRowStart: ", nodes.debug.visibleRowStart] }), _jsxs("div", { children: ["visibleRowEnd: ", nodes.debug.visibleRowEnd] })] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px' }, children: [_jsxs("div", { children: ["totalRows: ", nodes.debug.totalRows] }), _jsxs("div", { children: ["offsetsLength: ", nodes.debug.offsetsLength] }), _jsxs("div", { children: ["renderedCount: ", nodes.debug.renderedCount] })] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px' }, children: [_jsxs("div", { children: ["topPadding: ", nodes.topPadding.toFixed(0)] }), _jsxs("div", { children: ["bottomPadding: ", nodes.bottomPadding.toFixed(0)] }), _jsxs("div", { children: ["totalContentHeight: ", nodes.totalContentHeight.toFixed(0)] })] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px', color: '#ff0' }, children: [_jsxs("div", { children: ["cumulativeOffsets: ", this.state.cumulativeOffsets ? 'SET' : 'NULL'] }), _jsxs("div", { children: ["columnWidth: ", (_b = (_a = this.state.contentColumnWidth) === null || _a === void 0 ? void 0 : _a.toFixed(0)) !== null && _b !== void 0 ? _b : 'N/A', "px"] }), _jsxs("div", { children: ["charWidth: ", (_d = (_c = this.state.charWidth) === null || _c === void 0 ? void 0 : _c.toFixed(2)) !== null && _d !== void 0 ? _d : 'N/A', "px"] }), _jsxs("div", { children: ["charsPerRow: ", this.state.contentColumnWidth && this.state.charWidth ? Math.floor(this.state.contentColumnWidth / this.state.charWidth) : 'N/A'] })] }), this.state.cumulativeOffsets && (_jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px', color: '#0ff', fontSize: '10px' }, children: [_jsxs("div", { children: ["offsets[", nodes.debug.visibleRowEnd, "]: ", (_f = (_e = this.state.cumulativeOffsets[nodes.debug.visibleRowEnd]) === null || _e === void 0 ? void 0 : _e.toFixed(0)) !== null && _f !== void 0 ? _f : 'N/A'] }), _jsxs("div", { children: ["offsets[", nodes.debug.totalRows - 1, "]: ", (_h = (_g = this.state.cumulativeOffsets[nodes.debug.totalRows - 1]) === null || _g === void 0 ? void 0 : _g.toFixed(0)) !== null && _h !== void 0 ? _h : 'N/A'] }), _jsxs("div", { children: ["offsets[", nodes.debug.totalRows, "]: ", (_k = (_j = this.state.cumulativeOffsets[nodes.debug.totalRows]) === null || _j === void 0 ? void 0 : _j.toFixed(0)) !== null && _k !== void 0 ? _k : 'N/A'] }), _jsxs("div", { style: { marginTop: '3px' }, children: ["viewportEnd: ", (nodes.debug.contentScrollTop + nodes.debug.clientHeight).toFixed(0)] }), _jsxs("div", { style: { marginTop: '3px', color: '#f0f' }, children: ["scrollHeight: ", (_m = (_l = this.state.scrollableContainerRef.current) === null || _l === void 0 ? void 0 : _l.scrollHeight) !== null && _m !== void 0 ? _m : 'N/A'] }), _jsxs("div", { children: ["maxScrollTop: ", ((_p = (_o = this.state.scrollableContainerRef.current) === null || _o === void 0 ? void 0 : _o.scrollHeight) !== null && _p !== void 0 ? _p : 0) - nodes.debug.clientHeight] })] }))] }))] }));
805
+ left: 0,
806
+ right: 0,
807
+ bottom: 0,
808
+ zIndex: 3,
809
+ }, children: _jsx(LoadingElement, {}) })), _jsxs("div", { style: Object.assign(Object.assign({}, scrollDivStyle), { position: 'relative' }), onScroll: this.onScroll, ref: this.state.scrollableContainerRef, children: [(!this.props.hideSummary || leftTitle || rightTitle) && (_jsxs("div", { ref: this.stickyHeaderRef, className: this.styles.stickyHeader, children: [!this.props.hideSummary && (_jsxs("div", { className: this.styles.summary, role: "banner", children: [_jsx("button", { type: "button", className: this.styles.allExpandButton, onClick: () => {
810
+ this.setState({
811
+ expandedBlocks: allExpanded
812
+ ? []
813
+ : nodes.blocks.map((b) => b.index),
814
+ }, () => this.recalculateOffsets());
815
+ }, children: allExpanded ? _jsx(Fold, {}) : _jsx(Expand, {}) }), " ", totalChanges, _jsx("div", { style: { display: "flex", gap: "1px" }, children: blocks }), this.props.summary ? _jsx("span", { children: this.props.summary }) : null] })), (leftTitle || rightTitle) && (_jsxs("div", { className: this.styles.columnHeaders, children: [_jsx("div", { className: this.styles.titleBlock, children: leftTitle ? (_jsx("pre", { className: this.styles.contentText, children: leftTitle })) : null }), splitView && (_jsx("div", { className: this.styles.titleBlock, children: rightTitle ? (_jsx("pre", { className: this.styles.contentText, children: rightTitle })) : null }))] }))] })), this.props.infiniteLoading ? (_jsx("div", { style: {
816
+ height: nodes.totalContentHeight,
817
+ position: 'relative',
818
+ }, children: _jsx("div", { style: {
819
+ position: 'absolute',
820
+ top: nodes.topPadding,
821
+ left: 0,
822
+ right: 0,
823
+ visibility: this.state.isScrolling ? 'hidden' : 'visible',
824
+ }, children: tableElement }) })) : (tableElement), _jsx("span", { ref: this.charMeasureRef, style: {
825
+ position: 'absolute',
826
+ top: 0,
827
+ left: '-9999px',
828
+ visibility: 'hidden',
829
+ whiteSpace: 'pre',
830
+ fontFamily: 'monospace',
831
+ fontSize: 12,
832
+ }, "aria-hidden": "true", children: "M" }), this.props.infiniteLoading && this.props.showDebugInfo && (_jsxs("div", { style: {
833
+ position: 'fixed',
834
+ top: 10,
835
+ right: 10,
836
+ background: 'rgba(0,0,0,0.85)',
837
+ color: '#0f0',
838
+ padding: '10px',
839
+ fontFamily: 'monospace',
840
+ fontSize: '11px',
841
+ zIndex: 9999,
842
+ borderRadius: '4px',
843
+ maxWidth: '300px',
844
+ lineHeight: 1.4,
845
+ }, children: [_jsx("div", { style: { fontWeight: 'bold', marginBottom: '5px', color: '#fff' }, children: "Debug Info" }), _jsxs("div", { children: ["scrollTop: ", nodes.debug.scrollTop] }), _jsxs("div", { children: ["headerHeight: ", nodes.debug.headerHeight] }), _jsxs("div", { children: ["contentScrollTop: ", nodes.debug.contentScrollTop] }), _jsxs("div", { children: ["clientHeight: ", nodes.debug.clientHeight] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px' }, children: [_jsxs("div", { children: ["visibleRowStart: ", nodes.debug.visibleRowStart] }), _jsxs("div", { children: ["visibleRowEnd: ", nodes.debug.visibleRowEnd] })] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px' }, children: [_jsxs("div", { children: ["totalRows: ", nodes.debug.totalRows] }), _jsxs("div", { children: ["offsetsLength: ", nodes.debug.offsetsLength] }), _jsxs("div", { children: ["renderedCount: ", nodes.debug.renderedCount] })] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px' }, children: [_jsxs("div", { children: ["topPadding: ", nodes.topPadding.toFixed(0)] }), _jsxs("div", { children: ["bottomPadding: ", nodes.bottomPadding.toFixed(0)] }), _jsxs("div", { children: ["totalContentHeight: ", nodes.totalContentHeight.toFixed(0)] })] }), _jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px', color: '#ff0' }, children: [_jsxs("div", { children: ["cumulativeOffsets: ", this.state.cumulativeOffsets ? 'SET' : 'NULL'] }), _jsxs("div", { children: ["columnWidth: ", (_c = (_b = this.state.contentColumnWidth) === null || _b === void 0 ? void 0 : _b.toFixed(0)) !== null && _c !== void 0 ? _c : 'N/A', "px"] }), _jsxs("div", { children: ["charWidth: ", (_e = (_d = this.state.charWidth) === null || _d === void 0 ? void 0 : _d.toFixed(2)) !== null && _e !== void 0 ? _e : 'N/A', "px"] }), _jsxs("div", { children: ["charsPerRow: ", this.state.contentColumnWidth && this.state.charWidth ? Math.floor(this.state.contentColumnWidth / this.state.charWidth) : 'N/A'] })] }), this.state.cumulativeOffsets && (_jsxs("div", { style: { marginTop: '5px', borderTop: '1px solid #444', paddingTop: '5px', color: '#0ff', fontSize: '10px' }, children: [_jsxs("div", { children: ["offsets[", nodes.debug.visibleRowEnd, "]: ", (_g = (_f = this.state.cumulativeOffsets[nodes.debug.visibleRowEnd]) === null || _f === void 0 ? void 0 : _f.toFixed(0)) !== null && _g !== void 0 ? _g : 'N/A'] }), _jsxs("div", { children: ["offsets[", nodes.debug.totalRows - 1, "]: ", (_j = (_h = this.state.cumulativeOffsets[nodes.debug.totalRows - 1]) === null || _h === void 0 ? void 0 : _h.toFixed(0)) !== null && _j !== void 0 ? _j : 'N/A'] }), _jsxs("div", { children: ["offsets[", nodes.debug.totalRows, "]: ", (_l = (_k = this.state.cumulativeOffsets[nodes.debug.totalRows]) === null || _k === void 0 ? void 0 : _k.toFixed(0)) !== null && _l !== void 0 ? _l : 'N/A'] }), _jsxs("div", { style: { marginTop: '3px' }, children: ["viewportEnd: ", (nodes.debug.contentScrollTop + nodes.debug.clientHeight).toFixed(0)] }), _jsxs("div", { style: { marginTop: '3px', color: '#f0f' }, children: ["scrollHeight: ", (_o = (_m = this.state.scrollableContainerRef.current) === null || _m === void 0 ? void 0 : _m.scrollHeight) !== null && _o !== void 0 ? _o : 'N/A'] }), _jsxs("div", { children: ["maxScrollTop: ", ((_q = (_p = this.state.scrollableContainerRef.current) === null || _p === void 0 ? void 0 : _p.scrollHeight) !== null && _q !== void 0 ? _q : 0) - nodes.debug.clientHeight] })] }))] }))] })] }));
834
846
  };
835
847
  this.state = {
836
848
  expandedBlocks: [],
@@ -842,6 +854,7 @@ class DiffViewer extends React.Component {
842
854
  contentColumnWidth: null,
843
855
  charWidth: null,
844
856
  cumulativeOffsets: null,
857
+ isScrolling: false,
845
858
  };
846
859
  }
847
860
  /**
@@ -983,6 +996,9 @@ class DiffViewer extends React.Component {
983
996
  componentWillUnmount() {
984
997
  var _a;
985
998
  (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
999
+ if (this.scrollDebounceTimer) {
1000
+ clearTimeout(this.scrollDebounceTimer);
1001
+ }
986
1002
  }
987
1003
  }
988
1004
  DiffViewer.defaultProps = {
@@ -1,37 +1,41 @@
1
1
  import type { Interpolation } from "@emotion/react";
2
2
  export interface ReactDiffViewerStyles {
3
- diffContainer?: string;
4
- diffRemoved?: string;
5
- diffAdded?: string;
6
- diffChanged?: string;
7
- line?: string;
8
- highlightedGutter?: string;
9
- contentText?: string;
10
- lineContent?: string;
11
- gutter?: string;
12
- highlightedLine?: string;
13
- lineNumber?: string;
14
- marker?: string;
15
- wordDiff?: string;
16
- wordAdded?: string;
17
- wordRemoved?: string;
18
- codeFoldGutter?: string;
19
- codeFoldExpandButton?: string;
20
- summary?: string;
21
- codeFoldContentContainer?: string;
22
- emptyGutter?: string;
23
- emptyLine?: string;
24
- codeFold?: string;
25
- stickyHeader?: string;
26
- columnHeaders?: string;
27
- titleBlock?: string;
28
- content?: string;
29
- column?: string;
30
- noSelect?: string;
31
- noWrap?: string;
32
- splitView?: string;
33
- allExpandButton?: string;
34
- [key: string]: string | undefined;
3
+ diffContainer: string;
4
+ diffRemoved: string;
5
+ diffAdded: string;
6
+ diffChanged: string;
7
+ line: string;
8
+ highlightedGutter: string;
9
+ contentText: string;
10
+ lineContent: string;
11
+ gutter: string;
12
+ highlightedLine: string;
13
+ lineNumber: string;
14
+ marker: string;
15
+ wordDiff: string;
16
+ wordAdded: string;
17
+ wordRemoved: string;
18
+ codeFoldGutter: string;
19
+ codeFoldExpandButton: string;
20
+ summary: string;
21
+ codeFoldContentContainer: string;
22
+ emptyGutter: string;
23
+ emptyLine: string;
24
+ codeFold: string;
25
+ codeFoldContent: string;
26
+ stickyHeader: string;
27
+ columnHeaders: string;
28
+ titleBlock: string;
29
+ content: string;
30
+ column: string;
31
+ noSelect: string;
32
+ noWrap: string;
33
+ splitView: string;
34
+ allExpandButton: string;
35
+ block: string;
36
+ blockAddition: string;
37
+ blockDeletion: string;
38
+ [key: string]: string;
35
39
  }
36
40
  export interface ReactDiffViewerStylesVariables {
37
41
  diffViewerBackground?: string;
@@ -407,12 +407,8 @@ export default (styleOverride, useDarkTheme = false, nonce = "") => {
407
407
  titleBlock,
408
408
  allExpandButton,
409
409
  };
410
- const computerOverrideStyles = Object.keys(styles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), {
411
- [key]: css(styles[key]),
412
- })), {});
413
- return Object.keys(defaultStyles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), {
414
- [key]: computerOverrideStyles[key]
410
+ const computerOverrideStyles = Object.keys(styles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: css(styles[key]) })), {});
411
+ return Object.keys(defaultStyles).reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: computerOverrideStyles[key]
415
412
  ? cx(defaultStyles[key], computerOverrideStyles[key])
416
- : defaultStyles[key],
417
- })), {});
413
+ : defaultStyles[key] })), {});
418
414
  };