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.
Files changed (48) hide show
  1. package/README.md +57 -33
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +590 -577
  4. package/dist/types/components/WaveformChart.vue.d.ts +1 -0
  5. package/dist/types/components/core/constants.d.ts +2 -0
  6. package/dist/types/components/core/trackLayoutBuilder.d.ts +2 -1
  7. package/dist/types/components/core/useWaveformChartController.d.ts +6 -1
  8. package/dist/types/components/core/useWaveformLayout.d.ts +0 -1
  9. package/dist/types/components/core/useWaveformPresentation.d.ts +5 -0
  10. package/dist/types/components/core/waveformChartTypes.d.ts +3 -2
  11. package/dist/types/components/data/types.d.ts +1 -1
  12. package/dist/types/components/index.d.ts +1 -1
  13. package/dist/types/components/waveform.d.ts +1 -1
  14. package/dist/types/demo/types.d.ts +13 -1
  15. package/dist/types/demo/useDemoXAxisLabelControls.d.ts +32 -0
  16. package/dist/types/index.d.ts +1 -1
  17. package/dist/types/types/chart.d.ts +22 -0
  18. package/dist/types/types/index.d.ts +1 -1
  19. package/dist/types/utils/formatters.d.ts +5 -2
  20. package/dist/types/utils/index.d.ts +1 -1
  21. package/package.json +1 -1
  22. package/src/App.vue +17 -1
  23. package/src/components/WaveformChart.vue +1 -0
  24. package/src/components/WaveformChartView.vue +13 -10
  25. package/src/components/core/constants.ts +3 -0
  26. package/src/components/core/trackLayoutBuilder.ts +22 -4
  27. package/src/components/core/useWaveformLayout.ts +1 -3
  28. package/src/components/core/useWaveformPresentation.ts +17 -2
  29. package/src/components/core/waveformChartTypes.ts +3 -0
  30. package/src/components/data/types.ts +1 -0
  31. package/src/components/index.ts +1 -0
  32. package/src/components/rendering/WaveformTrackAxes.vue +6 -3
  33. package/src/components/waveform.ts +1 -0
  34. package/src/components/waveformChartCases/frameGridAndFormatting.test.ts +70 -3
  35. package/src/components/waveformChartCases/sizingAndTitles.test.ts +59 -0
  36. package/src/demo/DemoChartHost.vue +1 -0
  37. package/src/demo/DemoGridFrameControls.vue +99 -0
  38. package/src/demo/plotMarginControls.test.ts +29 -0
  39. package/src/demo/types.ts +13 -0
  40. package/src/demo/useDemoXAxisLabelControls.ts +77 -0
  41. package/src/demo/xAxisLabelControls.test.ts +86 -0
  42. package/src/index.ts +4 -0
  43. package/src/styles.css +9 -0
  44. package/src/types/chart.ts +29 -0
  45. package/src/types/index.ts +4 -0
  46. package/src/utils/formatters.test.ts +37 -5
  47. package/src/utils/formatters.ts +26 -16
  48. 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 integers in the selected display unit', () => {
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('1')
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')
@@ -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 formatAxisTimeValue(displayTime(value, timeUnit))
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
- void _domain
188
- return formatAxisTimeValue(displayTime(value, timeUnit))
198
+ return formatXAxisLabel(value, _domain ?? [value, value], timeUnit, 'tick')
189
199
  }
190
200
 
191
201
  /**
@@ -11,6 +11,7 @@ export {
11
11
  endpointFractionDigits,
12
12
  formatEndpointTime,
13
13
  formatAxisTime,
14
+ formatXAxisLabel,
14
15
  formatTooltipTime,
15
16
  formatAnnotationTime,
16
17
  formatPlainNumber,