@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.
@@ -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 === 1 / 0 ? 0 : min,
39
- max: max === -1 / 0 ? 0 : 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[], field: string): { min: number; max: number } => {\n let min = Infinity\n let max = -Infinity\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 }\n }\n\n return {\n min: min === Infinity ? 0 : min,\n max: max === -Infinity ? 0 : max,\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","min","Infinity","max","datum","Number","applyColorScale","scale","numValue","isNullish","getCellOriginalDataByDatum","hasDynamicFilter","originalDatum","tableInstance","originRowData","isArray","InnerRowIndex"],"mappings":";;;AAKA,MAAMA,gBAAgB;IACpB,iBAAiB;IACjB,WAAW;IACX,cAAc;IACd,aAAa;IACb,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;AACpB;AAWO,MAAMC,mBAAmB,CAC9BC,OACAC,UACAC,UACAC,UACAC;IAEA,MAAMC,aAAaC,WAAUH,UAAU,KAAK;IAC5C,MAAMI,WAAWD,WAAUF,UAAU,KAAK;IAG1C,MAAMI,aAAcR,AAAAA,CAAAA,QAAQC,QAAO,IAAMC,CAAAA,WAAWD,QAAO;IAC3D,MAAMQ,IAAIC,KAAK,GAAG,CAAC,GAAGA,KAAK,GAAG,CAAC,GAAGF;IAGlC,MAAMG,IAAID,KAAK,KAAK,CAACL,WAAW,CAAC,GAAIE,AAAAA,CAAAA,SAAS,CAAC,GAAGF,WAAW,CAAC,AAAD,IAAKI;IAClE,MAAMG,IAAIF,KAAK,KAAK,CAACL,WAAW,CAAC,GAAIE,AAAAA,CAAAA,SAAS,CAAC,GAAGF,WAAW,CAAC,AAAD,IAAKI;IAClE,MAAMI,IAAIH,KAAK,KAAK,CAACL,WAAW,CAAC,GAAIE,AAAAA,CAAAA,SAAS,CAAC,GAAGF,WAAW,CAAC,AAAD,IAAKI;IAElE,OAAO,CAAC,IAAI,EAAEE,EAAE,EAAE,EAAEC,EAAE,EAAE,EAAEC,EAAE,CAAC,CAAC;AAChC;AAKO,MAAMC,oBAAoB,CAACC,gBACxBC,OAAO,IAAI,CAAClB,eAAqD,MAAM,CAAsB,CAACmB,KAAKC;QACzG,IAAIA,OAAOH,eACTE,GAAG,CAACnB,aAAa,CAACoB,IAAI,CAAC,GAAGH,aAAa,CAACG,IAAI;QAG9C,OAAOD;IACT,GAAG,CAAC;AAMC,MAAME,kBAAkB,CAACC,SAAkBC;IAChD,IAAIC,MAAMC;IACV,IAAIC,MAAM,CAACD;IAEX,KAAK,MAAME,SAASL,QAAS;QAC3B,MAAMpB,QAAQ0B,OAAOD,KAAK,CAACJ,MAAM;QACjC,IAAI,CAACK,OAAO,KAAK,CAAC1B,QAAQ;YACxBsB,MAAMZ,KAAK,GAAG,CAACY,KAAKtB;YACpBwB,MAAMd,KAAK,GAAG,CAACc,KAAKxB;QACtB;IACF;IAEA,OAAO;QACL,KAAKsB,QAAQC,QAAW,IAAID;QAC5B,KAAKE,QAAQ,CAACD,QAAW,IAAIC;IAC/B;AACF;AAKO,MAAMG,kBAAkB,CAC7B3B,OACA4B;IAEA,IAAI,CAACA,OAAO;IAEZ,MAAMC,WAAWH,OAAO1B;IACxB,IAAI0B,OAAO,KAAK,CAACG,aAAaC,UAAU9B,QAAQ;IAEhD,MAAMC,WAAW2B,MAAM,QAAQ;IAC/B,MAAM1B,WAAW0B,MAAM,QAAQ;IAE/B,IAAI3B,aAAaC,UACf,OAAO0B,MAAM,QAAQ;IAGvB,OAAO7B,iBAAiB8B,UAAU5B,UAAUC,UAAU0B,MAAM,QAAQ,EAAEA,MAAM,QAAQ;AACtF;AAEO,MAAMG,6BAA6B,CAACN,OAAYO,kBAA2BC;IAChF,MAAMC,gBAAgBT,OAAO;IAC7B,IAAIU,gBACFD,iBAAiBF,mBAAmBE,eAAe,oBAAoBT,OAAO,KAAKA,OAAO,OAAO;IACnG,IAAIU,iBAAiBC,QAAQD,gBAC3BA,gBAAgBA,aAAa,CAAC,EAAE;IAElC,OAAOA,gBACH;QACE,GAAGF,aAAa;QAChB,CAACI,cAAc,EAAEF,eAAe,CAACE,cAAc;IACjD,IACA;AACN"}
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","cellHeaderPaths","headerPaths","originalDatum","path","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle","scaledColor","applyColorScale"],"mappings":"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"}
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.barMin ?? columnMax;
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.barMin ?? 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","cellStyle","config","chartType","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
+ {"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 || isEmpty(dataset)) throw new Error('dataset is required, and must be an array');
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 || isEmpty(dataset)) {\n throw new Error('dataset is required, and must be an array')\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","isEmpty","Array"],"mappings":";AAGO,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,WAAWI,QAAQJ,UACtB,MAAM,IAAIG,MAAM;IAElB,IAAIF,cAAc,CAACI,MAAM,OAAO,CAACJ,aAC/B,MAAM,IAAIE,MAAM;IAElB,IAAID,YAAY,CAACG,MAAM,OAAO,CAACH,WAC7B,MAAM,IAAIC,MAAM;AAEpB"}
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 || chunk_VCYTMP4D_n(dataset)) throw new Error('dataset is required, and must be an array');
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 === 1 / 0 ? 0 : min,
4372
- max: max === -1 / 0 ? 0 : 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.barMin ?? columnMax;
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 isNumber_isNumber = (value, fuzzy = !1)=>{
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 isNumber = isNumber_isNumber;
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 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);
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 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);
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 isPlainObject = function(value) {
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 common_isPlainObject = isPlainObject;
14363
- const isString_isString = (value, fuzzy = !1)=>{
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 isString = isString_isString;
14408
+ const common_isString = isString;
14368
14409
  function pickWithout(obj, keys) {
14369
- if (!obj || !common_isPlainObject(obj)) return 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
- (isString(itKey) && itKey === k || itKey instanceof RegExp && k.match(itKey)) && (match = !0);
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 common_isPlainObject(srcValue) ? (newValue = null != objValue ? objValue : {}, "function" != typeof objValue && "object" == typeof objValue || (newValue = {})) : isCommon = !1;
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) {