@canvas-components/pivot-table 0.1.9 → 0.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.
- package/dist/index.cjs +377 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -21
- package/dist/index.d.ts +34 -21
- package/dist/index.js +376 -74
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stringifyDataIndex, getValueByDataIndex, clamp, serializeCsvRows, isPointInRect, copyTextSync, copyText } from '@canvas-components/utils';
|
|
1
|
+
import { stringifyDataIndex, getValueByDataIndex, dividePreciseNumber, addPreciseNumbers, clamp, serializeCsvRows, isPointInRect, copyTextSync, copyText } from '@canvas-components/utils';
|
|
2
2
|
export { getValueByDataIndex, isSameDataIndex, stringifyDataIndex } from '@canvas-components/utils';
|
|
3
3
|
import * as XLSX from 'xlsx';
|
|
4
4
|
|
|
@@ -309,8 +309,6 @@ function indexPivotNodes(root) {
|
|
|
309
309
|
visit(root);
|
|
310
310
|
return nodeMap;
|
|
311
311
|
}
|
|
312
|
-
|
|
313
|
-
// src/domain/aggregation/built-in-aggregators.ts
|
|
314
312
|
function createBuiltInPivotAggregators() {
|
|
315
313
|
return {
|
|
316
314
|
sum: createNumericAggregator("sum"),
|
|
@@ -341,14 +339,14 @@ function createNumericAggregator(type) {
|
|
|
341
339
|
return;
|
|
342
340
|
}
|
|
343
341
|
state.numericCount += 1;
|
|
344
|
-
state.sum
|
|
342
|
+
state.sum = addPreciseNumbers(state.sum, numericValue) ?? state.sum;
|
|
345
343
|
state.min = state.min == null ? numericValue : Math.min(state.min, numericValue);
|
|
346
344
|
state.max = state.max == null ? numericValue : Math.max(state.max, numericValue);
|
|
347
345
|
},
|
|
348
346
|
merge(state, source) {
|
|
349
347
|
state.count += source.count;
|
|
350
348
|
state.numericCount += source.numericCount;
|
|
351
|
-
state.sum
|
|
349
|
+
state.sum = addPreciseNumbers(state.sum, source.sum) ?? state.sum;
|
|
352
350
|
state.min = mergeMinimum(state.min, source.min);
|
|
353
351
|
state.max = mergeMaximum(state.max, source.max);
|
|
354
352
|
source.distinctValues.forEach((value) => state.distinctValues.add(value));
|
|
@@ -356,9 +354,11 @@ function createNumericAggregator(type) {
|
|
|
356
354
|
finalize(state) {
|
|
357
355
|
if (type === "count") return state.count;
|
|
358
356
|
if (type === "distinctCount") return state.distinctValues.size;
|
|
359
|
-
if (type === "sum") return state.sum;
|
|
357
|
+
if (type === "sum") return Number(state.sum);
|
|
360
358
|
if (type === "avg") {
|
|
361
|
-
|
|
359
|
+
if (state.numericCount === 0) return null;
|
|
360
|
+
const average = dividePreciseNumber(state.sum, state.numericCount);
|
|
361
|
+
return average == null ? null : Number(average);
|
|
362
362
|
}
|
|
363
363
|
if (type === "min") return state.min;
|
|
364
364
|
return state.max;
|
|
@@ -369,7 +369,7 @@ function createAccumulator() {
|
|
|
369
369
|
return {
|
|
370
370
|
count: 0,
|
|
371
371
|
numericCount: 0,
|
|
372
|
-
sum: 0,
|
|
372
|
+
sum: "0",
|
|
373
373
|
min: null,
|
|
374
374
|
max: null,
|
|
375
375
|
distinctValues: /* @__PURE__ */ new Set()
|
|
@@ -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, {
|
|
@@ -2750,18 +2748,50 @@ function resolvePivotSelectionKind(selection) {
|
|
|
2750
2748
|
}
|
|
2751
2749
|
return selection?.activeNode?.axis ?? "cell";
|
|
2752
2750
|
}
|
|
2753
|
-
function drawPivotSelectionBorder(context, rect, color) {
|
|
2751
|
+
function drawPivotSelectionBorder(context, rect, color, options) {
|
|
2754
2752
|
context.save();
|
|
2755
2753
|
context.strokeStyle = color;
|
|
2756
2754
|
context.lineWidth = 1;
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2755
|
+
const left = rect.x + 0.5;
|
|
2756
|
+
const top = rect.y + 0.5;
|
|
2757
|
+
const width = Math.max(rect.width - 1, 0);
|
|
2758
|
+
const height = Math.max(rect.height - 1, 0);
|
|
2759
|
+
const right = left + width;
|
|
2760
|
+
const bottom = top + height;
|
|
2761
|
+
const viewport = options?.viewportRect;
|
|
2762
|
+
const radius = Math.min(options?.radius ?? 8, width / 2, height / 2);
|
|
2763
|
+
const topLeft = viewport && isSameCoordinate(rect.x, viewport.x) && isSameCoordinate(rect.y, viewport.y) ? radius : 0;
|
|
2764
|
+
const topRight = viewport && isSameCoordinate(rect.x + rect.width, viewport.x + viewport.width) && isSameCoordinate(rect.y, viewport.y) ? radius : 0;
|
|
2765
|
+
const bottomRight = viewport && isSameCoordinate(rect.x + rect.width, viewport.x + viewport.width) && isSameCoordinate(rect.y + rect.height, viewport.y + viewport.height) ? radius : 0;
|
|
2766
|
+
const bottomLeft = viewport && isSameCoordinate(rect.x, viewport.x) && isSameCoordinate(rect.y + rect.height, viewport.y + viewport.height) ? radius : 0;
|
|
2767
|
+
if (!topLeft && !topRight && !bottomRight && !bottomLeft) {
|
|
2768
|
+
context.strokeRect(left, top, width, height);
|
|
2769
|
+
context.restore();
|
|
2770
|
+
return;
|
|
2771
|
+
}
|
|
2772
|
+
context.beginPath();
|
|
2773
|
+
context.moveTo(left + topLeft, top);
|
|
2774
|
+
context.lineTo(right - topRight, top);
|
|
2775
|
+
if (topRight) context.arcTo(right, top, right, top + topRight, topRight);
|
|
2776
|
+
else context.lineTo(right, top);
|
|
2777
|
+
context.lineTo(right, bottom - bottomRight);
|
|
2778
|
+
if (bottomRight) {
|
|
2779
|
+
context.arcTo(right, bottom, right - bottomRight, bottom, bottomRight);
|
|
2780
|
+
} else context.lineTo(right, bottom);
|
|
2781
|
+
context.lineTo(left + bottomLeft, bottom);
|
|
2782
|
+
if (bottomLeft) {
|
|
2783
|
+
context.arcTo(left, bottom, left, bottom - bottomLeft, bottomLeft);
|
|
2784
|
+
} else context.lineTo(left, bottom);
|
|
2785
|
+
context.lineTo(left, top + topLeft);
|
|
2786
|
+
if (topLeft) context.arcTo(left, top, left + topLeft, top, topLeft);
|
|
2787
|
+
else context.lineTo(left, top);
|
|
2788
|
+
context.closePath();
|
|
2789
|
+
context.stroke();
|
|
2763
2790
|
context.restore();
|
|
2764
2791
|
}
|
|
2792
|
+
function isSameCoordinate(first, second) {
|
|
2793
|
+
return Math.abs(first - second) < 0.01;
|
|
2794
|
+
}
|
|
2765
2795
|
function resolveSelectionIndexes(layout, selection) {
|
|
2766
2796
|
const range = selection?.ranges[0];
|
|
2767
2797
|
if (range) {
|
|
@@ -2859,29 +2889,127 @@ var defaultPivotTableTheme = {
|
|
|
2859
2889
|
};
|
|
2860
2890
|
|
|
2861
2891
|
// src/rendering/draw-scrollbars.ts
|
|
2862
|
-
function drawPivotScrollbars(context, layout, borderColor) {
|
|
2892
|
+
function drawPivotScrollbars(context, layout, borderColor, verticalFrame) {
|
|
2863
2893
|
context.save();
|
|
2894
|
+
if (layout.horizontal && verticalFrame) {
|
|
2895
|
+
drawHorizontalScrollbarMask(
|
|
2896
|
+
context,
|
|
2897
|
+
layout.horizontal,
|
|
2898
|
+
verticalFrame.bodyBackgroundColor
|
|
2899
|
+
);
|
|
2900
|
+
}
|
|
2901
|
+
if (layout.vertical && verticalFrame) {
|
|
2902
|
+
drawVerticalScrollbarFrame(
|
|
2903
|
+
context,
|
|
2904
|
+
layout.vertical,
|
|
2905
|
+
verticalFrame,
|
|
2906
|
+
borderColor
|
|
2907
|
+
);
|
|
2908
|
+
}
|
|
2864
2909
|
if (layout.horizontal) {
|
|
2865
2910
|
drawAxis(context, layout.horizontal, "horizontal", borderColor);
|
|
2866
2911
|
}
|
|
2867
2912
|
if (layout.vertical) {
|
|
2868
2913
|
drawAxis(context, layout.vertical, "vertical", borderColor);
|
|
2869
2914
|
}
|
|
2915
|
+
if (layout.horizontal) {
|
|
2916
|
+
drawHorizontalScrollbarTopBorder(
|
|
2917
|
+
context,
|
|
2918
|
+
layout.horizontal,
|
|
2919
|
+
layout.vertical,
|
|
2920
|
+
borderColor
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
context.restore();
|
|
2924
|
+
}
|
|
2925
|
+
function drawHorizontalScrollbarMask(context, layout, backgroundColor) {
|
|
2926
|
+
const left = layout.decreaseButton.x;
|
|
2927
|
+
const right = layout.increaseButton.x + layout.increaseButton.width;
|
|
2928
|
+
const top = layout.decreaseButton.y;
|
|
2929
|
+
const height = layout.decreaseButton.height;
|
|
2930
|
+
if (right <= left || height <= 0) return;
|
|
2931
|
+
context.save();
|
|
2932
|
+
context.fillStyle = backgroundColor;
|
|
2933
|
+
context.fillRect(left, top, right - left, height);
|
|
2934
|
+
context.restore();
|
|
2935
|
+
}
|
|
2936
|
+
function drawHorizontalScrollbarTopBorder(context, horizontal, vertical, borderColor) {
|
|
2937
|
+
const left = Math.round(horizontal.decreaseButton.x) + 0.5;
|
|
2938
|
+
const horizontalRight = horizontal.increaseButton.x + horizontal.increaseButton.width;
|
|
2939
|
+
const verticalRight = vertical ? vertical.decreaseButton.x + vertical.decreaseButton.width : horizontalRight;
|
|
2940
|
+
const right = Math.round(Math.max(horizontalRight, verticalRight)) - 0.5;
|
|
2941
|
+
const top = Math.round(horizontal.decreaseButton.y) + 0.5;
|
|
2942
|
+
if (right <= left) return;
|
|
2943
|
+
context.save();
|
|
2944
|
+
context.strokeStyle = borderColor;
|
|
2945
|
+
context.lineWidth = 1;
|
|
2946
|
+
context.beginPath();
|
|
2947
|
+
context.moveTo(left, top);
|
|
2948
|
+
context.lineTo(right, top);
|
|
2949
|
+
context.stroke();
|
|
2870
2950
|
context.restore();
|
|
2871
2951
|
}
|
|
2872
2952
|
function drawAxis(context, layout, axis, borderColor) {
|
|
2873
|
-
drawTrack(context, layout.track, borderColor);
|
|
2874
2953
|
drawButton(context, layout.decreaseButton, axis, "decrease");
|
|
2875
2954
|
drawButton(context, layout.increaseButton, axis, "increase");
|
|
2876
2955
|
drawThumb(context, layout.thumb);
|
|
2956
|
+
drawTrackBorder(context, layout.track, axis, borderColor);
|
|
2957
|
+
}
|
|
2958
|
+
function drawTrackBorder(context, rect, axis, borderColor) {
|
|
2959
|
+
const left = Math.round(rect.x) + 0.5;
|
|
2960
|
+
const right = Math.round(rect.x + rect.width) - 0.5;
|
|
2961
|
+
const top = Math.round(rect.y) + 0.5;
|
|
2962
|
+
const bottom = Math.round(rect.y + rect.height) - 0.5;
|
|
2963
|
+
if (right <= left || bottom <= top) return;
|
|
2964
|
+
context.save();
|
|
2965
|
+
context.strokeStyle = borderColor;
|
|
2966
|
+
context.lineWidth = 1;
|
|
2967
|
+
context.beginPath();
|
|
2968
|
+
if (axis === "horizontal") {
|
|
2969
|
+
context.moveTo(left, top);
|
|
2970
|
+
context.lineTo(right, top);
|
|
2971
|
+
} else {
|
|
2972
|
+
context.moveTo(left, top);
|
|
2973
|
+
context.lineTo(left, bottom);
|
|
2974
|
+
}
|
|
2975
|
+
context.stroke();
|
|
2976
|
+
context.restore();
|
|
2877
2977
|
}
|
|
2878
|
-
function
|
|
2879
|
-
|
|
2978
|
+
function drawVerticalScrollbarFrame(context, layout, frame, borderColor) {
|
|
2979
|
+
const left = Math.round(layout.decreaseButton.x) + 0.5;
|
|
2980
|
+
const top = Math.round(frame.top) + 0.5;
|
|
2981
|
+
const bottom = Math.round(frame.top + frame.height) - 0.5;
|
|
2982
|
+
const headerBottom = Math.round(frame.headerBottom) + 0.5;
|
|
2983
|
+
if (bottom <= top) return;
|
|
2984
|
+
context.save();
|
|
2985
|
+
context.fillStyle = frame.headerBackgroundColor;
|
|
2986
|
+
context.fillRect(
|
|
2987
|
+
layout.decreaseButton.x,
|
|
2988
|
+
frame.top,
|
|
2989
|
+
layout.decreaseButton.width,
|
|
2990
|
+
Math.max(frame.headerBottom - frame.top, 0)
|
|
2991
|
+
);
|
|
2992
|
+
context.fillStyle = frame.bodyBackgroundColor;
|
|
2993
|
+
context.fillRect(
|
|
2994
|
+
layout.decreaseButton.x,
|
|
2995
|
+
frame.headerBottom,
|
|
2996
|
+
layout.decreaseButton.width,
|
|
2997
|
+
Math.max(frame.top + frame.height - frame.headerBottom, 0)
|
|
2998
|
+
);
|
|
2880
2999
|
context.strokeStyle = borderColor;
|
|
2881
3000
|
context.lineWidth = 1;
|
|
2882
|
-
|
|
2883
|
-
context.
|
|
3001
|
+
context.beginPath();
|
|
3002
|
+
context.moveTo(left, top);
|
|
3003
|
+
context.lineTo(left, bottom);
|
|
2884
3004
|
context.stroke();
|
|
3005
|
+
if (headerBottom > top && headerBottom < bottom) {
|
|
3006
|
+
const right = Math.round(layout.decreaseButton.x + layout.decreaseButton.width) - 0.5;
|
|
3007
|
+
context.beginPath();
|
|
3008
|
+
context.moveTo(left, headerBottom);
|
|
3009
|
+
context.lineTo(right, headerBottom);
|
|
3010
|
+
context.stroke();
|
|
3011
|
+
}
|
|
3012
|
+
context.restore();
|
|
2885
3013
|
}
|
|
2886
3014
|
function drawThumb(context, rect) {
|
|
2887
3015
|
context.fillStyle = "rgba(100, 116, 139, 0.8)";
|
|
@@ -2889,28 +3017,25 @@ function drawThumb(context, rect) {
|
|
|
2889
3017
|
context.fill();
|
|
2890
3018
|
}
|
|
2891
3019
|
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
3020
|
context.fillStyle = "rgba(71, 85, 105, 0.88)";
|
|
2899
3021
|
context.beginPath();
|
|
2900
3022
|
const centerX = rect.x + rect.width / 2;
|
|
2901
3023
|
const centerY = rect.y + rect.height / 2;
|
|
3024
|
+
const iconSize = Math.min(rect.width, rect.height) * 0.64;
|
|
3025
|
+
const directionOffset = iconSize * 0.4;
|
|
3026
|
+
const crossAxisOffset = iconSize / 2;
|
|
2902
3027
|
if (axis === "horizontal") {
|
|
2903
|
-
const tipX = centerX + (direction === "decrease" ? -1 : 1) *
|
|
2904
|
-
const tailX = centerX + (direction === "decrease" ? 1 : -1) *
|
|
3028
|
+
const tipX = centerX + (direction === "decrease" ? -1 : 1) * directionOffset;
|
|
3029
|
+
const tailX = centerX + (direction === "decrease" ? 1 : -1) * directionOffset;
|
|
2905
3030
|
context.moveTo(tipX, centerY);
|
|
2906
|
-
context.lineTo(tailX, centerY -
|
|
2907
|
-
context.lineTo(tailX, centerY +
|
|
3031
|
+
context.lineTo(tailX, centerY - crossAxisOffset);
|
|
3032
|
+
context.lineTo(tailX, centerY + crossAxisOffset);
|
|
2908
3033
|
} else {
|
|
2909
|
-
const tipY = centerY + (direction === "decrease" ? -1 : 1) *
|
|
2910
|
-
const tailY = centerY + (direction === "decrease" ? 1 : -1) *
|
|
3034
|
+
const tipY = centerY + (direction === "decrease" ? -1 : 1) * directionOffset;
|
|
3035
|
+
const tailY = centerY + (direction === "decrease" ? 1 : -1) * directionOffset;
|
|
2911
3036
|
context.moveTo(centerX, tipY);
|
|
2912
|
-
context.lineTo(centerX -
|
|
2913
|
-
context.lineTo(centerX +
|
|
3037
|
+
context.lineTo(centerX - crossAxisOffset, tailY);
|
|
3038
|
+
context.lineTo(centerX + crossAxisOffset, tailY);
|
|
2914
3039
|
}
|
|
2915
3040
|
context.closePath();
|
|
2916
3041
|
context.fill();
|
|
@@ -2974,14 +3099,22 @@ function drawPivotViewportRightBorder(context, rect, color) {
|
|
|
2974
3099
|
context.stroke();
|
|
2975
3100
|
context.restore();
|
|
2976
3101
|
}
|
|
2977
|
-
function
|
|
2978
|
-
|
|
3102
|
+
function clipPivotViewport(context, rect, radius = 8) {
|
|
3103
|
+
appendRoundedRectPath(context, rect, radius);
|
|
3104
|
+
context.clip();
|
|
3105
|
+
}
|
|
3106
|
+
function drawPivotViewportBorder(context, rect, color, radius = 8) {
|
|
3107
|
+
const borderRect = {
|
|
3108
|
+
x: rect.x + 0.5,
|
|
3109
|
+
y: rect.y + 0.5,
|
|
3110
|
+
width: Math.max(rect.width - 1, 0),
|
|
3111
|
+
height: Math.max(rect.height - 1, 0)
|
|
3112
|
+
};
|
|
3113
|
+
if (borderRect.width <= 0 || borderRect.height <= 0) return;
|
|
2979
3114
|
context.save();
|
|
2980
3115
|
context.strokeStyle = color;
|
|
2981
3116
|
context.lineWidth = 1;
|
|
2982
|
-
context
|
|
2983
|
-
context.moveTo(rect.x, y);
|
|
2984
|
-
context.lineTo(rect.x + rect.width, y);
|
|
3117
|
+
appendRoundedRectPath(context, borderRect, radius);
|
|
2985
3118
|
context.stroke();
|
|
2986
3119
|
context.restore();
|
|
2987
3120
|
}
|
|
@@ -2999,6 +3132,21 @@ function drawPivotHeaderBoundaries(context, options, color) {
|
|
|
2999
3132
|
context.stroke();
|
|
3000
3133
|
context.restore();
|
|
3001
3134
|
}
|
|
3135
|
+
function appendRoundedRectPath(context, rect, radius) {
|
|
3136
|
+
const nextRadius = Math.max(
|
|
3137
|
+
Math.min(radius, rect.width / 2, rect.height / 2),
|
|
3138
|
+
0
|
|
3139
|
+
);
|
|
3140
|
+
const right = rect.x + rect.width;
|
|
3141
|
+
const bottom = rect.y + rect.height;
|
|
3142
|
+
context.beginPath();
|
|
3143
|
+
context.moveTo(rect.x + nextRadius, rect.y);
|
|
3144
|
+
context.arcTo(right, rect.y, right, bottom, nextRadius);
|
|
3145
|
+
context.arcTo(right, bottom, rect.x, bottom, nextRadius);
|
|
3146
|
+
context.arcTo(rect.x, bottom, rect.x, rect.y, nextRadius);
|
|
3147
|
+
context.arcTo(rect.x, rect.y, right, rect.y, nextRadius);
|
|
3148
|
+
context.closePath();
|
|
3149
|
+
}
|
|
3002
3150
|
|
|
3003
3151
|
// src/domain/layout/sticky-row-header.ts
|
|
3004
3152
|
function resolveStickyRowHeaderContentRect(params) {
|
|
@@ -3035,7 +3183,21 @@ function renderPivotTable(params) {
|
|
|
3035
3183
|
activeNodePathKey
|
|
3036
3184
|
);
|
|
3037
3185
|
const areaSelection = isPivotAreaSelection(layout, params.selection);
|
|
3186
|
+
const viewportWidth = resolvePivotViewportWidth(layout);
|
|
3187
|
+
const tableViewportRect = {
|
|
3188
|
+
x: 0,
|
|
3189
|
+
y: 0,
|
|
3190
|
+
width: layout.tableWidth,
|
|
3191
|
+
height: layout.height
|
|
3192
|
+
};
|
|
3038
3193
|
context.clearRect(0, 0, layout.width, layout.height);
|
|
3194
|
+
context.save();
|
|
3195
|
+
clipPivotViewport(context, {
|
|
3196
|
+
x: 0,
|
|
3197
|
+
y: 0,
|
|
3198
|
+
width: viewportWidth,
|
|
3199
|
+
height: layout.height
|
|
3200
|
+
});
|
|
3039
3201
|
context.font = `${theme.fontSize}px ${theme.fontFamily}`;
|
|
3040
3202
|
context.textBaseline = "middle";
|
|
3041
3203
|
withClip(context, layout.reportFilterRect, () => {
|
|
@@ -3068,7 +3230,7 @@ function renderPivotTable(params) {
|
|
|
3068
3230
|
(cell) => drawPivotGridRect(context, cell.rect, theme.borderColor, {
|
|
3069
3231
|
skipTop: true,
|
|
3070
3232
|
skipLeft: cell.rect.x > 0,
|
|
3071
|
-
skipRight:
|
|
3233
|
+
skipRight: isSameCoordinate2(
|
|
3072
3234
|
cell.rect.x + cell.rect.width,
|
|
3073
3235
|
layout.rowHeaderRect.x + layout.rowHeaderRect.width
|
|
3074
3236
|
)
|
|
@@ -3091,11 +3253,11 @@ function renderPivotTable(params) {
|
|
|
3091
3253
|
(cell) => drawPivotGridRect(context, cell.rect, theme.borderColor, {
|
|
3092
3254
|
skipTop: cell.rect.y > 0,
|
|
3093
3255
|
skipLeft: true,
|
|
3094
|
-
skipRight:
|
|
3256
|
+
skipRight: isSameCoordinate2(
|
|
3095
3257
|
cell.rect.x + cell.rect.width,
|
|
3096
3258
|
layout.tableWidth
|
|
3097
3259
|
),
|
|
3098
|
-
skipBottom:
|
|
3260
|
+
skipBottom: isSameCoordinate2(
|
|
3099
3261
|
cell.rect.y + cell.rect.height,
|
|
3100
3262
|
layout.columnHeaderRect.y + layout.columnHeaderRect.height
|
|
3101
3263
|
)
|
|
@@ -3127,7 +3289,7 @@ function renderPivotTable(params) {
|
|
|
3127
3289
|
(cell) => drawPivotGridRect(context, cell.rect, theme.borderColor, {
|
|
3128
3290
|
skipTop: true,
|
|
3129
3291
|
skipLeft: true,
|
|
3130
|
-
skipRight:
|
|
3292
|
+
skipRight: isSameCoordinate2(
|
|
3131
3293
|
cell.rect.x + cell.rect.width,
|
|
3132
3294
|
layout.tableWidth
|
|
3133
3295
|
)
|
|
@@ -3149,15 +3311,24 @@ function renderPivotTable(params) {
|
|
|
3149
3311
|
theme.borderColor
|
|
3150
3312
|
);
|
|
3151
3313
|
if (options.debug) drawDebugOverlay(context, layout, theme);
|
|
3152
|
-
drawPivotScrollbars(context, layout.scrollbar, theme.borderColor
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
theme.
|
|
3157
|
-
|
|
3158
|
-
|
|
3314
|
+
drawPivotScrollbars(context, layout.scrollbar, theme.borderColor, {
|
|
3315
|
+
top: 0,
|
|
3316
|
+
height: contentHeight,
|
|
3317
|
+
headerBottom: layout.bodyRect.y,
|
|
3318
|
+
headerBackgroundColor: theme.columnHeaderBackgroundColor,
|
|
3319
|
+
bodyBackgroundColor: theme.backgroundColor
|
|
3320
|
+
});
|
|
3321
|
+
if (params.resizeGuideX != null) {
|
|
3322
|
+
drawPivotResizeGuide(context, params.resizeGuideX, contentHeight);
|
|
3323
|
+
}
|
|
3324
|
+
context.restore();
|
|
3325
|
+
context.save();
|
|
3326
|
+
clipPivotViewport(context, tableViewportRect);
|
|
3327
|
+
drawPivotViewportRightBorder(context, tableViewportRect, theme.borderColor);
|
|
3328
|
+
context.restore();
|
|
3329
|
+
drawPivotViewportBorder(
|
|
3159
3330
|
context,
|
|
3160
|
-
{ x: 0, y: 0, width:
|
|
3331
|
+
{ x: 0, y: 0, width: viewportWidth, height: contentHeight },
|
|
3161
3332
|
theme.borderColor
|
|
3162
3333
|
);
|
|
3163
3334
|
const selectionRect = resolvePivotSelectionRect(layout, params.selection);
|
|
@@ -3166,22 +3337,28 @@ function renderPivotTable(params) {
|
|
|
3166
3337
|
layout,
|
|
3167
3338
|
params.selection
|
|
3168
3339
|
);
|
|
3340
|
+
context.save();
|
|
3341
|
+
clipPivotViewport(context, tableViewportRect);
|
|
3169
3342
|
withClip(context, selectionClipRect, () => {
|
|
3170
3343
|
drawPivotSelectionBorder(
|
|
3171
3344
|
context,
|
|
3172
3345
|
selectionRect,
|
|
3173
|
-
theme.selectionBorderColor
|
|
3346
|
+
theme.selectionBorderColor,
|
|
3347
|
+
{ viewportRect: tableViewportRect }
|
|
3174
3348
|
);
|
|
3175
3349
|
});
|
|
3176
|
-
|
|
3177
|
-
if (params.resizeGuideX != null) {
|
|
3178
|
-
drawPivotResizeGuide(context, params.resizeGuideX, contentHeight);
|
|
3350
|
+
context.restore();
|
|
3179
3351
|
}
|
|
3180
3352
|
return {
|
|
3181
3353
|
headerCellCount: layout.reportFilterCells.length + layout.rowFieldHeaderCells.length + layout.rowHeaderCells.length + layout.columnHeaderCells.length,
|
|
3182
3354
|
bodyCellCount: layout.bodyCells.length
|
|
3183
3355
|
};
|
|
3184
3356
|
}
|
|
3357
|
+
function resolvePivotViewportWidth(layout) {
|
|
3358
|
+
const horizontalRight = layout.scrollbar.horizontal ? layout.scrollbar.horizontal.increaseButton.x + layout.scrollbar.horizontal.increaseButton.width : 0;
|
|
3359
|
+
const verticalRight = layout.scrollbar.vertical ? layout.scrollbar.vertical.decreaseButton.x + layout.scrollbar.vertical.decreaseButton.width : 0;
|
|
3360
|
+
return Math.max(layout.tableWidth, horizontalRight, verticalRight);
|
|
3361
|
+
}
|
|
3185
3362
|
function drawPivotResizeGuide(context, x, height) {
|
|
3186
3363
|
context.save();
|
|
3187
3364
|
context.strokeStyle = "#1677ff";
|
|
@@ -3216,7 +3393,7 @@ function drawDebugOverlay(context, layout, theme) {
|
|
|
3216
3393
|
layout.bodyRect
|
|
3217
3394
|
].forEach((rect) => strokeRect(context, rect, "#f04438"));
|
|
3218
3395
|
context.setLineDash([]);
|
|
3219
|
-
context.font =
|
|
3396
|
+
context.font = `${theme.fontSize}px ${theme.fontFamily}`;
|
|
3220
3397
|
context.textAlign = "left";
|
|
3221
3398
|
context.textBaseline = "top";
|
|
3222
3399
|
context.fillStyle = "#f04438";
|
|
@@ -3475,7 +3652,7 @@ function resolveSlotPathKey(slots, nodeId, indicatorKey) {
|
|
|
3475
3652
|
(slot) => (slot.nodeId ?? "") === nodeId && (!slot.indicatorKey || slot.indicatorKey === indicatorKey)
|
|
3476
3653
|
)?.pathKey ?? null;
|
|
3477
3654
|
}
|
|
3478
|
-
function
|
|
3655
|
+
function isSameCoordinate2(first, second) {
|
|
3479
3656
|
return Math.abs(first - second) < 0.01;
|
|
3480
3657
|
}
|
|
3481
3658
|
function resolveBodyDisplayText(cell, indicator) {
|
|
@@ -3935,6 +4112,16 @@ function hitTestPivotScrollbar(layout, x, y) {
|
|
|
3935
4112
|
}
|
|
3936
4113
|
return null;
|
|
3937
4114
|
}
|
|
4115
|
+
function resolvePivotScrollbarTrackScroll(params) {
|
|
4116
|
+
const movableLength = Math.max(params.trackLength - params.thumbLength, 0);
|
|
4117
|
+
if (movableLength === 0) return 0;
|
|
4118
|
+
const thumbStart = clamp(
|
|
4119
|
+
params.pointerValue - params.thumbLength / 2,
|
|
4120
|
+
params.trackStart,
|
|
4121
|
+
params.trackStart + movableLength
|
|
4122
|
+
);
|
|
4123
|
+
return (thumbStart - params.trackStart) / movableLength * params.maxScroll;
|
|
4124
|
+
}
|
|
3938
4125
|
function resolveRole(layout, x, y) {
|
|
3939
4126
|
if (isPointInRect(x, y, layout.thumb)) return "thumb";
|
|
3940
4127
|
if (isPointInRect(x, y, layout.decreaseButton)) return "decrease-button";
|
|
@@ -4101,6 +4288,8 @@ var PivotTable = class {
|
|
|
4101
4288
|
__publicField(this, "wheelScrollTarget", null);
|
|
4102
4289
|
__publicField(this, "wheelScrollFrameId", null);
|
|
4103
4290
|
__publicField(this, "wheelScrollLastTime", 0);
|
|
4291
|
+
__publicField(this, "continuousScrollTimer", null);
|
|
4292
|
+
__publicField(this, "continuousScrollPointerId", null);
|
|
4104
4293
|
__publicField(this, "resizeSession", null);
|
|
4105
4294
|
__publicField(this, "resizeGuideX", null);
|
|
4106
4295
|
__publicField(this, "suppressNextClick", false);
|
|
@@ -4179,6 +4368,7 @@ var PivotTable = class {
|
|
|
4179
4368
|
this.scheduleRender();
|
|
4180
4369
|
});
|
|
4181
4370
|
__publicField(this, "handleClick", (event) => {
|
|
4371
|
+
this.options.ui?.onContextMenuRequest?.(null);
|
|
4182
4372
|
if (this.suppressNextClick) {
|
|
4183
4373
|
this.suppressNextClick = false;
|
|
4184
4374
|
return;
|
|
@@ -4497,6 +4687,8 @@ var PivotTable = class {
|
|
|
4497
4687
|
});
|
|
4498
4688
|
__publicField(this, "handlePointerUp", (event) => {
|
|
4499
4689
|
if (!this.host) return;
|
|
4690
|
+
const endedContinuousScroll = this.continuousScrollPointerId === event.pointerId;
|
|
4691
|
+
if (endedContinuousScroll) this.stopContinuousScrollbarScroll();
|
|
4500
4692
|
const endedCellSelection = this.cellSelectionDrag?.pointerId === event.pointerId;
|
|
4501
4693
|
if (endedCellSelection) this.cellSelectionDrag = null;
|
|
4502
4694
|
if (this.textSelectionDrag?.pointerId === event.pointerId) {
|
|
@@ -4515,7 +4707,7 @@ var PivotTable = class {
|
|
|
4515
4707
|
if (this.scrollbarDrag?.pointerId === event.pointerId) {
|
|
4516
4708
|
this.scrollbarDrag = null;
|
|
4517
4709
|
}
|
|
4518
|
-
if (!this.resizeSession && !this.scrollbarDrag && !endedCellSelection && !endedRowHeaderSelection && !this.host.root.hasPointerCapture(event.pointerId))
|
|
4710
|
+
if (!this.resizeSession && !this.scrollbarDrag && !endedContinuousScroll && !endedCellSelection && !endedRowHeaderSelection && !this.host.root.hasPointerCapture(event.pointerId))
|
|
4519
4711
|
return;
|
|
4520
4712
|
if (this.host.root.hasPointerCapture(event.pointerId)) {
|
|
4521
4713
|
this.host.root.releasePointerCapture(event.pointerId);
|
|
@@ -4761,6 +4953,7 @@ var PivotTable = class {
|
|
|
4761
4953
|
if (this.frameId !== null) cancelAnimationFrame(this.frameId);
|
|
4762
4954
|
this.frameId = null;
|
|
4763
4955
|
this.stopWheelScrollSmoothing();
|
|
4956
|
+
this.stopContinuousScrollbarScroll();
|
|
4764
4957
|
this.stopResizeObserver?.();
|
|
4765
4958
|
this.stopResizeObserver = null;
|
|
4766
4959
|
this.host?.root.removeEventListener("pointermove", this.handlePointerMove);
|
|
@@ -5066,7 +5259,7 @@ var PivotTable = class {
|
|
|
5066
5259
|
measurePivotText(text) {
|
|
5067
5260
|
const context = this.host?.canvas.getContext("2d");
|
|
5068
5261
|
if (!context) return text.length * 8;
|
|
5069
|
-
context.font = `${this.options.theme?.fontSize ??
|
|
5262
|
+
context.font = `${this.options.theme?.fontSize ?? 14}px ${this.options.theme?.fontFamily ?? "sans-serif"}`;
|
|
5070
5263
|
return context.measureText(text).width;
|
|
5071
5264
|
}
|
|
5072
5265
|
updateRowHeaderSelectionDrag(event) {
|
|
@@ -5129,17 +5322,27 @@ var PivotTable = class {
|
|
|
5129
5322
|
event.preventDefault();
|
|
5130
5323
|
this.suppressNextClick = true;
|
|
5131
5324
|
if (hit.role === "decrease-button" || hit.role === "increase-button") {
|
|
5132
|
-
this.
|
|
5325
|
+
this.startContinuousScrollbarScroll(
|
|
5326
|
+
hit.axis,
|
|
5327
|
+
hit.role === "decrease-button" ? -1 : 1,
|
|
5328
|
+
event.pointerId
|
|
5329
|
+
);
|
|
5330
|
+
this.host.root.setPointerCapture(event.pointerId);
|
|
5133
5331
|
return;
|
|
5134
5332
|
}
|
|
5135
5333
|
const rootRect = this.host.root.getBoundingClientRect();
|
|
5136
5334
|
const pointer = hit.axis === "horizontal" ? event.clientX - rootRect.left : event.clientY - rootRect.top;
|
|
5137
5335
|
if (hit.role === "track") {
|
|
5138
|
-
const
|
|
5139
|
-
|
|
5336
|
+
const nextScroll = resolvePivotScrollbarTrackScroll({
|
|
5337
|
+
pointerValue: pointer,
|
|
5338
|
+
trackStart: hit.axis === "horizontal" ? axisLayout.track.x : axisLayout.track.y,
|
|
5339
|
+
trackLength: hit.axis === "horizontal" ? axisLayout.track.width : axisLayout.track.height,
|
|
5340
|
+
thumbLength: hit.axis === "horizontal" ? axisLayout.thumb.width : axisLayout.thumb.height,
|
|
5341
|
+
maxScroll: hit.axis === "horizontal" ? this.layout.viewport.maxScrollLeft : this.layout.viewport.maxScrollTop
|
|
5342
|
+
});
|
|
5140
5343
|
this.applyScrollPosition(
|
|
5141
|
-
|
|
5142
|
-
|
|
5344
|
+
hit.axis === "horizontal" ? nextScroll : this.scroll.left,
|
|
5345
|
+
hit.axis === "vertical" ? nextScroll : this.scroll.top
|
|
5143
5346
|
);
|
|
5144
5347
|
return;
|
|
5145
5348
|
}
|
|
@@ -5183,6 +5386,21 @@ var PivotTable = class {
|
|
|
5183
5386
|
this.scroll.top + (axis === "vertical" ? direction * this.layout.rowHeight : 0)
|
|
5184
5387
|
);
|
|
5185
5388
|
}
|
|
5389
|
+
startContinuousScrollbarScroll(axis, direction, pointerId) {
|
|
5390
|
+
this.stopContinuousScrollbarScroll();
|
|
5391
|
+
this.continuousScrollPointerId = pointerId;
|
|
5392
|
+
this.stepScrollbar(axis, direction);
|
|
5393
|
+
this.continuousScrollTimer = setInterval(() => {
|
|
5394
|
+
this.stepScrollbar(axis, direction);
|
|
5395
|
+
}, 80);
|
|
5396
|
+
}
|
|
5397
|
+
stopContinuousScrollbarScroll() {
|
|
5398
|
+
if (this.continuousScrollTimer !== null) {
|
|
5399
|
+
clearInterval(this.continuousScrollTimer);
|
|
5400
|
+
this.continuousScrollTimer = null;
|
|
5401
|
+
}
|
|
5402
|
+
this.continuousScrollPointerId = null;
|
|
5403
|
+
}
|
|
5186
5404
|
applyScrollPosition(left, top) {
|
|
5187
5405
|
if (!this.layout) return;
|
|
5188
5406
|
const next = {
|
|
@@ -5427,6 +5645,90 @@ function toArrayBuffer(value) {
|
|
|
5427
5645
|
return buffer;
|
|
5428
5646
|
}
|
|
5429
5647
|
|
|
5648
|
+
// src/adapters/storage/indexeddb-field-layout-storage.ts
|
|
5649
|
+
var DATABASE_NAME = "canvas_components_pivot_table_config";
|
|
5650
|
+
var STORE_NAME = "field_layout";
|
|
5651
|
+
var DB_VERSION = 1;
|
|
5652
|
+
var dbPromise = null;
|
|
5653
|
+
async function savePivotFieldLayout(key, layout) {
|
|
5654
|
+
try {
|
|
5655
|
+
const db = await openDatabase();
|
|
5656
|
+
await requestToPromise(
|
|
5657
|
+
db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).put(cloneLayout(layout), key)
|
|
5658
|
+
);
|
|
5659
|
+
} catch (error) {
|
|
5660
|
+
console.error("[PivotTable] \u5B57\u6BB5\u5E03\u5C40\u4FDD\u5B58\u5931\u8D25\uFF1A", error);
|
|
5661
|
+
}
|
|
5662
|
+
}
|
|
5663
|
+
async function loadPivotFieldLayout(key) {
|
|
5664
|
+
try {
|
|
5665
|
+
const db = await openDatabase();
|
|
5666
|
+
const value = await requestToPromise(
|
|
5667
|
+
db.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get(key)
|
|
5668
|
+
);
|
|
5669
|
+
return isPivotFieldLayout(value) ? cloneLayout(value) : void 0;
|
|
5670
|
+
} catch (error) {
|
|
5671
|
+
console.error("[PivotTable] \u5B57\u6BB5\u5E03\u5C40\u8BFB\u53D6\u5931\u8D25\uFF1A", error);
|
|
5672
|
+
return void 0;
|
|
5673
|
+
}
|
|
5674
|
+
}
|
|
5675
|
+
async function clearPivotFieldLayout(key) {
|
|
5676
|
+
try {
|
|
5677
|
+
const db = await openDatabase();
|
|
5678
|
+
await requestToPromise(
|
|
5679
|
+
db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).delete(key)
|
|
5680
|
+
);
|
|
5681
|
+
} catch (error) {
|
|
5682
|
+
console.error("[PivotTable] \u5B57\u6BB5\u5E03\u5C40\u6E05\u9664\u5931\u8D25\uFF1A", error);
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5685
|
+
function openDatabase() {
|
|
5686
|
+
if (dbPromise) return dbPromise;
|
|
5687
|
+
dbPromise = new Promise((resolve, reject) => {
|
|
5688
|
+
if (typeof indexedDB === "undefined") {
|
|
5689
|
+
reject(new Error("\u5F53\u524D\u73AF\u5883\u4E0D\u652F\u6301 IndexedDB"));
|
|
5690
|
+
return;
|
|
5691
|
+
}
|
|
5692
|
+
const request = indexedDB.open(DATABASE_NAME, DB_VERSION);
|
|
5693
|
+
request.onupgradeneeded = () => {
|
|
5694
|
+
const db = request.result;
|
|
5695
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
5696
|
+
db.createObjectStore(STORE_NAME);
|
|
5697
|
+
}
|
|
5698
|
+
};
|
|
5699
|
+
request.onsuccess = () => resolve(request.result);
|
|
5700
|
+
request.onerror = () => reject(request.error);
|
|
5701
|
+
});
|
|
5702
|
+
dbPromise.catch(() => {
|
|
5703
|
+
dbPromise = null;
|
|
5704
|
+
});
|
|
5705
|
+
return dbPromise;
|
|
5706
|
+
}
|
|
5707
|
+
function requestToPromise(request) {
|
|
5708
|
+
return new Promise((resolve, reject) => {
|
|
5709
|
+
request.onsuccess = () => resolve(request.result);
|
|
5710
|
+
request.onerror = () => reject(request.error);
|
|
5711
|
+
});
|
|
5712
|
+
}
|
|
5713
|
+
function isPivotFieldLayout(value) {
|
|
5714
|
+
if (!value || typeof value !== "object") return false;
|
|
5715
|
+
const layout = value;
|
|
5716
|
+
return ["filters", "columns", "rows", "values"].every(
|
|
5717
|
+
(key) => isStringArray(layout[key])
|
|
5718
|
+
);
|
|
5719
|
+
}
|
|
5720
|
+
function isStringArray(value) {
|
|
5721
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
5722
|
+
}
|
|
5723
|
+
function cloneLayout(layout) {
|
|
5724
|
+
return {
|
|
5725
|
+
filters: [...layout.filters],
|
|
5726
|
+
columns: [...layout.columns],
|
|
5727
|
+
rows: [...layout.rows],
|
|
5728
|
+
values: [...layout.values]
|
|
5729
|
+
};
|
|
5730
|
+
}
|
|
5731
|
+
|
|
5430
5732
|
// src/domain/field/pivot-field-layout.ts
|
|
5431
5733
|
function createEmptyPivotFieldLayout() {
|
|
5432
5734
|
return { filters: [], columns: [], rows: [], values: [] };
|
|
@@ -5574,6 +5876,6 @@ function areaToLayoutKey(area) {
|
|
|
5574
5876
|
return "values";
|
|
5575
5877
|
}
|
|
5576
5878
|
|
|
5577
|
-
export { PivotTable, aggregatePivotRecords, buildPivotDimensionTree, buildPivotLayoutSnapshot, computePivotScrollbarLayout, createBuiltInPivotAggregators, createEmptyPivotFieldLayout, createEmptyPivotFilterState, createPivotAggregatorRegistry, createPivotAxisSlots, createPivotCellKey, createPivotExportMatrix, createPivotFieldCatalog, createPivotFieldLayout, createPivotSelectionText, defaultPivotTableTheme, encodePivotDimensionValue, encodePivotPath, exportPivotMatrixToCsv, exportPivotMatrixToXlsx, filterPivotRecords, findPivotFieldArea, flattenVisiblePivotLeaves, getPivotDimensionFilterOptions, hitTestPivotLayout, hitTestPivotResize, hitTestPivotScrollbar, movePivotField, removePivotField, renderPivotTable, resolvePivotDefaultSorts, resolvePivotDimensionKey, resolvePivotDimensionTitle, resolvePivotDimensionValue, resolvePivotDimensionWidth, resolvePivotFieldLayoutOptions, resolvePivotIndicatorAggregator, resolvePivotValueFieldTitle };
|
|
5879
|
+
export { PivotTable, aggregatePivotRecords, buildPivotDimensionTree, buildPivotLayoutSnapshot, clearPivotFieldLayout, computePivotScrollbarLayout, createBuiltInPivotAggregators, createEmptyPivotFieldLayout, createEmptyPivotFilterState, createPivotAggregatorRegistry, createPivotAxisSlots, createPivotCellKey, createPivotExportMatrix, createPivotFieldCatalog, createPivotFieldLayout, createPivotSelectionText, defaultPivotTableTheme, encodePivotDimensionValue, encodePivotPath, exportPivotMatrixToCsv, exportPivotMatrixToXlsx, filterPivotRecords, findPivotFieldArea, flattenVisiblePivotLeaves, getPivotDimensionFilterOptions, hitTestPivotLayout, hitTestPivotResize, hitTestPivotScrollbar, loadPivotFieldLayout, movePivotField, removePivotField, renderPivotTable, resolvePivotDefaultSorts, resolvePivotDimensionKey, resolvePivotDimensionTitle, resolvePivotDimensionValue, resolvePivotDimensionWidth, resolvePivotFieldLayoutOptions, resolvePivotIndicatorAggregator, resolvePivotValueFieldTitle, savePivotFieldLayout };
|
|
5578
5880
|
//# sourceMappingURL=index.js.map
|
|
5579
5881
|
//# sourceMappingURL=index.js.map
|