@canvas-components/pivot-table 0.1.9 → 0.2.1

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/dist/index.d.cts CHANGED
@@ -153,6 +153,8 @@ interface PivotDimensionFilter {
153
153
  searchExact?: boolean;
154
154
  condition?: PivotFilterCondition;
155
155
  secondCondition?: PivotFilterCondition;
156
+ /** 动态条件列表;存在时优先于旧的两条件字段。 */
157
+ conditions?: PivotFilterCondition[];
156
158
  conditionRelation?: "and" | "or";
157
159
  }
158
160
  /** 行轴、列轴和报告筛选字段的独立过滤状态。 */
@@ -793,6 +795,8 @@ declare class PivotTable<RecordType = Record<string, unknown>> {
793
795
  private wheelScrollTarget;
794
796
  private wheelScrollFrameId;
795
797
  private wheelScrollLastTime;
798
+ private continuousScrollTimer;
799
+ private continuousScrollPointerId;
796
800
  private resizeSession;
797
801
  private resizeGuideX;
798
802
  private suppressNextClick;
@@ -920,6 +924,8 @@ declare class PivotTable<RecordType = Record<string, unknown>> {
920
924
  private beginScrollbarInteraction;
921
925
  private updateScrollbarDrag;
922
926
  private stepScrollbar;
927
+ private startContinuousScrollbarScroll;
928
+ private stopContinuousScrollbarScroll;
923
929
  private applyScrollPosition;
924
930
  private applyResize;
925
931
  private openFilterPanel;
package/dist/index.d.ts CHANGED
@@ -153,6 +153,8 @@ interface PivotDimensionFilter {
153
153
  searchExact?: boolean;
154
154
  condition?: PivotFilterCondition;
155
155
  secondCondition?: PivotFilterCondition;
156
+ /** 动态条件列表;存在时优先于旧的两条件字段。 */
157
+ conditions?: PivotFilterCondition[];
156
158
  conditionRelation?: "and" | "or";
157
159
  }
158
160
  /** 行轴、列轴和报告筛选字段的独立过滤状态。 */
@@ -793,6 +795,8 @@ declare class PivotTable<RecordType = Record<string, unknown>> {
793
795
  private wheelScrollTarget;
794
796
  private wheelScrollFrameId;
795
797
  private wheelScrollLastTime;
798
+ private continuousScrollTimer;
799
+ private continuousScrollPointerId;
796
800
  private resizeSession;
797
801
  private resizeGuideX;
798
802
  private suppressNextClick;
@@ -920,6 +924,8 @@ declare class PivotTable<RecordType = Record<string, unknown>> {
920
924
  private beginScrollbarInteraction;
921
925
  private updateScrollbarDrag;
922
926
  private stepScrollbar;
927
+ private startContinuousScrollbarScroll;
928
+ private stopContinuousScrollbarScroll;
923
929
  private applyScrollPosition;
924
930
  private applyResize;
925
931
  private openFilterPanel;
package/dist/index.js CHANGED
@@ -728,14 +728,11 @@ function matchesSearchKeyword(value, filter) {
728
728
  return filter.searchExact ? text === keyword : text.includes(keyword);
729
729
  }
730
730
  function matchesFilterConditions(value, filter) {
731
- const first = filter.condition;
732
- const second = filter.secondCondition;
733
- const firstActive = first && first.operator !== "none";
734
- const secondActive = second && second.operator !== "none";
735
- if (!firstActive && !secondActive) return true;
736
- if (!firstActive) return evaluateCondition(value, second);
737
- if (!secondActive) return evaluateCondition(value, first);
738
- return filter.conditionRelation === "or" ? evaluateCondition(value, first) || evaluateCondition(value, second) : evaluateCondition(value, first) && evaluateCondition(value, second);
731
+ const conditions = (filter.conditions?.length ? filter.conditions : [filter.condition, filter.secondCondition]).filter(
732
+ (condition) => condition != null && condition.operator !== "none"
733
+ );
734
+ if (conditions.length === 0) return true;
735
+ return filter.conditionRelation === "or" ? conditions.some((condition) => evaluateCondition(value, condition)) : conditions.every((condition) => evaluateCondition(value, condition));
739
736
  }
740
737
  function evaluateCondition(value, condition) {
741
738
  const text = value == null ? "" : String(value);
@@ -2631,6 +2628,7 @@ function createPivotDomHost(container) {
2631
2628
  right: "0",
2632
2629
  height: "100%",
2633
2630
  overflow: "hidden",
2631
+ borderRadius: "8px",
2634
2632
  touchAction: "none"
2635
2633
  });
2636
2634
  Object.assign(canvas.style, {
@@ -2859,29 +2857,127 @@ var defaultPivotTableTheme = {
2859
2857
  };
2860
2858
 
2861
2859
  // src/rendering/draw-scrollbars.ts
2862
- function drawPivotScrollbars(context, layout, borderColor) {
2860
+ function drawPivotScrollbars(context, layout, borderColor, verticalFrame) {
2863
2861
  context.save();
2862
+ if (layout.horizontal && verticalFrame) {
2863
+ drawHorizontalScrollbarMask(
2864
+ context,
2865
+ layout.horizontal,
2866
+ verticalFrame.bodyBackgroundColor
2867
+ );
2868
+ }
2869
+ if (layout.vertical && verticalFrame) {
2870
+ drawVerticalScrollbarFrame(
2871
+ context,
2872
+ layout.vertical,
2873
+ verticalFrame,
2874
+ borderColor
2875
+ );
2876
+ }
2864
2877
  if (layout.horizontal) {
2865
2878
  drawAxis(context, layout.horizontal, "horizontal", borderColor);
2866
2879
  }
2867
2880
  if (layout.vertical) {
2868
2881
  drawAxis(context, layout.vertical, "vertical", borderColor);
2869
2882
  }
2883
+ if (layout.horizontal) {
2884
+ drawHorizontalScrollbarTopBorder(
2885
+ context,
2886
+ layout.horizontal,
2887
+ layout.vertical,
2888
+ borderColor
2889
+ );
2890
+ }
2891
+ context.restore();
2892
+ }
2893
+ function drawHorizontalScrollbarMask(context, layout, backgroundColor) {
2894
+ const left = layout.decreaseButton.x;
2895
+ const right = layout.increaseButton.x + layout.increaseButton.width;
2896
+ const top = layout.decreaseButton.y;
2897
+ const height = layout.decreaseButton.height;
2898
+ if (right <= left || height <= 0) return;
2899
+ context.save();
2900
+ context.fillStyle = backgroundColor;
2901
+ context.fillRect(left, top, right - left, height);
2902
+ context.restore();
2903
+ }
2904
+ function drawHorizontalScrollbarTopBorder(context, horizontal, vertical, borderColor) {
2905
+ const left = Math.round(horizontal.decreaseButton.x) + 0.5;
2906
+ const horizontalRight = horizontal.increaseButton.x + horizontal.increaseButton.width;
2907
+ const verticalRight = vertical ? vertical.decreaseButton.x + vertical.decreaseButton.width : horizontalRight;
2908
+ const right = Math.round(Math.max(horizontalRight, verticalRight)) - 0.5;
2909
+ const top = Math.round(horizontal.decreaseButton.y) + 0.5;
2910
+ if (right <= left) return;
2911
+ context.save();
2912
+ context.strokeStyle = borderColor;
2913
+ context.lineWidth = 1;
2914
+ context.beginPath();
2915
+ context.moveTo(left, top);
2916
+ context.lineTo(right, top);
2917
+ context.stroke();
2870
2918
  context.restore();
2871
2919
  }
2872
2920
  function drawAxis(context, layout, axis, borderColor) {
2873
- drawTrack(context, layout.track, borderColor);
2874
2921
  drawButton(context, layout.decreaseButton, axis, "decrease");
2875
2922
  drawButton(context, layout.increaseButton, axis, "increase");
2876
2923
  drawThumb(context, layout.thumb);
2924
+ drawTrackBorder(context, layout.track, axis, borderColor);
2925
+ }
2926
+ function drawTrackBorder(context, rect, axis, borderColor) {
2927
+ const left = Math.round(rect.x) + 0.5;
2928
+ const right = Math.round(rect.x + rect.width) - 0.5;
2929
+ const top = Math.round(rect.y) + 0.5;
2930
+ const bottom = Math.round(rect.y + rect.height) - 0.5;
2931
+ if (right <= left || bottom <= top) return;
2932
+ context.save();
2933
+ context.strokeStyle = borderColor;
2934
+ context.lineWidth = 1;
2935
+ context.beginPath();
2936
+ if (axis === "horizontal") {
2937
+ context.moveTo(left, top);
2938
+ context.lineTo(right, top);
2939
+ } else {
2940
+ context.moveTo(left, top);
2941
+ context.lineTo(left, bottom);
2942
+ }
2943
+ context.stroke();
2944
+ context.restore();
2877
2945
  }
2878
- function drawTrack(context, rect, borderColor) {
2879
- context.fillStyle = "rgba(148, 163, 184, 0.16)";
2946
+ function drawVerticalScrollbarFrame(context, layout, frame, borderColor) {
2947
+ const left = Math.round(layout.decreaseButton.x) + 0.5;
2948
+ const top = Math.round(frame.top) + 0.5;
2949
+ const bottom = Math.round(frame.top + frame.height) - 0.5;
2950
+ const headerBottom = Math.round(frame.headerBottom) + 0.5;
2951
+ if (bottom <= top) return;
2952
+ context.save();
2953
+ context.fillStyle = frame.headerBackgroundColor;
2954
+ context.fillRect(
2955
+ layout.decreaseButton.x,
2956
+ frame.top,
2957
+ layout.decreaseButton.width,
2958
+ Math.max(frame.headerBottom - frame.top, 0)
2959
+ );
2960
+ context.fillStyle = frame.bodyBackgroundColor;
2961
+ context.fillRect(
2962
+ layout.decreaseButton.x,
2963
+ frame.headerBottom,
2964
+ layout.decreaseButton.width,
2965
+ Math.max(frame.top + frame.height - frame.headerBottom, 0)
2966
+ );
2880
2967
  context.strokeStyle = borderColor;
2881
2968
  context.lineWidth = 1;
2882
- roundRect(context, rect, rect.height / 2);
2883
- context.fill();
2969
+ context.beginPath();
2970
+ context.moveTo(left, top);
2971
+ context.lineTo(left, bottom);
2884
2972
  context.stroke();
2973
+ if (headerBottom > top && headerBottom < bottom) {
2974
+ const right = Math.round(layout.decreaseButton.x + layout.decreaseButton.width) - 0.5;
2975
+ context.beginPath();
2976
+ context.moveTo(left, headerBottom);
2977
+ context.lineTo(right, headerBottom);
2978
+ context.stroke();
2979
+ }
2980
+ context.restore();
2885
2981
  }
2886
2982
  function drawThumb(context, rect) {
2887
2983
  context.fillStyle = "rgba(100, 116, 139, 0.8)";
@@ -2889,28 +2985,25 @@ function drawThumb(context, rect) {
2889
2985
  context.fill();
2890
2986
  }
2891
2987
  function drawButton(context, rect, axis, direction) {
2892
- context.fillStyle = "rgba(226, 232, 240, 0.92)";
2893
- context.strokeStyle = "rgba(148, 163, 184, 0.65)";
2894
- context.lineWidth = 1;
2895
- roundRect(context, rect, rect.height / 2);
2896
- context.fill();
2897
- context.stroke();
2898
2988
  context.fillStyle = "rgba(71, 85, 105, 0.88)";
2899
2989
  context.beginPath();
2900
2990
  const centerX = rect.x + rect.width / 2;
2901
2991
  const centerY = rect.y + rect.height / 2;
2992
+ const iconSize = Math.min(rect.width, rect.height) * 0.64;
2993
+ const directionOffset = iconSize * 0.4;
2994
+ const crossAxisOffset = iconSize / 2;
2902
2995
  if (axis === "horizontal") {
2903
- const tipX = centerX + (direction === "decrease" ? -1 : 1) * rect.width * 0.14;
2904
- const tailX = centerX + (direction === "decrease" ? 1 : -1) * rect.width * 0.14;
2996
+ const tipX = centerX + (direction === "decrease" ? -1 : 1) * directionOffset;
2997
+ const tailX = centerX + (direction === "decrease" ? 1 : -1) * directionOffset;
2905
2998
  context.moveTo(tipX, centerY);
2906
- context.lineTo(tailX, centerY - rect.height * 0.22);
2907
- context.lineTo(tailX, centerY + rect.height * 0.22);
2999
+ context.lineTo(tailX, centerY - crossAxisOffset);
3000
+ context.lineTo(tailX, centerY + crossAxisOffset);
2908
3001
  } else {
2909
- const tipY = centerY + (direction === "decrease" ? -1 : 1) * rect.height * 0.14;
2910
- const tailY = centerY + (direction === "decrease" ? 1 : -1) * rect.height * 0.14;
3002
+ const tipY = centerY + (direction === "decrease" ? -1 : 1) * directionOffset;
3003
+ const tailY = centerY + (direction === "decrease" ? 1 : -1) * directionOffset;
2911
3004
  context.moveTo(centerX, tipY);
2912
- context.lineTo(centerX - rect.width * 0.22, tailY);
2913
- context.lineTo(centerX + rect.width * 0.22, tailY);
3005
+ context.lineTo(centerX - crossAxisOffset, tailY);
3006
+ context.lineTo(centerX + crossAxisOffset, tailY);
2914
3007
  }
2915
3008
  context.closePath();
2916
3009
  context.fill();
@@ -2963,25 +3056,22 @@ function drawPivotGridRect(context, rect, color, options) {
2963
3056
  context.stroke();
2964
3057
  context.restore();
2965
3058
  }
2966
- function drawPivotViewportRightBorder(context, rect, color) {
2967
- const x = rect.x + rect.width - 0.5;
2968
- context.save();
2969
- context.strokeStyle = color;
2970
- context.lineWidth = 1;
2971
- context.beginPath();
2972
- context.moveTo(x, rect.y);
2973
- context.lineTo(x, rect.y + rect.height);
2974
- context.stroke();
2975
- context.restore();
3059
+ function clipPivotViewport(context, rect, radius = 8) {
3060
+ appendRoundedRectPath(context, rect, radius);
3061
+ context.clip();
2976
3062
  }
2977
- function drawPivotViewportBottomBorder(context, rect, color) {
2978
- const y = rect.y + rect.height - 0.5;
3063
+ function drawPivotViewportBorder(context, rect, color, radius = 8) {
3064
+ const borderRect = {
3065
+ x: rect.x + 0.5,
3066
+ y: rect.y + 0.5,
3067
+ width: Math.max(rect.width - 1, 0),
3068
+ height: Math.max(rect.height - 1, 0)
3069
+ };
3070
+ if (borderRect.width <= 0 || borderRect.height <= 0) return;
2979
3071
  context.save();
2980
3072
  context.strokeStyle = color;
2981
3073
  context.lineWidth = 1;
2982
- context.beginPath();
2983
- context.moveTo(rect.x, y);
2984
- context.lineTo(rect.x + rect.width, y);
3074
+ appendRoundedRectPath(context, borderRect, radius);
2985
3075
  context.stroke();
2986
3076
  context.restore();
2987
3077
  }
@@ -2999,6 +3089,21 @@ function drawPivotHeaderBoundaries(context, options, color) {
2999
3089
  context.stroke();
3000
3090
  context.restore();
3001
3091
  }
3092
+ function appendRoundedRectPath(context, rect, radius) {
3093
+ const nextRadius = Math.max(
3094
+ Math.min(radius, rect.width / 2, rect.height / 2),
3095
+ 0
3096
+ );
3097
+ const right = rect.x + rect.width;
3098
+ const bottom = rect.y + rect.height;
3099
+ context.beginPath();
3100
+ context.moveTo(rect.x + nextRadius, rect.y);
3101
+ context.arcTo(right, rect.y, right, bottom, nextRadius);
3102
+ context.arcTo(right, bottom, rect.x, bottom, nextRadius);
3103
+ context.arcTo(rect.x, bottom, rect.x, rect.y, nextRadius);
3104
+ context.arcTo(rect.x, rect.y, right, rect.y, nextRadius);
3105
+ context.closePath();
3106
+ }
3002
3107
 
3003
3108
  // src/domain/layout/sticky-row-header.ts
3004
3109
  function resolveStickyRowHeaderContentRect(params) {
@@ -3035,7 +3140,15 @@ function renderPivotTable(params) {
3035
3140
  activeNodePathKey
3036
3141
  );
3037
3142
  const areaSelection = isPivotAreaSelection(layout, params.selection);
3143
+ const viewportWidth = resolvePivotViewportWidth(layout);
3038
3144
  context.clearRect(0, 0, layout.width, layout.height);
3145
+ context.save();
3146
+ clipPivotViewport(context, {
3147
+ x: 0,
3148
+ y: 0,
3149
+ width: viewportWidth,
3150
+ height: layout.height
3151
+ });
3039
3152
  context.font = `${theme.fontSize}px ${theme.fontFamily}`;
3040
3153
  context.textBaseline = "middle";
3041
3154
  withClip(context, layout.reportFilterRect, () => {
@@ -3149,17 +3262,13 @@ function renderPivotTable(params) {
3149
3262
  theme.borderColor
3150
3263
  );
3151
3264
  if (options.debug) drawDebugOverlay(context, layout, theme);
3152
- drawPivotScrollbars(context, layout.scrollbar, theme.borderColor);
3153
- drawPivotViewportRightBorder(
3154
- context,
3155
- { x: 0, y: 0, width: layout.tableWidth, height: contentHeight },
3156
- theme.borderColor
3157
- );
3158
- drawPivotViewportBottomBorder(
3159
- context,
3160
- { x: 0, y: 0, width: layout.tableWidth, height: contentHeight },
3161
- theme.borderColor
3162
- );
3265
+ drawPivotScrollbars(context, layout.scrollbar, theme.borderColor, {
3266
+ top: 0,
3267
+ height: contentHeight,
3268
+ headerBottom: layout.bodyRect.y,
3269
+ headerBackgroundColor: theme.columnHeaderBackgroundColor,
3270
+ bodyBackgroundColor: theme.backgroundColor
3271
+ });
3163
3272
  const selectionRect = resolvePivotSelectionRect(layout, params.selection);
3164
3273
  if (selectionRect) {
3165
3274
  const selectionClipRect = resolvePivotSelectionClipRect(
@@ -3177,11 +3286,22 @@ function renderPivotTable(params) {
3177
3286
  if (params.resizeGuideX != null) {
3178
3287
  drawPivotResizeGuide(context, params.resizeGuideX, contentHeight);
3179
3288
  }
3289
+ context.restore();
3290
+ drawPivotViewportBorder(
3291
+ context,
3292
+ { x: 0, y: 0, width: viewportWidth, height: contentHeight },
3293
+ theme.borderColor
3294
+ );
3180
3295
  return {
3181
3296
  headerCellCount: layout.reportFilterCells.length + layout.rowFieldHeaderCells.length + layout.rowHeaderCells.length + layout.columnHeaderCells.length,
3182
3297
  bodyCellCount: layout.bodyCells.length
3183
3298
  };
3184
3299
  }
3300
+ function resolvePivotViewportWidth(layout) {
3301
+ const horizontalRight = layout.scrollbar.horizontal ? layout.scrollbar.horizontal.increaseButton.x + layout.scrollbar.horizontal.increaseButton.width : 0;
3302
+ const verticalRight = layout.scrollbar.vertical ? layout.scrollbar.vertical.decreaseButton.x + layout.scrollbar.vertical.decreaseButton.width : 0;
3303
+ return Math.max(layout.tableWidth, horizontalRight, verticalRight);
3304
+ }
3185
3305
  function drawPivotResizeGuide(context, x, height) {
3186
3306
  context.save();
3187
3307
  context.strokeStyle = "#1677ff";
@@ -3935,6 +4055,16 @@ function hitTestPivotScrollbar(layout, x, y) {
3935
4055
  }
3936
4056
  return null;
3937
4057
  }
4058
+ function resolvePivotScrollbarTrackScroll(params) {
4059
+ const movableLength = Math.max(params.trackLength - params.thumbLength, 0);
4060
+ if (movableLength === 0) return 0;
4061
+ const thumbStart = clamp(
4062
+ params.pointerValue - params.thumbLength / 2,
4063
+ params.trackStart,
4064
+ params.trackStart + movableLength
4065
+ );
4066
+ return (thumbStart - params.trackStart) / movableLength * params.maxScroll;
4067
+ }
3938
4068
  function resolveRole(layout, x, y) {
3939
4069
  if (isPointInRect(x, y, layout.thumb)) return "thumb";
3940
4070
  if (isPointInRect(x, y, layout.decreaseButton)) return "decrease-button";
@@ -4101,6 +4231,8 @@ var PivotTable = class {
4101
4231
  __publicField(this, "wheelScrollTarget", null);
4102
4232
  __publicField(this, "wheelScrollFrameId", null);
4103
4233
  __publicField(this, "wheelScrollLastTime", 0);
4234
+ __publicField(this, "continuousScrollTimer", null);
4235
+ __publicField(this, "continuousScrollPointerId", null);
4104
4236
  __publicField(this, "resizeSession", null);
4105
4237
  __publicField(this, "resizeGuideX", null);
4106
4238
  __publicField(this, "suppressNextClick", false);
@@ -4179,6 +4311,7 @@ var PivotTable = class {
4179
4311
  this.scheduleRender();
4180
4312
  });
4181
4313
  __publicField(this, "handleClick", (event) => {
4314
+ this.options.ui?.onContextMenuRequest?.(null);
4182
4315
  if (this.suppressNextClick) {
4183
4316
  this.suppressNextClick = false;
4184
4317
  return;
@@ -4497,6 +4630,8 @@ var PivotTable = class {
4497
4630
  });
4498
4631
  __publicField(this, "handlePointerUp", (event) => {
4499
4632
  if (!this.host) return;
4633
+ const endedContinuousScroll = this.continuousScrollPointerId === event.pointerId;
4634
+ if (endedContinuousScroll) this.stopContinuousScrollbarScroll();
4500
4635
  const endedCellSelection = this.cellSelectionDrag?.pointerId === event.pointerId;
4501
4636
  if (endedCellSelection) this.cellSelectionDrag = null;
4502
4637
  if (this.textSelectionDrag?.pointerId === event.pointerId) {
@@ -4515,7 +4650,7 @@ var PivotTable = class {
4515
4650
  if (this.scrollbarDrag?.pointerId === event.pointerId) {
4516
4651
  this.scrollbarDrag = null;
4517
4652
  }
4518
- if (!this.resizeSession && !this.scrollbarDrag && !endedCellSelection && !endedRowHeaderSelection && !this.host.root.hasPointerCapture(event.pointerId))
4653
+ if (!this.resizeSession && !this.scrollbarDrag && !endedContinuousScroll && !endedCellSelection && !endedRowHeaderSelection && !this.host.root.hasPointerCapture(event.pointerId))
4519
4654
  return;
4520
4655
  if (this.host.root.hasPointerCapture(event.pointerId)) {
4521
4656
  this.host.root.releasePointerCapture(event.pointerId);
@@ -4761,6 +4896,7 @@ var PivotTable = class {
4761
4896
  if (this.frameId !== null) cancelAnimationFrame(this.frameId);
4762
4897
  this.frameId = null;
4763
4898
  this.stopWheelScrollSmoothing();
4899
+ this.stopContinuousScrollbarScroll();
4764
4900
  this.stopResizeObserver?.();
4765
4901
  this.stopResizeObserver = null;
4766
4902
  this.host?.root.removeEventListener("pointermove", this.handlePointerMove);
@@ -5129,17 +5265,27 @@ var PivotTable = class {
5129
5265
  event.preventDefault();
5130
5266
  this.suppressNextClick = true;
5131
5267
  if (hit.role === "decrease-button" || hit.role === "increase-button") {
5132
- this.stepScrollbar(hit.axis, hit.role === "decrease-button" ? -1 : 1);
5268
+ this.startContinuousScrollbarScroll(
5269
+ hit.axis,
5270
+ hit.role === "decrease-button" ? -1 : 1,
5271
+ event.pointerId
5272
+ );
5273
+ this.host.root.setPointerCapture(event.pointerId);
5133
5274
  return;
5134
5275
  }
5135
5276
  const rootRect = this.host.root.getBoundingClientRect();
5136
5277
  const pointer = hit.axis === "horizontal" ? event.clientX - rootRect.left : event.clientY - rootRect.top;
5137
5278
  if (hit.role === "track") {
5138
- const thumbStart2 = hit.axis === "horizontal" ? axisLayout.thumb.x : axisLayout.thumb.y;
5139
- const direction = pointer < thumbStart2 ? -1 : 1;
5279
+ const nextScroll = resolvePivotScrollbarTrackScroll({
5280
+ pointerValue: pointer,
5281
+ trackStart: hit.axis === "horizontal" ? axisLayout.track.x : axisLayout.track.y,
5282
+ trackLength: hit.axis === "horizontal" ? axisLayout.track.width : axisLayout.track.height,
5283
+ thumbLength: hit.axis === "horizontal" ? axisLayout.thumb.width : axisLayout.thumb.height,
5284
+ maxScroll: hit.axis === "horizontal" ? this.layout.viewport.maxScrollLeft : this.layout.viewport.maxScrollTop
5285
+ });
5140
5286
  this.applyScrollPosition(
5141
- this.scroll.left + (hit.axis === "horizontal" ? direction * this.layout.bodyRect.width : 0),
5142
- this.scroll.top + (hit.axis === "vertical" ? direction * this.layout.bodyRect.height : 0)
5287
+ hit.axis === "horizontal" ? nextScroll : this.scroll.left,
5288
+ hit.axis === "vertical" ? nextScroll : this.scroll.top
5143
5289
  );
5144
5290
  return;
5145
5291
  }
@@ -5183,6 +5329,21 @@ var PivotTable = class {
5183
5329
  this.scroll.top + (axis === "vertical" ? direction * this.layout.rowHeight : 0)
5184
5330
  );
5185
5331
  }
5332
+ startContinuousScrollbarScroll(axis, direction, pointerId) {
5333
+ this.stopContinuousScrollbarScroll();
5334
+ this.continuousScrollPointerId = pointerId;
5335
+ this.stepScrollbar(axis, direction);
5336
+ this.continuousScrollTimer = setInterval(() => {
5337
+ this.stepScrollbar(axis, direction);
5338
+ }, 80);
5339
+ }
5340
+ stopContinuousScrollbarScroll() {
5341
+ if (this.continuousScrollTimer !== null) {
5342
+ clearInterval(this.continuousScrollTimer);
5343
+ this.continuousScrollTimer = null;
5344
+ }
5345
+ this.continuousScrollPointerId = null;
5346
+ }
5186
5347
  applyScrollPosition(left, top) {
5187
5348
  if (!this.layout) return;
5188
5349
  const next = {