waveform-analysis 0.1.28 → 0.1.30
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/README.md +57 -33
- package/dist/index.cjs +1 -1
- package/dist/index.js +590 -577
- package/dist/types/components/WaveformChart.vue.d.ts +1 -0
- package/dist/types/components/core/constants.d.ts +2 -0
- package/dist/types/components/core/trackLayoutBuilder.d.ts +2 -1
- package/dist/types/components/core/useWaveformChartController.d.ts +6 -1
- package/dist/types/components/core/useWaveformLayout.d.ts +0 -1
- package/dist/types/components/core/useWaveformPresentation.d.ts +5 -0
- package/dist/types/components/core/waveformChartTypes.d.ts +3 -2
- package/dist/types/components/data/types.d.ts +1 -1
- package/dist/types/components/index.d.ts +1 -1
- package/dist/types/components/waveform.d.ts +1 -1
- package/dist/types/demo/types.d.ts +13 -1
- package/dist/types/demo/useDemoXAxisLabelControls.d.ts +32 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/types/chart.d.ts +22 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/utils/formatters.d.ts +5 -2
- package/dist/types/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/App.vue +17 -1
- package/src/components/WaveformChart.vue +1 -0
- package/src/components/WaveformChartView.vue +13 -10
- package/src/components/core/constants.ts +3 -0
- package/src/components/core/trackLayoutBuilder.ts +22 -4
- package/src/components/core/useWaveformLayout.ts +1 -3
- package/src/components/core/useWaveformPresentation.ts +17 -2
- package/src/components/core/waveformChartTypes.ts +3 -0
- package/src/components/data/types.ts +1 -0
- package/src/components/index.ts +1 -0
- package/src/components/rendering/WaveformTrackAxes.vue +6 -3
- package/src/components/waveform.ts +1 -0
- package/src/components/waveformChartCases/frameGridAndFormatting.test.ts +70 -3
- package/src/components/waveformChartCases/sizingAndTitles.test.ts +59 -0
- package/src/demo/DemoChartHost.vue +1 -0
- package/src/demo/DemoGridFrameControls.vue +99 -0
- package/src/demo/plotMarginControls.test.ts +29 -0
- package/src/demo/types.ts +13 -0
- package/src/demo/useDemoXAxisLabelControls.ts +77 -0
- package/src/demo/xAxisLabelControls.test.ts +86 -0
- package/src/index.ts +4 -0
- package/src/styles.css +9 -0
- package/src/types/chart.ts +29 -0
- package/src/types/index.ts +4 -0
- package/src/utils/formatters.test.ts +37 -5
- package/src/utils/formatters.ts +26 -16
- package/src/utils/index.ts +1 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
|
|
3
|
+
import type { WaveformXAxisLabelFormatter, WaveformXAxisLabelFormatterContext } from '../types'
|
|
3
4
|
import {
|
|
4
5
|
formatAnnotationTime,
|
|
5
6
|
formatAxisTime,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
formatScientificAxisLabel,
|
|
10
11
|
formatTooltipNumber,
|
|
11
12
|
formatTooltipTime,
|
|
13
|
+
formatXAxisLabel,
|
|
12
14
|
resolveScientificAxisExponent,
|
|
13
15
|
shouldUseScientificAxisLabel,
|
|
14
16
|
} from './formatters'
|
|
@@ -55,20 +57,50 @@ describe('waveform number formatters', () => {
|
|
|
55
57
|
expect(formatScientificAxisExponent(0, 0)).toBeNull()
|
|
56
58
|
})
|
|
57
59
|
|
|
58
|
-
it('formats X-axis ticks and endpoints as plain
|
|
60
|
+
it('formats X-axis ticks and endpoints as complete plain values in the display unit', () => {
|
|
59
61
|
const domain: [number, number] = [0, 1]
|
|
60
|
-
expect(formatAxisTime(0.5004, 'ms', domain)).toBe('500')
|
|
62
|
+
expect(formatAxisTime(0.5004, 'ms', domain)).toBe('500.4')
|
|
61
63
|
expect(formatEndpointTime(1, domain, 'ms')).toBe('1000')
|
|
62
|
-
expect(formatAxisTime(0.5, 's', domain)).toBe('
|
|
64
|
+
expect(formatAxisTime(0.5, 's', domain)).toBe('0.5')
|
|
63
65
|
expect(formatEndpointTime(1, domain, 's')).toBe('1')
|
|
64
66
|
|
|
65
67
|
const tinyDomain: [number, number] = [0, 0.000001]
|
|
66
|
-
expect(formatEndpointTime(0.000001, tinyDomain, 's')).toBe('0')
|
|
67
|
-
expect(formatAxisTime(-0.000001, 's', tinyDomain)).toBe('0')
|
|
68
|
+
expect(formatEndpointTime(0.000001, tinyDomain, 's')).toBe('0.000001')
|
|
69
|
+
expect(formatAxisTime(-0.000001, 's', tinyDomain)).toBe('-0.000001')
|
|
70
|
+
expect(formatAxisTime(-0, 's')).toBe('0')
|
|
68
71
|
expect(formatAxisTime(1e21, 's')).toBe('1000000000000000000000')
|
|
69
72
|
expect(formatAxisTime(Number.POSITIVE_INFINITY, 's')).toBe('Infinity')
|
|
70
73
|
})
|
|
71
74
|
|
|
75
|
+
it('passes display values and complete source context to X-axis label formatters', () => {
|
|
76
|
+
const domain: [number, number] = [0.125, 1.875]
|
|
77
|
+
const formatter: WaveformXAxisLabelFormatter = (value, context) =>
|
|
78
|
+
`${context.kind}:${value / 10}`
|
|
79
|
+
|
|
80
|
+
expect(formatXAxisLabel(0.5, domain, 'ms', 'tick', formatter)).toBe('tick:50')
|
|
81
|
+
expect(formatXAxisLabel(domain[0], domain, 'ms', 'start', formatter)).toBe('start:12.5')
|
|
82
|
+
expect(formatXAxisLabel(domain[1], domain, 'ms', 'end', formatter)).toBe('end:187.5')
|
|
83
|
+
|
|
84
|
+
let receivedContext: WaveformXAxisLabelFormatterContext | undefined
|
|
85
|
+
formatXAxisLabel(0.5, domain, 'ms', 'tick', (value, context) => {
|
|
86
|
+
receivedContext = context
|
|
87
|
+
return String(value)
|
|
88
|
+
})
|
|
89
|
+
expect(receivedContext).toEqual({
|
|
90
|
+
kind: 'tick',
|
|
91
|
+
rawValue: 0.5,
|
|
92
|
+
timeUnit: 'ms',
|
|
93
|
+
domain: [0.125, 1.875],
|
|
94
|
+
displayDomain: [125, 1875],
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
expect(() =>
|
|
98
|
+
formatXAxisLabel(0.5, domain, 's', 'tick', () => {
|
|
99
|
+
throw new Error('formatter failed')
|
|
100
|
+
}),
|
|
101
|
+
).toThrow('formatter failed')
|
|
102
|
+
})
|
|
103
|
+
|
|
72
104
|
it('formats tooltip and raw values for their display contexts', () => {
|
|
73
105
|
expect(formatTooltipNumber(12345.67891)).toBe('12,345.6789')
|
|
74
106
|
expect(formatTooltipNumber(-0)).toBe('0')
|
package/src/utils/formatters.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { WaveformXAxisLabelFormatter, WaveformXAxisLabelKind } from '../types'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* 时间单位类型
|
|
3
5
|
*/
|
|
@@ -22,10 +24,6 @@ const Y_AXIS_NUMBER_FORMATTER = new Intl.NumberFormat('zh-CN', {
|
|
|
22
24
|
const TOOLTIP_NUMBER_FORMATTER = new Intl.NumberFormat('zh-CN', {
|
|
23
25
|
maximumFractionDigits: 4,
|
|
24
26
|
})
|
|
25
|
-
const X_AXIS_TIME_FORMATTER = new Intl.NumberFormat('zh-CN', {
|
|
26
|
-
maximumFractionDigits: 0,
|
|
27
|
-
useGrouping: false,
|
|
28
|
-
})
|
|
29
27
|
|
|
30
28
|
function formatFixedNumber(value: number, precision: number): string {
|
|
31
29
|
const formatted = value.toFixed(Math.max(0, precision))
|
|
@@ -103,13 +101,6 @@ export function formatTooltipNumber(value: number): string {
|
|
|
103
101
|
return TOOLTIP_NUMBER_FORMATTER.format(value)
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
/** Format an X-axis time value as a plain integer without grouping separators. */
|
|
107
|
-
function formatAxisTimeValue(value: number): string {
|
|
108
|
-
if (!Number.isFinite(value)) return String(value)
|
|
109
|
-
const formatted = X_AXIS_TIME_FORMATTER.format(value)
|
|
110
|
-
return formatted === '-0' ? '0' : formatted
|
|
111
|
-
}
|
|
112
|
-
|
|
113
104
|
/** Convert a number to complete plain decimal text without forcing exponential notation. */
|
|
114
105
|
export function formatPlainNumber(value: number): string {
|
|
115
106
|
if (!Number.isFinite(value)) return String(value)
|
|
@@ -143,6 +134,26 @@ export function displayTime(value: number, timeUnit: TimeUnit): number {
|
|
|
143
134
|
return timeUnit === 'ms' ? value * 1000 : value
|
|
144
135
|
}
|
|
145
136
|
|
|
137
|
+
/** Format an X-axis value without changing its source coordinate. */
|
|
138
|
+
export function formatXAxisLabel(
|
|
139
|
+
rawValue: number,
|
|
140
|
+
domain: [number, number],
|
|
141
|
+
timeUnit: TimeUnit,
|
|
142
|
+
kind: WaveformXAxisLabelKind,
|
|
143
|
+
formatter?: WaveformXAxisLabelFormatter,
|
|
144
|
+
): string {
|
|
145
|
+
const value = displayTime(rawValue, timeUnit)
|
|
146
|
+
if (!formatter) return formatPlainNumber(value)
|
|
147
|
+
|
|
148
|
+
return formatter(value, {
|
|
149
|
+
kind,
|
|
150
|
+
rawValue,
|
|
151
|
+
timeUnit,
|
|
152
|
+
domain: [domain[0], domain[1]],
|
|
153
|
+
displayDomain: [displayTime(domain[0], timeUnit), displayTime(domain[1], timeUnit)],
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
146
157
|
/**
|
|
147
158
|
* 计算端点标签的小数位数
|
|
148
159
|
* @param domain 数据域 [最小值, 最大值]
|
|
@@ -158,7 +169,7 @@ export function endpointFractionDigits(domain: [number, number], timeUnit: TimeU
|
|
|
158
169
|
}
|
|
159
170
|
|
|
160
171
|
/**
|
|
161
|
-
* 将 X
|
|
172
|
+
* 将 X 轴端点时间格式化为当前显示单位下的普通十进制文本
|
|
162
173
|
* @param value 时间值(秒)
|
|
163
174
|
* @param _domain 数据域(为保持现有调用签名而保留)
|
|
164
175
|
* @param timeUnit 时间单位
|
|
@@ -169,11 +180,11 @@ export function formatEndpointTime(
|
|
|
169
180
|
_domain: [number, number],
|
|
170
181
|
timeUnit: TimeUnit,
|
|
171
182
|
): string {
|
|
172
|
-
return
|
|
183
|
+
return formatXAxisLabel(value, _domain, timeUnit, 'end')
|
|
173
184
|
}
|
|
174
185
|
|
|
175
186
|
/**
|
|
176
|
-
* 将 X
|
|
187
|
+
* 将 X 轴时间刻度格式化为当前显示单位下的普通十进制文本
|
|
177
188
|
* @param value 时间值(秒)
|
|
178
189
|
* @param timeUnit 时间单位
|
|
179
190
|
* @param _domain 数据域(为保持现有调用签名而保留)
|
|
@@ -184,8 +195,7 @@ export function formatAxisTime(
|
|
|
184
195
|
timeUnit: TimeUnit,
|
|
185
196
|
_domain?: [number, number],
|
|
186
197
|
): string {
|
|
187
|
-
|
|
188
|
-
return formatAxisTimeValue(displayTime(value, timeUnit))
|
|
198
|
+
return formatXAxisLabel(value, _domain ?? [value, value], timeUnit, 'tick')
|
|
189
199
|
}
|
|
190
200
|
|
|
191
201
|
/**
|