@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.cjs +221 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +221 -60
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
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
|
|
2879
|
-
|
|
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
|
-
|
|
2883
|
-
context.
|
|
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) *
|
|
2904
|
-
const tailX = centerX + (direction === "decrease" ? 1 : -1) *
|
|
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 -
|
|
2907
|
-
context.lineTo(tailX, centerY +
|
|
2999
|
+
context.lineTo(tailX, centerY - crossAxisOffset);
|
|
3000
|
+
context.lineTo(tailX, centerY + crossAxisOffset);
|
|
2908
3001
|
} else {
|
|
2909
|
-
const tipY = centerY + (direction === "decrease" ? -1 : 1) *
|
|
2910
|
-
const tailY = centerY + (direction === "decrease" ? 1 : -1) *
|
|
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 -
|
|
2913
|
-
context.lineTo(centerX +
|
|
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
|
|
2967
|
-
|
|
2968
|
-
context.
|
|
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
|
|
2978
|
-
const
|
|
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
|
|
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
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
theme.
|
|
3157
|
-
|
|
3158
|
-
|
|
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.
|
|
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
|
|
5139
|
-
|
|
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
|
-
|
|
5142
|
-
|
|
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 = {
|