@visactor/vseed 0.4.15 → 0.4.17
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/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.d.ts +2 -2
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.js +30 -3
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.js.map +1 -1
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/pivot.js +11 -0
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/pivot.js.map +1 -1
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/table.js +5 -3
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/table.js.map +1 -1
- package/dist/esm/pipeline/utils/valid/checkVSeed.js +4 -2
- package/dist/esm/pipeline/utils/valid/checkVSeed.js.map +1 -1
- package/dist/umd/index.js +62 -21
- package/dist/umd/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BodyCellStyle, Datum } from '../../../../../types';
|
|
1
|
+
import type { BodyCellStyle, Datum, TotalType } from '../../../../../types';
|
|
2
2
|
/**
|
|
3
3
|
* 计算线性颜色映射(使用 tinycolor2)
|
|
4
4
|
* @param value 实际值
|
|
@@ -16,7 +16,7 @@ export declare const pickBodyCellStyle: (bodyCellStyle: BodyCellStyle) => Record
|
|
|
16
16
|
/**
|
|
17
17
|
* 计算数据列的最小值和最大值
|
|
18
18
|
*/
|
|
19
|
-
export declare const getColumnMinMax: (allData: Datum[], field: string) => {
|
|
19
|
+
export declare const getColumnMinMax: (allData: Datum[], field: string, totalAggregation?: TotalType) => {
|
|
20
20
|
min: number;
|
|
21
21
|
max: number;
|
|
22
22
|
};
|
|
@@ -24,19 +24,46 @@ const pickBodyCellStyle = (bodyCellStyle)=>Object.keys(tableStyleMap).reduce((ac
|
|
|
24
24
|
if (key in bodyCellStyle) acc[tableStyleMap[key]] = bodyCellStyle[key];
|
|
25
25
|
return acc;
|
|
26
26
|
}, {});
|
|
27
|
-
const getColumnMinMax = (allData, field)=>{
|
|
27
|
+
const getColumnMinMax = (allData, field, totalAggregation)=>{
|
|
28
28
|
let min = 1 / 0;
|
|
29
29
|
let max = -1 / 0;
|
|
30
|
+
let sum = 0;
|
|
31
|
+
let count = 0;
|
|
32
|
+
const hasTotal = !!totalAggregation;
|
|
33
|
+
const aggregationType = 'string' == typeof totalAggregation ? totalAggregation : 'sum';
|
|
30
34
|
for (const datum of allData){
|
|
31
35
|
const value = Number(datum[field]);
|
|
32
36
|
if (!Number.isNaN(value)) {
|
|
33
37
|
min = Math.min(min, value);
|
|
34
38
|
max = Math.max(max, value);
|
|
39
|
+
sum += value;
|
|
40
|
+
count += 1;
|
|
35
41
|
}
|
|
36
42
|
}
|
|
43
|
+
const baseMin = min === 1 / 0 ? 0 : min;
|
|
44
|
+
const baseMax = max === -1 / 0 ? 0 : max;
|
|
45
|
+
if (!hasTotal) return {
|
|
46
|
+
min: baseMin,
|
|
47
|
+
max: baseMax
|
|
48
|
+
};
|
|
49
|
+
const total = (()=>{
|
|
50
|
+
switch(aggregationType){
|
|
51
|
+
case 'avg':
|
|
52
|
+
return count ? sum / count : 0;
|
|
53
|
+
case 'max':
|
|
54
|
+
return baseMax;
|
|
55
|
+
case 'min':
|
|
56
|
+
return baseMin;
|
|
57
|
+
case 'count':
|
|
58
|
+
return count;
|
|
59
|
+
case 'sum':
|
|
60
|
+
default:
|
|
61
|
+
return sum;
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
37
64
|
return {
|
|
38
|
-
min: min
|
|
39
|
-
max: max
|
|
65
|
+
min: Math.min(baseMin, total),
|
|
66
|
+
max: Math.max(baseMax, total)
|
|
40
67
|
};
|
|
41
68
|
};
|
|
42
69
|
const applyColorScale = (value, scale)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/common.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/common.ts"],"sourcesContent":["import { isArray, isNullish } from 'remeda'\nimport tinycolor from 'tinycolor2'\nimport { InnerRowIndex } from 'src/dataReshape'\nimport type { BodyCellStyle, Datum } from 'src/types'\n\nconst tableStyleMap = {\n backgroundColor: 'bgColor',\n textColor: 'color',\n textFontSize: 'fontSize',\n borderColor: 'borderColor',\n borderLineWidth: 'borderLineWidth',\n barPositiveColor: 'barPositiveColor',\n barNegativeColor: 'barNegativeColor',\n}\n\n/**\n * 计算线性颜色映射(使用 tinycolor2)\n * @param value 实际值\n * @param minValue 最小值\n * @param maxValue 最大值\n * @param minColor 最小值颜色\n * @param maxColor 最大值颜色\n * @returns RGB 颜色字符串\n */\nexport const interpolateColor = (\n value: number,\n minValue: number,\n maxValue: number,\n minColor: string,\n maxColor: string,\n): string => {\n const startColor = tinycolor(minColor).toRgb()\n const endColor = tinycolor(maxColor).toRgb()\n\n // 归一化值到 [0, 1]\n const normalized = (value - minValue) / (maxValue - minValue)\n const t = Math.max(0, Math.min(1, normalized))\n\n // 线性插值\n const r = Math.round(startColor.r + (endColor.r - startColor.r) * t)\n const g = Math.round(startColor.g + (endColor.g - startColor.g) * t)\n const b = Math.round(startColor.b + (endColor.b - startColor.b) * t)\n\n return `rgb(${r}, ${g}, ${b})`\n}\n\n/**\n * 从 bodyCellStyle 提取要应用到单元格的样式\n */\nexport const pickBodyCellStyle = (bodyCellStyle: BodyCellStyle) => {\n return (Object.keys(tableStyleMap) as Array<keyof typeof tableStyleMap>).reduce<Record<string, any>>((acc, key) => {\n if (key in bodyCellStyle) {\n acc[tableStyleMap[key]] = bodyCellStyle[key]\n }\n\n return acc\n }, {})\n}\n\n/**\n * 计算数据列的最小值和最大值\n */\nexport const getColumnMinMax = (allData: Datum[]
|
|
1
|
+
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/common.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/common.ts"],"sourcesContent":["import { isArray, isNullish } from 'remeda'\nimport tinycolor from 'tinycolor2'\nimport { InnerRowIndex } from 'src/dataReshape'\nimport type { BodyCellStyle, Datum, TotalType } from 'src/types'\n\nconst tableStyleMap = {\n backgroundColor: 'bgColor',\n textColor: 'color',\n textFontSize: 'fontSize',\n borderColor: 'borderColor',\n borderLineWidth: 'borderLineWidth',\n barPositiveColor: 'barPositiveColor',\n barNegativeColor: 'barNegativeColor',\n}\n\n/**\n * 计算线性颜色映射(使用 tinycolor2)\n * @param value 实际值\n * @param minValue 最小值\n * @param maxValue 最大值\n * @param minColor 最小值颜色\n * @param maxColor 最大值颜色\n * @returns RGB 颜色字符串\n */\nexport const interpolateColor = (\n value: number,\n minValue: number,\n maxValue: number,\n minColor: string,\n maxColor: string,\n): string => {\n const startColor = tinycolor(minColor).toRgb()\n const endColor = tinycolor(maxColor).toRgb()\n\n // 归一化值到 [0, 1]\n const normalized = (value - minValue) / (maxValue - minValue)\n const t = Math.max(0, Math.min(1, normalized))\n\n // 线性插值\n const r = Math.round(startColor.r + (endColor.r - startColor.r) * t)\n const g = Math.round(startColor.g + (endColor.g - startColor.g) * t)\n const b = Math.round(startColor.b + (endColor.b - startColor.b) * t)\n\n return `rgb(${r}, ${g}, ${b})`\n}\n\n/**\n * 从 bodyCellStyle 提取要应用到单元格的样式\n */\nexport const pickBodyCellStyle = (bodyCellStyle: BodyCellStyle) => {\n return (Object.keys(tableStyleMap) as Array<keyof typeof tableStyleMap>).reduce<Record<string, any>>((acc, key) => {\n if (key in bodyCellStyle) {\n acc[tableStyleMap[key]] = bodyCellStyle[key]\n }\n\n return acc\n }, {})\n}\n\n/**\n * 计算数据列的最小值和最大值\n */\nexport const getColumnMinMax = (\n allData: Datum[],\n field: string,\n totalAggregation?: TotalType,\n): { min: number; max: number } => {\n let min = Infinity\n let max = -Infinity\n let sum = 0\n let count = 0\n\n const hasTotal = !!totalAggregation\n const aggregationType: TotalType = typeof totalAggregation === 'string' ? totalAggregation : 'sum'\n\n for (const datum of allData) {\n const value = Number(datum[field])\n if (!Number.isNaN(value)) {\n min = Math.min(min, value)\n max = Math.max(max, value)\n sum += value\n count += 1\n }\n }\n\n const baseMin = min === Infinity ? 0 : min\n const baseMax = max === -Infinity ? 0 : max\n\n if (!hasTotal) {\n return {\n min: baseMin,\n max: baseMax,\n }\n }\n\n const total = (() => {\n switch (aggregationType) {\n case 'avg':\n return count ? sum / count : 0\n case 'max':\n return baseMax\n case 'min':\n return baseMin\n case 'count':\n return count\n case 'sum':\n default:\n return sum\n }\n })()\n\n return {\n min: Math.min(baseMin, total),\n max: Math.max(baseMax, total),\n }\n}\n\n/**\n * 应用 scale 颜色映射\n */\nexport const applyColorScale = (\n value: any,\n scale: { minValue: number; maxValue: number; minColor: string; maxColor: string } | undefined,\n): string | undefined => {\n if (!scale) return undefined\n\n const numValue = Number(value)\n if (Number.isNaN(numValue) || isNullish(value)) return undefined\n\n const minValue = scale.minValue\n const maxValue = scale.maxValue\n\n if (minValue === maxValue) {\n return scale.minColor\n }\n\n return interpolateColor(numValue, minValue, maxValue, scale.minColor, scale.maxColor)\n}\n\nexport const getCellOriginalDataByDatum = (datum: any, hasDynamicFilter: boolean, originalDatum: Datum) => {\n const tableInstance = datum?.table\n let originRowData =\n tableInstance && hasDynamicFilter ? tableInstance?.getCellOriginRecord(datum?.col, datum?.row) : null\n if (originRowData && isArray(originRowData)) {\n originRowData = originRowData[0]\n }\n return originRowData\n ? {\n ...originalDatum,\n [InnerRowIndex]: originRowData?.[InnerRowIndex], // 内部行号字段\n }\n : null\n}\n"],"names":["tableStyleMap","interpolateColor","value","minValue","maxValue","minColor","maxColor","startColor","tinycolor","endColor","normalized","t","Math","r","g","b","pickBodyCellStyle","bodyCellStyle","Object","acc","key","getColumnMinMax","allData","field","totalAggregation","min","Infinity","max","sum","count","hasTotal","aggregationType","datum","Number","baseMin","baseMax","total","applyColorScale","scale","numValue","isNullish","getCellOriginalDataByDatum","hasDynamicFilter","originalDatum","tableInstance","originRowData","isArray","InnerRowIndex"],"mappings":"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"}
|
|
@@ -2,6 +2,16 @@ import { array } from "@visactor/vutils";
|
|
|
2
2
|
import { isString } from "remeda";
|
|
3
3
|
import { matchesFieldSelector, selector, selectorWithDynamicFilter } from "../../../../../dataSelector/selector.js";
|
|
4
4
|
import { applyColorScale, getCellOriginalDataByDatum, getColumnMinMax, pickBodyCellStyle } from "./common.js";
|
|
5
|
+
const isPivotTotalCell = (styleArg)=>{
|
|
6
|
+
const cellHeaderPaths = styleArg?.cellHeaderPaths;
|
|
7
|
+
if (!cellHeaderPaths) return false;
|
|
8
|
+
if ('sub-total' === cellHeaderPaths.role || 'grand-total' === cellHeaderPaths.role) return true;
|
|
9
|
+
const headerPaths = [
|
|
10
|
+
...cellHeaderPaths.colHeaderPaths || [],
|
|
11
|
+
...cellHeaderPaths.rowHeaderPaths || []
|
|
12
|
+
];
|
|
13
|
+
return headerPaths.some((path)=>path?.role === 'sub-total' || path?.role === 'grand-total');
|
|
14
|
+
};
|
|
5
15
|
const pivotTableBodyCell = (spec, context)=>{
|
|
6
16
|
const { advancedVSeed } = context;
|
|
7
17
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
@@ -70,6 +80,7 @@ const pivotTableBodyCell = (spec, context)=>{
|
|
|
70
80
|
cellStyle.barMarkWidth = themeConfig?.barMarkWidth;
|
|
71
81
|
cellStyle.barPadding = themeConfig?.barPadding;
|
|
72
82
|
cellStyle.barRightToLeft = themeConfig?.barRightToLeft;
|
|
83
|
+
cellStyle.showBar = !isPivotTotalCell(datum);
|
|
73
84
|
}
|
|
74
85
|
return {
|
|
75
86
|
...result,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/pivot.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/pivot.ts"],"sourcesContent":["import type { IIndicator, PivotTableConstructorOptions } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isString } from 'remeda'\nimport { matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, Datum, PivotTableSpecPipe, TableConfig } from 'src/types'\nimport type { FieldSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport type { IProgressbarColumnIndicator } from '@visactor/vtable/es/ts-types/pivot-table/indicator/progress-indicator'\n\nexport const pivotTableBodyCell: PivotTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle, config, chartType } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as PivotTableConstructorOptions\n }\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const indicators = (spec as PivotTableConstructorOptions).indicators || []\n const selectedPos: { col: number; row: number }[] = []\n const hasDynamicFilter = bodyCellStyleList.some((style) => !!style.dynamicFilter)\n const allData = advancedVSeed.dataset || []\n\n const newIndicators = indicators.map((ind) => {\n const newInd = isString(ind)\n ? ({\n indicatorKey: ind,\n } as IIndicator)\n : ind\n\n const { indicatorKey } = newInd\n\n // 前置处理:检查是否需要 progressBar 或 backgroundColorScale\n const progressBarStyle = bodyCellStyleList\n .filter(\n (s) => s.enableProgressBar && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n .pop()\n const backgroundColorScale = bodyCellStyleList.find(\n (s) =>\n s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, indicatorKey)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n newInd.cellType = 'progressbar'\n ;(newInd as IProgressbarColumnIndicator).barType = 'negative'\n ;(newInd as IProgressbarColumnIndicator).min = progressBarStyle.barMin ?? columnMin\n ;(newInd as IProgressbarColumnIndicator).max = progressBarStyle.barMax ?? columnMax\n }\n }\n\n newInd.style = (datum: any) => {\n const { dataValue, cellHeaderPaths } = datum\n const headerPaths = [...cellHeaderPaths.colHeaderPaths, ...cellHeaderPaths.rowHeaderPaths]\n\n const originalDatum: Datum = {\n [indicatorKey]: dataValue,\n }\n\n headerPaths.forEach((path: any) => {\n if (path.dimensionKey) {\n originalDatum[path.dimensionKey] = path.value\n }\n })\n\n const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum)\n\n const mergedStyle = bodyCellStyleList.reduce<Record<string, any>>((result, style) => {\n const shouldApply = style.dynamicFilter\n ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector)\n : selector(originalDatum, style.selector)\n if (shouldApply) {\n if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) {\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n\n const cellStyle = pickBodyCellStyle(style)\n\n // 应用 backgroundColorScale\n if (style.enableBackgroundColorScale) {\n const scaledColor = applyColorScale(dataValue, {\n minValue: columnMin,\n maxValue: columnMax,\n ...themeConfig.backgroundColorScale,\n ...style.backgroundColorScale,\n } as any)\n if (scaledColor) {\n cellStyle.bgColor = scaledColor\n }\n }\n\n // 如果开启了数据条样式\n if (newInd.cellType === 'progressbar') {\n cellStyle.barHeight = themeConfig?.barHeight\n cellStyle.barMarkInBar = themeConfig?.barMarkInBar\n cellStyle.barMarkWidth = themeConfig?.barMarkWidth\n cellStyle.barPadding = themeConfig?.barPadding\n cellStyle.barRightToLeft = themeConfig?.barRightToLeft\n }\n\n return {\n ...result,\n ...cellStyle,\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\n }\n return newInd\n })\n return {\n ...spec,\n runningConfig: {\n ...((spec as any)?.runningConfig || {}),\n selectedPos,\n },\n indicators: newIndicators,\n } as PivotTableConstructorOptions\n}\n"],"names":["pivotTableBodyCell","spec","context","advancedVSeed","cellStyle","config","chartType","bodyCellStyle","themeConfig","bodyCellStyleList","array","indicators","selectedPos","hasDynamicFilter","style","allData","newIndicators","ind","newInd","isString","indicatorKey","progressBarStyle","s","matchesFieldSelector","backgroundColorScale","columnMin","columnMax","min","max","getColumnMinMax","datum","dataValue","
|
|
1
|
+
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/pivot.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/pivot.ts"],"sourcesContent":["import type { IIndicator, PivotTableConstructorOptions } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isString } from 'remeda'\nimport { matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, Datum, PivotTableSpecPipe, TableConfig } from 'src/types'\nimport type { FieldSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport type { IProgressbarColumnIndicator } from '@visactor/vtable/es/ts-types/pivot-table/indicator/progress-indicator'\n\nconst isPivotTotalCell = (styleArg: any): boolean => {\n const cellHeaderPaths = styleArg?.cellHeaderPaths\n if (!cellHeaderPaths) {\n return false\n }\n\n if (cellHeaderPaths.role === 'sub-total' || cellHeaderPaths.role === 'grand-total') {\n return true\n }\n\n const headerPaths = [...(cellHeaderPaths.colHeaderPaths || []), ...(cellHeaderPaths.rowHeaderPaths || [])]\n return headerPaths.some((path: any) => path?.role === 'sub-total' || path?.role === 'grand-total')\n}\n\nexport const pivotTableBodyCell: PivotTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle, config, chartType } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as PivotTableConstructorOptions\n }\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const indicators = (spec as PivotTableConstructorOptions).indicators || []\n const selectedPos: { col: number; row: number }[] = []\n const hasDynamicFilter = bodyCellStyleList.some((style) => !!style.dynamicFilter)\n const allData = advancedVSeed.dataset || []\n\n const newIndicators = indicators.map((ind) => {\n const newInd = isString(ind)\n ? ({\n indicatorKey: ind,\n } as IIndicator)\n : ind\n\n const { indicatorKey } = newInd\n\n // 前置处理:检查是否需要 progressBar 或 backgroundColorScale\n const progressBarStyle = bodyCellStyleList\n .filter(\n (s) => s.enableProgressBar && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n .pop()\n const backgroundColorScale = bodyCellStyleList.find(\n (s) =>\n s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, indicatorKey)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n newInd.cellType = 'progressbar'\n ;(newInd as IProgressbarColumnIndicator).barType = 'negative'\n ;(newInd as IProgressbarColumnIndicator).min = progressBarStyle.barMin ?? columnMin\n ;(newInd as IProgressbarColumnIndicator).max = progressBarStyle.barMax ?? columnMax\n }\n }\n\n newInd.style = (datum: any) => {\n const { dataValue, cellHeaderPaths } = datum\n const headerPaths = [...cellHeaderPaths.colHeaderPaths, ...cellHeaderPaths.rowHeaderPaths]\n\n const originalDatum: Datum = {\n [indicatorKey]: dataValue,\n }\n\n headerPaths.forEach((path: any) => {\n if (path.dimensionKey) {\n originalDatum[path.dimensionKey] = path.value\n }\n })\n\n const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum)\n\n const mergedStyle = bodyCellStyleList.reduce<Record<string, any>>((result, style) => {\n const shouldApply = style.dynamicFilter\n ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector)\n : selector(originalDatum, style.selector)\n if (shouldApply) {\n if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) {\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n\n const cellStyle = pickBodyCellStyle(style)\n\n // 应用 backgroundColorScale\n if (style.enableBackgroundColorScale) {\n const scaledColor = applyColorScale(dataValue, {\n minValue: columnMin,\n maxValue: columnMax,\n ...themeConfig.backgroundColorScale,\n ...style.backgroundColorScale,\n } as any)\n if (scaledColor) {\n cellStyle.bgColor = scaledColor\n }\n }\n\n // 如果开启了数据条样式\n if (newInd.cellType === 'progressbar') {\n cellStyle.barHeight = themeConfig?.barHeight\n cellStyle.barMarkInBar = themeConfig?.barMarkInBar\n cellStyle.barMarkWidth = themeConfig?.barMarkWidth\n cellStyle.barPadding = themeConfig?.barPadding\n cellStyle.barRightToLeft = themeConfig?.barRightToLeft\n cellStyle.showBar = !isPivotTotalCell(datum)\n }\n\n return {\n ...result,\n ...cellStyle,\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\n }\n return newInd\n })\n return {\n ...spec,\n runningConfig: {\n ...((spec as any)?.runningConfig || {}),\n selectedPos,\n },\n indicators: newIndicators,\n } as PivotTableConstructorOptions\n}\n"],"names":["isPivotTotalCell","styleArg","cellHeaderPaths","headerPaths","path","pivotTableBodyCell","spec","context","advancedVSeed","cellStyle","config","chartType","bodyCellStyle","themeConfig","bodyCellStyleList","array","indicators","selectedPos","hasDynamicFilter","style","allData","newIndicators","ind","newInd","isString","indicatorKey","progressBarStyle","s","matchesFieldSelector","backgroundColorScale","columnMin","columnMax","min","max","getColumnMinMax","datum","dataValue","originalDatum","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle","scaledColor","applyColorScale"],"mappings":"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"}
|
|
@@ -4,8 +4,10 @@ import { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFil
|
|
|
4
4
|
import { applyColorScale, getCellOriginalDataByDatum, getColumnMinMax, pickBodyCellStyle } from "./common.js";
|
|
5
5
|
import { preorderTraverse } from "../../../../utils/tree/traverse.js";
|
|
6
6
|
const tableBodyCell = (spec, context)=>{
|
|
7
|
-
const { advancedVSeed } = context;
|
|
7
|
+
const { advancedVSeed, vseed } = context;
|
|
8
|
+
const { totals } = vseed || {};
|
|
8
9
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
10
|
+
const totalAggregation = 'string' == typeof totals ? totals : void 0;
|
|
9
11
|
const bodyCellStyle = cellStyle?.bodyCellStyle;
|
|
10
12
|
const themeConfig = config?.[chartType];
|
|
11
13
|
if (!bodyCellStyle) return spec;
|
|
@@ -32,14 +34,14 @@ const tableBodyCell = (spec, context)=>{
|
|
|
32
34
|
let columnMin;
|
|
33
35
|
let columnMax;
|
|
34
36
|
if (progressBarStyle || backgroundColorScale) {
|
|
35
|
-
const { min, max } = getColumnMinMax(allData, field);
|
|
37
|
+
const { min, max } = getColumnMinMax(allData, field, totalAggregation);
|
|
36
38
|
columnMin = min;
|
|
37
39
|
columnMax = max;
|
|
38
40
|
if (progressBarStyle) {
|
|
39
41
|
col.cellType = 'progressbar';
|
|
40
42
|
col.barType = 'negative';
|
|
41
43
|
col.min = progressBarStyle.barMin ?? columnMin;
|
|
42
|
-
col.max = progressBarStyle.
|
|
44
|
+
col.max = progressBarStyle.barMax ?? columnMax;
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
col.style = (datum)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/table.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/table.ts"],"sourcesContent":["import type { ListTableConstructorOptions, ColumnDefine, ProgressbarColumnDefine } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isNullish, isNumber, isPlainObject, isString } from 'remeda'\nimport { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, ListTableSpecPipe, TableConfig } from 'src/types'\nimport type { FieldSelector, MeasureSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport { preorderTraverse } from 'src/pipeline/utils/tree/traverse'\n\nexport const tableBodyCell: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle, config, chartType } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as ListTableConstructorOptions\n }\n\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const columns = (spec as ListTableConstructorOptions).columns || []\n const selectedPos: { col: number; row: number }[] = []\n const allData = advancedVSeed.dataset || []\n\n const setStyleOfColumn = (col: ColumnDefine) => {\n const field = col.field as string\n\n // 过滤出匹配当前列的样式配置\n const matchedStyles = bodyCellStyleList.filter((style) => {\n // 检查 dynamicFilter\n if (style?.dynamicFilter) {\n return style.dynamicFilter?.result?.success === true || !!style.dynamicFilter?.fallback\n }\n\n // 检查 selector\n if (isNullish(style.selector)) {\n return true\n }\n\n const selectors = array(style.selector) as any[]\n return selectors.some((sel) => {\n // 1. FieldSelector(字段选择器)\n if (isFieldSelector(sel)) {\n return matchesFieldSelector(field, sel)\n }\n\n // 2. MeasureSelector/DimensionSelector(条件选择器)\n if (isPlainObject(sel)) {\n return isNullish(sel.field) || (sel as MeasureSelector).field === field\n }\n\n // 3. ValueSelector(值选择器)\n return isNumber(sel) || isString(sel)\n })\n })\n\n if (!matchedStyles.length) {\n return false\n }\n\n const hasDynamicFilter = matchedStyles.some((style) => !!style.dynamicFilter)\n\n // 前置处理:检查是否需要 progressBar\n const progressBarStyle = matchedStyles\n .filter((s) => s.enableProgressBar && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector))\n .pop()\n const backgroundColorScale = matchedStyles.find(\n (s) => s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, field)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n col.cellType = 'progressbar'\n ;(col as ProgressbarColumnDefine).barType = 'negative'\n ;(col as ProgressbarColumnDefine).min = progressBarStyle.barMin ?? columnMin\n ;(col as ProgressbarColumnDefine).max = progressBarStyle.
|
|
1
|
+
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/table.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/table.ts"],"sourcesContent":["import type { ListTableConstructorOptions, ColumnDefine, ProgressbarColumnDefine } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isNullish, isNumber, isPlainObject, isString } from 'remeda'\nimport { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, ListTableSpecPipe, Table, TableConfig } from 'src/types'\nimport type { FieldSelector, MeasureSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport { preorderTraverse } from 'src/pipeline/utils/tree/traverse'\n\nexport const tableBodyCell: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed, vseed } = context\n const { totals } = (vseed || {}) as Table\n const { cellStyle, config, chartType } = advancedVSeed\n const totalAggregation = typeof totals === 'string' ? totals : undefined\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as ListTableConstructorOptions\n }\n\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const columns = (spec as ListTableConstructorOptions).columns || []\n const selectedPos: { col: number; row: number }[] = []\n const allData = advancedVSeed.dataset || []\n\n const setStyleOfColumn = (col: ColumnDefine) => {\n const field = col.field as string\n\n // 过滤出匹配当前列的样式配置\n const matchedStyles = bodyCellStyleList.filter((style) => {\n // 检查 dynamicFilter\n if (style?.dynamicFilter) {\n return style.dynamicFilter?.result?.success === true || !!style.dynamicFilter?.fallback\n }\n\n // 检查 selector\n if (isNullish(style.selector)) {\n return true\n }\n\n const selectors = array(style.selector) as any[]\n return selectors.some((sel) => {\n // 1. FieldSelector(字段选择器)\n if (isFieldSelector(sel)) {\n return matchesFieldSelector(field, sel)\n }\n\n // 2. MeasureSelector/DimensionSelector(条件选择器)\n if (isPlainObject(sel)) {\n return isNullish(sel.field) || (sel as MeasureSelector).field === field\n }\n\n // 3. ValueSelector(值选择器)\n return isNumber(sel) || isString(sel)\n })\n })\n\n if (!matchedStyles.length) {\n return false\n }\n\n const hasDynamicFilter = matchedStyles.some((style) => !!style.dynamicFilter)\n\n // 前置处理:检查是否需要 progressBar\n const progressBarStyle = matchedStyles\n .filter((s) => s.enableProgressBar && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector))\n .pop()\n const backgroundColorScale = matchedStyles.find(\n (s) => s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, field, totalAggregation)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n col.cellType = 'progressbar'\n ;(col as ProgressbarColumnDefine).barType = 'negative'\n ;(col as ProgressbarColumnDefine).min = progressBarStyle.barMin ?? columnMin\n ;(col as ProgressbarColumnDefine).max = progressBarStyle.barMax ?? columnMax\n }\n }\n\n // 统一的 col.style 回调\n col.style = (datum: any) => {\n const originalDatum = {\n [field]: datum.dataValue,\n }\n const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum)\n\n const mergedStyle = matchedStyles.reduce<Record<string, any>>((result, style) => {\n const shouldApply = style.dynamicFilter\n ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector)\n : selector(originalDatum, style.selector)\n\n if (shouldApply) {\n if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) {\n // 说明重复进入了,清空历史\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n\n let cellStyle = pickBodyCellStyle(style)\n\n // 应用 backgroundColorScale\n if (style.enableBackgroundColorScale) {\n const scaledColor = applyColorScale(datum.dataValue, {\n minValue: columnMin,\n maxValue: columnMax,\n ...themeConfig.backgroundColorScale,\n ...style?.backgroundColorScale,\n } as any)\n if (scaledColor) {\n cellStyle.bgColor = scaledColor\n }\n }\n // 如果开启了数据条样式\n if (col.cellType === 'progressbar') {\n cellStyle = {\n ...cellStyle,\n barHeight: themeConfig?.barHeight,\n barMarkInBar: themeConfig?.barMarkInBar,\n barMarkWidth: themeConfig?.barMarkWidth,\n barPadding: themeConfig?.barPadding,\n barRightToLeft: themeConfig?.barRightToLeft,\n barAxisColor: themeConfig?.barAxisColor,\n }\n }\n\n return {\n ...result,\n ...cellStyle,\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\n }\n\n return false\n }\n\n preorderTraverse<ColumnDefine, 'columns'>(columns, setStyleOfColumn, 'columns')\n ;(spec as any).runningConfig = {\n ...((spec as any).runningConfig || {}),\n selectedPos,\n }\n\n return spec as ListTableConstructorOptions\n}\n"],"names":["tableBodyCell","spec","context","advancedVSeed","vseed","totals","cellStyle","config","chartType","totalAggregation","undefined","bodyCellStyle","themeConfig","bodyCellStyleList","array","columns","selectedPos","allData","setStyleOfColumn","col","field","matchedStyles","style","isNullish","selectors","sel","isFieldSelector","matchesFieldSelector","isPlainObject","isNumber","isString","hasDynamicFilter","progressBarStyle","s","backgroundColorScale","columnMin","columnMax","min","max","getColumnMinMax","datum","originalDatum","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle","scaledColor","applyColorScale","preorderTraverse"],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { isEmpty } from "remeda";
|
|
1
|
+
import { isArray, isEmpty } from "remeda";
|
|
2
|
+
import { isVTable } from "../chatType.js";
|
|
2
3
|
const checkVSeed = (vseed)=>{
|
|
3
4
|
const { chartType, dataset, dimensions, measures } = vseed;
|
|
4
5
|
if (!chartType) throw new Error('chartType is required');
|
|
5
|
-
if (!dataset ||
|
|
6
|
+
if (!dataset || !isArray(dataset)) throw new Error('dataset is required, and must be an array');
|
|
7
|
+
if (isEmpty(dataset) && !isVTable(vseed)) throw new Error('dataset can not empty');
|
|
6
8
|
if (dimensions && !Array.isArray(dimensions)) throw new Error('dimensions must be an array');
|
|
7
9
|
if (measures && !Array.isArray(measures)) throw new Error('measures must be an array');
|
|
8
10
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/utils/valid/checkVSeed.js","sources":["webpack://@visactor/vseed/./src/pipeline/utils/valid/checkVSeed.ts"],"sourcesContent":["import { isEmpty } from 'remeda'\nimport type { VSeed } from 'src/types'\n\nexport const checkVSeed = (vseed: VSeed) => {\n const { chartType, dataset, dimensions, measures } = vseed\n if (!chartType) {\n throw new Error('chartType is required')\n }\n if (!dataset ||
|
|
1
|
+
{"version":3,"file":"pipeline/utils/valid/checkVSeed.js","sources":["webpack://@visactor/vseed/./src/pipeline/utils/valid/checkVSeed.ts"],"sourcesContent":["import { isArray, isEmpty } from 'remeda'\nimport type { VSeed } from 'src/types'\nimport { isVTable } from '../chatType'\n\nexport const checkVSeed = (vseed: VSeed) => {\n const { chartType, dataset, dimensions, measures } = vseed\n if (!chartType) {\n throw new Error('chartType is required')\n }\n if (!dataset || !isArray(dataset)) {\n throw new Error('dataset is required, and must be an array')\n }\n if (isEmpty(dataset) && !isVTable(vseed)) {\n throw new Error('dataset can not empty')\n }\n if (dimensions && !Array.isArray(dimensions)) {\n throw new Error('dimensions must be an array')\n }\n if (measures && !Array.isArray(measures)) {\n throw new Error('measures must be an array')\n }\n}\n"],"names":["checkVSeed","vseed","chartType","dataset","dimensions","measures","Error","isArray","isEmpty","isVTable","Array"],"mappings":";;AAIO,MAAMA,aAAa,CAACC;IACzB,MAAM,EAAEC,SAAS,EAAEC,OAAO,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAGJ;IACrD,IAAI,CAACC,WACH,MAAM,IAAII,MAAM;IAElB,IAAI,CAACH,WAAW,CAACI,QAAQJ,UACvB,MAAM,IAAIG,MAAM;IAElB,IAAIE,QAAQL,YAAY,CAACM,SAASR,QAChC,MAAM,IAAIK,MAAM;IAElB,IAAIF,cAAc,CAACM,MAAM,OAAO,CAACN,aAC/B,MAAM,IAAIE,MAAM;IAElB,IAAID,YAAY,CAACK,MAAM,OAAO,CAACL,WAC7B,MAAM,IAAIC,MAAM;AAEpB"}
|
package/dist/umd/index.js
CHANGED
|
@@ -3395,13 +3395,17 @@ self.R = R;
|
|
|
3395
3395
|
};
|
|
3396
3396
|
return advancedVSeed;
|
|
3397
3397
|
};
|
|
3398
|
+
function chunk_BO3LQZNF_o(r) {
|
|
3399
|
+
return Array.isArray(r);
|
|
3400
|
+
}
|
|
3398
3401
|
function chunk_VCYTMP4D_n(e) {
|
|
3399
3402
|
return void 0 === e ? !0 : "string" == typeof e || Array.isArray(e) ? 0 === e.length : 0 === Object.keys(e).length;
|
|
3400
3403
|
}
|
|
3401
3404
|
const checkVSeed = (vseed)=>{
|
|
3402
3405
|
const { chartType, dataset, dimensions, measures } = vseed;
|
|
3403
3406
|
if (!chartType) throw new Error('chartType is required');
|
|
3404
|
-
if (!dataset ||
|
|
3407
|
+
if (!dataset || !chunk_BO3LQZNF_o(dataset)) throw new Error('dataset is required, and must be an array');
|
|
3408
|
+
if (chunk_VCYTMP4D_n(dataset) && !isVTable(vseed)) throw new Error('dataset can not empty');
|
|
3405
3409
|
if (dimensions && !Array.isArray(dimensions)) throw new Error('dimensions must be an array');
|
|
3406
3410
|
if (measures && !Array.isArray(measures)) throw new Error('measures must be an array');
|
|
3407
3411
|
};
|
|
@@ -4329,9 +4333,6 @@ self.R = R;
|
|
|
4329
4333
|
arr
|
|
4330
4334
|
] : [];
|
|
4331
4335
|
}
|
|
4332
|
-
function chunk_BO3LQZNF_o(r) {
|
|
4333
|
-
return Array.isArray(r);
|
|
4334
|
-
}
|
|
4335
4336
|
var tinycolor = __webpack_require__("../../node_modules/.pnpm/tinycolor2@1.4.2/node_modules/tinycolor2/tinycolor.js");
|
|
4336
4337
|
var tinycolor_default = /*#__PURE__*/ __webpack_require__.n(tinycolor);
|
|
4337
4338
|
const tableStyleMap = {
|
|
@@ -4357,19 +4358,46 @@ self.R = R;
|
|
|
4357
4358
|
if (key in bodyCellStyle) acc[tableStyleMap[key]] = bodyCellStyle[key];
|
|
4358
4359
|
return acc;
|
|
4359
4360
|
}, {});
|
|
4360
|
-
const getColumnMinMax = (allData, field)=>{
|
|
4361
|
+
const getColumnMinMax = (allData, field, totalAggregation)=>{
|
|
4361
4362
|
let min = 1 / 0;
|
|
4362
4363
|
let max = -1 / 0;
|
|
4364
|
+
let sum = 0;
|
|
4365
|
+
let count = 0;
|
|
4366
|
+
const hasTotal = !!totalAggregation;
|
|
4367
|
+
const aggregationType = 'string' == typeof totalAggregation ? totalAggregation : 'sum';
|
|
4363
4368
|
for (const datum of allData){
|
|
4364
4369
|
const value = Number(datum[field]);
|
|
4365
4370
|
if (!Number.isNaN(value)) {
|
|
4366
4371
|
min = Math.min(min, value);
|
|
4367
4372
|
max = Math.max(max, value);
|
|
4373
|
+
sum += value;
|
|
4374
|
+
count += 1;
|
|
4368
4375
|
}
|
|
4369
4376
|
}
|
|
4377
|
+
const baseMin = min === 1 / 0 ? 0 : min;
|
|
4378
|
+
const baseMax = max === -1 / 0 ? 0 : max;
|
|
4379
|
+
if (!hasTotal) return {
|
|
4380
|
+
min: baseMin,
|
|
4381
|
+
max: baseMax
|
|
4382
|
+
};
|
|
4383
|
+
const total = (()=>{
|
|
4384
|
+
switch(aggregationType){
|
|
4385
|
+
case 'avg':
|
|
4386
|
+
return count ? sum / count : 0;
|
|
4387
|
+
case 'max':
|
|
4388
|
+
return baseMax;
|
|
4389
|
+
case 'min':
|
|
4390
|
+
return baseMin;
|
|
4391
|
+
case 'count':
|
|
4392
|
+
return count;
|
|
4393
|
+
case 'sum':
|
|
4394
|
+
default:
|
|
4395
|
+
return sum;
|
|
4396
|
+
}
|
|
4397
|
+
})();
|
|
4370
4398
|
return {
|
|
4371
|
-
min: min
|
|
4372
|
-
max: max
|
|
4399
|
+
min: Math.min(baseMin, total),
|
|
4400
|
+
max: Math.max(baseMax, total)
|
|
4373
4401
|
};
|
|
4374
4402
|
};
|
|
4375
4403
|
const applyColorScale = (value, scale)=>{
|
|
@@ -4391,8 +4419,10 @@ self.R = R;
|
|
|
4391
4419
|
} : null;
|
|
4392
4420
|
};
|
|
4393
4421
|
const tableBodyCell = (spec, context)=>{
|
|
4394
|
-
const { advancedVSeed } = context;
|
|
4422
|
+
const { advancedVSeed, vseed } = context;
|
|
4423
|
+
const { totals } = vseed || {};
|
|
4395
4424
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
4425
|
+
const totalAggregation = 'string' == typeof totals ? totals : void 0;
|
|
4396
4426
|
const bodyCellStyle = cellStyle?.bodyCellStyle;
|
|
4397
4427
|
const themeConfig = config?.[chartType];
|
|
4398
4428
|
if (!bodyCellStyle) return spec;
|
|
@@ -4419,14 +4449,14 @@ self.R = R;
|
|
|
4419
4449
|
let columnMin;
|
|
4420
4450
|
let columnMax;
|
|
4421
4451
|
if (progressBarStyle || backgroundColorScale) {
|
|
4422
|
-
const { min, max } = getColumnMinMax(allData, field);
|
|
4452
|
+
const { min, max } = getColumnMinMax(allData, field, totalAggregation);
|
|
4423
4453
|
columnMin = min;
|
|
4424
4454
|
columnMax = max;
|
|
4425
4455
|
if (progressBarStyle) {
|
|
4426
4456
|
col.cellType = 'progressbar';
|
|
4427
4457
|
col.barType = 'negative';
|
|
4428
4458
|
col.min = progressBarStyle.barMin ?? columnMin;
|
|
4429
|
-
col.max = progressBarStyle.
|
|
4459
|
+
col.max = progressBarStyle.barMax ?? columnMax;
|
|
4430
4460
|
}
|
|
4431
4461
|
}
|
|
4432
4462
|
col.style = (datum)=>{
|
|
@@ -4799,6 +4829,16 @@ self.R = R;
|
|
|
4799
4829
|
};
|
|
4800
4830
|
return result;
|
|
4801
4831
|
};
|
|
4832
|
+
const isPivotTotalCell = (styleArg)=>{
|
|
4833
|
+
const cellHeaderPaths = styleArg?.cellHeaderPaths;
|
|
4834
|
+
if (!cellHeaderPaths) return false;
|
|
4835
|
+
if ('sub-total' === cellHeaderPaths.role || 'grand-total' === cellHeaderPaths.role) return true;
|
|
4836
|
+
const headerPaths = [
|
|
4837
|
+
...cellHeaderPaths.colHeaderPaths || [],
|
|
4838
|
+
...cellHeaderPaths.rowHeaderPaths || []
|
|
4839
|
+
];
|
|
4840
|
+
return headerPaths.some((path)=>path?.role === 'sub-total' || path?.role === 'grand-total');
|
|
4841
|
+
};
|
|
4802
4842
|
const pivotTableBodyCell = (spec, context)=>{
|
|
4803
4843
|
const { advancedVSeed } = context;
|
|
4804
4844
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
@@ -4867,6 +4907,7 @@ self.R = R;
|
|
|
4867
4907
|
cellStyle.barMarkWidth = themeConfig?.barMarkWidth;
|
|
4868
4908
|
cellStyle.barPadding = themeConfig?.barPadding;
|
|
4869
4909
|
cellStyle.barRightToLeft = themeConfig?.barRightToLeft;
|
|
4910
|
+
cellStyle.showBar = !isPivotTotalCell(datum);
|
|
4870
4911
|
}
|
|
4871
4912
|
return {
|
|
4872
4913
|
...result,
|
|
@@ -7336,11 +7377,11 @@ self.R = R;
|
|
|
7336
7377
|
markArea: markArea
|
|
7337
7378
|
};
|
|
7338
7379
|
};
|
|
7339
|
-
const
|
|
7380
|
+
const isNumber = (value, fuzzy = !1)=>{
|
|
7340
7381
|
const type = typeof value;
|
|
7341
7382
|
return fuzzy ? "number" === type : "number" === type || isType(value, "Number");
|
|
7342
7383
|
};
|
|
7343
|
-
const
|
|
7384
|
+
const common_isNumber = isNumber;
|
|
7344
7385
|
const clamp_clamp = function(input, min, max) {
|
|
7345
7386
|
return input < min ? min : input > max ? max : input;
|
|
7346
7387
|
};
|
|
@@ -7522,10 +7563,10 @@ self.R = R;
|
|
|
7522
7563
|
return ((value = Math.max(0, Math.min(255, Math.round(value) || 0))) < 16 ? "0" : "") + value.toString(16);
|
|
7523
7564
|
}
|
|
7524
7565
|
function Color_rgb(value) {
|
|
7525
|
-
return
|
|
7566
|
+
return common_isNumber(value) ? new RGB(value >> 16, value >> 8 & 255, 255 & value, 1) : common_isArray(value) ? new RGB(value[0], value[1], value[2]) : new RGB(255, 255, 255);
|
|
7526
7567
|
}
|
|
7527
7568
|
function rgba(value) {
|
|
7528
|
-
return
|
|
7569
|
+
return common_isNumber(value) ? new RGB(value >>> 24, value >>> 16 & 255, value >>> 8 & 255, 255 & value) : common_isArray(value) ? new RGB(value[0], value[1], value[2], value[3]) : new RGB(255, 255, 255, 1);
|
|
7529
7570
|
}
|
|
7530
7571
|
function SRGBToLinear(c) {
|
|
7531
7572
|
return c < .04045 ? .0773993808 * c : Math.pow(.9478672986 * c + .0521327014, 2.4);
|
|
@@ -14352,27 +14393,27 @@ self.R = R;
|
|
|
14352
14393
|
};
|
|
14353
14394
|
const isObjectLike = (value)=>"object" == typeof value && null !== value;
|
|
14354
14395
|
const common_isObjectLike = isObjectLike;
|
|
14355
|
-
const
|
|
14396
|
+
const isPlainObject_isPlainObject = function(value) {
|
|
14356
14397
|
if (!common_isObjectLike(value) || !isType(value, "Object")) return !1;
|
|
14357
14398
|
if (null === Object.getPrototypeOf(value)) return !0;
|
|
14358
14399
|
let proto = value;
|
|
14359
14400
|
for(; null !== Object.getPrototypeOf(proto);)proto = Object.getPrototypeOf(proto);
|
|
14360
14401
|
return Object.getPrototypeOf(value) === proto;
|
|
14361
14402
|
};
|
|
14362
|
-
const
|
|
14363
|
-
const
|
|
14403
|
+
const isPlainObject = isPlainObject_isPlainObject;
|
|
14404
|
+
const isString = (value, fuzzy = !1)=>{
|
|
14364
14405
|
const type = typeof value;
|
|
14365
14406
|
return fuzzy ? "string" === type : "string" === type || isType(value, "String");
|
|
14366
14407
|
};
|
|
14367
|
-
const
|
|
14408
|
+
const common_isString = isString;
|
|
14368
14409
|
function pickWithout(obj, keys) {
|
|
14369
|
-
if (!obj || !
|
|
14410
|
+
if (!obj || !isPlainObject(obj)) return obj;
|
|
14370
14411
|
const result = {};
|
|
14371
14412
|
return Object.keys(obj).forEach((k)=>{
|
|
14372
14413
|
const v = obj[k];
|
|
14373
14414
|
let match = !1;
|
|
14374
14415
|
keys.forEach((itKey)=>{
|
|
14375
|
-
(
|
|
14416
|
+
(common_isString(itKey) && itKey === k || itKey instanceof RegExp && k.match(itKey)) && (match = !0);
|
|
14376
14417
|
}), match || (result[k] = v);
|
|
14377
14418
|
}), result;
|
|
14378
14419
|
}
|
|
@@ -16780,7 +16821,7 @@ self.R = R;
|
|
|
16780
16821
|
const length = objValue.length;
|
|
16781
16822
|
for(; ++index < length;)newValue[index] = objValue[index];
|
|
16782
16823
|
}
|
|
16783
|
-
} else
|
|
16824
|
+
} else isPlainObject(srcValue) ? (newValue = null != objValue ? objValue : {}, "function" != typeof objValue && "object" == typeof objValue || (newValue = {})) : isCommon = !1;
|
|
16784
16825
|
isCommon && baseMerge(newValue, srcValue, shallowArray, skipTargetArray), assignMergeValue(target, key, newValue);
|
|
16785
16826
|
}
|
|
16786
16827
|
function assignMergeValue(target, key, value) {
|