@zerodep-dev/vue-tsx-pro-ui 0.3.3 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts/AreaChart.d.ts +1 -1
- package/dist/charts/AreaChart.js +6 -48
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.js +6 -49
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/ChordChart.d.ts +7 -2
- package/dist/charts/ChordChart.js +151 -60
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/ComboChart.d.ts +2 -1
- package/dist/charts/ComboChart.js +17 -93
- package/dist/charts/ComboChart.js.map +1 -1
- package/dist/charts/DonutChart.d.ts +6 -1
- package/dist/charts/DonutChart.js +134 -51
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.d.ts +22 -10
- package/dist/charts/GraphChart.js +415 -175
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/LineChart.d.ts +1 -29
- package/dist/charts/LineChart.js +6 -54
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/MapChart.d.ts +21 -48
- package/dist/charts/MapChart.js +426 -353
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.d.ts +7 -2
- package/dist/charts/SankeyChart.js +164 -76
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart.d.ts +7 -1
- package/dist/charts/ScatterChart.js +45 -30
- package/dist/charts/ScatterChart.js.map +1 -1
- package/dist/charts/TimelineChart.d.ts +8 -1
- package/dist/charts/TimelineChart.js +141 -89
- package/dist/charts/TimelineChart.js.map +1 -1
- package/dist/charts/TreemapChart.d.ts +6 -0
- package/dist/charts/TreemapChart.js +174 -58
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart.d.ts +6 -7
- package/dist/charts/WaterfallChart.js +46 -51
- package/dist/charts/WaterfallChart.js.map +1 -1
- package/dist/charts/XYChart.d.ts +44 -35
- package/dist/charts/XYChart.js +493 -281
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/axis-ticks.d.ts +1 -1
- package/dist/charts/axis-ticks.js +4 -5
- package/dist/charts/axis-ticks.js.map +1 -1
- package/dist/charts/flow.d.ts +4 -11
- package/dist/charts/flow.js +4 -4
- package/dist/charts/flow.js.map +1 -1
- package/dist/charts/frame.d.ts +6 -30
- package/dist/charts/frame.js +6 -99
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/geo/projection.d.ts +45 -0
- package/dist/charts/geo/projection.js +201 -0
- package/dist/charts/geo/projection.js.map +1 -0
- package/dist/charts/geo/topojson.d.ts +50 -0
- package/dist/charts/geo/topojson.js +119 -0
- package/dist/charts/geo/topojson.js.map +1 -0
- package/dist/charts/index.d.ts +21 -9
- package/dist/charts/index.js +19 -8
- package/dist/charts/label-layout.js.map +1 -1
- package/dist/charts/layout/chord.d.ts +44 -0
- package/dist/charts/layout/chord.js +45 -0
- package/dist/charts/layout/chord.js.map +1 -0
- package/dist/charts/layout/graph.d.ts +49 -0
- package/dist/charts/layout/graph.js +268 -0
- package/dist/charts/layout/graph.js.map +1 -0
- package/dist/charts/layout/sankey.d.ts +79 -0
- package/dist/charts/layout/sankey.js +200 -0
- package/dist/charts/layout/sankey.js.map +1 -0
- package/dist/charts/layout/treemap.d.ts +46 -0
- package/dist/charts/layout/treemap.js +152 -0
- package/dist/charts/layout/treemap.js.map +1 -0
- package/dist/charts/marks.d.ts +79 -0
- package/dist/charts/marks.js +231 -0
- package/dist/charts/marks.js.map +1 -0
- package/dist/charts/plot.d.ts +107 -0
- package/dist/charts/plot.js +231 -0
- package/dist/charts/plot.js.map +1 -0
- package/dist/charts/scale.d.ts +29 -0
- package/dist/charts/scale.js +244 -0
- package/dist/charts/scale.js.map +1 -0
- package/dist/charts/shape.d.ts +46 -0
- package/dist/charts/shape.js +131 -0
- package/dist/charts/shape.js.map +1 -0
- package/dist/charts/stack.d.ts +17 -0
- package/dist/charts/stack.js +35 -0
- package/dist/charts/stack.js.map +1 -0
- package/dist/charts/text-size.d.ts +12 -0
- package/dist/charts/text-size.js +32 -0
- package/dist/charts/text-size.js.map +1 -0
- package/dist/config/createUi.d.ts +21 -2
- package/dist/config/createUi.js +18 -1
- package/dist/config/createUi.js.map +1 -1
- package/dist/config/theme/preference.js +2 -1
- package/dist/config/theme/preference.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/maps/china-provinces.js +35680 -0
- package/dist/maps/china-provinces.js.map +1 -0
- package/dist/maps/china.d.ts +13 -0
- package/dist/maps/china.js +8 -0
- package/dist/maps/china.js.map +1 -0
- package/dist/maps/index.d.ts +9 -0
- package/dist/maps/index.js +3 -0
- package/dist/maps/world-countries.js +22273 -0
- package/dist/maps/world-countries.js.map +1 -0
- package/dist/maps/world.d.ts +13 -0
- package/dist/maps/world.js +8 -0
- package/dist/maps/world.js.map +1 -0
- package/dist/overlay/detached.js.map +1 -1
- package/dist/utils/request/use-request.d.ts +25 -1
- package/dist/utils/request/use-request.js +35 -3
- package/dist/utils/request/use-request.js.map +1 -1
- package/package.json +7 -8
- package/dist/charts/single.d.ts +0 -41
- package/dist/charts/single.js +0 -66
- package/dist/charts/single.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XYChart.js","names":["_createVNode","_mergeProps","_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_shallowRef"],"sources":["../../src/charts/XYChart.tsx"],"sourcesContent":["/**\n * 直角坐标图表(柱状图、折线图、面积图)的公共部分:坐标轴、十字线与提示框、数值范围;外层结构(图例、单位、\n * 空与加载状态、给读屏的数据表)交给 ChartFrame。\n * 绘图交给 Unovis 的 XYContainer:组件实例只建一次,数据与配置变化时 update,卸载时 destroy;\n * 绘图区换了元素(加载、空状态之后重新出现)时容器连同全部实例一起重建。\n * 各种图只决定画什么(kind.components),坐标轴、十字线、提示框、配色都在这里统一。\n * 目标线(targets)用 Unovis 的 Plotline。点了下钻(onItemClick):有图形可点的图(柱子)按图形的点击事件\n * (kind.itemSelector),折线、面积图按十字线所在的那一行,散点图按悬停的点。\n *\n * 标注(annotations):类目上的事件画成竖线(Plotline),圈出某个系列的值画成空心圈带文字(Scatter);\n * 区间(bands)画成浅色的带(Plotband)。百分比堆叠(kind.percent)按每个类目里各系列的占比画。\n * 第二数值轴(kind.secondary,组合图):刻度与主轴对齐(alignedTicks),第二轴的系列换算到主轴的坐标里画,\n * 右侧的刻度文字是不裁剪的 Plotline 标签。\n */\nimport {\n Axis,\n AxisType,\n Crosshair,\n Plotband,\n PlotbandLabelPosition,\n Plotline,\n PlotlineLabelPosition,\n PlotlineLineStylePresets,\n Position,\n Scatter,\n Tooltip,\n XYContainer,\n type XYComponentCore,\n} from '@unovis/ts';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport { useId, type VNodeChild } from 'vue';\nimport { useDetachedRender } from '../overlay/detached';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { Button } from '../base/Button';\nimport { Slider } from '../input/Slider';\nimport { alignedTicks, type AlignedAxes } from './axis-ticks';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport type { PartProps } from '../utils/props';\nimport {\n ChartFrame,\n chartDuration,\n chartTooltip,\n createChartInstances,\n uniqueHighlightFilter,\n useChartValueText,\n usePlotSeen,\n type ChartFrameParts,\n type ChartTable,\n type ChartTooltipItem,\n} from './frame';\nimport {\n resolveColor,\n resolveSeries,\n seriesNumber,\n seriesValue,\n type ChartColor,\n type ChartSeries,\n type ResolvedSeries,\n} from './series';\n\n/** 目标线(参考线):数值轴上的一条虚线 */\nexport interface ChartTarget {\n /** 位置:数值轴上的值 */\n value: NumericValue;\n /** 标签:写在线的一端,后面带上格式化的数值(“年度指标 1,200”) */\n label?: string;\n /** 颜色;默认是 danger(要够到的线) */\n color?: ChartColor;\n}\n\n/** 标注:类目上发生的事(竖线),或圈出某个系列在这个类目上的值 */\nexport interface ChartAnnotation {\n /** 标在哪个类目上:index 字段的值(散点图是横轴上的数值) */\n at: unknown;\n /** 文字 */\n label: string;\n /** 圈出这个系列在这里的值(系列的 key);不写时是一条竖线(换供应商、调价生效这类事件) */\n series?: string;\n /** 颜色;竖线默认是次要色,圈默认是系列色 */\n color?: ChartColor;\n}\n\n/** 区间:类目轴上的一段(试运行期、促销期),或数值轴上的一段(目标区间) */\nexport interface ChartBand {\n /** 在哪条轴上,默认 index(类目轴) */\n axis?: 'index' | 'value';\n /** 起点:类目轴是 index 字段的值(含这一项),数值轴是数值 */\n from: unknown;\n /** 终点:同 from(含这一项) */\n to: unknown;\n /** 文字:类目轴上的写在带的左下角,数值轴上的写在左上角 */\n label?: string;\n /** 颜色,默认 neutral;画成很浅的底色 */\n color?: ChartColor;\n}\n\n/** 第二数值轴(右侧):哪些系列画在它上面,它的格式与单位 */\nexport interface ChartSecondaryAxis {\n /** 画在第二数值轴上的系列 */\n keys: readonly string[];\n /** 数值的格式 */\n format?: NumericFormat;\n /** 单位:显示在右上方,提示框与数据表的数值后面带上 */\n unit?: string;\n}\n\n/** 加载中的骨架 */\nexport interface ChartSkeletons {\n /** 一排高低不一的柱(柱状图) */\n bars: unknown;\n /** 一整块(默认) */\n block: unknown;\n}\n\n/** 直角坐标图表共有的属性;未声明的属性落到外层 div(role=\"figure\")上,aria-label 是图表的名称 */\nexport interface XYChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 数据:每一行是类目轴上的一项(一个月、一个项目) */\n data: readonly T[];\n /** 类目字段:类目轴的刻度、提示框的标题、数据表的第一列 */\n index: keyof T & string;\n /** 系列:每个系列画成一组柱子、一条线或一片面积 */\n series: readonly ChartSeries<T>[];\n /** 类目的显示文字;不写时把字段的值转成字符串 */\n indexFormat?: (value: T[keyof T & string], row: T) => string;\n /**\n * 数值的格式:数值轴、提示框、数据表共用,按当前语言格式化。以万元为单位画金额时写\n * `{ scale: 10_000, maximumFractionDigits: 1 }` 并配 `unit=\"万元\"`\n */\n valueFormat?: NumericFormat;\n /** 单位:显示在数值轴上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 240\n */\n height?: number | string;\n /** 图例:默认多于一个系列时显示;点图例可以隐藏、恢复系列 */\n legend?: boolean;\n /**\n * 数值轴的网格线\n * @default true\n */\n grid?: boolean;\n /** 数值轴的范围 [最小, 最大];不写的一端按数据自动取,最小值默认从 0 起(数据有负数时取负数) */\n valueDomain?: readonly [number | undefined, number | undefined];\n /**\n * 悬停时的提示框\n * @default true\n */\n tooltip?: boolean;\n /**\n * 加载中:绘图区显示扫光的骨架(柱状图是一排高低不一的柱),带 aria-busy\n * @default false\n */\n loading?: boolean;\n /** 隐藏的系列(存系列的 key):点图例时写回,父级可以写 _hiddenSeries={keys} */\n _hiddenSeries?: string[];\n /** 没有数据时显示的内容,默认是“暂无数据” */\n empty?: VNodeChild;\n /** 目标线、参考线:数值轴上的虚线(横向图是竖线),如年度销售指标;数值轴的范围会包含它 */\n targets?: readonly ChartTarget[];\n /** 标注:类目上的事件(竖线),或圈出某个系列的值(横向图只画竖线) */\n annotations?: readonly ChartAnnotation[];\n /** 区间:类目轴或数值轴上的一段,画成浅色的带(数值轴的范围会包含它) */\n bands?: readonly ChartBand[];\n /**\n * 点了一个类目(下钻,如跳到筛好条件的台账):参数是这一行与它的位置;写了它时绘图区的指针是手形。\n * 点图是鼠标的捷径:同样的去处在页面上还要有链接或按钮,键盘与读屏才到得了(WCAG 2.1.1)\n */\n onItemClick?: (row: T, index: number) => void;\n /** 缩放:绘图区下面一条区间滑块,选一段类目放大看(几年的月度数据);读屏的数据表仍是全部 */\n zoom?: boolean;\n /** 缩放的区间 [起, 止]:类目的位置,含两端;父级可以写 _zoomRange={range},null 是全部 */\n _zoomRange?: [number, number] | null;\n}\n\n/** 交给各种图的绘制上下文 */\nexport interface XYChartContext<T extends object> {\n /** 显示中的系列(去掉了图例里隐藏的),颜色已定 */\n series: ResolvedSeries<T>[];\n /** 类目的位置:第几行 */\n x: (row: T, index: number) => number;\n /** 系列的取值函数,空值返回 undefined(Unovis 跳过) */\n y: (series: ResolvedSeries<T>) => (row: T) => number | undefined;\n /** 取一个跨渲染保留的组件实例:第一次调用时创建;Unovis 组件保留实例,更新时才有过渡动画 */\n instance: <C>(key: string, create: () => C) => C;\n /** 点图形下钻的事件(写了 itemSelector 时):并进组件的 events;没有 onItemClick 时是空的。参数同 Unovis:图形的数据、事件、位置 */\n events: Record<string, Record<string, (row: T, event: Event, index: number) => void>>;\n}\n\n/** 一种图:画哪些组件,以及与坐标轴、十字线有关的差别 */\nexport interface XYChartKind<T extends object> {\n /** 配置并返回要画的 Unovis 组件(每次数据或属性变化都会调用) */\n components: (context: XYChartContext<T>) => XYComponentCore<T>[];\n /** 横向:类目在纵轴、数值在横轴 */\n horizontal?: boolean;\n /** 十字线上给每个系列画圆点(折线图、面积图);柱状图不画 */\n crosshairDots?: boolean;\n /** 加载中的骨架,默认 block */\n skeleton?: keyof ChartSkeletons;\n /** 绘图区四周的留白(px):折线两端不贴着边缘 */\n padding?: { left?: number; right?: number; top?: number; bottom?: number };\n /** 数值范围按堆叠后的总和算(堆叠的柱子、面积) */\n stacked?: boolean;\n /** 百分比堆叠:各系列按它在这个类目里的占比画(加起来 100%),数值轴是百分比,提示框带上占比 */\n percent?: boolean;\n /** 第二数值轴(组合图):这些系列画在右侧的轴上,刻度与主轴对齐 */\n secondary?: ChartSecondaryAxis;\n /** 十字线只在这些系列上画圆点(组合图里只给线画);不写时按 crosshairDots */\n crosshairSeries?: (series: ResolvedSeries<T>) => boolean;\n /** 横轴是连续的数值(散点图):取值、刻度与提示框里的写法、数据表的列名、轴下方的标题;不写时横轴是类目(第几行) */\n continuousX?: {\n value: (row: T) => number | undefined;\n format: (value: number) => string;\n label: string;\n title?: string;\n };\n /** 数值轴默认从 0 起(数据有负数时取负数);false 时按数据自动取(散点图) */\n zeroBaseline?: boolean;\n /** 提示框跟着数据点(散点图),没有十字线:按选择器触发,悬停的数据是这一行 */\n pointTooltip?: string;\n /** 提示框里列的项;不写时每个显示中的系列一行(瀑布图列变动与累计) */\n tooltipItems?: (row: T) => ChartTooltipItem[];\n /** 数值轴(主轴)的范围要包含的值;shown 是显示中的系列(第二数值轴的已去掉)。不写时按系列的值(stacked 时按正负各自的总和) */\n domainValues?: (rows: readonly T[], shown: readonly ResolvedSeries<T>[]) => number[];\n /** 给读屏的数据表;不写时类目一列加每个系列一列 */\n table?: (rows: readonly T[]) => ChartTable;\n /** 点哪种图形算点了这一行(柱子的选择器,图形绑定的数据是这一行);不写时按十字线所在的那一行 */\n itemSelector?: string;\n}\n\n/** 第二数值轴的刻度文字占的宽度(px) */\nconst SECONDARY_AXIS_WIDTH = 48;\n\n/** 骨架柱的高度(百分比):高低错落,看起来像一组数据 */\nconst SKELETON_BARS = [55, 80, 40, 70, 90, 50, 65];\n\n/** XYChart 的样式:hideCrosshairLine 与加载中的骨架(外层结构的样式见 chartStyles) */\nexport const xyChartStyles = css.create({\n // 柱状图的十字线只用来定位提示框,不画竖线\n hideCrosshairLine: { '--vis-crosshair-line-stroke-opacity': '0' },\n skeleton: { display: 'block', width: '100%', height: '100%' },\n // 缩放:滑块占满,“显示全部”在结束边\n zoom: { display: 'flex', alignItems: 'center', gap: '_md', paddingInline: '_sm' },\n zoomSlider: { flexGrow: 1, minWidth: 0 },\n skeletonBars: {\n display: 'flex',\n alignItems: 'flex-end',\n justifyContent: 'space-around',\n gap: '_md',\n height: '100%',\n },\n skeletonBarsHorizontal: { flexDirection: 'column', alignItems: 'flex-start' },\n skeletonBar: { display: 'block', flexGrow: 1, flexBasis: 0, borderRadius: '_sm' },\n skeletonBarSize: (percent: string) => ({ height: percent }),\n skeletonBarSizeHorizontal: (percent: string) => ({ width: percent }),\n});\n\n/** 加载中绘图区的骨架:柱状图是一排高低不一的柱(横向时是条),其余是一整块 */\nfunction chartSkeleton({\n skeleton = 'block',\n horizontal = false,\n}: Pick<XYChartKind<object>, 'skeleton' | 'horizontal'>) {\n if (skeleton === 'block') return <Skeleton sx={xyChartStyles.skeleton} />;\n return (\n <div\n aria-hidden=\"true\"\n {...css.attrs(xyChartStyles.skeletonBars, horizontal && xyChartStyles.skeletonBarsHorizontal)}\n >\n {SKELETON_BARS.map((percent, position) => (\n <Skeleton\n key={position}\n sx={[\n xyChartStyles.skeletonBar,\n horizontal\n ? xyChartStyles.skeletonBarSizeHorizontal(`${percent}%`)\n : xyChartStyles.skeletonBarSize(`${percent}%`),\n ]}\n />\n ))}\n </div>\n );\n}\n\n/** 直角坐标图表的公共实现(组件库内部用,见 BarChart、LineChart、AreaChart) */\nexport const XYChart = _component(\n <T extends object>({\n data,\n index,\n series,\n indexFormat,\n valueFormat,\n unit,\n height = 240,\n legend,\n grid = true,\n valueDomain,\n tooltip = true,\n loading = false,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n empty,\n targets,\n annotations,\n bands,\n onItemClick,\n zoom = false,\n _zoomRange: zoomRange = _bindable<[number, number] | null>(null),\n kind,\n sx,\n ...rest\n }: XYChartProps<T> & { kind: XYChartKind<T> }) => {\n const lang = useLang();\n const format = useFormat();\n const id = useId();\n const resolved = _derived(resolveSeries(series));\n const visible = _derived(resolved.filter((item) => !hiddenSeries.includes(item.key)));\n\n const categoryText = (row: T | undefined) =>\n row === undefined\n ? ''\n : indexFormat\n ? indexFormat(row[index], row)\n : String(row[index] ?? '');\n const valueText = useChartValueText(() => ({ valueFormat, unit }));\n const secondaryText = useChartValueText(() => ({\n valueFormat: kind.secondary?.format,\n unit: kind.secondary?.unit,\n }));\n const onSecondary = (key: string) => kind.secondary?.keys.includes(key) ?? false;\n /** 一个系列的值的文字:第二数值轴上的按它的格式与单位 */\n const seriesText = (key: string, value: NumericValue | undefined) =>\n onSecondary(key) ? secondaryText(value) : valueText(value);\n /** 一行里显示中的系列的总和(百分比堆叠的分母;负数不计) */\n const rowTotal = (row: T) =>\n visible.reduce((sum, item) => sum + Math.max(seriesNumber(row, item.key) ?? 0, 0), 0);\n const percentText = (value: number) =>\n format.number(value, { style: 'percent', maximumFractionDigits: 1 });\n\n const xText = (row: T) => {\n const x = kind.continuousX?.value(row);\n return x === undefined ? lang.emptyValue : kind.continuousX!.format(x);\n };\n\n function toggle(key: string) {\n hiddenSeries = hiddenSeries.includes(key)\n ? hiddenSeries.filter((item) => item !== key)\n : [...hiddenSeries, key];\n }\n\n /** 缩放的滑块:两端是类目;缩小过时旁边有“显示全部” */\n const zoomBar = () => {\n const last = data.length - 1;\n return (\n <div {...css.attrs(xyChartStyles.zoom)}>\n <Slider\n _value={zoomRange ?? [0, last]}\n onUpdate:_value={(next: [number, number]) =>\n (zoomRange = next[0] === 0 && next[1] === last ? null : next)\n }\n min={0}\n max={last}\n step={1}\n size=\"sm\"\n valueText={(position) => categoryText(data[position])}\n aria-label={lang.chartZoom}\n propsRoot={{ sx: xyChartStyles.zoomSlider }}\n />\n {zoomRange && (\n <Button variant=\"link\" size=\"sm\" onClick={() => (zoomRange = null)}>\n {lang.chartZoomReset}\n </Button>\n )}\n </div>\n );\n };\n\n const instances = createChartInstances();\n let tooltipElement: HTMLElement | undefined;\n // 提示框的内容渲染进 Unovis 管的元素:带上调用处的主题与语言,组件卸载时一起卸载\n const renderDetached = useDetachedRender();\n\n // 指针所在的那一行:十字线移动时记下,点绘图区时下钻到它;离开绘图区时清掉\n let hovered: { row: T; index: number } | null = null;\n const hover = (row: T | undefined) => {\n hovered = row === undefined ? null : { row, index: data.indexOf(row) };\n };\n\n /** 十字线的提示框:内容用 Vue 渲染进同一个元素,交给 Unovis 定位 */\n function renderTooltip(row: T) {\n tooltipElement ??= document.createElement('div');\n // 跟着数据点的提示框(散点图)没有十字线:悬停哪个点就是哪一行\n if (kind.pointTooltip) hover(row);\n renderDetached(\n chartTooltip(\n categoryText(row),\n kind.tooltipItems?.(row) ?? [\n ...(kind.continuousX\n ? [{ label: kind.continuousX.label, color: 'transparent', value: xText(row) }]\n : []),\n // 跟着数据点的提示框只列这一行有值的系列(散点图里一行通常只落在一个系列上)\n ...visible\n .filter((item) => !kind.pointTooltip || seriesValue(row, item.key) !== undefined)\n .map((item) => {\n const value = seriesValue(row, item.key);\n const total = kind.percent ? rowTotal(row) : 0;\n return {\n label: item.label,\n color: item.color,\n value:\n kind.percent && value !== undefined && total > 0\n ? `${seriesText(item.key, value)}(${percentText(toNumber(value) / total)})`\n : seriesText(item.key, value),\n };\n }),\n ],\n ),\n tooltipElement,\n );\n return tooltipElement;\n }\n\n let plot = _state.raw<HTMLElement | null>(null);\n const seen = usePlotSeen(() => plot);\n let container: XYContainer<T> | undefined;\n let containerElement: HTMLElement | undefined;\n _effect(() => () => {\n container?.destroy();\n });\n _effect(() => {\n // 缩放:只画选中的一段(散点图的横轴是连续的数值,不按类目缩放)\n const range = zoom && !kind.continuousX ? zoomRange : null;\n const rows = range ? data.slice(range[0], range[1] + 1) : [...data];\n const shown = visible;\n const element = plot;\n if (!element || loading || rows.length === 0 || !seen()) return;\n // 绘图区换了元素:旧容器连同它的组件、坐标轴一起销毁,实例表清空后重新创建\n if (container && containerElement !== element) {\n container.destroy();\n container = undefined;\n instances.reset();\n }\n\n const primarySeries = shown.filter((item) => !onSecondary(item.key));\n const secondarySeries = shown.filter((item) => onSecondary(item.key));\n const totals = rows.map((row) =>\n primarySeries.map((item) => seriesNumber(row, item.key) ?? 0),\n );\n const seriesValues = kind.domainValues\n ? kind.domainValues(rows, primarySeries)\n : kind.stacked\n ? totals.flatMap((row) => [\n row.reduce((sum, value) => sum + Math.max(value, 0), 0),\n row.reduce((sum, value) => sum + Math.min(value, 0), 0),\n ])\n : totals.flat();\n // 目标线、数值轴上的区间要落在数值轴的范围里\n const values = [\n ...seriesValues,\n ...(targets ?? []).map((target) => toNumber(target.value)),\n ...(bands ?? [])\n .filter((band) => band.axis === 'value')\n .flatMap((band) => [Number(band.from), Number(band.to)]),\n ];\n // 第二数值轴:两条轴的刻度对齐,第二轴的值换算到主轴的坐标\n const aligned: AlignedAxes | undefined =\n secondarySeries.length > 0\n ? alignedTicks(\n [\n ...values,\n ...[valueDomain?.[0], valueDomain?.[1]].filter(\n (end): end is number => end !== undefined,\n ),\n ],\n rows.flatMap((row) =>\n secondarySeries.map((item) => seriesNumber(row, item.key) ?? 0),\n ),\n )\n : undefined;\n const domain: [number | undefined, number | undefined] = kind.percent\n ? [0, 1]\n : aligned\n ? aligned.primary.domain\n : [\n valueDomain?.[0] ??\n (kind.zeroBaseline === false ? undefined : Math.min(0, ...values)),\n valueDomain?.[1],\n ];\n const x = kind.continuousX\n ? (row: T) => kind.continuousX!.value(row) ?? Number.NaN\n : (_row: T, position: number) => position;\n const y = (item: (typeof shown)[number]) => {\n if (kind.percent)\n return (row: T) => {\n const value = seriesNumber(row, item.key);\n const total = rowTotal(row);\n return value === undefined || total === 0 ? undefined : value / total;\n };\n if (aligned && onSecondary(item.key))\n return (row: T) => {\n const value = seriesNumber(row, item.key);\n return value === undefined ? undefined : aligned.toPrimary(value);\n };\n return (row: T) => seriesNumber(row, item.key);\n };\n /** 类目在类目轴上的位置:散点图是横轴的数值,其余是第几行;找不到时 undefined */\n const positionOf = (at: unknown) => {\n if (kind.continuousX) return Number(at);\n const found = rows.findIndex((row) => row[index] === at);\n return found < 0 ? undefined : found;\n };\n const categoryAxisName = kind.horizontal ? AxisType.Y : AxisType.X;\n const valueAxisName = kind.horizontal ? AxisType.X : AxisType.Y;\n const lines = (targets ?? []).map((target, position) => {\n const line = instances.get(`target-${position}`, () => new Plotline<T>({}));\n const value = toNumber(target.value);\n const label = valueText(target.value);\n line.setConfig({\n axis: kind.horizontal ? 'x' : 'y',\n value,\n color: resolveColor(target.color ?? 'danger', 0),\n lineWidth: 1.5,\n lineStyle: PlotlineLineStylePresets.Dash,\n labelText: target.label ? `${target.label} ${label}` : label,\n labelPosition: kind.horizontal\n ? PlotlineLabelPosition.TopRight\n : PlotlineLabelPosition.TopLeft,\n labelOffsetX: 4,\n labelOffsetY: 10,\n });\n return line;\n });\n\n // 区间:浅色的带,文字在左上角\n const bandComponents = (bands ?? []).flatMap((band, position) => {\n const onIndex = band.axis !== 'value';\n const from = onIndex ? positionOf(band.from) : Number(band.from);\n const to = onIndex ? positionOf(band.to) : Number(band.to);\n if (from === undefined || to === undefined) return [];\n // 类目轴上的区间盖住两端的类目:往外各扩半格\n const half = onIndex && !kind.continuousX ? 0.5 : 0;\n const plotband = instances.get(`band-${position}`, () => new Plotband<T>({}));\n plotband.setConfig({\n axis: onIndex ? categoryAxisName : valueAxisName,\n from: Math.min(from, to) - half,\n to: Math.max(from, to) + half,\n color: `color-mix(in srgb, ${resolveColor(band.color ?? 'neutral', 0)} 12%, transparent)`,\n labelText: band.label,\n // 类目轴上的区间文字在左下角:顶上留给事件竖线的文字\n labelPosition: onIndex\n ? PlotbandLabelPosition.BottomLeftInside\n : PlotbandLabelPosition.TopLeftInside,\n labelColor: colors.textMuted,\n labelOffsetX: 6,\n labelOffsetY: 6,\n });\n return [plotband];\n });\n\n // 标注:事件是类目上的竖线;圈出的值是一个空心圈,文字在上方\n const events = (annotations ?? []).filter((item) => item.series === undefined);\n const eventLines = events.flatMap((item, position) => {\n const at = positionOf(item.at);\n if (at === undefined) return [];\n const line = instances.get(`event-${position}`, () => new Plotline<T>({}));\n line.setConfig({\n axis: categoryAxisName,\n value: at,\n color: resolveColor(item.color ?? 'neutral', 0),\n lineWidth: 1,\n lineStyle: PlotlineLineStylePresets.ShortDash,\n labelText: item.label,\n labelPosition: kind.horizontal\n ? PlotlineLabelPosition.BottomRight\n : PlotlineLabelPosition.TopRight,\n labelOffsetX: 4,\n labelOffsetY: 4,\n });\n return [line];\n });\n const marked = (annotations ?? []).filter(\n (item) => item.series !== undefined && !kind.horizontal,\n );\n const markOf = (row: T) => {\n const at = kind.continuousX ? kind.continuousX.value(row) : rows.indexOf(row);\n return marked.find(\n (item) =>\n positionOf(item.at) === at && shown.some((series) => series.key === item.series),\n );\n };\n /** 圈的位置:系列的值;堆叠时是它在这一摞里的顶端 */\n const markY = (row: T) => {\n const mark = markOf(row);\n if (!mark) return undefined;\n const series = shown.find((item) => item.key === mark.series)!;\n if (!kind.stacked || kind.percent) return y(series)(row);\n const upTo = shown.slice(0, shown.indexOf(series) + 1);\n return upTo.reduce((sum, item) => sum + Math.max(y(item)(row) ?? 0, 0), 0);\n };\n const markColor = (row: T) => {\n const mark = markOf(row);\n const series = shown.find((item) => item.key === mark?.series);\n return mark?.color ? resolveColor(mark.color, 0) : (series?.color ?? colors.textMuted);\n };\n const marks = instances.get('marks', () => new Scatter<T>({ x, y: () => undefined }));\n marks.setConfig({\n x,\n y: markY,\n size: 16,\n color: 'transparent',\n strokeColor: markColor,\n strokeWidth: 2,\n label: (row: T) => markOf(row)?.label ?? '',\n labelPosition: Position.Top,\n labelColor: colors.text,\n });\n\n // 第二数值轴的刻度:与主轴的刻度同高,文字在绘图区右侧(不裁剪的 Plotline 标签,线本身透明)\n const secondaryLabels = aligned\n ? aligned.secondary.ticks.map((tick, position) => {\n const label = instances.get(`secondary-${position}`, () => {\n const line = new Plotline<T>({});\n line.clippable = false;\n return line;\n });\n label.setConfig({\n axis: 'y',\n value: aligned.primary.ticks[position]!,\n color: 'transparent',\n lineWidth: 0,\n labelText: format.number(tick, kind.secondary?.format),\n labelPosition: PlotlineLabelPosition.Right,\n labelOffsetX: -(SECONDARY_AXIS_WIDTH - 4),\n labelColor: colors.textMuted,\n });\n return label;\n })\n : [];\n const components = [\n ...bandComponents,\n ...kind.components({\n series: shown,\n x,\n y,\n instance: instances.get,\n events:\n kind.itemSelector && onItemClick\n ? {\n [kind.itemSelector]: {\n // 分组柱给的是原来的行;堆叠柱给的是拼出来的副本,第三个参数才是行的位置\n click: (row: T, _event: Event, index: number) => {\n const position = data.indexOf(row);\n const at = position >= 0 ? position : index;\n onItemClick(data[at] ?? row, at);\n },\n },\n }\n : {},\n }),\n ...lines,\n ...eventLines,\n ...(marked.length > 0 ? [marks] : []),\n ...secondaryLabels,\n ];\n const xAxis = instances.get('xAxis', () => new Axis<T>({ type: 'x' }));\n const yAxis = instances.get('yAxis', () => new Axis<T>({ type: 'y' }));\n const crosshair = instances.get('crosshair', () => new Crosshair<T>());\n const tooltipBox = instances.get('tooltip', () => new Tooltip());\n const [categoryAxis, valueAxis] = kind.horizontal ? [yAxis, xAxis] : [xAxis, yAxis];\n const continuous = kind.continuousX;\n categoryAxis.setConfig({\n type: kind.horizontal ? 'y' : 'x',\n // 连续的横轴:Unovis 自己取刻度,网格线与数值轴一样;类目轴:每行一个刻度\n tickValues: continuous ? undefined : rows.map((_row, position) => position),\n numTicks: continuous ? 6 : undefined,\n tickFormat: continuous\n ? (tick) => continuous.format(Number(tick))\n : (tick) => categoryText(rows[Number(tick)]),\n gridLine: continuous ? grid : false,\n tickLine: false,\n domainLine: false,\n tickTextHideOverlapping: true,\n tickPadding: 8,\n label: continuous?.title,\n labelMargin: 8,\n });\n valueAxis.setConfig({\n type: kind.horizontal ? 'x' : 'y',\n numTicks: 5,\n // 有第二数值轴时用对齐的刻度,两边的刻度落在同一组网格线上\n tickValues: aligned?.primary.ticks,\n tickFormat: (tick) =>\n kind.percent\n ? format.number(Number(tick), { style: 'percent', maximumFractionDigits: 0 })\n : format.number(Number(tick), valueFormat),\n gridLine: grid,\n tickLine: false,\n domainLine: false,\n tickPadding: 8,\n });\n const dotted = kind.crosshairSeries ? shown.filter(kind.crosshairSeries) : shown;\n crosshair.setConfig({\n // 访问器直接给:容器还没按尺寸渲染过时不会把组件的访问器转交十字线,Unovis 会报 “Y accessors have not been configured”\n x,\n ...(kind.stacked ? { yStacked: dotted.map(y) } : { y: dotted.map(y) }),\n template: (row: T) => renderTooltip(row),\n color: (_row: T, position: number) => dotted[position]?.color ?? 'transparent',\n getCircles: kind.crosshairDots ? undefined : () => [],\n hideWhenFarFromPointer: false,\n onCrosshairMove: (_x, row) => hover(row),\n });\n\n tooltipBox.setConfig({\n triggers: kind.pointTooltip ? { [kind.pointTooltip]: (row: T) => renderTooltip(row) } : {},\n });\n const config = {\n components,\n xAxis,\n yAxis,\n // 能下钻时没有提示框也要十字线:靠它知道指针在哪一行\n crosshair:\n (tooltip || (onItemClick && !kind.itemSelector)) && !kind.pointTooltip\n ? crosshair\n : undefined,\n tooltip: tooltip ? tooltipBox : undefined,\n [kind.horizontal ? 'xDomain' : 'yDomain']: domain,\n // 第二数值轴的刻度文字画在右侧留出的空白里\n padding: aligned\n ? { ...kind.padding, right: Math.max(kind.padding?.right ?? 0, SECONDARY_AXIS_WIDTH) }\n : (kind.padding ?? {}),\n ariaLabel: null,\n duration: chartDuration(element),\n onRenderComplete: haloPlotlineLabels,\n };\n if (container) container.update(config, undefined, rows);\n else {\n container = new XYContainer<T>(element, config, rows);\n containerElement = element;\n uniqueHighlightFilter(element, `${id}-highlight`);\n }\n });\n\n return () => (\n <ChartFrame\n {...rest}\n sx={[!kind.crosshairDots && xyChartStyles.hideCrosshairLine, sx]}\n // 百分比堆叠时数值轴是占比:轴上方不写单位(提示框、数据表里仍带)\n unit={kind.percent ? undefined : unit}\n unitEnd={kind.secondary?.unit}\n height={height}\n legend={(legend ?? resolved.length > 1) ? resolved : []}\n hiddenKeys={hiddenSeries}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={chartSkeleton(kind)}\n isEmpty={data.length === 0}\n empty={empty}\n clickable={onItemClick != null}\n onPlotClick={\n onItemClick && !kind.itemSelector\n ? () => {\n if (hovered) onItemClick(hovered.row, hovered.index);\n }\n : undefined\n }\n table={\n kind.table?.(data) ?? {\n columns: [\n lang.chartCategory,\n ...(kind.continuousX ? [kind.continuousX.label] : []),\n ...resolved.map((item) => {\n const itemUnit = onSecondary(item.key) ? kind.secondary?.unit : unit;\n return itemUnit ? `${item.label}(${itemUnit})` : item.label;\n }),\n ],\n rows: data.map((row) => ({\n header: categoryText(row),\n cells: [\n ...(kind.continuousX ? [xText(row)] : []),\n ...resolved.map((item) => {\n const value = seriesValue(row, item.key);\n return value === undefined\n ? lang.emptyValue\n : format.number(\n value,\n onSecondary(item.key) ? kind.secondary?.format : valueFormat,\n );\n }),\n ],\n })),\n }\n }\n plotRef={(element) => (plot = element)}\n footer={zoom && !kind.continuousX && data.length > 2 ? zoomBar() : undefined}\n />\n );\n },\n);\n\n/**\n * 目标线、事件竖线的文字描一圈表面色的边(同地图上地点的名字):压在柱子、折线上也看得清。\n * Unovis 的 Plotline 文字没有描边的配置项,渲染完成后补在元素上;导出图片时按计算样式一并带走\n */\nfunction haloPlotlineLabels(svg: SVGSVGElement) {\n for (const label of svg.querySelectorAll<SVGTextElement>('text[class*=\"plotline-label\"]')) {\n label.style.setProperty('paint-order', 'stroke');\n label.style.setProperty('stroke', colors.surface);\n label.style.setProperty('stroke-width', '3px');\n label.style.setProperty('stroke-linejoin', 'round');\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"XYChart.js","names":["_createVNode","_mergeProps","_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_shallowRef"],"sources":["../../src/charts/XYChart.tsx"],"sourcesContent":["/**\n * 直角坐标图表(柱状图、折线图、面积图、散点图、组合图、瀑布图)的公共部分:比例尺与坐标轴、网格、十字线与提示框、\n * 目标线、标注与区间、缩放、下钻;外层结构(图例、单位、空与加载状态、给读屏的数据表)交给 ChartFrame。\n * 各种图只决定画什么(kind.render),坐标由 XYChartContext 换算,配色、坐标轴、提示框都在这里统一。\n *\n * - 类目轴:每行一个类目。柱(kind.band)每个类目占一格、画在格子中间;折线、面积的第一个、最后一个类目贴着两端。\n * 刻度文字放不下时隔几个写一个;横向(kind.horizontal)时类目在纵轴,名字太长截短。\n * - 数值轴:范围默认从 0 起(有负数时含负数),两端扩到“好看”的刻度上;valueDomain 指定的一端不扩。\n * 百分比堆叠(kind.percent)按每个类目里各系列的占比画,数值轴是 0–100%。\n * - 第二数值轴(kind.secondary,组合图):刻度与主轴对齐(alignedTicks),第二轴的系列换算到主轴的坐标里画。\n * - 悬停:指针所在的类目画十字线(折线、面积给各系列标出圆点)或一层浅底(柱),提示框列出这一类目的各系列;\n * 散点图(kind.pointTooltip)按离指针最近的点。点了下钻(onItemClick):点在柱上按那根柱,其余按悬停的类目。\n * - 标注(annotations):类目上的事件是竖线,圈出某个系列的值是空心圈带文字;区间(bands)是浅色的带。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { Button } from '../base/Button';\nimport { Slider } from '../input/Slider';\nimport { svgNumber } from '../utils/data/number';\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport type { PartProps } from '../utils/props';\nimport { alignedTicks, type AlignedAxes } from './axis-ticks';\nimport {\n ChartFrame,\n chartTooltip,\n useChartValueText,\n type ChartFrameParts,\n type ChartTable,\n type ChartTooltipItem,\n} from './frame';\nimport {\n ChartTooltipBox,\n chartAxis,\n chartSvgStyles,\n pointerIn,\n usePlotArea,\n type AxisTick,\n type ChartTip,\n type PlotRect,\n} from './plot';\nimport { linearScale, linearTicks, niceDomain } from './scale';\nimport {\n resolveColor,\n resolveSeries,\n seriesNumber,\n seriesValue,\n type ChartColor,\n type ChartSeries,\n type ResolvedSeries,\n} from './series';\nimport { stackValues, type StackSegment } from './stack';\nimport { estimateTextWidth, truncateText } from './text-size';\n\n/** 目标线(参考线):数值轴上的一条虚线 */\nexport interface ChartTarget {\n /** 位置:数值轴上的值 */\n value: NumericValue;\n /** 标签:写在线的一端,后面带上格式化的数值(“年度指标 1,200”) */\n label?: string;\n /** 颜色;默认是 danger(要够到的线) */\n color?: ChartColor;\n}\n\n/** 标注:类目上发生的事(竖线),或圈出某个系列在这个类目上的值 */\nexport interface ChartAnnotation {\n /** 标在哪个类目上:index 字段的值(散点图是横轴上的数值) */\n at: unknown;\n /** 文字 */\n label: string;\n /** 圈出这个系列在这里的值(系列的 key);不写时是一条竖线(换供应商、调价生效这类事件) */\n series?: string;\n /** 颜色;竖线默认是次要色,圈默认是系列色 */\n color?: ChartColor;\n}\n\n/** 区间:类目轴上的一段(试运行期、促销期),或数值轴上的一段(目标区间) */\nexport interface ChartBand {\n /** 在哪条轴上,默认 index(类目轴) */\n axis?: 'index' | 'value';\n /** 起点:类目轴是 index 字段的值(含这一项),数值轴是数值 */\n from: unknown;\n /** 终点:同 from(含这一项) */\n to: unknown;\n /** 文字:类目轴上的写在带的左下角,数值轴上的写在左上角 */\n label?: string;\n /** 颜色,默认 neutral;画成很浅的底色 */\n color?: ChartColor;\n}\n\n/** 第二数值轴(右侧):哪些系列画在它上面,它的格式与单位 */\nexport interface ChartSecondaryAxis {\n /** 画在第二数值轴上的系列 */\n keys: readonly string[];\n /** 数值的格式 */\n format?: NumericFormat;\n /** 单位:显示在右上方,提示框与数据表的数值后面带上 */\n unit?: string;\n}\n\n/** 加载中的骨架 */\nexport interface ChartSkeletons {\n /** 一排高低不一的柱(柱状图) */\n bars: unknown;\n /** 一整块(默认) */\n block: unknown;\n}\n\n/** 直角坐标图表共有的属性;未声明的属性落到外层 div(role=\"figure\")上,aria-label 是图表的名称 */\nexport interface XYChartProps<T extends object>\n extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 数据:每一行是类目轴上的一项(一个月、一个项目) */\n data: readonly T[];\n /** 类目字段:类目轴的刻度、提示框的标题、数据表的第一列 */\n index: keyof T & string;\n /** 系列:每个系列画成一组柱子、一条线或一片面积 */\n series: readonly ChartSeries<T>[];\n /** 类目的显示文字;不写时把字段的值转成字符串 */\n indexFormat?: (value: T[keyof T & string], row: T) => string;\n /**\n * 数值的格式:数值轴、提示框、数据表共用,按当前语言格式化。以万元为单位画金额时写\n * `{ scale: 10_000, maximumFractionDigits: 1 }` 并配 `unit=\"万元\"`\n */\n valueFormat?: NumericFormat;\n /** 单位:显示在数值轴上方,提示框与数据表的数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 240\n */\n height?: number | string;\n /** 图例:默认多于一个系列时显示;点图例可以隐藏、恢复系列 */\n legend?: boolean;\n /**\n * 数值轴的网格线\n * @default true\n */\n grid?: boolean;\n /** 数值轴的范围 [最小, 最大];不写的一端按数据自动取,最小值默认从 0 起(数据有负数时取负数) */\n valueDomain?: readonly [number | undefined, number | undefined];\n /**\n * 悬停时的提示框\n * @default true\n */\n tooltip?: boolean;\n /**\n * 加载中:绘图区显示扫光的骨架(柱状图是一排高低不一的柱),带 aria-busy\n * @default false\n */\n loading?: boolean;\n /** 隐藏的系列(存系列的 key):点图例时写回,父级可以写 _hiddenSeries={keys} */\n _hiddenSeries?: string[];\n /** 没有数据时显示的内容,默认是“暂无数据” */\n empty?: VNodeChild;\n /** 目标线、参考线:数值轴上的虚线(横向图是竖线),如年度销售指标;数值轴的范围会包含它 */\n targets?: readonly ChartTarget[];\n /** 标注:类目上的事件(竖线),或圈出某个系列的值(横向图只画竖线) */\n annotations?: readonly ChartAnnotation[];\n /** 区间:类目轴或数值轴上的一段,画成浅色的带(数值轴的范围会包含它) */\n bands?: readonly ChartBand[];\n /**\n * 点了一个类目(下钻,如跳到筛好条件的台账):参数是这一行与它的位置;写了它时绘图区的指针是手形。\n * 点图是鼠标的捷径:同样的去处在页面上还要有链接或按钮,键盘与读屏才到得了(WCAG 2.1.1)\n */\n onItemClick?: (row: T, index: number) => void;\n /** 缩放:绘图区下面一条区间滑块,选一段类目放大看(几年的月度数据);读屏的数据表仍是全部 */\n zoom?: boolean;\n /** 缩放的区间 [起, 止]:类目的位置,含两端;父级可以写 _zoomRange={range},null 是全部 */\n _zoomRange?: [number, number] | null;\n}\n\n/** 交给各种图的绘制上下文:坐标都是 SVG 里的 px */\nexport interface XYChartContext<T extends object> {\n /** 显示中的系列(去掉了图例里隐藏的),颜色已定 */\n series: ResolvedSeries<T>[];\n /** 画的行(缩放时是选中的一段) */\n rows: readonly T[];\n /** 横向:类目在纵轴、数值在横轴 */\n horizontal: boolean;\n /** 绘图区(坐标轴以内) */\n plot: PlotRect;\n /** 一个类目在类目轴上占的长度:柱按它定宽 */\n step: number;\n /** 数值轴的范围 */\n domain: readonly [number, number];\n /** 第 index 行在类目轴上的坐标(格子的中心);散点图是横轴数值的位置 */\n category: (row: T, index: number) => number;\n /** 数值 → 数值轴上的坐标 */\n value: (value: number) => number;\n /** 系列在一行上画的值:百分比堆叠时是占比,第二数值轴上的换算到主轴;空值 undefined */\n valueOf: (series: ResolvedSeries<T>, row: T) => number | undefined;\n /** 堆叠(kind.stacked)后各系列每一行的一段:系列的 key → 每行一段 */\n stacks: ReadonlyMap<string, readonly StackSegment[]>;\n /** 类目坐标、数值坐标 → SVG 的 [x, y](横向时对调) */\n point: (category: number, value: number) => [number, number];\n /** 指针所在的那一行(在 rows 里的位置),没有时为 null */\n hovered: number | null;\n}\n\n/** 一种图:画什么,以及与坐标轴、十字线有关的差别 */\nexport interface XYChartKind<T extends object> {\n /** 画出图形(坐标轴、网格、目标线、标注、十字线由 XYChart 画);每次数据、属性、悬停变化都会调用 */\n render: (context: XYChartContext<T>) => VNodeChild;\n /** 类目占一格(柱):图形画在格子中间、两端各留半格;不写时第一个、最后一个类目贴着两端(折线、面积) */\n band?: boolean;\n /** 横向:类目在纵轴、数值在横轴 */\n horizontal?: boolean;\n /** 十字线上给每个系列画圆点(折线图、面积图);柱状图不画,悬停的类目铺一层浅底 */\n crosshairDots?: boolean;\n /** 加载中的骨架,默认 block */\n skeleton?: keyof ChartSkeletons;\n /** 绘图区四周的留白(px):折线两端不贴着边缘 */\n padding?: { left?: number; right?: number; top?: number; bottom?: number };\n /** 数值范围按堆叠后的总和算(堆叠的柱子、面积) */\n stacked?: boolean;\n /** 参与堆叠的系列(组合图只叠柱);不写时是全部显示中的系列 */\n stackSeries?: (series: ResolvedSeries<T>) => boolean;\n /** 百分比堆叠:各系列按它在这个类目里的占比画(加起来 100%),数值轴是百分比,提示框带上占比 */\n percent?: boolean;\n /** 第二数值轴(组合图):这些系列画在右侧的轴上,刻度与主轴对齐 */\n secondary?: ChartSecondaryAxis;\n /** 十字线只在这些系列上画圆点(组合图里只给线画);不写时按 crosshairDots */\n crosshairSeries?: (series: ResolvedSeries<T>) => boolean;\n /** 横轴是连续的数值(散点图):取值、刻度与提示框里的写法、数据表的列名、轴下方的标题;不写时横轴是类目(第几行) */\n continuousX?: {\n value: (row: T) => number | undefined;\n format: (value: number) => string;\n label: string;\n title?: string;\n };\n /** 数值轴默认从 0 起(数据有负数时取负数);false 时按数据自动取(散点图) */\n zeroBaseline?: boolean;\n /** 提示框跟着离指针最近的数据点(散点图),没有十字线 */\n pointTooltip?: boolean;\n /** 提示框里列的项;不写时每个显示中的系列一行(瀑布图列变动与累计) */\n tooltipItems?: (row: T) => ChartTooltipItem[];\n /** 数值轴(主轴)的范围要包含的值;shown 是显示中的系列(第二数值轴的已去掉)。不写时按系列的值(stacked 时按正负各自的总和) */\n domainValues?: (rows: readonly T[], shown: readonly ResolvedSeries<T>[]) => number[];\n /** 给读屏的数据表;不写时类目一列加每个系列一列 */\n table?: (rows: readonly T[]) => ChartTable;\n}\n\n/** 刻度文字的字号(px):主题的 xs */\nconst TICK_FONT = 12;\n/** 刻度文字与绘图区的距离 */\nconst TICK_GAP = 8;\n/** 散点图找最近的点时,离指针多远以内算悬停在点上(px) */\nconst POINT_REACH = 24;\n\n/** 骨架柱的高度(百分比):高低错落,看起来像一组数据 */\nconst SKELETON_BARS = [55, 80, 40, 70, 90, 50, 65];\n\n/** XYChart 的样式:缩放的滑块、加载中的骨架、标注(外层结构的样式见 chartStyles) */\nexport const xyChartStyles = css.create({\n svg: { touchAction: 'pan-y' },\n skeleton: { display: 'block', width: '100%', height: '100%' },\n // 缩放:滑块占满,“显示全部”在结束边\n zoom: { display: 'flex', alignItems: 'center', gap: '_md', paddingInline: '_sm' },\n zoomSlider: { flexGrow: 1, minWidth: 0 },\n skeletonBars: {\n display: 'flex',\n alignItems: 'flex-end',\n justifyContent: 'space-around',\n gap: '_md',\n height: '100%',\n },\n skeletonBarsHorizontal: { flexDirection: 'column', alignItems: 'flex-start' },\n skeletonBar: { display: 'block', flexGrow: 1, flexBasis: 0, borderRadius: '_sm' },\n skeletonBarSize: (percent: string) => ({ height: percent }),\n skeletonBarSizeHorizontal: (percent: string) => ({ width: percent }),\n targetLine: { strokeWidth: 1.5, strokeDasharray: '6 4', pointerEvents: 'none' },\n eventLine: { strokeWidth: 1, strokeDasharray: '3 3', pointerEvents: 'none' },\n mark: { fill: 'none', strokeWidth: 2, pointerEvents: 'none' },\n crosshairDot: { stroke: '_surface', strokeWidth: 2, pointerEvents: 'none' },\n bandFill: (color: string) => ({ fill: `color-mix(in srgb, ${color} 12%, transparent)` }),\n textFill: (color: string) => ({ fill: color }),\n});\n\n/** 加载中绘图区的骨架:柱状图是一排高低不一的柱(横向时是条),其余是一整块 */\nfunction chartSkeleton({\n skeleton = 'block',\n horizontal = false,\n}: Pick<XYChartKind<object>, 'skeleton' | 'horizontal'>) {\n if (skeleton === 'block') return <Skeleton sx={xyChartStyles.skeleton} />;\n return (\n <div\n aria-hidden=\"true\"\n {...css.attrs(xyChartStyles.skeletonBars, horizontal && xyChartStyles.skeletonBarsHorizontal)}\n >\n {SKELETON_BARS.map((percent, position) => (\n <Skeleton\n key={position}\n sx={[\n xyChartStyles.skeletonBar,\n horizontal\n ? xyChartStyles.skeletonBarSizeHorizontal(`${percent}%`)\n : xyChartStyles.skeletonBarSize(`${percent}%`),\n ]}\n />\n ))}\n </div>\n );\n}\n\n/** 数值轴上约几格:每格不少于 45px(横着的轴 90px),2–6 格 */\nconst tickCount = (length: number, horizontal: boolean) =>\n Math.max(2, Math.min(6, Math.round(length / (horizontal ? 90 : 45))));\n\n/** 指针悬停的状态:行的位置、提示框的位置 */\ninterface Hover {\n index: number;\n x: number;\n y: number;\n}\n\n/** 直角坐标图表的公共实现(组件库内部用,见 BarChart、LineChart、AreaChart) */\nexport const XYChart = _component(\n <T extends object>({\n data,\n index,\n series,\n indexFormat,\n valueFormat,\n unit,\n height = 240,\n legend,\n grid = true,\n valueDomain,\n tooltip = true,\n loading = false,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n empty,\n targets,\n annotations,\n bands,\n onItemClick,\n zoom = false,\n _zoomRange: zoomRange = _bindable<[number, number] | null>(null),\n kind,\n ...rest\n }: XYChartProps<T> & { kind: XYChartKind<T> }) => {\n const lang = useLang();\n const format = useFormat();\n const area = usePlotArea();\n const resolved = _derived(resolveSeries(series));\n const visible = _derived(resolved.filter((item) => !hiddenSeries.includes(item.key)));\n let hover = _state.raw<Hover | null>(null);\n\n const categoryText = (row: T | undefined) =>\n row === undefined\n ? ''\n : indexFormat\n ? indexFormat(row[index], row)\n : String(row[index] ?? '');\n const valueText = useChartValueText(() => ({ valueFormat, unit }));\n const secondaryText = useChartValueText(() => ({\n valueFormat: kind.secondary?.format,\n unit: kind.secondary?.unit,\n }));\n const onSecondary = (key: string) => kind.secondary?.keys.includes(key) ?? false;\n /** 一个系列的值的文字:第二数值轴上的按它的格式与单位 */\n const seriesText = (key: string, value: NumericValue | undefined) =>\n onSecondary(key) ? secondaryText(value) : valueText(value);\n /** 一行里显示中的系列的总和(百分比堆叠的分母;负数不计) */\n const rowTotal = (row: T) =>\n visible.reduce((sum, item) => sum + Math.max(seriesNumber(row, item.key) ?? 0, 0), 0);\n const percentText = (value: number) =>\n format.number(value, { style: 'percent', maximumFractionDigits: 1 });\n\n const xText = (row: T) => {\n const x = kind.continuousX?.value(row);\n return x === undefined ? lang.emptyValue : kind.continuousX!.format(x);\n };\n\n function toggle(key: string) {\n hiddenSeries = hiddenSeries.includes(key)\n ? hiddenSeries.filter((item) => item !== key)\n : [...hiddenSeries, key];\n }\n\n /** 缩放的滑块:两端是类目;缩小过时旁边有“显示全部” */\n const zoomBar = () => {\n const last = data.length - 1;\n return (\n <div {...css.attrs(xyChartStyles.zoom)}>\n <Slider\n _value={zoomRange ?? [0, last]}\n onUpdate:_value={(next: [number, number]) =>\n (zoomRange = next[0] === 0 && next[1] === last ? null : next)\n }\n min={0}\n max={last}\n step={1}\n size=\"sm\"\n valueText={(position) => categoryText(data[position])}\n aria-label={lang.chartZoom}\n propsRoot={{ sx: xyChartStyles.zoomSlider }}\n />\n {zoomRange && (\n <Button variant=\"link\" size=\"sm\" onClick={() => (zoomRange = null)}>\n {lang.chartZoomReset}\n </Button>\n )}\n </div>\n );\n };\n\n /** 提示框的内容:类目(或点的名字)与各系列的值 */\n function tooltipContent(row: T) {\n return chartTooltip(\n categoryText(row),\n kind.tooltipItems?.(row) ?? [\n ...(kind.continuousX\n ? [{ label: kind.continuousX.label, color: 'transparent', value: xText(row) }]\n : []),\n // 跟着数据点的提示框只列这一行有值的系列(散点图里一行通常只落在一个系列上)\n ...visible\n .filter((item) => !kind.pointTooltip || seriesValue(row, item.key) !== undefined)\n .map((item) => {\n const value = seriesValue(row, item.key);\n const total = kind.percent ? rowTotal(row) : 0;\n return {\n label: item.label,\n color: item.color,\n value:\n kind.percent && value !== undefined && total > 0\n ? `${seriesText(item.key, value)}(${percentText(toNumber(value) / total)})`\n : seriesText(item.key, value),\n };\n }),\n ],\n );\n }\n\n /** 缩放:只画选中的一段(散点图的横轴是连续的数值,不按类目缩放) */\n const range = () => (zoom && !kind.continuousX ? zoomRange : null);\n const shownRows = _derived.by(() => {\n const selected = range();\n return selected ? data.slice(selected[0], selected[1] + 1) : data;\n });\n\n /** 画图要的一切:比例尺、刻度、边距;随数据、属性、绘图区大小变 */\n const layout = _derived.by(() => {\n const rows = shownRows;\n const width = area.width;\n const plotHeight = area.height;\n const horizontal = kind.horizontal ?? false;\n const shown = visible;\n const primarySeries = shown.filter((item) => !onSecondary(item.key));\n const secondarySeries = shown.filter((item) => onSecondary(item.key));\n\n // 数值轴的范围要包含的值:系列(堆叠时按正负各自的总和)、目标线、数值轴上的区间。\n // 不叠的系列里空值不算:散点图里一行通常只落在一个系列上,其余系列是空的\n const totals = rows.map((row) =>\n primarySeries.map((item) => seriesNumber(row, item.key) ?? 0),\n );\n const seriesValues = kind.domainValues\n ? kind.domainValues(rows, primarySeries)\n : kind.stacked\n ? totals.flatMap((row) => [\n row.reduce((sum, value) => sum + Math.max(value, 0), 0),\n row.reduce((sum, value) => sum + Math.min(value, 0), 0),\n ])\n : rows.flatMap((row) =>\n primarySeries.flatMap((item) => seriesNumber(row, item.key) ?? []),\n );\n const values = [\n ...seriesValues,\n ...(targets ?? []).map((target) => toNumber(target.value)),\n ...(bands ?? [])\n .filter((band) => band.axis === 'value')\n .flatMap((band) => [Number(band.from), Number(band.to)]),\n ].filter(Number.isFinite);\n const aligned: AlignedAxes | undefined =\n secondarySeries.length > 0\n ? alignedTicks(\n [\n ...values,\n ...[valueDomain?.[0], valueDomain?.[1]].filter(\n (end): end is number => end !== undefined,\n ),\n ],\n rows.flatMap((row) =>\n secondarySeries.map((item) => seriesNumber(row, item.key) ?? 0),\n ),\n )\n : undefined;\n\n const valueLength = horizontal ? width : plotHeight;\n let domain: [number, number];\n let ticks: number[];\n if (kind.percent) {\n domain = [0, 1];\n ticks = linearTicks(0, 1, tickCount(valueLength, horizontal));\n } else if (aligned) {\n domain = aligned.primary.domain;\n ticks = aligned.primary.ticks;\n } else {\n const fromZero = kind.zeroBaseline !== false;\n const low = values.length ? Math.min(...values, ...(fromZero ? [0] : [])) : 0;\n const high = values.length ? Math.max(...values, ...(fromZero ? [0] : [])) : 1;\n const [autoLow, autoHigh] = low === high ? [low - 1, high + 1] : [low, high];\n const nice = niceDomain(\n [valueDomain?.[0] ?? autoLow, valueDomain?.[1] ?? autoHigh],\n tickCount(valueLength, horizontal),\n );\n domain = [valueDomain?.[0] ?? nice[0], valueDomain?.[1] ?? nice[1]];\n ticks = linearTicks(domain[0], domain[1], tickCount(valueLength, horizontal));\n }\n const valueLabel = (tick: number) =>\n kind.percent\n ? format.number(tick, { style: 'percent', maximumFractionDigits: 0 })\n : format.number(tick, valueFormat);\n const valueLabels = ticks.map(valueLabel);\n const secondaryLabels = aligned\n ? aligned.secondary.ticks.map((tick) => format.number(tick, kind.secondary?.format))\n : [];\n\n // 连续的横轴(散点图):按数据取范围与刻度\n const continuous = kind.continuousX;\n const xValues = continuous\n ? rows.map((row) => continuous.value(row)).filter((x): x is number => x !== undefined)\n : [];\n const xDomain = niceDomain(\n xValues.length ? [Math.min(...xValues), Math.max(...xValues)] : [0, 1],\n tickCount(width, true),\n );\n const xTicks = continuous ? linearTicks(xDomain[0], xDomain[1], tickCount(width, true)) : [];\n\n // 边距:放得下刻度文字\n const widest = (labels: readonly string[]) =>\n Math.max(0, ...labels.map((label) => estimateTextWidth(label, TICK_FONT)));\n const categoryLabels = rows.map((row) => categoryText(row));\n const padding = { left: 0, right: 0, top: 0, bottom: 0, ...kind.padding };\n const bottomLabels = horizontal\n ? valueLabels\n : continuous\n ? xTicks.map(continuous.format)\n : categoryLabels;\n const margin = horizontal\n ? {\n left: Math.min(widest(categoryLabels), width * 0.3) + TICK_GAP,\n right: Math.max(8, widest(valueLabels.slice(-1)) / 2),\n top: 4,\n bottom: TICK_FONT + TICK_GAP + 2,\n }\n : {\n left: widest(valueLabels) + TICK_GAP,\n right: aligned ? widest(secondaryLabels) + TICK_GAP : 8,\n top: 8,\n bottom: TICK_FONT + TICK_GAP + 2 + (continuous?.title ? TICK_FONT + 8 : 0),\n };\n // 横轴两端的文字居中在端点上:别伸出绘图区外\n if (!horizontal && bottomLabels.length && !kind.band) {\n margin.left = Math.max(margin.left, widest(bottomLabels.slice(0, 1)) / 2 - padding.left);\n margin.right = Math.max(margin.right, widest(bottomLabels.slice(-1)) / 2 - padding.right);\n }\n const plot: PlotRect = {\n left: margin.left,\n top: margin.top,\n width: Math.max(0, width - margin.left - margin.right),\n height: Math.max(0, plotHeight - margin.top - margin.bottom),\n };\n\n // 类目轴:带(柱)每个类目一格;点(折线)首尾贴边;散点图是连续的数值\n const [cStart, cEnd] = horizontal\n ? [plot.top + padding.top, plot.top + plot.height - padding.bottom]\n : [plot.left + padding.left, plot.left + plot.width - padding.right];\n const count = rows.length;\n const step = kind.band\n ? (cEnd - cStart) / Math.max(count, 1)\n : count > 1\n ? (cEnd - cStart) / (count - 1)\n : cEnd - cStart;\n const xScale = linearScale(xDomain, [cStart, cEnd]);\n const category = continuous\n ? (row: T) => xScale(continuous.value(row) ?? Number.NaN)\n : (_row: T, position: number) =>\n kind.band\n ? cStart + step * (position + 0.5)\n : count > 1\n ? cStart + step * position\n : (cStart + cEnd) / 2;\n const valueScale = horizontal\n ? linearScale(domain, [plot.left + padding.left, plot.left + plot.width - padding.right])\n : linearScale(domain, [plot.top + plot.height - padding.bottom, plot.top + padding.top]);\n\n const valueOf = (item: ResolvedSeries<T>, row: T) => {\n const value = seriesNumber(row, item.key);\n if (value === undefined) return undefined;\n if (kind.percent) {\n const total = rowTotal(row);\n return total === 0 ? undefined : value / total;\n }\n return aligned && onSecondary(item.key) ? aligned.toPrimary(value) : value;\n };\n const stacked = kind.stacked ? shown.filter(kind.stackSeries ?? (() => true)) : [];\n const segments = stackValues(stacked.map((item) => rows.map((row) => valueOf(item, row))));\n const stacks = new Map(stacked.map((item, s) => [item.key, segments[s]!]));\n\n // 类目刻度:放不下时隔几个写一个(横着排时按文字宽度,竖着排时按行高)\n const every = continuous\n ? 1\n : Math.max(\n 1,\n Math.ceil(\n (horizontal ? TICK_FONT + 4 : widest(categoryLabels) + 12) / Math.max(step, 1),\n ),\n );\n const categoryTicks: AxisTick[] = continuous\n ? xTicks.map((tick) => ({ position: xScale(tick), label: continuous.format(tick) }))\n : rows.map((row, position) => ({\n position: category(row, position),\n label:\n position % every === 0\n ? horizontal\n ? truncateText(categoryLabels[position]!, width * 0.3, TICK_FONT)\n : categoryLabels[position]!\n : '',\n }));\n const valueTicks: AxisTick[] = ticks.map((tick, position) => ({\n position: valueScale(tick),\n label: valueLabels[position]!,\n }));\n const secondaryTicks: AxisTick[] = aligned\n ? aligned.primary.ticks.map((tick, position) => ({\n position: valueScale(tick),\n label: secondaryLabels[position]!,\n }))\n : [];\n return {\n rows,\n shown,\n horizontal,\n plot,\n step,\n domain,\n category,\n valueScale,\n valueOf,\n stacks,\n categoryTicks,\n valueTicks,\n secondaryTicks,\n };\n });\n\n /** 一个类目在类目轴上的位置(标注、区间用):散点图是横轴的数值,其余是第几行;找不到时 undefined */\n function positionOf(at: unknown): number | undefined {\n const { rows, category } = layout;\n if (kind.continuousX) {\n const row = rows.find((item) => kind.continuousX!.value(item) === Number(at));\n return row ? category(row, 0) : undefined;\n }\n const found = rows.findIndex((row) => row[index] === at);\n return found < 0 ? undefined : category(rows[found]!, found);\n }\n\n /** 指针移动:找出悬停的行(散点图是最近的点) */\n function onPointermove(event: PointerEvent) {\n const svg = event.currentTarget as SVGSVGElement;\n const { x, y } = pointerIn(event, svg);\n const { rows, plot, horizontal, category, valueScale, valueOf, shown, step } = layout;\n const inside =\n x >= plot.left - 4 &&\n x <= plot.left + plot.width + 4 &&\n y >= plot.top - 4 &&\n y <= plot.top + plot.height + 4;\n if (!inside || rows.length === 0) {\n hover = null;\n return;\n }\n if (kind.pointTooltip) {\n let best: Hover | null = null;\n let distance = POINT_REACH;\n rows.forEach((row, position) => {\n for (const item of shown) {\n const value = valueOf(item, row);\n if (value === undefined) continue;\n const [px, py] = [category(row, position), valueScale(value)];\n const d = Math.hypot(px - x, py - y);\n if (d < distance) {\n distance = d;\n best = { index: position, x: px, y: py };\n }\n }\n });\n hover = best;\n return;\n }\n const along = horizontal ? y : x;\n let nearest = 0;\n rows.forEach((row, position) => {\n if (\n Math.abs(category(row, position) - along) <\n Math.abs(category(rows[nearest]!, nearest) - along)\n )\n nearest = position;\n });\n const center = category(rows[nearest]!, nearest);\n if (Math.abs(center - along) > Math.max(step, 8)) {\n hover = null;\n return;\n }\n hover = horizontal ? { index: nearest, x, y: center } : { index: nearest, x: center, y };\n }\n\n /** 点击下钻:点在柱上按那根柱(data-index),其余按悬停的行 */\n function onClick(event: MouseEvent) {\n if (!onItemClick) return;\n const target = (event.target as Element | null)?.closest?.('[data-index]');\n const position = target ? Number(target.getAttribute('data-index')) : hover?.index;\n if (position === undefined || Number.isNaN(position)) return;\n const offset = range()?.[0] ?? 0;\n const row = layout.rows[position];\n if (row !== undefined) onItemClick(row, offset + position);\n }\n\n /** 区间:浅色的带,文字在左下角(类目轴)或左上角(数值轴) */\n function renderBands() {\n const { plot, horizontal, step, valueScale } = layout;\n return (bands ?? []).map((band, position) => {\n const onIndex = band.axis !== 'value';\n const color = resolveColor(band.color ?? 'neutral', 0);\n let from: number | undefined;\n let to: number | undefined;\n if (onIndex) {\n const a = positionOf(band.from);\n const b = positionOf(band.to);\n if (a === undefined || b === undefined) return null;\n // 类目轴上的区间盖住两端的类目:往外各扩半格\n const half = kind.continuousX ? 0 : step / 2;\n from = Math.min(a, b) - half;\n to = Math.max(a, b) + half;\n } else {\n from = Math.min(valueScale(Number(band.from)), valueScale(Number(band.to)));\n to = Math.max(valueScale(Number(band.from)), valueScale(Number(band.to)));\n }\n const alongCategory = onIndex !== horizontal;\n const clampedFrom = Math.max(from, alongCategory ? plot.left : plot.top);\n const clampedTo = Math.min(\n to,\n alongCategory ? plot.left + plot.width : plot.top + plot.height,\n );\n const rect = alongCategory\n ? { x: clampedFrom, y: plot.top, width: clampedTo - clampedFrom, height: plot.height }\n : { x: plot.left, y: clampedFrom, width: plot.width, height: clampedTo - clampedFrom };\n if (rect.width <= 0 || rect.height <= 0) return null;\n return (\n <g key={`band-${position}`} data-part=\"band\">\n <rect\n {...rect}\n {...css.attrs(xyChartStyles.bandFill(color), chartSvgStyles.noPointer)}\n />\n {band.label && (\n <text\n x={rect.x + 6}\n y={onIndex && !horizontal ? rect.y + rect.height - 6 : rect.y + 6}\n dominant-baseline={onIndex && !horizontal ? 'auto' : 'hanging'}\n {...css.attrs(chartSvgStyles.labelMuted, chartSvgStyles.noPointer)}\n >\n {band.label}\n </text>\n )}\n </g>\n );\n });\n }\n\n /** 目标线与事件竖线 */\n function renderLines() {\n const { plot, horizontal, valueScale } = layout;\n const right = plot.left + plot.width;\n const bottom = plot.top + plot.height;\n const targetLines = (targets ?? []).map((target, position) => {\n const color = resolveColor(target.color ?? 'danger', 0);\n const at = svgNumber(valueScale(toNumber(target.value)));\n const label = target.label\n ? `${target.label} ${valueText(target.value)}`\n : valueText(target.value);\n return (\n <g key={`target-${position}`} data-part=\"target\">\n {horizontal ? (\n <line\n x1={at}\n x2={at}\n y1={plot.top}\n y2={bottom}\n {...css.attrs(xyChartStyles.targetLine, chartSvgStyles.stroke(color))}\n />\n ) : (\n <line\n x1={plot.left}\n x2={right}\n y1={at}\n y2={at}\n {...css.attrs(xyChartStyles.targetLine, chartSvgStyles.stroke(color))}\n />\n )}\n <text\n x={horizontal ? at + 4 : plot.left + 4}\n y={horizontal ? plot.top + 4 : at - 5}\n dominant-baseline={horizontal ? 'hanging' : 'auto'}\n {...css.attrs(\n chartSvgStyles.labelMuted,\n chartSvgStyles.halo,\n xyChartStyles.textFill(color),\n chartSvgStyles.noPointer,\n )}\n >\n {label}\n </text>\n </g>\n );\n });\n const events = (annotations ?? [])\n .filter((item) => item.series === undefined)\n .map((item, position) => {\n const at = positionOf(item.at);\n if (at === undefined) return null;\n const color = resolveColor(item.color ?? 'neutral', 0);\n const p = svgNumber(at);\n return (\n <g key={`event-${position}`} data-part=\"event\">\n {horizontal ? (\n <line\n x1={plot.left}\n x2={right}\n y1={p}\n y2={p}\n {...css.attrs(xyChartStyles.eventLine, chartSvgStyles.stroke(color))}\n />\n ) : (\n <line\n x1={p}\n x2={p}\n y1={plot.top}\n y2={bottom}\n {...css.attrs(xyChartStyles.eventLine, chartSvgStyles.stroke(color))}\n />\n )}\n <text\n x={horizontal ? right - 4 : p + 4}\n y={horizontal ? p - 4 : plot.top + 4}\n text-anchor={horizontal ? 'end' : 'start'}\n dominant-baseline={horizontal ? 'auto' : 'hanging'}\n {...css.attrs(\n chartSvgStyles.labelMuted,\n chartSvgStyles.halo,\n chartSvgStyles.noPointer,\n )}\n >\n {item.label}\n </text>\n </g>\n );\n });\n return [...targetLines, ...events];\n }\n\n /** 一个系列在一行上的值的坐标:堆叠时是它在这一摞里的外端 */\n function valuePosition(item: ResolvedSeries<T>, row: T, position: number): number | undefined {\n const segment = layout.stacks.get(item.key)?.[position];\n if (segment)\n return segment.value === undefined\n ? undefined\n : segment.value < 0\n ? segment.low\n : segment.high;\n return layout.valueOf(item, row);\n }\n\n /** 标注圈出的值:空心圈,文字在上方 */\n function renderMarks() {\n if (layout.horizontal) return null;\n return (annotations ?? [])\n .filter((item) => item.series !== undefined)\n .map((item, position) => {\n const series = layout.shown.find((entry) => entry.key === item.series);\n const rowIndex = kind.continuousX\n ? layout.rows.findIndex((row) => kind.continuousX!.value(row) === Number(item.at))\n : layout.rows.findIndex((row) => row[index] === item.at);\n const row = layout.rows[rowIndex];\n if (!series || row === undefined) return null;\n const value = valuePosition(series, row, rowIndex);\n if (value === undefined) return null;\n const [x, y] = [\n svgNumber(layout.category(row, rowIndex)),\n svgNumber(layout.valueScale(value)),\n ];\n const color = item.color ? resolveColor(item.color, 0) : series.color;\n // 文字居中在圈的上方;靠近绘图区两端时改成对齐圈的外沿,不伸出去\n const half = estimateTextWidth(item.label, TICK_FONT) / 2;\n const { left, width } = layout.plot;\n const anchor = x + half > left + width ? 'end' : x - half < left ? 'start' : 'middle';\n const textX = anchor === 'end' ? x + 8 : anchor === 'start' ? x - 8 : x;\n return (\n <g key={`mark-${position}`} data-part=\"mark\">\n <circle\n cx={x}\n cy={y}\n r={8}\n {...css.attrs(xyChartStyles.mark, chartSvgStyles.stroke(color))}\n />\n <text\n x={textX}\n y={y - 14}\n text-anchor={anchor}\n {...css.attrs(chartSvgStyles.label, chartSvgStyles.halo, chartSvgStyles.noPointer)}\n >\n {item.label}\n </text>\n </g>\n );\n });\n }\n\n /** 十字线:悬停的类目一条竖线,线上给各系列画圆点;柱状图铺一层浅底 */\n function renderCrosshair(front: boolean) {\n const current = hover;\n if (!current || kind.pointTooltip) return null;\n const { rows, plot, horizontal, step, category, valueScale } = layout;\n const row = rows[current.index];\n if (row === undefined) return null;\n const center = category(row, current.index);\n if (!front) {\n if (kind.crosshairDots && !kind.band) return null;\n const half = Math.max(step / 2, 1);\n return horizontal ? (\n <rect\n x={plot.left}\n y={center - half}\n width={plot.width}\n height={half * 2}\n {...css.attrs(chartSvgStyles.hoverBand)}\n />\n ) : (\n <rect\n x={center - half}\n y={plot.top}\n width={half * 2}\n height={plot.height}\n {...css.attrs(chartSvgStyles.hoverBand)}\n />\n );\n }\n if (!kind.crosshairDots) return null;\n const dotted = kind.crosshairSeries\n ? layout.shown.filter(kind.crosshairSeries)\n : layout.shown;\n const p = Math.round(center) + 0.5;\n return (\n <g data-part=\"crosshair\">\n {!kind.band && (\n <line\n x1={p}\n x2={p}\n y1={plot.top}\n y2={plot.top + plot.height}\n {...css.attrs(chartSvgStyles.crosshair)}\n />\n )}\n {dotted.map((item) => {\n const value = valuePosition(item, row, current.index);\n if (value === undefined) return null;\n return (\n <circle\n key={item.key}\n cx={svgNumber(center)}\n cy={svgNumber(valueScale(value))}\n r={4.5}\n {...css.attrs(xyChartStyles.crosshairDot, chartSvgStyles.fill(item.color))}\n />\n );\n })}\n </g>\n );\n }\n\n /** 绘图区的 SVG */\n function renderPlot() {\n const { rows, shown, horizontal, plot, step, domain, category, valueScale, valueOf, stacks } =\n layout;\n const context: XYChartContext<T> = {\n series: shown,\n rows,\n horizontal,\n plot,\n step,\n domain,\n category,\n value: valueScale,\n valueOf,\n stacks,\n point: (c, v) => (horizontal ? [v, c] : [c, v]),\n hovered: hover?.index ?? null,\n };\n const zero = valueScale(0);\n const showZero = domain[0] < 0 && domain[1] > 0;\n return (\n <svg\n width={area.width}\n height={area.height}\n {...css.attrs(chartSvgStyles.svg, xyChartStyles.svg)}\n onPointermove={onPointermove}\n onPointerleave={() => (hover = null)}\n onClick={onClick}\n >\n {renderBands()}\n {chartAxis({\n side: horizontal ? 'bottom' : 'left',\n ticks: layout.valueTicks,\n plot,\n grid,\n })}\n {chartAxis({\n side: horizontal ? 'left' : 'bottom',\n ticks: layout.categoryTicks,\n plot,\n grid: kind.continuousX ? grid : false,\n })}\n {layout.secondaryTicks.length > 0 &&\n chartAxis({ side: 'right', ticks: layout.secondaryTicks, plot })}\n {kind.continuousX?.title && (\n <text\n x={plot.left + plot.width / 2}\n y={area.height - 2}\n text-anchor=\"middle\"\n {...css.attrs(chartSvgStyles.axisTitle)}\n >\n {kind.continuousX.title}\n </text>\n )}\n {showZero &&\n (horizontal ? (\n <line\n x1={Math.round(zero) + 0.5}\n x2={Math.round(zero) + 0.5}\n y1={plot.top}\n y2={plot.top + plot.height}\n {...css.attrs(chartSvgStyles.baseline)}\n />\n ) : (\n <line\n x1={plot.left}\n x2={plot.left + plot.width}\n y1={Math.round(zero) + 0.5}\n y2={Math.round(zero) + 0.5}\n {...css.attrs(chartSvgStyles.baseline)}\n />\n ))}\n {renderCrosshair(false)}\n {kind.render(context)}\n {renderLines()}\n {renderMarks()}\n {renderCrosshair(true)}\n </svg>\n );\n }\n\n const tip = (): ChartTip | null => {\n const current = hover;\n if (!tooltip || !current) return null;\n const row = layout.rows[current.index];\n return row === undefined\n ? null\n : { x: current.x, y: current.y, content: tooltipContent(row) };\n };\n\n return () => (\n <ChartFrame\n {...rest}\n // 百分比堆叠时数值轴是占比:轴上方不写单位(提示框、数据表里仍带)\n unit={kind.percent ? undefined : unit}\n unitEnd={kind.secondary?.unit}\n height={height}\n legend={(legend ?? resolved.length > 1) ? resolved : []}\n hiddenKeys={hiddenSeries}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={chartSkeleton(kind)}\n isEmpty={data.length === 0}\n empty={empty}\n clickable={onItemClick != null}\n table={\n kind.table?.(data) ?? {\n columns: [\n lang.chartCategory,\n ...(kind.continuousX ? [kind.continuousX.label] : []),\n ...resolved.map((item) => {\n const itemUnit = onSecondary(item.key) ? kind.secondary?.unit : unit;\n return itemUnit ? `${item.label}(${itemUnit})` : item.label;\n }),\n ],\n rows: data.map((row) => ({\n header: categoryText(row),\n cells: [\n ...(kind.continuousX ? [xText(row)] : []),\n ...resolved.map((item) => {\n const value = seriesValue(row, item.key);\n return value === undefined\n ? lang.emptyValue\n : format.number(\n value,\n onSecondary(item.key) ? kind.secondary?.format : valueFormat,\n );\n }),\n ],\n })),\n }\n }\n plotRef={area.ref}\n plot={\n area.ready && shownRows.length > 0\n ? [renderPlot(), <ChartTooltipBox key=\"tooltip\" tip={tip()} width={area.width} />]\n : null\n }\n footer={zoom && !kind.continuousX && data.length > 2 ? zoomBar() : undefined}\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
@@ -18,6 +18,6 @@ export interface AlignedAxes {
|
|
|
18
18
|
export declare function niceStep(raw: number): number;
|
|
19
19
|
/**
|
|
20
20
|
* 两组值的对齐刻度:primary、secondary 是两条轴要包含的值(含 0 时从 0 起)。
|
|
21
|
-
* 主轴约 count
|
|
21
|
+
* 主轴约 count 格(范围扩到刻度上),第二轴取同样多的格
|
|
22
22
|
*/
|
|
23
23
|
export declare function alignedTicks(primary: readonly number[], secondary: readonly number[], count?: number): AlignedAxes;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { linearTicks, niceDomain } from "./scale.js";
|
|
2
2
|
//#region src/charts/axis-ticks.ts
|
|
3
3
|
/**
|
|
4
4
|
* 双数值轴的刻度对齐(组合图):主轴按数据取“好看”的刻度,第二数值轴取同样多的格、每格也是好看的步长,
|
|
@@ -20,14 +20,13 @@ function niceStep(raw) {
|
|
|
20
20
|
var tidy = (value) => Number(value.toPrecision(12));
|
|
21
21
|
/**
|
|
22
22
|
* 两组值的对齐刻度:primary、secondary 是两条轴要包含的值(含 0 时从 0 起)。
|
|
23
|
-
* 主轴约 count
|
|
23
|
+
* 主轴约 count 格(范围扩到刻度上),第二轴取同样多的格
|
|
24
24
|
*/
|
|
25
25
|
function alignedTicks(primary, secondary, count = 5) {
|
|
26
26
|
const finite = (values) => values.filter(Number.isFinite);
|
|
27
27
|
const p = finite(primary);
|
|
28
|
-
const
|
|
29
|
-
const ticks =
|
|
30
|
-
const [p0, p1] = scale.domain();
|
|
28
|
+
const [p0, p1] = niceDomain([Math.min(...p, 0), Math.max(...p, 0) || 1], count);
|
|
29
|
+
const ticks = linearTicks(p0, p1, count).map(tidy);
|
|
31
30
|
const intervals = Math.max(ticks.length - 1, 1);
|
|
32
31
|
const s = finite(secondary);
|
|
33
32
|
const low = Math.min(...s, 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"axis-ticks.js","names":[],"sources":["../../src/charts/axis-ticks.ts"],"sourcesContent":["/**\n * 双数值轴的刻度对齐(组合图):主轴按数据取“好看”的刻度,第二数值轴取同样多的格、每格也是好看的步长,\n * 两边的刻度落在同一组网格线上(同 ECharts 的 alignTicks)。第二轴上的值换算到主轴的坐标里画。\n *\n * const axes = alignedTicks([0, 1280, 960], [0.12, 0.35]);\n * axes.primary.ticks // [0, 200, 400, …, 1400]\n * axes.secondary.ticks // [0, 0.05, 0.1, …, 0.35]\n * axes.toPrimary(0.2) // 第二轴的 0.2 在主轴坐标里的位置\n */\nimport {
|
|
1
|
+
{"version":3,"file":"axis-ticks.js","names":[],"sources":["../../src/charts/axis-ticks.ts"],"sourcesContent":["/**\n * 双数值轴的刻度对齐(组合图):主轴按数据取“好看”的刻度,第二数值轴取同样多的格、每格也是好看的步长,\n * 两边的刻度落在同一组网格线上(同 ECharts 的 alignTicks)。第二轴上的值换算到主轴的坐标里画。\n *\n * const axes = alignedTicks([0, 1280, 960], [0.12, 0.35]);\n * axes.primary.ticks // [0, 200, 400, …, 1400]\n * axes.secondary.ticks // [0, 0.05, 0.1, …, 0.35]\n * axes.toPrimary(0.2) // 第二轴的 0.2 在主轴坐标里的位置\n */\nimport { linearTicks, niceDomain } from './scale';\n\n/** 一条数值轴:范围与刻度 */\nexport interface AxisTicks {\n /** 范围 [最小, 最大],两端都是刻度 */\n domain: [number, number];\n /** 刻度,从小到大 */\n ticks: number[];\n}\n\n/** 对齐的两条数值轴 */\nexport interface AlignedAxes {\n /** 主轴(左侧) */\n primary: AxisTicks;\n /** 第二数值轴(右侧):刻度数与主轴相同 */\n secondary: AxisTicks;\n /** 第二轴的值换算到主轴的坐标 */\n toPrimary: (value: number) => number;\n}\n\n/** 不小于 raw 的“好看”步长:1、2、2.5、5 乘 10 的整数次幂 */\nexport function niceStep(raw: number): number {\n if (!(raw > 0)) return 1;\n const power = 10 ** Math.floor(Math.log10(raw));\n const fraction = raw / power;\n const nice =\n fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;\n return nice * power;\n}\n\n/** 浮点误差:0.1 + 0.2 这类算出来的刻度取到 12 位有效数字 */\nconst tidy = (value: number) => Number(value.toPrecision(12));\n\n/**\n * 两组值的对齐刻度:primary、secondary 是两条轴要包含的值(含 0 时从 0 起)。\n * 主轴约 count 格(范围扩到刻度上),第二轴取同样多的格\n */\nexport function alignedTicks(\n primary: readonly number[],\n secondary: readonly number[],\n count = 5,\n): AlignedAxes {\n const finite = (values: readonly number[]) => values.filter(Number.isFinite);\n const p = finite(primary);\n const [p0, p1] = niceDomain([Math.min(...p, 0), Math.max(...p, 0) || 1], count);\n const ticks = linearTicks(p0, p1, count).map(tidy);\n const intervals = Math.max(ticks.length - 1, 1);\n\n const s = finite(secondary);\n const low = Math.min(...s, 0);\n const high = Math.max(...s, 0) || 1;\n let step = niceStep((high - low) / intervals);\n let start = Math.floor(low / step) * step;\n // 起点向下取整后可能盖不住最大值:换下一档步长\n for (let guard = 0; start + intervals * step < high && guard < 10; guard += 1) {\n step = niceStep(step * 1.01);\n start = Math.floor(low / step) * step;\n }\n const secondaryTicks = Array.from({ length: intervals + 1 }, (_, i) => tidy(start + i * step));\n const s0 = secondaryTicks[0]!;\n const s1 = secondaryTicks.at(-1)!;\n return {\n primary: { domain: [p0, p1], ticks },\n secondary: { domain: [s0, s1], ticks: secondaryTicks },\n toPrimary: (value) => p0 + ((value - s0) / (s1 - s0)) * (p1 - p0),\n };\n}\n"],"mappings":";;;;;;;;;;;;AA8BA,SAAgB,SAAS,KAAqB;CAC5C,IAAI,EAAE,MAAM,IAAI,OAAO;CACvB,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAC;CAC9C,MAAM,WAAW,MAAM;CAGvB,QADE,YAAY,IAAI,IAAI,YAAY,IAAI,IAAI,YAAY,MAAM,MAAM,YAAY,IAAI,IAAI,MACxE;AAChB;;AAGA,IAAM,QAAQ,UAAkB,OAAO,MAAM,YAAY,EAAE,CAAC;;;;;AAM5D,SAAgB,aACd,SACA,WACA,QAAQ,GACK;CACb,MAAM,UAAU,WAA8B,OAAO,OAAO,OAAO,QAAQ;CAC3E,MAAM,IAAI,OAAO,OAAO;CACxB,MAAM,CAAC,IAAI,MAAM,WAAW,CAAC,KAAK,IAAI,GAAG,GAAG,CAAC,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK;CAC9E,MAAM,QAAQ,YAAY,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI;CACjD,MAAM,YAAY,KAAK,IAAI,MAAM,SAAS,GAAG,CAAC;CAE9C,MAAM,IAAI,OAAO,SAAS;CAC1B,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;CAC5B,MAAM,OAAO,KAAK,IAAI,GAAG,GAAG,CAAC,KAAK;CAClC,IAAI,OAAO,UAAU,OAAO,OAAO,SAAS;CAC5C,IAAI,QAAQ,KAAK,MAAM,MAAM,IAAI,IAAI;CAErC,KAAK,IAAI,QAAQ,GAAG,QAAQ,YAAY,OAAO,QAAQ,QAAQ,IAAI,SAAS,GAAG;EAC7E,OAAO,SAAS,OAAO,IAAI;EAC3B,QAAQ,KAAK,MAAM,MAAM,IAAI,IAAI;CACnC;CACA,MAAM,iBAAiB,MAAM,KAAK,EAAE,QAAQ,YAAY,EAAE,IAAI,GAAG,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC;CAC7F,MAAM,KAAK,eAAe;CAC1B,MAAM,KAAK,eAAe,GAAG,EAAE;CAC/B,OAAO;EACL,SAAS;GAAE,QAAQ,CAAC,IAAI,EAAE;GAAG;EAAM;EACnC,WAAW;GAAE,QAAQ,CAAC,IAAI,EAAE;GAAG,OAAO;EAAe;EACrD,YAAY,UAAU,MAAO,QAAQ,OAAO,KAAK,OAAQ,KAAK;CAChE;AACF"}
|
package/dist/charts/flow.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* 流向图(桑基图、弦图)共用的数据:节点与节点之间的流向。节点的颜色按顺序取图表色板;
|
|
3
|
+
* 布局只接受正的流量,值不是正数、指向不存在节点的流向在布局前去掉。
|
|
4
4
|
*/
|
|
5
5
|
import { type NumericValue } from '../utils/data/numeric';
|
|
6
6
|
import { type ChartColor } from './series';
|
|
@@ -31,16 +31,9 @@ export interface ResolvedFlowNode extends FlowNode {
|
|
|
31
31
|
}
|
|
32
32
|
/** 节点的颜色与名字定下来;按 id 查 */
|
|
33
33
|
export declare function resolveFlowNodes(nodes: readonly FlowNode[]): Map<string, ResolvedFlowNode>;
|
|
34
|
-
/**
|
|
34
|
+
/** 布局用的数据:节点按原来的顺序;值不是正数、指向不存在的节点的流向去掉,流量转成 number(amount) */
|
|
35
35
|
export declare function flowData(nodes: ReadonlyMap<string, ResolvedFlowNode>, links: readonly FlowLink[]): {
|
|
36
|
-
nodes:
|
|
37
|
-
/** 节点的 id:流向里用它指节点 */
|
|
38
|
-
id: string;
|
|
39
|
-
/** 显示的名字:没写 label 时是 id */
|
|
40
|
-
label: string;
|
|
41
|
-
/** 实际的颜色:没写 color 时按顺序取的图表色板 */
|
|
42
|
-
color: string;
|
|
43
|
-
}[];
|
|
36
|
+
nodes: ResolvedFlowNode[];
|
|
44
37
|
links: {
|
|
45
38
|
/** 起点节点的 id */
|
|
46
39
|
source: string;
|
package/dist/charts/flow.js
CHANGED
|
@@ -2,8 +2,8 @@ import { toNumber } from "../utils/data/numeric.js";
|
|
|
2
2
|
import { resolveColor } from "./series.js";
|
|
3
3
|
//#region src/charts/flow.ts
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 流向图(桑基图、弦图)共用的数据:节点与节点之间的流向。节点的颜色按顺序取图表色板;
|
|
6
|
+
* 布局只接受正的流量,值不是正数、指向不存在节点的流向在布局前去掉。
|
|
7
7
|
*/
|
|
8
8
|
/** 节点的颜色与名字定下来;按 id 查 */
|
|
9
9
|
function resolveFlowNodes(nodes) {
|
|
@@ -13,10 +13,10 @@ function resolveFlowNodes(nodes) {
|
|
|
13
13
|
color: resolveColor(node.color, index)
|
|
14
14
|
}]));
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
16
|
+
/** 布局用的数据:节点按原来的顺序;值不是正数、指向不存在的节点的流向去掉,流量转成 number(amount) */
|
|
17
17
|
function flowData(nodes, links) {
|
|
18
18
|
return {
|
|
19
|
-
nodes: [...nodes.values()]
|
|
19
|
+
nodes: [...nodes.values()],
|
|
20
20
|
links: links.filter((link) => nodes.has(link.source) && nodes.has(link.target) && toNumber(link.value) > 0).map((link) => ({
|
|
21
21
|
...link,
|
|
22
22
|
amount: toNumber(link.value)
|
package/dist/charts/flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","names":[],"sources":["../../src/charts/flow.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"file":"flow.js","names":[],"sources":["../../src/charts/flow.ts"],"sourcesContent":["/**\n * 流向图(桑基图、弦图)共用的数据:节点与节点之间的流向。节点的颜色按顺序取图表色板;\n * 布局只接受正的流量,值不是正数、指向不存在节点的流向在布局前去掉。\n */\nimport { toNumber, type NumericValue } from '../utils/data/numeric';\nimport { resolveColor, type ChartColor } from './series';\n\n/** 一个节点 */\nexport interface FlowNode {\n /** 节点的 id:流向里用它指节点 */\n id: string;\n /** 显示的名字;不写时用 id */\n label?: string;\n /** 颜色;不写时按顺序取图表色板 */\n color?: ChartColor;\n}\n\n/** 一条流向:从 source 到 target 的量 */\nexport interface FlowLink {\n /** 起点节点的 id */\n source: string;\n /** 终点节点的 id */\n target: string;\n /** 流量:number、bigint 或 Decimal,要大于 0 */\n value: NumericValue;\n}\n\n/** 节点加上实际的颜色与名字 */\nexport interface ResolvedFlowNode extends FlowNode {\n /** 显示的名字:没写 label 时是 id */\n label: string;\n /** 实际的颜色:没写 color 时按顺序取的图表色板 */\n color: string;\n}\n\n/** 节点的颜色与名字定下来;按 id 查 */\nexport function resolveFlowNodes(nodes: readonly FlowNode[]): Map<string, ResolvedFlowNode> {\n return new Map(\n nodes.map((node, index) => [\n node.id,\n { ...node, label: node.label ?? node.id, color: resolveColor(node.color, index) },\n ]),\n );\n}\n\n/** 布局用的数据:节点按原来的顺序;值不是正数、指向不存在的节点的流向去掉,流量转成 number(amount) */\nexport function flowData(nodes: ReadonlyMap<string, ResolvedFlowNode>, links: readonly FlowLink[]) {\n return {\n nodes: [...nodes.values()],\n links: links\n .filter(\n (link) => nodes.has(link.source) && nodes.has(link.target) && toNumber(link.value) > 0,\n )\n .map((link) => ({ ...link, amount: toNumber(link.value) })),\n };\n}\n"],"mappings":";;;;;;;;AAoCA,SAAgB,iBAAiB,OAA2D;CAC1F,OAAO,IAAI,IACT,MAAM,KAAK,MAAM,UAAU,CACzB,KAAK,IACL;EAAE,GAAG;EAAM,OAAO,KAAK,SAAS,KAAK;EAAI,OAAO,aAAa,KAAK,OAAO,KAAK;CAAE,CAClF,CAAC,CACH;AACF;;AAGA,SAAgB,SAAS,OAA8C,OAA4B;CACjG,OAAO;EACL,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;EACzB,OAAO,MACJ,QACE,SAAS,MAAM,IAAI,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,SAAS,KAAK,KAAK,IAAI,CACvF,CAAC,CACA,KAAK,UAAU;GAAE,GAAG;GAAM,QAAQ,SAAS,KAAK,KAAK;EAAE,EAAE;CAC9D;AACF"}
|
package/dist/charts/frame.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';
|
|
2
|
-
import {
|
|
2
|
+
import type { VNodeChild } from 'vue';
|
|
3
3
|
import { type ButtonBaseProps } from '../base/ButtonBase';
|
|
4
4
|
import { type NumericFormat } from '../config/lang/format';
|
|
5
5
|
import type { NumericValue } from '../utils/data/numeric';
|
|
@@ -37,12 +37,12 @@ export interface ChartFrameParts {
|
|
|
37
37
|
propsLegend?: PartProps<'div', 'role'>;
|
|
38
38
|
/** 图例每一项(按钮)的部件属性 */
|
|
39
39
|
propsLegendItem?: Omit<Partial<ButtonBaseProps>, 'aria-pressed' | 'onClick'>;
|
|
40
|
-
/** 绘图区(
|
|
40
|
+
/** 绘图区(SVG 画在这里)的部件属性 */
|
|
41
41
|
propsPlot?: PartProps<'div', 'aria-hidden'>;
|
|
42
42
|
/** 给读屏的数据表的部件属性 */
|
|
43
43
|
propsTable?: PartProps<'table'>;
|
|
44
44
|
}
|
|
45
|
-
/** 图表共用的样式:root
|
|
45
|
+
/** 图表共用的样式:root、header、unit、legend、swatch、plot、tooltip… */
|
|
46
46
|
export declare const chartStyles: Readonly<{
|
|
47
47
|
readonly root: css.CompiledStyles;
|
|
48
48
|
readonly header: css.CompiledStyles;
|
|
@@ -72,7 +72,7 @@ export interface ChartTooltipItem {
|
|
|
72
72
|
/** 格式化好的数值 */
|
|
73
73
|
value: string;
|
|
74
74
|
}
|
|
75
|
-
/** 提示框的内容:标题(类目、扇区名)+
|
|
75
|
+
/** 提示框的内容:标题(类目、扇区名)+ 每个系列一行;放进 ChartTooltipBox 跟着指针显示 */
|
|
76
76
|
export declare function chartTooltip(title: string, items: readonly ChartTooltipItem[]): import("@zerodep-dev/vue-tsx-pro-tsx/jsx-runtime").JSX.Element;
|
|
77
77
|
/**
|
|
78
78
|
* 图表里数值的文字(提示框、读屏数据表、扇区标签):按 valueFormat 格式化、带上单位;
|
|
@@ -82,30 +82,6 @@ export declare function useChartValueText(read: () => {
|
|
|
82
82
|
valueFormat?: NumericFormat;
|
|
83
83
|
unit?: string;
|
|
84
84
|
}): (value: NumericValue | undefined) => string;
|
|
85
|
-
/**
|
|
86
|
-
* 绘图区进入过视口:之前不画,进来之后一直算看见(滚出去不拆掉)。一页很多图表时先画看得见的,
|
|
87
|
-
* 其余的滚到附近再画(地图、网络图绘制很重)。在 setup 里调用,绘制的 effect 里读返回的函数。
|
|
88
|
-
* 挂上时就在视口附近的立即算看见(不等观察器的第一次回调;没有布局的测试环境里框都在原点,也算看见);
|
|
89
|
-
* 打印前全部画上;没有 IntersectionObserver 的环境当作看见了。
|
|
90
|
-
*/
|
|
91
|
-
export declare function usePlotSeen(plot: () => HTMLElement | null | undefined): () => boolean;
|
|
92
|
-
/** 主题的 lg 时长(毫秒),减少动态效果时为 0;读不到(元素不在主题范围内)时不要动画 */
|
|
93
|
-
export declare function chartDuration(element: Element): number;
|
|
94
|
-
/**
|
|
95
|
-
* Unovis 每个容器都插一个 id 固定为 saturate 的滤镜(悬停高亮用),一页多张图时 id 重复;
|
|
96
|
-
* 改成每张图自己的 id,并让引用它的 CSS 变量指过去
|
|
97
|
-
*/
|
|
98
|
-
export declare function uniqueHighlightFilter(element: HTMLElement, id: string): void;
|
|
99
|
-
/**
|
|
100
|
-
* Unovis 实例表:组件、坐标轴、十字线只建一次,之后 setConfig + update(保留实例才有过渡动画)。
|
|
101
|
-
* 容器 destroy 时会连带销毁这些实例:重建容器前 reset,下次取用时重新创建
|
|
102
|
-
*/
|
|
103
|
-
export declare function createChartInstances(): {
|
|
104
|
-
/** 取一个实例:第一次调用时创建 */
|
|
105
|
-
get: <C>(key: string, create: () => C) => C;
|
|
106
|
-
/** 容器销毁了:清空,之后重新创建 */
|
|
107
|
-
reset(): void;
|
|
108
|
-
};
|
|
109
85
|
/** ChartFrame 的属性:未声明的属性落到外层 div(role="figure")上 */
|
|
110
86
|
export interface ChartFrameProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {
|
|
111
87
|
/** 单位:显示在左上方 */
|
|
@@ -130,9 +106,9 @@ export interface ChartFrameProps extends PartProps<'div', 'role' | 'aria-busy'>,
|
|
|
130
106
|
empty?: VNodeChild;
|
|
131
107
|
/** 给读屏的数据表 */
|
|
132
108
|
table: ChartTable;
|
|
133
|
-
/**
|
|
109
|
+
/** 取得绘图区元素(量大小用,见 usePlotArea);加载、空状态之后重新出现时是新的元素 */
|
|
134
110
|
plotRef?: (element: HTMLElement | null) => void;
|
|
135
|
-
/**
|
|
111
|
+
/** 绘图区里的内容(图表画的 SVG、提示框,漏斗图的横条);同样对读屏隐藏 */
|
|
136
112
|
plot?: VNodeChild;
|
|
137
113
|
/** 绘图区下面的内容(缩放的滑块、地图的色带) */
|
|
138
114
|
footer?: VNodeChild;
|