From 48563b2dca69fdc2877c77a1f90b92cd73637424 Mon Sep 17 00:00:00 2001 From: ZJU_czx <952370295@qq.com> Date: Thu, 2 Apr 2026 14:38:01 +0800 Subject: [PATCH 1/5] feat: support token theme register --- packages/vseed/src/theme/index.ts | 2 + packages/vseed/src/theme/tokenTheme.ts | 287 ++++++++++++++++++ .../vseed/tests/unit/theme/tokenTheme.test.ts | 100 ++++++ 3 files changed, 389 insertions(+) create mode 100644 packages/vseed/src/theme/tokenTheme.ts create mode 100644 packages/vseed/tests/unit/theme/tokenTheme.test.ts diff --git a/packages/vseed/src/theme/index.ts b/packages/vseed/src/theme/index.ts index 7cdca9e602..092ec7a94a 100644 --- a/packages/vseed/src/theme/index.ts +++ b/packages/vseed/src/theme/index.ts @@ -1,2 +1,4 @@ export { darkTheme } from './dark' export { lightTheme } from './light' +export { createTokenThemeConfig, registerTokenTheme, registerTokenThemes } from './tokenTheme' +export type { RegisterTokenThemeOptions, TokenThemeBase, TokenThemeDefinition, TokenThemeRegistry } from './tokenTheme' diff --git a/packages/vseed/src/theme/tokenTheme.ts b/packages/vseed/src/theme/tokenTheme.ts new file mode 100644 index 0000000000..140426219e --- /dev/null +++ b/packages/vseed/src/theme/tokenTheme.ts @@ -0,0 +1,287 @@ +import tinycolor from 'tinycolor2' +import type { Config, CustomThemeConfig } from 'src/types' +import { registerAll } from '../builder/register/all' +import { registerCustomTheme } from '../builder/register/theme' +import { darkTheme } from './dark' +import { lightTheme } from './light' + +export type TokenThemeBase = 'light' | 'dark' + +export type TokenThemeDefinition = { + baseTheme: TokenThemeBase + colorScheme: [string, string, ...string[]] + linearColorScheme: [string, string] + textPrimary: string + textSecondary: string + borderColor: string + surfaceColor?: string + surfaceBackgroundColor?: string + accentColor?: string + positiveColor?: string + negativeColor?: string + tooltipBackgroundColor: string + tooltipBorderColor?: string + axisLabelColor?: string + axisTitleColor?: string + axisGridColor?: string + axisLineColor?: string + labelColor?: string + labelStroke?: string + legendLabelColor?: string + legendPagerIconColor?: string + legendPagerIconDisableColor?: string + playerRailColor?: string + playerSliderHandleColor?: string + playerSliderHandleBorderColor?: string + tableBorderColor?: string + tableBodyFontColor?: string + tableHeaderFontColor?: string + tableHeaderBackgroundColor?: string + tableHoverBodyBackgroundColor?: string + tableHoverBodyInlineBackgroundColor?: string + tableHoverHeaderBackgroundColor?: string + tableHoverHeaderInlineBackgroundColor?: string + tableSelectedBorderColor?: string + tableSelectedBackgroundColor?: string +} + +export type TokenThemeRegistry = Record + +export type RegisterTokenThemeOptions = { + ensureRegisterAll?: boolean +} + +type ThemeConfigMap = NonNullable +type ThemeConfigKey = keyof ThemeConfigMap + +const raceChartTypes: ThemeConfigKey[] = ['raceBar', 'raceColumn', 'raceScatter', 'raceLine', 'racePie', 'raceDonut'] + +let hasEnsuredRegisterAll = false + +const isRecord = (value: unknown): value is Record => { + return typeof value === 'object' && value !== null && !Array.isArray(value) +} + +const mergeThemeNode = (base: T, patch: Partial): T => { + if (!isRecord(base) || !isRecord(patch)) { + return patch as T + } + + const result: Record = { ...base } + for (const [key, patchValue] of Object.entries(patch)) { + if (patchValue === undefined) { + continue + } + + const currentValue = result[key] + if (Array.isArray(patchValue)) { + result[key] = [...patchValue] + continue + } + + if (isRecord(currentValue) && isRecord(patchValue)) { + result[key] = mergeThemeNode(currentValue, patchValue) + continue + } + + result[key] = patchValue + } + + return result as T +} + +const withAlpha = (color: string, alpha: number) => tinycolor(color).setAlpha(alpha).toRgbString() + +const ensureRegisterAll = (options?: RegisterTokenThemeOptions) => { + if (options?.ensureRegisterAll === false || hasEnsuredRegisterAll) { + return + } + + registerAll() + hasEnsuredRegisterAll = true +} + +const getAccentColor = (tokens: TokenThemeDefinition) => tokens.accentColor || tokens.colorScheme[0] + +const getAxisPatch = (tokens: TokenThemeDefinition) => ({ + label: { + labelColor: tokens.axisLabelColor || tokens.textSecondary, + }, + title: { + titleColor: tokens.axisTitleColor || tokens.textSecondary, + }, + grid: { + gridColor: tokens.axisGridColor || tokens.borderColor, + }, + tick: { + tickColor: tokens.axisLineColor || tokens.borderColor, + }, + line: { + lineColor: tokens.axisLineColor || tokens.borderColor, + }, +}) + +const getPivotGridPatch = (tokens: TokenThemeDefinition) => ({ + borderColor: tokens.tableBorderColor || tokens.borderColor, + bodyFontColor: tokens.tableBodyFontColor || tokens.textPrimary, + headerFontColor: tokens.tableHeaderFontColor || tokens.textPrimary, + headerBackgroundColor: tokens.tableHeaderBackgroundColor || tokens.surfaceColor || 'transparent', + hoverHeaderBackgroundColor: tokens.tableHoverHeaderBackgroundColor || withAlpha(getAccentColor(tokens), 0.18), + hoverHeaderInlineBackgroundColor: + tokens.tableHoverHeaderInlineBackgroundColor || withAlpha(getAccentColor(tokens), 0.08), + titleFontColor: tokens.textPrimary, + chartGridColor: tokens.axisGridColor || tokens.borderColor, + axisLabelColor: tokens.axisLabelColor || tokens.textSecondary, +}) + +const getPlayerPatch = (tokens: TokenThemeDefinition) => { + const accentColor = getAccentColor(tokens) + + return { + railColor: tokens.playerRailColor || tokens.borderColor, + trackColor: accentColor, + sliderHandleColor: tokens.playerSliderHandleColor || tokens.surfaceColor || '#ffffff', + sliderHandleBorderColor: tokens.playerSliderHandleBorderColor || accentColor, + startButtonColor: accentColor, + pauseButtonColor: accentColor, + backwardButtonColor: accentColor, + forwardButtonColor: accentColor, + } +} + +const getTablePatch = (tokens: TokenThemeDefinition) => { + const accentColor = getAccentColor(tokens) + + return { + borderColor: tokens.tableBorderColor || tokens.borderColor, + bodyFontColor: tokens.tableBodyFontColor || tokens.textPrimary, + headerFontColor: tokens.tableHeaderFontColor || tokens.textPrimary, + headerBackgroundColor: tokens.tableHeaderBackgroundColor || tokens.surfaceColor || 'transparent', + hoverBodyBackgroundColor: tokens.tableHoverBodyBackgroundColor || withAlpha(accentColor, 0.18), + hoverBodyInlineBackgroundColor: tokens.tableHoverBodyInlineBackgroundColor || withAlpha(accentColor, 0.08), + hoverHeaderBackgroundColor: tokens.tableHoverHeaderBackgroundColor || withAlpha(accentColor, 0.18), + hoverHeaderInlineBackgroundColor: tokens.tableHoverHeaderInlineBackgroundColor || withAlpha(accentColor, 0.08), + selectedBorderColor: tokens.tableSelectedBorderColor || accentColor, + selectedBackgroundColor: tokens.tableSelectedBackgroundColor || withAlpha(accentColor, 0.12), + backgroundColor: tokens.surfaceBackgroundColor || 'transparent', + barAxisColor: tokens.axisLineColor || tokens.borderColor, + backgroundColorScale: { + minColor: tokens.linearColorScheme[0], + maxColor: tokens.linearColorScheme[1], + }, + } +} + +const getChartPatch = (tokens: TokenThemeDefinition) => ({ + backgroundColor: 'transparent', + color: { + colorScheme: [...tokens.colorScheme], + linearColorScheme: [...tokens.linearColorScheme], + positiveColor: tokens.positiveColor, + negativeColor: tokens.negativeColor, + }, + label: { + labelColor: tokens.labelColor || tokens.textPrimary, + labelStroke: tokens.labelStroke, + }, + legend: { + labelColor: tokens.legendLabelColor || tokens.textSecondary, + pagerIconColor: tokens.legendPagerIconColor || tokens.textSecondary, + pagerIconDisableColor: tokens.legendPagerIconDisableColor || tokens.borderColor, + }, + tooltip: { + backgroundColor: tokens.tooltipBackgroundColor, + borderColor: tokens.tooltipBorderColor || tokens.borderColor, + keyColor: tokens.textSecondary, + valueColor: tokens.textPrimary, + titleColor: tokens.textPrimary, + }, +}) + +const withAxesAndExtras = ( + chartType: ThemeConfigKey, + chartConfig: NonNullable, + tokens: TokenThemeDefinition, +) => { + let nextChartConfig = mergeThemeNode(chartConfig, getChartPatch(tokens)) + const chartRecord = nextChartConfig as Record + + if (Object.prototype.hasOwnProperty.call(chartRecord, 'xAxis')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { xAxis: getAxisPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + if (Object.prototype.hasOwnProperty.call(chartRecord, 'yAxis')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { yAxis: getAxisPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + if (Object.prototype.hasOwnProperty.call(chartRecord, 'primaryYAxis')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { primaryYAxis: getAxisPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + if (Object.prototype.hasOwnProperty.call(chartRecord, 'secondaryYAxis')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { secondaryYAxis: getAxisPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + if (Object.prototype.hasOwnProperty.call(chartRecord, 'pivotGrid')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { pivotGrid: getPivotGridPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + if (raceChartTypes.includes(chartType) && Object.prototype.hasOwnProperty.call(chartRecord, 'player')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { player: getPlayerPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + return nextChartConfig +} + +export const createTokenThemeConfig = (tokens: TokenThemeDefinition): CustomThemeConfig => { + const baseTheme = tokens.baseTheme === 'dark' ? darkTheme() : lightTheme() + const baseConfig = (baseTheme.config || {}) as ThemeConfigMap + const nextConfig = {} as ThemeConfigMap + + for (const chartType of Object.keys(baseConfig) as ThemeConfigKey[]) { + const chartConfig = baseConfig[chartType] + if (!chartConfig) { + continue + } + + if (chartType === 'table' || chartType === 'pivotTable') { + nextConfig[chartType] = mergeThemeNode(chartConfig, getTablePatch(tokens)) as ThemeConfigMap[ThemeConfigKey] + continue + } + + nextConfig[chartType] = withAxesAndExtras(chartType, chartConfig, tokens) as ThemeConfigMap[ThemeConfigKey] + } + + return { + config: nextConfig as Config, + } +} + +export const registerTokenTheme = ( + themeName: string, + tokens: TokenThemeDefinition, + options?: RegisterTokenThemeOptions, +) => { + ensureRegisterAll(options) + registerCustomTheme(themeName, createTokenThemeConfig(tokens)) +} + +export const registerTokenThemes = (themes: TokenThemeRegistry, options?: RegisterTokenThemeOptions) => { + ensureRegisterAll(options) + + for (const [themeName, tokens] of Object.entries(themes)) { + registerCustomTheme(themeName, createTokenThemeConfig(tokens)) + } +} diff --git a/packages/vseed/tests/unit/theme/tokenTheme.test.ts b/packages/vseed/tests/unit/theme/tokenTheme.test.ts new file mode 100644 index 0000000000..a411c19b23 --- /dev/null +++ b/packages/vseed/tests/unit/theme/tokenTheme.test.ts @@ -0,0 +1,100 @@ +import { beforeAll, describe, expect, test } from 'vitest' +import type { VSeed } from '@visactor/vseed' +import { Builder, registerTokenTheme, registerTokenThemes } from '@visactor/vseed' + +const lineVSeed: VSeed = { + chartType: 'line', + theme: 'unit-light', + dataset: [ + { date: '2019', sales: 20 }, + { date: '2020', sales: 60 }, + { date: '2021', sales: 40 }, + ], +} + +const tableVSeed: VSeed = { + chartType: 'table', + theme: 'unit-earth', + dataset: [ + { date: '2019', sales: 20 }, + { date: '2020', sales: 60 }, + { date: '2021', sales: 40 }, + ], +} + +beforeAll(() => { + registerTokenThemes({ + 'unit-light': { + baseTheme: 'light', + colorScheme: ['#B83280', '#3182CE', '#38A169'], + linearColorScheme: ['#F8C7E7', '#B83280'], + textPrimary: '#1A202C', + textSecondary: '#4A5568', + borderColor: 'rgba(45, 55, 72, 0.16)', + surfaceColor: '#FFFFFF', + tooltipBackgroundColor: 'rgba(255, 255, 255, 0.96)', + tableHeaderBackgroundColor: '#F7FAFC', + tableSelectedBorderColor: '#B83280', + }, + 'unit-earth': { + baseTheme: 'light', + colorScheme: ['#C05621', '#2F855A', '#2B6CB0'], + linearColorScheme: ['#FBD38D', '#C05621'], + textPrimary: '#2D3748', + textSecondary: '#718096', + borderColor: 'rgba(45, 55, 72, 0.12)', + surfaceColor: '#FFFAF0', + tooltipBackgroundColor: 'rgba(255, 250, 240, 0.96)', + tableHeaderBackgroundColor: '#FEFCF7', + tableSelectedBorderColor: '#C05621', + }, + }) +}) + +describe('tokenTheme', () => { + test('should register themes from a token registry', () => { + expect(Builder.getTheme('unit-light')).toBeDefined() + expect(Builder.getTheme('unit-earth')).toBeDefined() + }) + + test('should apply token theme to chart config', () => { + const builder = Builder.from(lineVSeed) + const advanced = builder.buildAdvanced() + const lineConfig = advanced?.config?.line + + expect(lineConfig?.color?.colorScheme).toEqual(['#B83280', '#3182CE', '#38A169']) + expect(lineConfig?.tooltip?.backgroundColor).toBe('rgba(255, 255, 255, 0.96)') + expect(lineConfig?.legend?.labelColor).toBe('#4A5568') + expect(lineConfig?.xAxis?.label?.labelColor).toBe('#4A5568') + }) + + test('should apply token theme to table config', () => { + const builder = Builder.from(tableVSeed) + const advanced = builder.buildAdvanced() + const tableConfig = advanced?.config?.table + + expect(tableConfig?.headerBackgroundColor).toBe('#FEFCF7') + expect(tableConfig?.bodyFontColor).toBe('#2D3748') + expect(tableConfig?.backgroundColorScale?.maxColor).toBe('#C05621') + }) + + test('should register ad-hoc token theme with one call', () => { + registerTokenTheme('agent-custom', { + baseTheme: 'dark', + colorScheme: ['#00C2A8', '#F46060', '#FFB347'], + linearColorScheme: ['#C3FFF7', '#00C2A8'], + textPrimary: '#F5F7FA', + textSecondary: '#AAB4C0', + borderColor: '#334155', + surfaceColor: '#111827', + tooltipBackgroundColor: '#111827', + tableHeaderBackgroundColor: '#0F172A', + }) + + const theme = Builder.getTheme('agent-custom') + + expect(theme?.config?.line?.color?.colorScheme).toEqual(['#00C2A8', '#F46060', '#FFB347']) + expect(theme?.config?.raceBar?.player?.trackColor).toBe('#00C2A8') + expect(theme?.config?.table?.headerBackgroundColor).toBe('#0F172A') + }) +}) \ No newline at end of file From 238fd912f4c9108d99793ffff1e8be0d18d197b6 Mon Sep 17 00:00:00 2001 From: ZJU_czx <952370295@qq.com> Date: Thu, 2 Apr 2026 15:58:19 +0800 Subject: [PATCH 2/5] chore: add chageset --- .changeset/chilly-coins-remain.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilly-coins-remain.md diff --git a/.changeset/chilly-coins-remain.md b/.changeset/chilly-coins-remain.md new file mode 100644 index 0000000000..8fb2592f9a --- /dev/null +++ b/.changeset/chilly-coins-remain.md @@ -0,0 +1,5 @@ +--- +'@visactor/vseed': patch +--- + +Add token theme feature From f6804f78fd2dad7405e56131fe6d374fee520403 Mon Sep 17 00:00:00 2001 From: ZJU_czx <952370295@qq.com> Date: Thu, 2 Apr 2026 19:12:44 +0800 Subject: [PATCH 3/5] feat(vseed): support theme fontFamily pipelines --- .../vseed/src/builder/builder/buildSpec.ts | 9 ++- .../src/pipeline/spec/chart/pipeline/area.ts | 3 + .../spec/chart/pipeline/areaPercent.ts | 3 + .../src/pipeline/spec/chart/pipeline/bar.ts | 3 + .../spec/chart/pipeline/barParallel.ts | 3 + .../spec/chart/pipeline/barPercent.ts | 3 + .../pipeline/spec/chart/pipeline/boxplot.ts | 3 + .../spec/chart/pipeline/circlePacking.ts | 3 + .../pipeline/spec/chart/pipeline/column.ts | 3 + .../spec/chart/pipeline/columnParallel.ts | 3 + .../spec/chart/pipeline/columnPercent.ts | 3 + .../src/pipeline/spec/chart/pipeline/donut.ts | 3 + .../pipeline/spec/chart/pipeline/dualAxis.ts | 3 + .../pipeline/spec/chart/pipeline/funnel.ts | 3 + .../pipeline/spec/chart/pipeline/heatmap.ts | 3 + .../pipeline/spec/chart/pipeline/histogram.ts | 3 + .../src/pipeline/spec/chart/pipeline/line.ts | 3 + .../src/pipeline/spec/chart/pipeline/pie.ts | 3 + .../pipeline/spec/chart/pipeline/raceBar.ts | 2 + .../spec/chart/pipeline/raceColumn.ts | 2 + .../pipeline/spec/chart/pipeline/raceDonut.ts | 2 + .../pipeline/spec/chart/pipeline/raceLine.ts | 2 + .../pipeline/spec/chart/pipeline/racePie.ts | 2 + .../spec/chart/pipeline/raceScatter.ts | 2 + .../src/pipeline/spec/chart/pipeline/radar.ts | 3 + .../src/pipeline/spec/chart/pipeline/rose.ts | 3 + .../spec/chart/pipeline/roseParallel.ts | 3 + .../pipeline/spec/chart/pipeline/scatter.ts | 3 + .../pipeline/spec/chart/pipeline/sunburst.ts | 3 + .../pipeline/spec/chart/pipeline/treeMap.ts | 3 + .../src/pipeline/spec/chart/pipes/index.ts | 1 + .../chart/pipes/pivotChart/pivotGridStyle.ts | 8 ++- .../spec/chart/pipes/player/playerBar.ts | 5 +- .../spec/chart/pipes/player/playerScatter.ts | 5 +- .../spec/chart/pipes/theme/fontFamily.ts | 27 ++++++++ .../pipeline/spec/chart/pipes/theme/index.ts | 1 + .../spec/table/pipes/theme/bodyStyle.ts | 2 + .../table/pipes/theme/bottomFrozenStyle.ts | 2 + .../table/pipes/theme/cornerHeaderStyle.ts | 2 + .../spec/table/pipes/theme/headerStyle.ts | 2 + .../spec/table/pipes/theme/rowHeaderStyle.ts | 2 + packages/vseed/src/theme/tokenTheme.ts | 5 ++ .../types/properties/config/player/player.ts | 4 ++ .../types/properties/config/player/zPlayer.ts | 1 + .../src/types/properties/config/table.ts | 2 + .../vseed/tests/unit/theme/tokenTheme.test.ts | 64 ++++++++++++++++++- 46 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 packages/vseed/src/pipeline/spec/chart/pipes/theme/fontFamily.ts create mode 100644 packages/vseed/src/pipeline/spec/chart/pipes/theme/index.ts diff --git a/packages/vseed/src/builder/builder/buildSpec.ts b/packages/vseed/src/builder/builder/buildSpec.ts index 042c0767b9..3995a23f46 100644 --- a/packages/vseed/src/builder/builder/buildSpec.ts +++ b/packages/vseed/src/builder/builder/buildSpec.ts @@ -1,8 +1,7 @@ -import type { AdvancedVSeed, Spec, SpecPipelineContext, VChartSpecPipeline } from 'src/types' +import type { AdvancedVSeed, Pipe, Spec, SpecPipelineContext } from 'src/types' import { Builder } from './builder' import { execPipeline } from '../../pipeline' import { intl } from 'src/i18n' -import type { ISpec } from '@visactor/vchart' export const buildSpec = (builder: Builder, advancedVSeed: AdvancedVSeed): Spec => { const start = typeof performance !== 'undefined' ? performance.now() : Date.now() @@ -25,9 +24,9 @@ export const buildSpec = (builder: Builder, advancedVSeed: AdvancedVSeed): Spec } try { - const spec = execPipeline(pipeline as VChartSpecPipeline, context) - builder.spec = spec - return spec + const spec = execPipeline(pipeline as Array>, context) + builder.spec = spec as Spec + return spec as Spec } catch (e) { // eslint-disable-next-line no-console console.error(e) diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/area.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/area.ts index 618fcf35e0..ccbe6ca4ea 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/area.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/area.ts @@ -41,9 +41,11 @@ import { splitLine, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const area: VChartSpecPipeline = [ + fontFamilyTheme, initArea, stackInverse, colorAdapter(color, linearColor), @@ -74,6 +76,7 @@ const pivotArea: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initArea, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/areaPercent.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/areaPercent.ts index 89ecdb1b91..29b10b9c41 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/areaPercent.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/areaPercent.ts @@ -41,9 +41,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const areaPercent: VChartSpecPipeline = [ + fontFamilyTheme, initArea, stackInverse, colorAdapter(color, linearColor), @@ -75,6 +77,7 @@ const pivotAreaPercent: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initArea, stackInverse, colorAdapter(color, linearColor), diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/bar.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/bar.ts index eb4eca0249..cdeb5a971d 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/bar.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/bar.ts @@ -36,9 +36,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const bar: VChartSpecPipeline = [ + fontFamilyTheme, initBar, stackCornerRadius, barMaxWidth, @@ -67,6 +69,7 @@ const pivotBar: PivotChartSpecPipeline = [ pivotIndicatorsAsCol, datasetPivot, pivotIndicators([ + fontFamilyTheme, initBar, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/barParallel.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/barParallel.ts index 27e92d6b43..2455c11e17 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/barParallel.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/barParallel.ts @@ -37,9 +37,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const barParallel: VChartSpecPipeline = [ + fontFamilyTheme, initBarParallel, stackCornerRadius, barMaxWidth, @@ -68,6 +70,7 @@ const pivotBarParallel: PivotChartSpecPipeline = [ pivotIndicatorsAsCol, datasetPivot, pivotIndicators([ + fontFamilyTheme, initBarParallel, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/barPercent.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/barPercent.ts index e3e9a53c54..48a61cb83b 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/barPercent.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/barPercent.ts @@ -37,9 +37,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const barPercent: VChartSpecPipeline = [ + fontFamilyTheme, initBar, stackCornerRadius, barMaxWidth, @@ -68,6 +70,7 @@ const pivotBarPercent: PivotChartSpecPipeline = [ pivotIndicatorsAsCol, datasetPivot, pivotIndicators([ + fontFamilyTheme, initBar, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/boxplot.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/boxplot.ts index 2bb5eedf2e..b049f66b4c 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/boxplot.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/boxplot.ts @@ -36,9 +36,11 @@ import { colorBoxPlotStyleFill, outlierStyle, discreteLegend, + fontFamilyTheme, } from '../pipes' const boxplot: VChartSpecPipeline = [ + fontFamilyTheme, initBoxplot, stackCornerRadius, boxMaxWidth, @@ -66,6 +68,7 @@ const pivotBoxplot: PivotChartSpecPipeline = [ pivotGridStyle, datasetPivot, pivotIndicators([ + fontFamilyTheme, initBoxplot, stackCornerRadius, boxMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/circlePacking.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/circlePacking.ts index c7c06674d3..9d0da43c4d 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/circlePacking.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/circlePacking.ts @@ -23,9 +23,11 @@ import { pivotHideIndicatorName, datasetPivotHierarchy, drill, + fontFamilyTheme, } from '../pipes' const circlePacking: VChartSpecPipeline = [ + fontFamilyTheme, initCirclePacking, drill, datasetHierarchy, @@ -43,6 +45,7 @@ const pivotCirclePacking: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivotHierarchy, pivotIndicators([ + fontFamilyTheme, initCirclePacking, datasetHierarchy, colorAdapter(color, linearColor), diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/column.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/column.ts index 529bfc57a4..b1293fdad1 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/column.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/column.ts @@ -38,9 +38,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const column: VChartSpecPipeline = [ + fontFamilyTheme, initColumn, stackCornerRadius, barMaxWidth, @@ -70,6 +72,7 @@ const pivotColumn: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initColumn, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/columnParallel.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/columnParallel.ts index d3c0561338..39c2680820 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/columnParallel.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/columnParallel.ts @@ -37,9 +37,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const columnParallel: VChartSpecPipeline = [ + fontFamilyTheme, initColumnParallel, stackCornerRadius, barMaxWidth, @@ -68,6 +70,7 @@ const pivotColumnParallel: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initColumnParallel, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/columnPercent.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/columnPercent.ts index d9f5941a11..010c75a966 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/columnPercent.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/columnPercent.ts @@ -38,9 +38,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const columnPercent: VChartSpecPipeline = [ + fontFamilyTheme, initColumn, stackCornerRadius, stackInverse, @@ -70,6 +72,7 @@ const pivotColumnPercent: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initColumn, stackCornerRadius, stackInverse, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/donut.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/donut.ts index 6cbf175041..b3489d8204 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/donut.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/donut.ts @@ -32,9 +32,11 @@ import { addRegionPadding, brush, dimensionLinkage, + fontFamilyTheme, } from '../pipes' const donut: VChartSpecPipeline = [ + fontFamilyTheme, initDonut, colorAdapter(color, linearColor), backgroundColor, @@ -58,6 +60,7 @@ const pivotDonut: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivot, pivotIndicators([ + fontFamilyTheme, initDonut, addRegionPadding, colorAdapter(color, linearColor), diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/dualAxis.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/dualAxis.ts index 6931a5e307..95d1d37c3e 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/dualAxis.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/dualAxis.ts @@ -54,9 +54,11 @@ import { labelDualAxis, tooltipOfDualAxisSeries, adjustXField, + fontFamilyTheme, } from '../pipes' const dualAxis: VChartSpecPipeline = [ + fontFamilyTheme, seriesDualAxis( [initDualAxis, dualChartType, datasetDualAxis, labelDualAxis, tooltipOfDualAxisSeries], @@ -99,6 +101,7 @@ const pivotDualAxis: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, series( [initDualAxis, dualChartType, datasetDualAxis, labelDualAxis, tooltipOfDualAxisSeries], diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/funnel.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/funnel.ts index 5a8601de5a..fd544411a2 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/funnel.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/funnel.ts @@ -30,9 +30,11 @@ import { funnelTransformStyle, pivotTitle, addRegionPadding, + fontFamilyTheme, } from '../pipes' const funnel: VChartSpecPipeline = [ + fontFamilyTheme, initFunnel, backgroundColor, datasetXY, @@ -55,6 +57,7 @@ const pivotFunnel: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivot, pivotIndicators([ + fontFamilyTheme, initFunnel, addRegionPadding, backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/heatmap.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/heatmap.ts index 3fe1d36227..51d90a309c 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/heatmap.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/heatmap.ts @@ -29,10 +29,12 @@ import { pivotColorLegend, heatmapColorDomain, brush, + fontFamilyTheme, } from '../pipes' import { initHeatmap } from '../pipes/init/heatmap' const heatmap: VChartSpecPipeline = [ + fontFamilyTheme, initHeatmap, backgroundColor, datasetXY, @@ -55,6 +57,7 @@ const pivotHeatmap: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initHeatmap, backgroundColor, datasetXY, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/histogram.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/histogram.ts index cbda37042c..c12272d988 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/histogram.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/histogram.ts @@ -35,9 +35,11 @@ import { dimensionLinkage, histogramXLinear, brush, + fontFamilyTheme, } from '../pipes' const histogram: VChartSpecPipeline = [ + fontFamilyTheme, initHistogram, colorAdapter(color, linearColor), backgroundColor, @@ -64,6 +66,7 @@ const pivotHistogram: PivotChartSpecPipeline = [ pivotGridStyle, datasetPivot, pivotIndicators([ + fontFamilyTheme, initHistogram, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/line.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/line.ts index 6f6a04ff62..9300090210 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/line.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/line.ts @@ -38,9 +38,11 @@ import { splitLine, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const line: VChartSpecPipeline = [ + fontFamilyTheme, initLine, colorAdapter(color, linearColor), backgroundColor, @@ -69,6 +71,7 @@ const pivotLine: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initLine, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/pie.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/pie.ts index a36edeec84..a46499dccc 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/pie.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/pie.ts @@ -32,9 +32,11 @@ import { addRegionPadding, brush, dimensionLinkage, + fontFamilyTheme, } from '../pipes' const pie: VChartSpecPipeline = [ + fontFamilyTheme, initPie, colorAdapter(color, linearColor), backgroundColor, @@ -58,6 +60,7 @@ const pivotPie: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivot, pivotIndicators([ + fontFamilyTheme, initPie, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/raceBar.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/raceBar.ts index 6bf507acf6..034bb3e681 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/raceBar.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/raceBar.ts @@ -25,9 +25,11 @@ import { yBand, datasetYX, isPlayer, + fontFamilyTheme, } from '../pipes' const raceBar: VChartSpecPipeline = [ + fontFamilyTheme, initBar, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/raceColumn.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/raceColumn.ts index ed1059ffc9..4729d76124 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/raceColumn.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/raceColumn.ts @@ -25,9 +25,11 @@ import { yLinear, datasetXY, isPlayer, + fontFamilyTheme, } from '../pipes' const raceColumn: VChartSpecPipeline = [ + fontFamilyTheme, initColumn, stackCornerRadius, barMaxWidth, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/raceDonut.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/raceDonut.ts index 98036468da..5cc5538945 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/raceDonut.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/raceDonut.ts @@ -20,9 +20,11 @@ import { annotationArea, datasetXY, isPlayer, + fontFamilyTheme, } from '../pipes' const raceDonut: VChartSpecPipeline = [ + fontFamilyTheme, initDonut, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/raceLine.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/raceLine.ts index c3d88269a6..2ea86d6bfc 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/raceLine.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/raceLine.ts @@ -24,9 +24,11 @@ import { annotationPoint, datasetXY, isPlayer, + fontFamilyTheme, } from '../pipes' const raceLine: VChartSpecPipeline = [ + fontFamilyTheme, initLine, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/racePie.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/racePie.ts index b51c9e3ffa..460ed774f8 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/racePie.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/racePie.ts @@ -20,9 +20,11 @@ import { annotationArea, datasetXY, isPlayer, + fontFamilyTheme, } from '../pipes' const racePie: VChartSpecPipeline = [ + fontFamilyTheme, initPie, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/raceScatter.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/raceScatter.ts index 8e87e59092..46798dfd3b 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/raceScatter.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/raceScatter.ts @@ -30,8 +30,10 @@ import { logisticRegressionLine, datasetScatter, isPlayer, + fontFamilyTheme, } from '../pipes' const raceScatter: VChartSpecPipeline = [ + fontFamilyTheme, initScatter, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/radar.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/radar.ts index f0437e5980..e0f3d4b1bf 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/radar.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/radar.ts @@ -34,9 +34,11 @@ import { pivotHideIndicatorName, pivotTitle, addRegionPadding, + fontFamilyTheme, } from '../pipes' const radar: VChartSpecPipeline = [ + fontFamilyTheme, initRadar, colorAdapter(color, linearColor), backgroundColor, @@ -65,6 +67,7 @@ const pivotRadar: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivot, pivotIndicators([ + fontFamilyTheme, initRadar, addRegionPadding, colorAdapter(color, linearColor), diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/rose.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/rose.ts index d18daa013f..99e6b57bdf 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/rose.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/rose.ts @@ -31,9 +31,11 @@ import { pivotTitle, addRegionPadding, dimensionLinkage, + fontFamilyTheme, } from '../pipes' const rose: VChartSpecPipeline = [ + fontFamilyTheme, initRose, stackCornerRadius, stackInverse, @@ -56,6 +58,7 @@ const pivotRose: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivot, pivotIndicators([ + fontFamilyTheme, initRose, addRegionPadding, stackCornerRadius, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/roseParallel.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/roseParallel.ts index 57d06da4d1..d653ec7da0 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/roseParallel.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/roseParallel.ts @@ -34,9 +34,11 @@ import { pivotTitle, addRegionPadding, dimensionLinkage, + fontFamilyTheme, } from '../pipes' const roseParallel: VChartSpecPipeline = [ + fontFamilyTheme, initRoseParallel, stackCornerRadius, colorAdapter(color, linearColor), @@ -62,6 +64,7 @@ const pivotRoseParallel: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivot, pivotIndicators([ + fontFamilyTheme, initRoseParallel, addRegionPadding, stackCornerRadius, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/scatter.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/scatter.ts index cda0675083..40aef9b6b1 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/scatter.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/scatter.ts @@ -41,9 +41,11 @@ import { pivotTitle, dimensionLinkage, brush, + fontFamilyTheme, } from '../pipes' const scatter: VChartSpecPipeline = [ + fontFamilyTheme, initScatter, colorAdapter(color, linearColor), backgroundColor, @@ -76,6 +78,7 @@ const pivotScatter: PivotChartSpecPipeline = [ pivotIndicatorsAsRow, datasetPivot, pivotIndicators([ + fontFamilyTheme, initScatter, colorAdapter(color, linearColor), backgroundColor, diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/sunburst.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/sunburst.ts index eb0312ece0..ce203dc2fd 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/sunburst.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/sunburst.ts @@ -23,9 +23,11 @@ import { pivotHideIndicatorName, datasetPivotHierarchy, drill, + fontFamilyTheme, } from '../pipes' const sunburst: VChartSpecPipeline = [ + fontFamilyTheme, initSunburst, drill, datasetHierarchy, @@ -43,6 +45,7 @@ const pivotSunburst: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivotHierarchy, pivotIndicators([ + fontFamilyTheme, initSunburst, datasetHierarchy, colorAdapter(color, linearColor), diff --git a/packages/vseed/src/pipeline/spec/chart/pipeline/treeMap.ts b/packages/vseed/src/pipeline/spec/chart/pipeline/treeMap.ts index 02e6957885..ff9a59ae9b 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipeline/treeMap.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipeline/treeMap.ts @@ -23,10 +23,12 @@ import { pivotIndicatorsAsCol, pivotHideIndicatorName, drill, + fontFamilyTheme, } from '../pipes' import { tooltipTreeMap } from '../pipes/tooltip/tooltipTreeMap' const treeMap: VChartSpecPipeline = [ + fontFamilyTheme, initTreeMap, drill, datasetHierarchy, @@ -45,6 +47,7 @@ const pivotTreeMap: PivotChartSpecPipeline = [ pivotHideIndicatorName, datasetPivotHierarchy, pivotIndicators([ + fontFamilyTheme, initTreeMap, datasetHierarchy, colorAdapter(color, linearColor), diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/index.ts b/packages/vseed/src/pipeline/spec/chart/pipes/index.ts index 645e329601..77d777eb8c 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/index.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/index.ts @@ -23,3 +23,4 @@ export * from './region' export * from './pipeFilter' export * from './player' export * from './hierarchy' +export * from './theme' diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts b/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts index 8874c4233b..68f652e8dc 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts @@ -6,7 +6,9 @@ import { isNullish } from 'remeda' export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { const { vseed, advancedVSeed } = context const { config, chartType } = advancedVSeed - const themConfig = (config?.[chartType] as Config['line'])?.pivotGrid ?? {} + const chartConfig = (config?.[chartType] as (Config['line'] & { fontFamily?: string }) | undefined) ?? {} + const themConfig = chartConfig?.pivotGrid ?? {} + const fontFamily = chartConfig?.fontFamily const onlyCombination = !isPivot(vseed) && isCombination(vseed) @@ -41,6 +43,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { bodyStyle: { borderColor, color: bodyFontColor, + fontFamily, borderLineWidth: (arg: { row: number; col: number; table: any }) => { const noYAxis = chartType === 'pie' || @@ -66,6 +69,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { headerStyle: { borderColor, fontSize: 12, + fontFamily, // borderLineWidth: [outlineBorderLineWidth, outlineBorderLineWidth, 1, 1], borderLineWidth: (arg: { row: number; col: number }) => { return [outlineBorderLineWidth, outlineBorderLineWidth, 1, arg.col === 0 ? outlineBorderLineWidth : 1] @@ -82,6 +86,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { rowHeaderStyle: { borderColor, fontSize: 12, + fontFamily, color: headerFontColor, padding: [0, 12, 0, 4], borderLineWidth: (arg: { row: number }) => { @@ -98,6 +103,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { borderColor, textAlign: 'center', fontSize: 12, + fontFamily, color: headerFontColor, padding: [0, 12, 0, 4], fontWeight: 'bold', diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts index 203a1d0842..b5012ae8a9 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts @@ -7,13 +7,14 @@ export const playerBar: VChartSpecPipe = (spec, context) => { const { advancedVSeed } = context const { dimensions = [], datasetReshapeInfo, chartType, encoding } = advancedVSeed - const baseConfig = advancedVSeed.config[chartType] as { player: Player } + const baseConfig = advancedVSeed.config[chartType] as { fontFamily?: string; player: Player } const result = datasetYX(spec, context) if (!baseConfig || !baseConfig.player) { return result } const { player } = baseConfig + const fontFamily = player.fontFamily || baseConfig.fontFamily const id = datasetReshapeInfo[0].id const { unfoldInfo, foldInfo } = datasetReshapeInfo[0] const { encodingPlayer, encodingY } = unfoldInfo @@ -128,7 +129,7 @@ export const playerBar: VChartSpecPipe = (spec, context) => { textBaseline: 'bottom', fontSize: textSize, textAlign: 'right', - fontFamily: 'PingFang SC', + fontFamily, fontWeight: 600, text: (datum: any) => datum[encodingPlayer], x: (_datum: any, ctx: any) => { diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts index 9c78abd9e5..211d53e39a 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts @@ -6,13 +6,14 @@ import { datasetScatter } from '../dataset' export const playerScatter: VChartSpecPipe = (spec, context) => { const { advancedVSeed } = context const { datasetReshapeInfo, dimensions = [], chartType, encoding } = advancedVSeed - const baseConfig = advancedVSeed.config[chartType] as { player: Player } + const baseConfig = advancedVSeed.config[chartType] as { fontFamily?: string; player: Player } const result = datasetScatter(spec, context) if (!baseConfig || !baseConfig.player) { return result } const { player } = baseConfig + const fontFamily = player.fontFamily || baseConfig.fontFamily const id = datasetReshapeInfo[0].id const { unfoldInfo } = datasetReshapeInfo[0] @@ -116,7 +117,7 @@ export const playerScatter: VChartSpecPipe = (spec, context) => { textBaseline: 'bottom', fontSize: textSize, textAlign: 'right', - fontFamily: 'PingFang SC', + fontFamily, fontWeight: 600, text: (datum: any) => datum[encodingPlayer], x: (datum: any, ctx: any) => { diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/theme/fontFamily.ts b/packages/vseed/src/pipeline/spec/chart/pipes/theme/fontFamily.ts new file mode 100644 index 0000000000..504f152752 --- /dev/null +++ b/packages/vseed/src/pipeline/spec/chart/pipes/theme/fontFamily.ts @@ -0,0 +1,27 @@ +import type { VChartSpecPipe } from 'src/types' + +type FontFamilyAwareChartConfig = { + fontFamily?: string +} + +export const fontFamilyTheme: VChartSpecPipe = (spec, context) => { + const result = { ...spec } as Record + const { advancedVSeed } = context + const chartConfig = (advancedVSeed.config?.[advancedVSeed.chartType] || {}) as FontFamilyAwareChartConfig + + if (!chartConfig.fontFamily) { + return result + } + + const theme = + typeof result.theme === 'object' && result.theme !== null && !Array.isArray(result.theme) + ? (result.theme as Record) + : {} + + result.theme = { + ...theme, + fontFamily: chartConfig.fontFamily, + } + + return result +} diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/theme/index.ts b/packages/vseed/src/pipeline/spec/chart/pipes/theme/index.ts new file mode 100644 index 0000000000..2c95239140 --- /dev/null +++ b/packages/vseed/src/pipeline/spec/chart/pipes/theme/index.ts @@ -0,0 +1 @@ +export { fontFamilyTheme } from './fontFamily' diff --git a/packages/vseed/src/pipeline/spec/table/pipes/theme/bodyStyle.ts b/packages/vseed/src/pipeline/spec/table/pipes/theme/bodyStyle.ts index 5d97e2c5fb..506633ae6a 100644 --- a/packages/vseed/src/pipeline/spec/table/pipes/theme/bodyStyle.ts +++ b/packages/vseed/src/pipeline/spec/table/pipes/theme/bodyStyle.ts @@ -14,6 +14,7 @@ export const bodyStyle: PivotTableSpecPipe = (spec, context) => { const backgroundColor = themeConfig.bodyBackgroundColor || '#fff' const fontColor = themeConfig.bodyFontColor || '#1B1F23' const fontSize = themeConfig.bodyFontSize || 12 + const fontFamily = themeConfig.bodyFontFamily // Interaction const hoverCellBgColor = themeConfig.hoverBodyBackgroundColor || '#bedaff' const hoverInlineColor = themeConfig.hoverBodyInlineBackgroundColor || '#bedaff' @@ -31,6 +32,7 @@ export const bodyStyle: PivotTableSpecPipe = (spec, context) => { }, color: fontColor, fontSize: fontSize, + fontFamily: fontFamily, fontStyle: 'normal', fontWeight: 'normal', fontVariant: 'normal', diff --git a/packages/vseed/src/pipeline/spec/table/pipes/theme/bottomFrozenStyle.ts b/packages/vseed/src/pipeline/spec/table/pipes/theme/bottomFrozenStyle.ts index da5221ed3d..0806d2aab7 100644 --- a/packages/vseed/src/pipeline/spec/table/pipes/theme/bottomFrozenStyle.ts +++ b/packages/vseed/src/pipeline/spec/table/pipes/theme/bottomFrozenStyle.ts @@ -13,6 +13,7 @@ export const bottomFrozenStyle: PivotTableSpecPipe = (spec, context) => { const backgroundColor = themConfig.headerBackgroundColor || '#EEF1F5' const fontColor = themConfig.headerFontColor || '#1B1F23' const fontSize = themConfig.headerFontSize || 12 + const fontFamily = themConfig.headerFontFamily const hoverCellBgColor = themConfig.hoverHeaderBackgroundColor || '#bedaff' const hoverInlineColor = themConfig.hoverHeaderInlineBackgroundColor || '#bedaff' @@ -31,6 +32,7 @@ export const bottomFrozenStyle: PivotTableSpecPipe = (spec, context) => { borderLineWidth: [0, 0, 1, 0], }, fontSize, + fontFamily, fontVariant: 'normal', fontStyle: 'normal', fontWeight: 'bold', diff --git a/packages/vseed/src/pipeline/spec/table/pipes/theme/cornerHeaderStyle.ts b/packages/vseed/src/pipeline/spec/table/pipes/theme/cornerHeaderStyle.ts index 5d73d5721f..b0672ce8c5 100644 --- a/packages/vseed/src/pipeline/spec/table/pipes/theme/cornerHeaderStyle.ts +++ b/packages/vseed/src/pipeline/spec/table/pipes/theme/cornerHeaderStyle.ts @@ -14,6 +14,7 @@ export const cornerHeaderStyle: PivotTableSpecPipe = (spec, context) => { const backgroundColor = themConfig.headerBackgroundColor || '#EEF1F5' const fontColor = themConfig.headerFontColor || '#1B1F23' const fontSize = themConfig.headerFontSize || 12 + const fontFamily = themConfig.headerFontFamily // Interaction const hoverInlineColor = themConfig.hoverHeaderInlineBackgroundColor const hoverCellColor = themConfig.hoverHeaderBackgroundColor @@ -33,6 +34,7 @@ export const cornerHeaderStyle: PivotTableSpecPipe = (spec, context) => { borderLineWidth: [0, 1, 1, 0], }, fontSize: fontSize, + fontFamily: fontFamily, fontVariant: 'normal', fontStyle: 'normal', fontWeight: 'bold', diff --git a/packages/vseed/src/pipeline/spec/table/pipes/theme/headerStyle.ts b/packages/vseed/src/pipeline/spec/table/pipes/theme/headerStyle.ts index 87b3027af5..b0a058daff 100644 --- a/packages/vseed/src/pipeline/spec/table/pipes/theme/headerStyle.ts +++ b/packages/vseed/src/pipeline/spec/table/pipes/theme/headerStyle.ts @@ -14,6 +14,7 @@ export const headerStyle: PivotTableSpecPipe = (spec, context) => { const backgroundColor = themConfig.headerBackgroundColor || '#EEF1F5' const fontColor = themConfig.headerFontColor || '#1B1F23' const fontSize = themConfig.headerFontSize || 12 + const fontFamily = themConfig.headerFontFamily // Interaction const hoverCellBgColor = themConfig.hoverHeaderBackgroundColor || '#bedaff' const hoverInlineColor = themConfig.hoverHeaderInlineBackgroundColor || '#bedaff' @@ -33,6 +34,7 @@ export const headerStyle: PivotTableSpecPipe = (spec, context) => { borderLineWidth: [0, 0, 1, 0], }, fontSize: fontSize, + fontFamily: fontFamily, fontVariant: 'normal', fontStyle: 'normal', fontWeight: 'bold', diff --git a/packages/vseed/src/pipeline/spec/table/pipes/theme/rowHeaderStyle.ts b/packages/vseed/src/pipeline/spec/table/pipes/theme/rowHeaderStyle.ts index b2ee561df3..3481869bb6 100644 --- a/packages/vseed/src/pipeline/spec/table/pipes/theme/rowHeaderStyle.ts +++ b/packages/vseed/src/pipeline/spec/table/pipes/theme/rowHeaderStyle.ts @@ -14,6 +14,7 @@ export const rowHeaderStyle: PivotTableSpecPipe = (spec, context) => { const backgroundColor = themConfig.headerBackgroundColor || '#EEF1F5' const fontColor = themConfig.headerFontColor || '#1B1F23' const fontSize = themConfig.headerFontSize || 12 + const fontFamily = themConfig.headerFontFamily // Interaction const hoverCellBgColor = themConfig.hoverHeaderBackgroundColor || '#bedaff' const hoverInlineColor = themConfig.hoverHeaderInlineBackgroundColor || '#bedaff' @@ -33,6 +34,7 @@ export const rowHeaderStyle: PivotTableSpecPipe = (spec, context) => { borderLineWidth: [0, 1, 0, 0], }, fontSize: fontSize, + fontFamily: fontFamily, fontVariant: 'normal', fontStyle: 'normal', fontWeight: 'bold', diff --git a/packages/vseed/src/theme/tokenTheme.ts b/packages/vseed/src/theme/tokenTheme.ts index 140426219e..3ab7e170c2 100644 --- a/packages/vseed/src/theme/tokenTheme.ts +++ b/packages/vseed/src/theme/tokenTheme.ts @@ -9,6 +9,7 @@ export type TokenThemeBase = 'light' | 'dark' export type TokenThemeDefinition = { baseTheme: TokenThemeBase + fontFamily?: string colorScheme: [string, string, ...string[]] linearColorScheme: [string, string] textPrimary: string @@ -138,6 +139,7 @@ const getPlayerPatch = (tokens: TokenThemeDefinition) => { const accentColor = getAccentColor(tokens) return { + fontFamily: tokens.fontFamily, railColor: tokens.playerRailColor || tokens.borderColor, trackColor: accentColor, sliderHandleColor: tokens.playerSliderHandleColor || tokens.surfaceColor || '#ffffff', @@ -154,7 +156,9 @@ const getTablePatch = (tokens: TokenThemeDefinition) => { return { borderColor: tokens.tableBorderColor || tokens.borderColor, + bodyFontFamily: tokens.fontFamily, bodyFontColor: tokens.tableBodyFontColor || tokens.textPrimary, + headerFontFamily: tokens.fontFamily, headerFontColor: tokens.tableHeaderFontColor || tokens.textPrimary, headerBackgroundColor: tokens.tableHeaderBackgroundColor || tokens.surfaceColor || 'transparent', hoverBodyBackgroundColor: tokens.tableHoverBodyBackgroundColor || withAlpha(accentColor, 0.18), @@ -174,6 +178,7 @@ const getTablePatch = (tokens: TokenThemeDefinition) => { const getChartPatch = (tokens: TokenThemeDefinition) => ({ backgroundColor: 'transparent', + fontFamily: tokens.fontFamily, color: { colorScheme: [...tokens.colorScheme], linearColorScheme: [...tokens.linearColorScheme], diff --git a/packages/vseed/src/types/properties/config/player/player.ts b/packages/vseed/src/types/properties/config/player/player.ts index a27997a439..3494009eab 100644 --- a/packages/vseed/src/types/properties/config/player/player.ts +++ b/packages/vseed/src/types/properties/config/player/player.ts @@ -27,6 +27,10 @@ export type Player = { * @description 播放器进度条轨道颜色 */ railColor?: string + /** + * @description 播放器文本字体 + */ + fontFamily?: string /** * @description 播放器进度条进度颜色 */ diff --git a/packages/vseed/src/types/properties/config/player/zPlayer.ts b/packages/vseed/src/types/properties/config/player/zPlayer.ts index 525813f75f..1d595f9246 100644 --- a/packages/vseed/src/types/properties/config/player/zPlayer.ts +++ b/packages/vseed/src/types/properties/config/player/zPlayer.ts @@ -8,6 +8,7 @@ export const zPlayer = z.object({ position: z.enum(['top', 'bottom', 'left', 'right']).optional(), railColor: z.string().optional(), + fontFamily: z.string().optional(), trackColor: z.string().optional(), sliderHandleColor: z.string().optional(), diff --git a/packages/vseed/src/types/properties/config/table.ts b/packages/vseed/src/types/properties/config/table.ts index 8708466606..4a4b03e48a 100644 --- a/packages/vseed/src/types/properties/config/table.ts +++ b/packages/vseed/src/types/properties/config/table.ts @@ -9,6 +9,7 @@ export const zTableConfig = z.object({ // Body bodyFontSize: z.number().nullish(), + bodyFontFamily: z.string().nullish(), bodyFontColor: z.string().nullish(), bodyBackgroundColor: z.string().nullish(), // Body interaction @@ -17,6 +18,7 @@ export const zTableConfig = z.object({ // Header headerFontSize: z.number().nullish(), + headerFontFamily: z.string().nullish(), headerFontColor: z.string().nullish(), headerBackgroundColor: z.string().nullish(), // Header interaction diff --git a/packages/vseed/tests/unit/theme/tokenTheme.test.ts b/packages/vseed/tests/unit/theme/tokenTheme.test.ts index a411c19b23..f473a9d8a2 100644 --- a/packages/vseed/tests/unit/theme/tokenTheme.test.ts +++ b/packages/vseed/tests/unit/theme/tokenTheme.test.ts @@ -2,6 +2,8 @@ import { beforeAll, describe, expect, test } from 'vitest' import type { VSeed } from '@visactor/vseed' import { Builder, registerTokenTheme, registerTokenThemes } from '@visactor/vseed' +const fontFamily = '"Inter", "Noto Sans SC", sans-serif' + const lineVSeed: VSeed = { chartType: 'line', theme: 'unit-light', @@ -12,6 +14,28 @@ const lineVSeed: VSeed = { ], } +const raceBarVSeed: VSeed = { + chartType: 'raceBar', + theme: 'unit-light', + measures: [{ id: 'sales', alias: '销售额', autoFormat: true }], + dimensions: [ + { id: 'category', alias: '分类' }, + { id: 'date', alias: '日期' }, + ], + dataset: [ + { date: '2019', category: 'A', sales: 100 }, + { date: '2019', category: 'B', sales: 150 }, + { date: '2020', category: 'A', sales: 120 }, + { date: '2020', category: 'B', sales: 180 }, + { date: '2021', category: 'A', sales: 140 }, + { date: '2021', category: 'B', sales: 200 }, + ], + player: { + enable: true, + field: 'date', + } as any, +} + const tableVSeed: VSeed = { chartType: 'table', theme: 'unit-earth', @@ -22,10 +46,21 @@ const tableVSeed: VSeed = { ], } +const pivotTableVSeed: VSeed = { + chartType: 'pivotTable', + theme: 'unit-earth', + dataset: [ + { date: '2019', type: 'A', sales: 100 }, + { date: '2020', type: 'A', sales: 320 }, + { date: '2021', type: 'A', sales: 300 }, + ], +} + beforeAll(() => { registerTokenThemes({ 'unit-light': { baseTheme: 'light', + fontFamily, colorScheme: ['#B83280', '#3182CE', '#38A169'], linearColorScheme: ['#F8C7E7', '#B83280'], textPrimary: '#1A202C', @@ -38,6 +73,7 @@ beforeAll(() => { }, 'unit-earth': { baseTheme: 'light', + fontFamily, colorScheme: ['#C05621', '#2F855A', '#2B6CB0'], linearColorScheme: ['#FBD38D', '#C05621'], textPrimary: '#2D3748', @@ -60,9 +96,10 @@ describe('tokenTheme', () => { test('should apply token theme to chart config', () => { const builder = Builder.from(lineVSeed) const advanced = builder.buildAdvanced() - const lineConfig = advanced?.config?.line + const lineConfig = advanced?.config?.line as any expect(lineConfig?.color?.colorScheme).toEqual(['#B83280', '#3182CE', '#38A169']) + expect(lineConfig?.fontFamily).toBe(fontFamily) expect(lineConfig?.tooltip?.backgroundColor).toBe('rgba(255, 255, 255, 0.96)') expect(lineConfig?.legend?.labelColor).toBe('#4A5568') expect(lineConfig?.xAxis?.label?.labelColor).toBe('#4A5568') @@ -75,12 +112,35 @@ describe('tokenTheme', () => { expect(tableConfig?.headerBackgroundColor).toBe('#FEFCF7') expect(tableConfig?.bodyFontColor).toBe('#2D3748') + expect((tableConfig as any)?.bodyFontFamily).toBe(fontFamily) + expect((tableConfig as any)?.headerFontFamily).toBe(fontFamily) expect(tableConfig?.backgroundColorScale?.maxColor).toBe('#C05621') }) + test('should apply fontFamily to final chart spec and race player text', () => { + const builder = Builder.from(lineVSeed) + const spec = builder.build() as any + const raceSpec = Builder.from(raceBarVSeed).build() as any + + expect(spec?.theme?.fontFamily).toBe(fontFamily) + expect(raceSpec?.theme?.fontFamily).toBe(fontFamily) + expect(raceSpec?.customMark?.[0]?.style?.fontFamily).toBe(fontFamily) + }) + + test('should apply fontFamily to final table spec', () => { + const tableSpec = Builder.from(tableVSeed).build() as any + const pivotTableSpec = Builder.from(pivotTableVSeed).build() as any + + expect(tableSpec?.theme?.bodyStyle?.fontFamily).toBe(fontFamily) + expect(tableSpec?.theme?.headerStyle?.fontFamily).toBe(fontFamily) + expect(pivotTableSpec?.theme?.rowHeaderStyle?.fontFamily).toBe(fontFamily) + expect(pivotTableSpec?.theme?.cornerHeaderStyle?.fontFamily).toBe(fontFamily) + }) + test('should register ad-hoc token theme with one call', () => { registerTokenTheme('agent-custom', { baseTheme: 'dark', + fontFamily, colorScheme: ['#00C2A8', '#F46060', '#FFB347'], linearColorScheme: ['#C3FFF7', '#00C2A8'], textPrimary: '#F5F7FA', @@ -94,7 +154,9 @@ describe('tokenTheme', () => { const theme = Builder.getTheme('agent-custom') expect(theme?.config?.line?.color?.colorScheme).toEqual(['#00C2A8', '#F46060', '#FFB347']) + expect((theme?.config?.line as any)?.fontFamily).toBe(fontFamily) expect(theme?.config?.raceBar?.player?.trackColor).toBe('#00C2A8') + expect(theme?.config?.raceBar?.player?.fontFamily).toBe(fontFamily) expect(theme?.config?.table?.headerBackgroundColor).toBe('#0F172A') }) }) \ No newline at end of file From c2469f1d5b15c5041d1a9ba4dddfb69b6d751610 Mon Sep 17 00:00:00 2001 From: ZJU_czx <952370295@qq.com> Date: Fri, 3 Apr 2026 10:41:31 +0800 Subject: [PATCH 4/5] feat(vseed): support token fontSize themes --- .../spec/chart/pipes/label/labelSunburst.ts | 2 +- .../chart/pipes/label/labelTreeMapGroup.ts | 2 +- .../chart/pipes/pivotChart/pivotAxisStyle.ts | 4 + .../chart/pipes/pivotChart/pivotGridStyle.ts | 12 ++- .../spec/chart/pipes/player/playerBar.ts | 2 +- .../spec/chart/pipes/player/playerColumn.ts | 6 +- .../spec/chart/pipes/player/playerPie.ts | 6 +- .../spec/chart/pipes/player/playerScatter.ts | 2 +- packages/vseed/src/theme/common/label.ts | 1 + packages/vseed/src/theme/common/player.ts | 2 + packages/vseed/src/theme/common/table.ts | 4 + packages/vseed/src/theme/tokenTheme.ts | 67 +++++++++++++ .../properties/config/pivotGrid/pivotGrid.ts | 3 + .../types/properties/config/player/player.ts | 4 + .../types/properties/config/player/zPlayer.ts | 1 + .../vseed/tests/unit/theme/tokenTheme.test.ts | 96 ++++++++++++++++++- 16 files changed, 202 insertions(+), 12 deletions(-) diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/label/labelSunburst.ts b/packages/vseed/src/pipeline/spec/chart/pipes/label/labelSunburst.ts index c1d0ff4fae..88ec011ede 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/label/labelSunburst.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/label/labelSunburst.ts @@ -40,7 +40,7 @@ export const labelSunburst: VChartSpecPipe = (spec, context) => { }, style: { ...labelSpec?.style, - fontSize: 12, + fontSize: label?.labelFontSize ?? 12, fillOpacity: (datum: any) => { if (encoding.hierarchy?.length === 1) { return 1 diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/label/labelTreeMapGroup.ts b/packages/vseed/src/pipeline/spec/chart/pipes/label/labelTreeMapGroup.ts index 1c8763d607..65579c84b3 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/label/labelTreeMapGroup.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/label/labelTreeMapGroup.ts @@ -41,7 +41,7 @@ export const labelTreeMapGroup: VChartSpecPipe = (spec, context) => { text: (data: any) => { return formatHierarchyName(String(data.name ?? ''), data.depth) }, - fontSize: 12, + fontSize: label?.labelFontSize ?? 12, fill: '#000', }, } diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotAxisStyle.ts b/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotAxisStyle.ts index 715ed2c994..f75cf2aeed 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotAxisStyle.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotAxisStyle.ts @@ -26,6 +26,10 @@ export const pivotAxisStyle = (axisStyle: VChartSpecPipe): VChartSpecPipe => { axis.label.style.fill = themConfig.axisLabelColor } + if (themConfig.axisLabelFontSize && axis.label && axis.label.visible && axis.label.style) { + axis.label.style.fontSize = themConfig.axisLabelFontSize + } + if (axis.type === 'band') { if (axis.orient === 'left' || axis.orient === 'right') { axis.innerOffset = { diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts b/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts index 68f652e8dc..ca41a85c0f 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotGridStyle.ts @@ -16,7 +16,9 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { const transparent = 'rgba(0,0,0,0)' const borderColor = themConfig.borderColor ?? '#e3e5eb' + const bodyFontSize = themConfig.bodyFontSize ?? 12 const bodyFontColor = themConfig.bodyFontColor ?? '#141414' + const headerFontSize = themConfig.headerFontSize ?? 12 const headerFontColor = themConfig.headerFontColor ?? '#21252c' const headerBackgroundColor = themConfig.headerBackgroundColor ?? 'rgba(0,0,0,0)' const hoverHeaderBackgroundColor = onlyCombination @@ -43,6 +45,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { bodyStyle: { borderColor, color: bodyFontColor, + fontSize: bodyFontSize, fontFamily, borderLineWidth: (arg: { row: number; col: number; table: any }) => { const noYAxis = @@ -68,7 +71,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { }, headerStyle: { borderColor, - fontSize: 12, + fontSize: headerFontSize, fontFamily, // borderLineWidth: [outlineBorderLineWidth, outlineBorderLineWidth, 1, 1], borderLineWidth: (arg: { row: number; col: number }) => { @@ -85,7 +88,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { }, rowHeaderStyle: { borderColor, - fontSize: 12, + fontSize: headerFontSize, fontFamily, color: headerFontColor, padding: [0, 12, 0, 4], @@ -102,7 +105,7 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { cornerHeaderStyle: { borderColor, textAlign: 'center', - fontSize: 12, + fontSize: headerFontSize, fontFamily, color: headerFontColor, padding: [0, 12, 0, 4], @@ -171,6 +174,9 @@ export const pivotGridStyle: PivotChartSpecPipe = (spec, context) => { bottomFrozenStyle: { borderColor, + fontSize: headerFontSize, + color: headerFontColor, + fontFamily, borderLineWidth: [1, outlineBorderLineWidth, outlineBorderLineWidth, 1], bgColor: headerBackgroundColor, hover: { diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts index b5012ae8a9..679565e13a 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerBar.ts @@ -15,6 +15,7 @@ export const playerBar: VChartSpecPipe = (spec, context) => { } const { player } = baseConfig const fontFamily = player.fontFamily || baseConfig.fontFamily + const textSize = player.fontSize ?? 36 const id = datasetReshapeInfo[0].id const { unfoldInfo, foldInfo } = datasetReshapeInfo[0] const { encodingPlayer, encodingY } = unfoldInfo @@ -63,7 +64,6 @@ export const playerBar: VChartSpecPipe = (spec, context) => { }) const dataKey = dimensions.filter((d) => !encoding.player?.includes(d.id)).map((d) => d.id) - const textSize = 36 const padding = 12 return { diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerColumn.ts b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerColumn.ts index 2d24fb0485..7d8c341f78 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerColumn.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerColumn.ts @@ -6,13 +6,15 @@ import { datasetXY } from '../dataset' export const playerColumn: VChartSpecPipe = (spec, context) => { const { advancedVSeed } = context const { dimensions = [], datasetReshapeInfo, chartType, encoding } = advancedVSeed - const baseConfig = advancedVSeed.config[chartType] as { player: Player } + const baseConfig = advancedVSeed.config[chartType] as { fontFamily?: string; player: Player } const result = datasetXY(spec, context) if (!baseConfig || !baseConfig.player) { return result } const { player } = baseConfig + const fontFamily = player.fontFamily || baseConfig.fontFamily + const textSize = player.fontSize ?? 36 const id = datasetReshapeInfo[0].id const { unfoldInfo, foldInfo } = datasetReshapeInfo[0] @@ -63,7 +65,6 @@ export const playerColumn: VChartSpecPipe = (spec, context) => { const dataKey = dimensions.filter((d) => !encoding.player?.includes(d.id)).map((d) => d.id) - const textSize = 36 const padding = 12 return { ...result, @@ -147,6 +148,7 @@ export const playerColumn: VChartSpecPipe = (spec, context) => { textBaseline: 'bottom', fontSize: textSize, textAlign: 'right', + fontFamily, text: (datum: any) => datum[encodingPlayer], x: (_datum: any, ctx: any) => { return ctx.vchart.getChart().getCanvasRect()?.width - padding diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerPie.ts b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerPie.ts index 2a270dd606..2f4e109d54 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerPie.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerPie.ts @@ -6,13 +6,15 @@ import { datasetXY } from '../dataset' export const playerPie: VChartSpecPipe = (spec, context) => { const { advancedVSeed } = context const { dimensions = [], datasetReshapeInfo, chartType, encoding } = advancedVSeed - const baseConfig = advancedVSeed.config[chartType] as { player: Player } + const baseConfig = advancedVSeed.config[chartType] as { fontFamily?: string; player: Player } const result = datasetXY(spec, context) if (!baseConfig || !baseConfig.player) { return result } const { player } = baseConfig + const fontFamily = player.fontFamily || baseConfig.fontFamily + const textSize = player.fontSize ?? 36 const id = datasetReshapeInfo[0].id const { unfoldInfo } = datasetReshapeInfo[0] @@ -56,7 +58,6 @@ export const playerPie: VChartSpecPipe = (spec, context) => { const dataKey = dimensions.filter((d) => !encoding.player?.includes(d.id)).map((d) => d.id) - const textSize = 36 const padding = 12 return { ...result, @@ -116,6 +117,7 @@ export const playerPie: VChartSpecPipe = (spec, context) => { textBaseline: 'bottom', fontSize: textSize, textAlign: 'right', + fontFamily, text: (datum: any) => datum[encodingPlayer], x: (_datum: any, ctx: any) => { return ctx.vchart.getChart().getCanvasRect()?.width - padding diff --git a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts index 211d53e39a..dedffdb5a1 100644 --- a/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts +++ b/packages/vseed/src/pipeline/spec/chart/pipes/player/playerScatter.ts @@ -14,6 +14,7 @@ export const playerScatter: VChartSpecPipe = (spec, context) => { } const { player } = baseConfig const fontFamily = player.fontFamily || baseConfig.fontFamily + const textSize = player.fontSize ?? 36 const id = datasetReshapeInfo[0].id const { unfoldInfo } = datasetReshapeInfo[0] @@ -50,7 +51,6 @@ export const playerScatter: VChartSpecPipe = (spec, context) => { const exchangeDuration = interval * 0.6 const dataKey = dimensions.filter((d) => !encoding.player?.includes(d.id)).map((d) => d.id) const padding = 12 - const textSize = 36 return { ...result, dataKey, diff --git a/packages/vseed/src/theme/common/label.ts b/packages/vseed/src/theme/common/label.ts index fd83a6d4ae..a9053cfbfd 100644 --- a/packages/vseed/src/theme/common/label.ts +++ b/packages/vseed/src/theme/common/label.ts @@ -3,6 +3,7 @@ export const getDefaultLabel = () => ({ wrap: true, showValue: true, showValuePercent: false, + labelFontSize: 12, labelColorSmartInvert: false, labelOverlap: true, }) diff --git a/packages/vseed/src/theme/common/player.ts b/packages/vseed/src/theme/common/player.ts index b85dd9c9ed..f9b256cdb0 100644 --- a/packages/vseed/src/theme/common/player.ts +++ b/packages/vseed/src/theme/common/player.ts @@ -10,6 +10,7 @@ export const getDarkPlayer = (): Omit => { loop: false, autoPlay: true, position: 'bottom', + fontSize: 36, railColor: '#404349', trackColor: primaryColor, @@ -32,6 +33,7 @@ export const getLightPlayer = (): Omit => { loop: false, autoPlay: true, position: 'bottom', + fontSize: 36, railColor: '#f1f3f4', trackColor: primaryColor, diff --git a/packages/vseed/src/theme/common/table.ts b/packages/vseed/src/theme/common/table.ts index 9e10960a1c..2b7db778f9 100644 --- a/packages/vseed/src/theme/common/table.ts +++ b/packages/vseed/src/theme/common/table.ts @@ -62,7 +62,9 @@ const pickPivotChartGridConfig = (tableConfig: any) => { outlineBorderLineWidth: 0, frameCornerRadius: 0, borderColor: tableConfig.borderColor, + bodyFontSize: tableConfig.bodyFontSize, bodyFontColor: tableConfig.bodyFontColor, + headerFontSize: tableConfig.headerFontSize, headerFontColor: tableConfig.headerFontColor, headerBackgroundColor: 'transparent', @@ -72,6 +74,8 @@ const pickPivotChartGridConfig = (tableConfig: any) => { titleFontColor: tableConfig.headerFontColor, titleFontSize: tableConfig.headerFontSize, titleFontWeight: 'bold', + + axisLabelFontSize: tableConfig.bodyFontSize, } } diff --git a/packages/vseed/src/theme/tokenTheme.ts b/packages/vseed/src/theme/tokenTheme.ts index 3ab7e170c2..b44a2a7857 100644 --- a/packages/vseed/src/theme/tokenTheme.ts +++ b/packages/vseed/src/theme/tokenTheme.ts @@ -10,6 +10,13 @@ export type TokenThemeBase = 'light' | 'dark' export type TokenThemeDefinition = { baseTheme: TokenThemeBase fontFamily?: string + tableHeaderFontSize?: number + tableBodyFontSize?: number + labelFontSize?: number + tooltipFontSize?: number + axisFontSize?: number + legendFontSize?: number + playerFontSize?: number colorScheme: [string, string, ...string[]] linearColorScheme: [string, string] textPrimary: string @@ -107,9 +114,11 @@ const getAccentColor = (tokens: TokenThemeDefinition) => tokens.accentColor || t const getAxisPatch = (tokens: TokenThemeDefinition) => ({ label: { labelColor: tokens.axisLabelColor || tokens.textSecondary, + labelFontSize: tokens.axisFontSize, }, title: { titleColor: tokens.axisTitleColor || tokens.textSecondary, + titleFontSize: tokens.axisFontSize, }, grid: { gridColor: tokens.axisGridColor || tokens.borderColor, @@ -124,15 +133,19 @@ const getAxisPatch = (tokens: TokenThemeDefinition) => ({ const getPivotGridPatch = (tokens: TokenThemeDefinition) => ({ borderColor: tokens.tableBorderColor || tokens.borderColor, + bodyFontSize: tokens.tableBodyFontSize, bodyFontColor: tokens.tableBodyFontColor || tokens.textPrimary, + headerFontSize: tokens.tableHeaderFontSize, headerFontColor: tokens.tableHeaderFontColor || tokens.textPrimary, headerBackgroundColor: tokens.tableHeaderBackgroundColor || tokens.surfaceColor || 'transparent', hoverHeaderBackgroundColor: tokens.tableHoverHeaderBackgroundColor || withAlpha(getAccentColor(tokens), 0.18), hoverHeaderInlineBackgroundColor: tokens.tableHoverHeaderInlineBackgroundColor || withAlpha(getAccentColor(tokens), 0.08), titleFontColor: tokens.textPrimary, + titleFontSize: tokens.tableHeaderFontSize, chartGridColor: tokens.axisGridColor || tokens.borderColor, axisLabelColor: tokens.axisLabelColor || tokens.textSecondary, + axisLabelFontSize: tokens.axisFontSize, }) const getPlayerPatch = (tokens: TokenThemeDefinition) => { @@ -140,6 +153,7 @@ const getPlayerPatch = (tokens: TokenThemeDefinition) => { return { fontFamily: tokens.fontFamily, + fontSize: tokens.playerFontSize, railColor: tokens.playerRailColor || tokens.borderColor, trackColor: accentColor, sliderHandleColor: tokens.playerSliderHandleColor || tokens.surfaceColor || '#ffffff', @@ -156,8 +170,10 @@ const getTablePatch = (tokens: TokenThemeDefinition) => { return { borderColor: tokens.tableBorderColor || tokens.borderColor, + bodyFontSize: tokens.tableBodyFontSize, bodyFontFamily: tokens.fontFamily, bodyFontColor: tokens.tableBodyFontColor || tokens.textPrimary, + headerFontSize: tokens.tableHeaderFontSize, headerFontFamily: tokens.fontFamily, headerFontColor: tokens.tableHeaderFontColor || tokens.textPrimary, headerBackgroundColor: tokens.tableHeaderBackgroundColor || tokens.surfaceColor || 'transparent', @@ -186,23 +202,62 @@ const getChartPatch = (tokens: TokenThemeDefinition) => ({ negativeColor: tokens.negativeColor, }, label: { + labelFontSize: tokens.labelFontSize, labelColor: tokens.labelColor || tokens.textPrimary, labelStroke: tokens.labelStroke, }, legend: { labelColor: tokens.legendLabelColor || tokens.textSecondary, + labelFontSize: tokens.legendFontSize, pagerIconColor: tokens.legendPagerIconColor || tokens.textSecondary, pagerIconDisableColor: tokens.legendPagerIconDisableColor || tokens.borderColor, }, tooltip: { backgroundColor: tokens.tooltipBackgroundColor, borderColor: tokens.tooltipBorderColor || tokens.borderColor, + fontSize: tokens.tooltipFontSize, keyColor: tokens.textSecondary, valueColor: tokens.textPrimary, titleColor: tokens.textPrimary, }, }) +const getAnnotationPatch = (tokens: TokenThemeDefinition) => ({ + annotationPoint: { + textFontSize: tokens.labelFontSize, + }, + annotationHorizontalLine: { + textFontSize: tokens.labelFontSize, + }, + annotationVerticalLine: { + textFontSize: tokens.labelFontSize, + }, + annotationArea: { + textFontSize: tokens.labelFontSize, + }, +}) + +const getRegressionLinePatch = (tokens: TokenThemeDefinition) => ({ + kdeRegressionLine: { + textFontSize: tokens.labelFontSize, + }, + ecdfRegressionLine: { + textFontSize: tokens.labelFontSize, + }, + linearRegressionLine: { + textFontSize: tokens.labelFontSize, + }, + lowessRegressionLine: { + textFontSize: tokens.labelFontSize, + }, + polynomialRegressionLine: { + textFontSize: tokens.labelFontSize, + }, + logisticRegressionLine: { + textFontSize: tokens.labelFontSize, + }, +}) + const withAxesAndExtras = ( chartType: ThemeConfigKey, chartConfig: NonNullable, @@ -241,6 +296,18 @@ const withAxesAndExtras = ( >) } + if (Object.prototype.hasOwnProperty.call(chartRecord, 'annotation')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { annotation: getAnnotationPatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + + if (Object.prototype.hasOwnProperty.call(chartRecord, 'regressionLine')) { + nextChartConfig = mergeThemeNode(nextChartConfig, { regressionLine: getRegressionLinePatch(tokens) } as Partial< + typeof nextChartConfig + >) + } + if (raceChartTypes.includes(chartType) && Object.prototype.hasOwnProperty.call(chartRecord, 'player')) { nextChartConfig = mergeThemeNode(nextChartConfig, { player: getPlayerPatch(tokens) } as Partial< typeof nextChartConfig diff --git a/packages/vseed/src/types/properties/config/pivotGrid/pivotGrid.ts b/packages/vseed/src/types/properties/config/pivotGrid/pivotGrid.ts index c18cf0e3eb..8d1bc614a8 100644 --- a/packages/vseed/src/types/properties/config/pivotGrid/pivotGrid.ts +++ b/packages/vseed/src/types/properties/config/pivotGrid/pivotGrid.ts @@ -2,7 +2,9 @@ import { z } from 'zod' export const zPivotChartGridConfig = z.object({ borderColor: z.string().nullish(), + bodyFontSize: z.number().nullish(), bodyFontColor: z.string().nullish(), + headerFontSize: z.number().nullish(), headerFontColor: z.string().nullish(), headerBackgroundColor: z.string().nullish(), hoverHeaderBackgroundColor: z.string().nullish(), @@ -19,6 +21,7 @@ export const zPivotChartGridConfig = z.object({ chartGridColor: z.string().nullish(), axisLabelColor: z.string().nullish(), + axisLabelFontSize: z.number().nullish(), }) export type PivotChartGridConfig = z.infer diff --git a/packages/vseed/src/types/properties/config/player/player.ts b/packages/vseed/src/types/properties/config/player/player.ts index 3494009eab..388271dd5a 100644 --- a/packages/vseed/src/types/properties/config/player/player.ts +++ b/packages/vseed/src/types/properties/config/player/player.ts @@ -31,6 +31,10 @@ export type Player = { * @description 播放器文本字体 */ fontFamily?: string + /** + * @description 播放器文本字号 + */ + fontSize?: number /** * @description 播放器进度条进度颜色 */ diff --git a/packages/vseed/src/types/properties/config/player/zPlayer.ts b/packages/vseed/src/types/properties/config/player/zPlayer.ts index 1d595f9246..dd4037b2b2 100644 --- a/packages/vseed/src/types/properties/config/player/zPlayer.ts +++ b/packages/vseed/src/types/properties/config/player/zPlayer.ts @@ -9,6 +9,7 @@ export const zPlayer = z.object({ railColor: z.string().optional(), fontFamily: z.string().optional(), + fontSize: z.number().optional(), trackColor: z.string().optional(), sliderHandleColor: z.string().optional(), diff --git a/packages/vseed/tests/unit/theme/tokenTheme.test.ts b/packages/vseed/tests/unit/theme/tokenTheme.test.ts index f473a9d8a2..a38abe7386 100644 --- a/packages/vseed/tests/unit/theme/tokenTheme.test.ts +++ b/packages/vseed/tests/unit/theme/tokenTheme.test.ts @@ -3,6 +3,13 @@ import type { VSeed } from '@visactor/vseed' import { Builder, registerTokenTheme, registerTokenThemes } from '@visactor/vseed' const fontFamily = '"Inter", "Noto Sans SC", sans-serif' +const tableHeaderFontSize = 15 +const tableBodyFontSize = 13 +const labelFontSize = 16 +const tooltipFontSize = 17 +const axisFontSize = 18 +const legendFontSize = 19 +const playerFontSize = 42 const lineVSeed: VSeed = { chartType: 'line', @@ -14,6 +21,18 @@ const lineVSeed: VSeed = { ], } +const columnVSeed: VSeed = { + chartType: 'column', + theme: 'unit-light', + measures: [{ id: 'sales', alias: '销售额', autoFormat: true }], + dimensions: [{ id: 'date', alias: '日期' }], + dataset: [ + { date: '2019', sales: 20 }, + { date: '2020', sales: 60 }, + { date: '2021', sales: 40 }, + ], +} + const raceBarVSeed: VSeed = { chartType: 'raceBar', theme: 'unit-light', @@ -56,11 +75,42 @@ const pivotTableVSeed: VSeed = { ], } +const pivotLineVSeed: VSeed = { + chartType: 'line', + theme: 'unit-light', + measures: [ + { id: 'sales', alias: '销售额', autoFormat: true }, + { id: 'profit', alias: '利润', autoFormat: true }, + ], + dimensions: [ + { id: 'month', alias: '月' }, + { id: 'date', alias: '年', encoding: 'column' }, + { id: 'type', alias: '类型', encoding: 'row' }, + ], + dataset: [ + { date: '2019', type: 'A', month: '1', profit: 10000, sales: 200000 }, + { date: '2019', type: 'A', month: '2', profit: 20000, sales: 400000 }, + { date: '2019', type: 'B', month: '1', profit: 12000, sales: 180000 }, + { date: '2019', type: 'B', month: '2', profit: 16000, sales: 260000 }, + { date: '2020', type: 'A', month: '1', profit: 15000, sales: 230000 }, + { date: '2020', type: 'A', month: '2', profit: 22000, sales: 420000 }, + { date: '2020', type: 'B', month: '1', profit: 14000, sales: 210000 }, + { date: '2020', type: 'B', month: '2', profit: 19000, sales: 310000 }, + ], +} + beforeAll(() => { registerTokenThemes({ 'unit-light': { baseTheme: 'light', fontFamily, + tableHeaderFontSize, + tableBodyFontSize, + labelFontSize, + tooltipFontSize, + axisFontSize, + legendFontSize, + playerFontSize, colorScheme: ['#B83280', '#3182CE', '#38A169'], linearColorScheme: ['#F8C7E7', '#B83280'], textPrimary: '#1A202C', @@ -74,6 +124,13 @@ beforeAll(() => { 'unit-earth': { baseTheme: 'light', fontFamily, + tableHeaderFontSize, + tableBodyFontSize, + labelFontSize, + tooltipFontSize, + axisFontSize, + legendFontSize, + playerFontSize, colorScheme: ['#C05621', '#2F855A', '#2B6CB0'], linearColorScheme: ['#FBD38D', '#C05621'], textPrimary: '#2D3748', @@ -97,24 +154,39 @@ describe('tokenTheme', () => { const builder = Builder.from(lineVSeed) const advanced = builder.buildAdvanced() const lineConfig = advanced?.config?.line as any + const columnConfig = Builder.from(columnVSeed).buildAdvanced()?.config?.column as any expect(lineConfig?.color?.colorScheme).toEqual(['#B83280', '#3182CE', '#38A169']) expect(lineConfig?.fontFamily).toBe(fontFamily) + expect(lineConfig?.label?.labelFontSize).toBe(labelFontSize) + expect(lineConfig?.tooltip?.fontSize).toBe(tooltipFontSize) + expect(lineConfig?.legend?.labelFontSize).toBe(legendFontSize) + expect(lineConfig?.xAxis?.label?.labelFontSize).toBe(axisFontSize) + expect(lineConfig?.xAxis?.title?.titleFontSize).toBe(axisFontSize) expect(lineConfig?.tooltip?.backgroundColor).toBe('rgba(255, 255, 255, 0.96)') expect(lineConfig?.legend?.labelColor).toBe('#4A5568') expect(lineConfig?.xAxis?.label?.labelColor).toBe('#4A5568') + expect(columnConfig?.annotation?.annotationPoint?.textFontSize).toBe(labelFontSize) + expect(columnConfig?.regressionLine?.linearRegressionLine?.textFontSize).toBe(labelFontSize) }) test('should apply token theme to table config', () => { const builder = Builder.from(tableVSeed) const advanced = builder.buildAdvanced() const tableConfig = advanced?.config?.table + const pivotLineConfig = Builder.from(pivotLineVSeed).buildAdvanced()?.config?.line as any expect(tableConfig?.headerBackgroundColor).toBe('#FEFCF7') expect(tableConfig?.bodyFontColor).toBe('#2D3748') + expect((tableConfig as any)?.bodyFontSize).toBe(tableBodyFontSize) expect((tableConfig as any)?.bodyFontFamily).toBe(fontFamily) + expect((tableConfig as any)?.headerFontSize).toBe(tableHeaderFontSize) expect((tableConfig as any)?.headerFontFamily).toBe(fontFamily) expect(tableConfig?.backgroundColorScale?.maxColor).toBe('#C05621') + expect(pivotLineConfig?.pivotGrid?.bodyFontSize).toBe(tableBodyFontSize) + expect(pivotLineConfig?.pivotGrid?.headerFontSize).toBe(tableHeaderFontSize) + expect(pivotLineConfig?.pivotGrid?.titleFontSize).toBe(tableHeaderFontSize) + expect(pivotLineConfig?.pivotGrid?.axisLabelFontSize).toBe(axisFontSize) }) test('should apply fontFamily to final chart spec and race player text', () => { @@ -125,22 +197,39 @@ describe('tokenTheme', () => { expect(spec?.theme?.fontFamily).toBe(fontFamily) expect(raceSpec?.theme?.fontFamily).toBe(fontFamily) expect(raceSpec?.customMark?.[0]?.style?.fontFamily).toBe(fontFamily) + expect(raceSpec?.customMark?.[0]?.style?.fontSize).toBe(playerFontSize) }) - test('should apply fontFamily to final table spec', () => { + test('should apply fontFamily and fontSize to final table spec', () => { const tableSpec = Builder.from(tableVSeed).build() as any const pivotTableSpec = Builder.from(pivotTableVSeed).build() as any + const pivotLineSpec = Builder.from(pivotLineVSeed).build() as any expect(tableSpec?.theme?.bodyStyle?.fontFamily).toBe(fontFamily) + expect(tableSpec?.theme?.bodyStyle?.fontSize).toBe(tableBodyFontSize) expect(tableSpec?.theme?.headerStyle?.fontFamily).toBe(fontFamily) + expect(tableSpec?.theme?.headerStyle?.fontSize).toBe(tableHeaderFontSize) expect(pivotTableSpec?.theme?.rowHeaderStyle?.fontFamily).toBe(fontFamily) + expect(pivotTableSpec?.theme?.rowHeaderStyle?.fontSize).toBe(tableHeaderFontSize) expect(pivotTableSpec?.theme?.cornerHeaderStyle?.fontFamily).toBe(fontFamily) + expect(pivotTableSpec?.theme?.cornerHeaderStyle?.fontSize).toBe(tableHeaderFontSize) + expect(pivotLineSpec?.theme?.bodyStyle?.fontSize).toBe(tableBodyFontSize) + expect(pivotLineSpec?.theme?.headerStyle?.fontSize).toBe(tableHeaderFontSize) + expect(pivotLineSpec?.theme?.rowHeaderStyle?.fontSize).toBe(tableHeaderFontSize) + expect(pivotLineSpec?.title?.textStyle?.fontSize).toBe(tableHeaderFontSize) }) test('should register ad-hoc token theme with one call', () => { registerTokenTheme('agent-custom', { baseTheme: 'dark', fontFamily, + tableHeaderFontSize, + tableBodyFontSize, + labelFontSize, + tooltipFontSize, + axisFontSize, + legendFontSize, + playerFontSize, colorScheme: ['#00C2A8', '#F46060', '#FFB347'], linearColorScheme: ['#C3FFF7', '#00C2A8'], textPrimary: '#F5F7FA', @@ -155,8 +244,13 @@ describe('tokenTheme', () => { expect(theme?.config?.line?.color?.colorScheme).toEqual(['#00C2A8', '#F46060', '#FFB347']) expect((theme?.config?.line as any)?.fontFamily).toBe(fontFamily) + expect((theme?.config?.line as any)?.label?.labelFontSize).toBe(labelFontSize) + expect((theme?.config?.line as any)?.xAxis?.label?.labelFontSize).toBe(axisFontSize) expect(theme?.config?.raceBar?.player?.trackColor).toBe('#00C2A8') expect(theme?.config?.raceBar?.player?.fontFamily).toBe(fontFamily) + expect(theme?.config?.raceBar?.player?.fontSize).toBe(playerFontSize) + expect(theme?.config?.table?.bodyFontSize).toBe(tableBodyFontSize) + expect(theme?.config?.table?.headerFontSize).toBe(tableHeaderFontSize) expect(theme?.config?.table?.headerBackgroundColor).toBe('#0F172A') }) }) \ No newline at end of file From 59960517f49192a71a0af2a436e1a3f1b7534b28 Mon Sep 17 00:00:00 2001 From: ZJU_czx <952370295@qq.com> Date: Fri, 3 Apr 2026 11:47:24 +0800 Subject: [PATCH 5/5] fix(vseed): preserve default fontSize behavior --- packages/vseed/src/theme/common/label.ts | 1 - packages/vseed/src/theme/common/player.ts | 2 -- packages/vseed/src/theme/common/table.ts | 4 ---- packages/vseed/tests/unit/theme/tokenTheme.test.ts | 10 ++++++++++ 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/vseed/src/theme/common/label.ts b/packages/vseed/src/theme/common/label.ts index a9053cfbfd..fd83a6d4ae 100644 --- a/packages/vseed/src/theme/common/label.ts +++ b/packages/vseed/src/theme/common/label.ts @@ -3,7 +3,6 @@ export const getDefaultLabel = () => ({ wrap: true, showValue: true, showValuePercent: false, - labelFontSize: 12, labelColorSmartInvert: false, labelOverlap: true, }) diff --git a/packages/vseed/src/theme/common/player.ts b/packages/vseed/src/theme/common/player.ts index f9b256cdb0..b85dd9c9ed 100644 --- a/packages/vseed/src/theme/common/player.ts +++ b/packages/vseed/src/theme/common/player.ts @@ -10,7 +10,6 @@ export const getDarkPlayer = (): Omit => { loop: false, autoPlay: true, position: 'bottom', - fontSize: 36, railColor: '#404349', trackColor: primaryColor, @@ -33,7 +32,6 @@ export const getLightPlayer = (): Omit => { loop: false, autoPlay: true, position: 'bottom', - fontSize: 36, railColor: '#f1f3f4', trackColor: primaryColor, diff --git a/packages/vseed/src/theme/common/table.ts b/packages/vseed/src/theme/common/table.ts index 2b7db778f9..9e10960a1c 100644 --- a/packages/vseed/src/theme/common/table.ts +++ b/packages/vseed/src/theme/common/table.ts @@ -62,9 +62,7 @@ const pickPivotChartGridConfig = (tableConfig: any) => { outlineBorderLineWidth: 0, frameCornerRadius: 0, borderColor: tableConfig.borderColor, - bodyFontSize: tableConfig.bodyFontSize, bodyFontColor: tableConfig.bodyFontColor, - headerFontSize: tableConfig.headerFontSize, headerFontColor: tableConfig.headerFontColor, headerBackgroundColor: 'transparent', @@ -74,8 +72,6 @@ const pickPivotChartGridConfig = (tableConfig: any) => { titleFontColor: tableConfig.headerFontColor, titleFontSize: tableConfig.headerFontSize, titleFontWeight: 'bold', - - axisLabelFontSize: tableConfig.bodyFontSize, } } diff --git a/packages/vseed/tests/unit/theme/tokenTheme.test.ts b/packages/vseed/tests/unit/theme/tokenTheme.test.ts index a38abe7386..3bebd0df3b 100644 --- a/packages/vseed/tests/unit/theme/tokenTheme.test.ts +++ b/packages/vseed/tests/unit/theme/tokenTheme.test.ts @@ -145,6 +145,16 @@ beforeAll(() => { }) describe('tokenTheme', () => { + test('should preserve undefined default fontSize in base theme config', () => { + const lightTheme = Builder.getTheme('light') + + expect(lightTheme?.config?.line?.label?.labelFontSize).toBeUndefined() + expect(lightTheme?.config?.raceBar?.player?.fontSize).toBeUndefined() + expect((lightTheme?.config?.line as any)?.pivotGrid?.bodyFontSize).toBeUndefined() + expect((lightTheme?.config?.line as any)?.pivotGrid?.headerFontSize).toBeUndefined() + expect((lightTheme?.config?.line as any)?.pivotGrid?.axisLabelFontSize).toBeUndefined() + }) + test('should register themes from a token registry', () => { expect(Builder.getTheme('unit-light')).toBeDefined() expect(Builder.getTheme('unit-earth')).toBeDefined()