waveform-analysis 0.1.32 → 0.1.36

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 (44) hide show
  1. package/README.md +28 -3
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +426 -411
  4. package/dist/style.css +1 -1
  5. package/dist/types/components/WaveformChart.vue.d.ts +1 -0
  6. package/dist/types/components/core/trackLayoutBuilder.d.ts +2 -1
  7. package/dist/types/components/core/types.d.ts +2 -0
  8. package/dist/types/components/core/useWaveformChartController.d.ts +1 -0
  9. package/dist/types/components/core/waveformChartTypes.d.ts +3 -2
  10. package/dist/types/components/core/xDomain.d.ts +3 -0
  11. package/dist/types/components/data/types.d.ts +1 -1
  12. package/dist/types/components/interaction/WaveformTooltip.vue.d.ts +1 -0
  13. package/dist/types/components/waveform.d.ts +1 -1
  14. package/dist/types/index.d.ts +1 -1
  15. package/dist/types/types/chart.d.ts +10 -0
  16. package/dist/types/types/data.d.ts +3 -0
  17. package/dist/types/types/index.d.ts +1 -1
  18. package/package.json +1 -1
  19. package/src/components/WaveformChart.vue +1 -0
  20. package/src/components/core/trackLayoutBuilder.ts +19 -7
  21. package/src/components/core/types.ts +2 -0
  22. package/src/components/core/useWaveformChartLifecycle.ts +1 -0
  23. package/src/components/core/useWaveformLayout.ts +19 -6
  24. package/src/components/core/waveformChartTypes.ts +3 -0
  25. package/src/components/core/xDomain.test.ts +28 -0
  26. package/src/components/core/xDomain.ts +25 -0
  27. package/src/components/data/types.ts +1 -0
  28. package/src/components/interaction/WaveformTooltip.test.ts +17 -9
  29. package/src/components/interaction/WaveformTooltip.vue +41 -45
  30. package/src/components/interaction/useWaveformHover.ts +1 -0
  31. package/src/components/waveform.ts +1 -0
  32. package/src/components/waveformChartCases/compactAndSharedHover.test.ts +4 -4
  33. package/src/components/waveformChartCases/dataAndHoverPerformance.test.ts +2 -2
  34. package/src/components/waveformChartCases/viewportReset.test.ts +35 -0
  35. package/src/components/waveformChartCases/xDomainStrategy.test.ts +96 -0
  36. package/src/core/data.test.ts +22 -0
  37. package/src/core/data.ts +1 -0
  38. package/src/data/simulatedWaveforms.test.ts +1 -0
  39. package/src/data/simulatedWaveforms.ts +7 -1
  40. package/src/index.ts +1 -0
  41. package/src/types/chart.ts +11 -0
  42. package/src/types/data.ts +3 -0
  43. package/src/types/index.ts +1 -0
  44. package/src/views/FixedYDomainDemo.vue +2 -0
@@ -1,12 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
- import { resolveWaveformPointErrors } from '../../core'
4
3
  import { formatTooltipNumber, formatTooltipTime } from '../../utils'
5
4
  import type { WaveformPoint } from '../data/types'
6
5
 
7
6
  interface SeriesPoint {
8
7
  trackIndex: number
9
8
  name: string
9
+ shotNo?: string
10
10
  color: string
11
11
  unit?: string
12
12
  point: WaveformPoint
@@ -34,7 +34,7 @@ const props = defineProps<Props>()
34
34
  const tooltipGap = 12
35
35
  const containerPadding = 8
36
36
  const tooltipPlacementWidth = 238
37
- const tooltipMaxWidth = 320
37
+ const tooltipMaxWidth = 560
38
38
  const tooltipHorizontalPadding = 20
39
39
  const tooltipLineHeight = 20
40
40
 
@@ -45,18 +45,18 @@ function estimateLineCount(text: string, width: number): number {
45
45
  }
46
46
 
47
47
  function formatSeriesText(seriesPoint: SeriesPoint): string {
48
- const error = formatError(seriesPoint.point)
49
- return `${seriesPoint.name ? `${seriesPoint.name}: ` : ''}${formatTooltipNumber(seriesPoint.point.y)}${
50
- seriesPoint.unit ? ` ${seriesPoint.unit}` : ''
51
- }${error ? ` ${error}` : ''}`
48
+ const timeText = formatTooltipTime(props.hoveredPoint?.x ?? seriesPoint.point.x, props.timeUnit)
49
+ return `${seriesPoint.shotNo?.trim() || '未配置炮号'}: ${seriesPoint.name}${
50
+ seriesPoint.unit ? `(${seriesPoint.unit})` : ''
51
+ } (x:${timeText} y:${formatTooltipNumber(seriesPoint.point.y)})`
52
52
  }
53
53
 
54
- function estimateTooltipHeight(width: number, timeText: string): number {
54
+ function estimateTooltipHeight(width: number): number {
55
55
  const seriesLines = props.seriesPoints.reduce(
56
56
  (total, seriesPoint) => total + estimateLineCount(formatSeriesText(seriesPoint), width),
57
57
  0,
58
58
  )
59
- return 16 + tooltipLineHeight * (estimateLineCount(timeText, width) + seriesLines) + 5
59
+ return 16 + tooltipLineHeight * seriesLines + 5
60
60
  }
61
61
 
62
62
  const tooltipStyle = computed(() => {
@@ -84,25 +84,18 @@ const tooltipStyle = computed(() => {
84
84
  : { left: `${containerPadding}px`, maxWidth: `${availableWidth}px` }
85
85
 
86
86
  const maxWidth = Number.parseFloat(horizontalStyle.maxWidth)
87
- const timeText = `${props.timeUnit}: ${formatTooltipTime(props.hoveredPoint.x, props.timeUnit)}`
88
-
89
87
  return {
90
88
  ...horizontalStyle,
91
89
  top: `${Math.max(
92
90
  8,
93
91
  Math.min(
94
92
  props.position.y - 18,
95
- props.containerHeight - estimateTooltipHeight(maxWidth, timeText) - 8,
93
+ props.containerHeight - estimateTooltipHeight(maxWidth) - 8,
96
94
  ),
97
95
  )}px`,
98
96
  }
99
97
  })
100
98
 
101
- function formatError(point: WaveformPoint): string | null {
102
- const { lower, upper } = resolveWaveformPointErrors(point)
103
- if (lower === 0 && upper === 0) return null
104
- return `(+${formatTooltipNumber(upper)} / -${formatTooltipNumber(lower)})`
105
- }
106
99
  </script>
107
100
 
108
101
  <template>
@@ -111,9 +104,6 @@ function formatError(point: WaveformPoint): string | null {
111
104
  class="waveform-tooltip waveform-chart__tooltip"
112
105
  :style="tooltipStyle"
113
106
  >
114
- <span class="waveform-tooltip__time waveform-chart__tooltip-time">
115
- {{ timeUnit }}: {{ formatTooltipTime(hoveredPoint.x, timeUnit) }}
116
- </span>
117
107
  <span
118
108
  v-for="seriesPoint in seriesPoints"
119
109
  :key="`${seriesPoint.trackIndex}-${seriesPoint.name}`"
@@ -121,12 +111,12 @@ function formatError(point: WaveformPoint): string | null {
121
111
  >
122
112
  <i :style="{ backgroundColor: seriesPoint.color }" />
123
113
  <span class="waveform-tooltip__series-content">
124
- <strong v-if="seriesPoint.name">{{ seriesPoint.name }}:</strong>
125
- <span class="waveform-tooltip__value">
126
- {{ formatTooltipNumber(seriesPoint.point.y)
127
- }}{{ seriesPoint.unit ? ` ${seriesPoint.unit}` : '' }}
128
- <small v-if="formatError(seriesPoint.point)">{{ formatError(seriesPoint.point) }}</small>
129
- </span>
114
+ <span class="waveform-tooltip__series-label">{{ seriesPoint.shotNo?.trim() || '未配置炮号' }}: {{
115
+ seriesPoint.name
116
+ }}<template v-if="seriesPoint.unit">({{ seriesPoint.unit }})</template></span>
117
+ <span class="waveform-tooltip__value">(x:{{ formatTooltipTime(hoveredPoint.x, timeUnit) }} y:{{
118
+ formatTooltipNumber(seriesPoint.point.y)
119
+ }})</span>
130
120
  </span>
131
121
  </span>
132
122
  </div>
@@ -138,26 +128,17 @@ function formatError(point: WaveformPoint): string | null {
138
128
  position: absolute;
139
129
  z-index: 2;
140
130
  display: grid;
141
- gap: 3px;
131
+ gap: 2px;
142
132
  width: max-content;
143
- max-width: min(320px, calc(100% - 16px));
144
- padding: 8px 10px;
145
- color: #333;
146
- font:
147
- 12px/1.45 ui-monospace,
148
- SFMono-Regular,
149
- Consolas,
150
- monospace;
133
+ max-width: min(560px, calc(100% - 16px));
134
+ padding: 9px 12px;
135
+ color: #505050;
136
+ font: 14px/1.35 Arial, sans-serif;
151
137
  pointer-events: none;
152
138
  background: #fff;
153
- border: 1px solid #d9d9d9;
154
- border-radius: 2px;
155
- box-shadow: 0 4px 12px rgb(16 24 40 / 12%);
156
- }
157
-
158
- .waveform-tooltip__time {
159
- padding-bottom: 4px;
160
- border-bottom: 1px solid #f0f0f0;
139
+ border: 1px solid #e3e7eb;
140
+ border-radius: 4px;
141
+ box-shadow: 0 3px 10px rgb(16 24 40 / 15%);
161
142
  }
162
143
 
163
144
  .waveform-tooltip__series {
@@ -176,9 +157,24 @@ function formatError(point: WaveformPoint): string | null {
176
157
  }
177
158
 
178
159
  .waveform-tooltip__series-content {
160
+ display: flex;
161
+ flex-wrap: nowrap;
162
+ gap: 12px;
163
+ align-items: baseline;
164
+ min-width: 0;
165
+ }
166
+
167
+ .waveform-tooltip__series-label {
168
+ flex: 1 1 auto;
179
169
  min-width: 0;
180
- overflow-wrap: anywhere;
181
- white-space: normal;
170
+ overflow: hidden;
171
+ text-overflow: ellipsis;
172
+ white-space: nowrap;
173
+ }
174
+
175
+ .waveform-tooltip__value {
176
+ flex: 0 0 auto;
177
+ white-space: nowrap;
182
178
  }
183
179
 
184
180
  .waveform-tooltip__series strong {
@@ -186,7 +182,7 @@ function formatError(point: WaveformPoint): string | null {
186
182
  }
187
183
 
188
184
  .waveform-tooltip__value {
189
- overflow-wrap: anywhere;
185
+ color: #555;
190
186
  }
191
187
 
192
188
  .waveform-tooltip__series small {
@@ -85,6 +85,7 @@ export function useWaveformHover(context: HoverContext) {
85
85
  point: WaveformPoint,
86
86
  ): HoveredSeriesPoint => ({
87
87
  id: series.id,
88
+ shotNo: series.shotNo,
88
89
  name: series.name,
89
90
  color: series.color,
90
91
  unit: series.unit,
@@ -9,6 +9,7 @@ export type {
9
9
  WaveformDisplayMode,
10
10
  WaveformOverlayMode,
11
11
  WaveformInteractionMode,
12
+ WaveformXDomainStrategy,
12
13
  WaveformAnnotationStyle,
13
14
  WaveformAnnotation,
14
15
  WaveformRenderingOptions,
@@ -179,10 +179,10 @@ describe('WaveformChart', () => {
179
179
  await flushPromises()
180
180
 
181
181
  const tooltip = wrapper.get('.waveform-chart__tooltip')
182
- expect(tooltip.text()).toContain('BT2_2M:')
183
- expect(tooltip.text()).toContain('2 T')
184
- expect(tooltip.text()).toContain('BT1_2M:')
185
- expect(tooltip.text()).toContain('4 T')
182
+ expect(tooltip.text()).toContain('未配置炮号: BT2_2M')
183
+ expect(tooltip.text()).toContain('(x:1,000 y:2)')
184
+ expect(tooltip.text()).toContain('未配置炮号: BT1_2M')
185
+ expect(tooltip.text()).toContain('(x:1,000 y:4)')
186
186
  const crosshairLines = wrapper.findAll('.waveform-chart__crosshair line')
187
187
  expect(crosshairLines).toHaveLength(2)
188
188
  crosshairLines.forEach((line) => {
@@ -178,7 +178,7 @@ describe('WaveformChart', () => {
178
178
  await flushPromises()
179
179
  expect(wrapper.emitted('point-hover')?.at(-1)).toEqual([{ x: 1, y: 5 }])
180
180
  expect(wrapper.find('.waveform-chart__tooltip').exists()).toBe(true)
181
- expect(wrapper.get('.waveform-chart__tooltip-time').text()).toBe('ms: 1,000')
181
+ expect(wrapper.get('.waveform-tooltip__series-label').text()).toContain('未配置炮号:')
182
182
  const crosshairLines = wrapper.findAll('.waveform-chart__crosshair line')
183
183
  expect(crosshairLines).toHaveLength(1)
184
184
  expect(crosshairLines[0].attributes('x1')).toBe(crosshairLines[0].attributes('x2'))
@@ -303,7 +303,7 @@ describe('WaveformChart', () => {
303
303
  flushAnimationFrames()
304
304
  await flushPromises()
305
305
 
306
- expect(wrapper.get('.waveform-chart__tooltip-time').text()).toBe('ms: 1,000')
306
+ expect(wrapper.get('.waveform-tooltip__series-label').text()).toContain('未配置炮号:')
307
307
  expect(wrapper.findAll('.waveform-chart__crosshair line')).toHaveLength(1)
308
308
  expect(wrapper.get('.waveform-chart__line').element).toBe(pathBeforeHover)
309
309
  expect(chartUpdate).not.toHaveBeenCalled()
@@ -5,6 +5,13 @@ import { flushAnimationFrames } from '../../test/setup'
5
5
  import { gridSeries, mountSizedChart } from '../../test/waveformChart'
6
6
 
7
7
  describe('WaveformChart viewport reset', () => {
8
+ const niceExplicitStrategy = {
9
+ type: 'nice' as const,
10
+ bounds: 'end' as const,
11
+ tickCount: 10,
12
+ includeExplicit: true,
13
+ }
14
+
8
15
  it('resets a shared viewport on double-click and emits a global payload', async () => {
9
16
  const wrapper = await mountSizedChart(
10
17
  {
@@ -111,4 +118,32 @@ describe('WaveformChart viewport reset', () => {
111
118
  expect(wrapper.findAll('.waveform-chart__axis-endpoint--start')[0].text()).toBe('0')
112
119
  expect(wrapper.findAll('.waveform-chart__axis-endpoint--end')[0].text()).toBe('1000')
113
120
  })
121
+
122
+ it('resets shared and independent explicit domains to their included nice bounds', async () => {
123
+ const shared = await mountSizedChart(
124
+ {
125
+ kind: 'points',
126
+ points: [
127
+ { x: 0, y: 0 },
128
+ { x: 4.999999, y: 1 },
129
+ ],
130
+ },
131
+ { initialXDomain: [0, 4.999999], xDomainStrategy: niceExplicitStrategy },
132
+ )
133
+ const independent = await mountSizedChart(gridSeries(2), {
134
+ displayMode: 'independent',
135
+ initialXDomains: { 'channel-0': [0, 4.999999] },
136
+ xDomainStrategy: niceExplicitStrategy,
137
+ })
138
+
139
+ ;(shared.vm as unknown as { resetViewport: () => void }).resetViewport()
140
+ ;(independent.vm as unknown as { resetViewport: () => void }).resetViewport()
141
+ await flushPromises()
142
+
143
+ expect(shared.get('.waveform-chart__axis-endpoint--start').text()).toBe('0')
144
+ expect(shared.get('.waveform-chart__axis-endpoint--end').text()).toBe('5000')
145
+ const firstTrack = independent.findAll('.waveform-chart__track')[0]
146
+ expect(firstTrack.get('.waveform-chart__axis-endpoint--start').text()).toBe('0')
147
+ expect(firstTrack.get('.waveform-chart__axis-endpoint--end').text()).toBe('5000')
148
+ })
114
149
  })
@@ -0,0 +1,96 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { gridSeries, mountSizedChart } from '../../test/waveformChart'
4
+
5
+ describe('WaveformChart x domain strategy', () => {
6
+ it('expands automatic x domains without changing source seconds', async () => {
7
+ const data = {
8
+ kind: 'points' as const,
9
+ points: [
10
+ { x: 0, y: 0 },
11
+ { x: 4.999999, y: 1 },
12
+ ],
13
+ }
14
+ const wrapper = await mountSizedChart(data, {
15
+ timeUnit: 'ms',
16
+ xDomainStrategy: { type: 'nice', bounds: 'end' },
17
+ })
18
+
19
+ expect(wrapper.get('.waveform-chart__axis-endpoint--start').text()).toBe('0')
20
+ expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('5000')
21
+ expect(data.points[1]?.x).toBe(4.999999)
22
+ })
23
+
24
+ it('keeps explicit initial x domains exact by default', async () => {
25
+ const wrapper = await mountSizedChart(
26
+ {
27
+ kind: 'points',
28
+ points: [
29
+ { x: 123, y: 0 },
30
+ { x: 456, y: 1 },
31
+ ],
32
+ },
33
+ {
34
+ timeUnit: 's',
35
+ initialXDomain: [120, 460],
36
+ xDomainStrategy: { type: 'nice' },
37
+ },
38
+ )
39
+
40
+ expect(wrapper.get('.waveform-chart__axis-endpoint--start').text()).toBe('120')
41
+ expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('460')
42
+ })
43
+
44
+ it('keeps explicit per-track initial x domains exact by default', async () => {
45
+ const wrapper = await mountSizedChart(gridSeries(1), {
46
+ displayMode: 'independent',
47
+ initialXDomains: { 'channel-0': [0, 4.999999] },
48
+ xDomainStrategy: { type: 'nice', bounds: 'end' },
49
+ })
50
+
51
+ expect(wrapper.get('.waveform-chart__axis-endpoint--start').text()).toBe('0')
52
+ expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('4999.999')
53
+ })
54
+
55
+ it('includes an explicit shared initial x domain when requested', async () => {
56
+ const wrapper = await mountSizedChart(
57
+ {
58
+ kind: 'points',
59
+ points: [
60
+ { x: 0, y: 0 },
61
+ { x: 4.999999, y: 1 },
62
+ ],
63
+ },
64
+ {
65
+ initialXDomain: [0, 4.999999],
66
+ xDomainStrategy: {
67
+ type: 'nice',
68
+ bounds: 'end',
69
+ tickCount: 10,
70
+ includeExplicit: true,
71
+ },
72
+ },
73
+ )
74
+
75
+ expect(wrapper.get('.waveform-chart__axis-endpoint--start').text()).toBe('0')
76
+ expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('5000')
77
+ })
78
+
79
+ it('includes explicit per-track initial x domains in independent mode', async () => {
80
+ const wrapper = await mountSizedChart(gridSeries(2), {
81
+ displayMode: 'independent',
82
+ grid: { rowCount: 1, columnCount: 2 },
83
+ initialXDomains: {
84
+ 'channel-0': [0, 4.999999],
85
+ 'channel-1': [10, 14.999999],
86
+ },
87
+ xDomainStrategy: { type: 'nice', bounds: 'end', tickCount: 10, includeExplicit: true },
88
+ })
89
+
90
+ const tracks = wrapper.findAll('.waveform-chart__track')
91
+ expect(tracks[0]?.get('.waveform-chart__axis-endpoint--start').text()).toBe('0')
92
+ expect(tracks[0]?.get('.waveform-chart__axis-endpoint--end').text()).toBe('5000')
93
+ expect(tracks[1]?.get('.waveform-chart__axis-endpoint--start').text()).toBe('10000')
94
+ expect(tracks[1]?.get('.waveform-chart__axis-endpoint--end').text()).toBe('15000')
95
+ })
96
+ })
@@ -102,4 +102,26 @@ describe('waveform data normalization', () => {
102
102
  'solid',
103
103
  ])
104
104
  })
105
+
106
+ it('preserves trimmed shot numbers and omits blank values', () => {
107
+ const result = normalizeWaveformSeries({
108
+ kind: 'series',
109
+ series: [
110
+ {
111
+ id: 'with-shot',
112
+ shotNo: ' 13300 ',
113
+ name: '通道 A',
114
+ data: { kind: 'points', points: [{ x: 0, y: 1 }] },
115
+ },
116
+ {
117
+ id: 'without-shot',
118
+ shotNo: ' ',
119
+ name: '通道 B',
120
+ data: { kind: 'points', points: [{ x: 0, y: 2 }] },
121
+ },
122
+ ],
123
+ })
124
+
125
+ expect(result.map((series) => series.shotNo)).toEqual(['13300', undefined])
126
+ })
105
127
  })
package/src/core/data.ts CHANGED
@@ -132,6 +132,7 @@ export function normalizeWaveformSeries(data: WaveformData): NormalizedWaveformS
132
132
 
133
133
  return {
134
134
  id: uniqueId,
135
+ shotNo: series.shotNo?.trim() || undefined,
135
136
  trackId: series.trackId?.trim() || undefined,
136
137
  name: series.name,
137
138
  unit: series.unit,
@@ -13,6 +13,7 @@ describe('simulated waveform data', () => {
13
13
 
14
14
  expect(first.series).toHaveLength(6)
15
15
  expect(new Set(first.series.map((series) => series.id)).size).toBe(6)
16
+ expect(new Set(first.series.map((series) => series.shotNo))).toEqual(new Set(['13300']))
16
17
  first.series.forEach((series) => {
17
18
  expect(series.data.kind).toBe('points')
18
19
  if (series.data.kind !== 'points') return
@@ -13,7 +13,7 @@ type ErrorGenerator = (
13
13
 
14
14
  interface SimulatedSeriesDefinition extends Pick<
15
15
  WaveformSeries,
16
- 'id' | 'name' | 'unit' | 'lineType' | 'pointType' | 'errorBar'
16
+ 'id' | 'shotNo' | 'name' | 'unit' | 'lineType' | 'pointType' | 'errorBar'
17
17
  > {
18
18
  signal: SignalGenerator
19
19
  errors?: ErrorGenerator
@@ -46,6 +46,7 @@ function createPoints(
46
46
  const seriesDefinitions: SimulatedSeriesDefinition[] = [
47
47
  {
48
48
  id: 'simulated-sine',
49
+ shotNo: '13300',
49
50
  name: '正弦基波',
50
51
  unit: 'V',
51
52
  lineType: 'none',
@@ -59,6 +60,7 @@ const seriesDefinitions: SimulatedSeriesDefinition[] = [
59
60
  },
60
61
  {
61
62
  id: 'simulated-harmonic',
63
+ shotNo: '13300',
62
64
  name: '谐波扰动',
63
65
  unit: 'V',
64
66
  lineType: 'linear',
@@ -68,6 +70,7 @@ const seriesDefinitions: SimulatedSeriesDefinition[] = [
68
70
  },
69
71
  {
70
72
  id: 'simulated-damped',
73
+ shotNo: '13300',
71
74
  name: '阻尼振荡',
72
75
  unit: 'A',
73
76
  lineType: 'linear',
@@ -79,6 +82,7 @@ const seriesDefinitions: SimulatedSeriesDefinition[] = [
79
82
  },
80
83
  {
81
84
  id: 'simulated-step',
85
+ shotNo: '13300',
82
86
  name: '阶跃响应',
83
87
  unit: 'V',
84
88
  lineType: 'linear',
@@ -87,6 +91,7 @@ const seriesDefinitions: SimulatedSeriesDefinition[] = [
87
91
  },
88
92
  {
89
93
  id: 'simulated-pulse',
94
+ shotNo: '13300',
90
95
  name: '脉冲响应',
91
96
  unit: 'V',
92
97
  lineType: 'linear',
@@ -95,6 +100,7 @@ const seriesDefinitions: SimulatedSeriesDefinition[] = [
95
100
  },
96
101
  {
97
102
  id: 'simulated-noise',
103
+ shotNo: '13300',
98
104
  name: '带噪信号',
99
105
  unit: 'A',
100
106
  lineType: 'linear',
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ export type {
13
13
  WaveformDisplayMode,
14
14
  WaveformOverlayMode,
15
15
  WaveformInteractionMode,
16
+ WaveformXDomainStrategy,
16
17
  WaveformZoomEndPayload,
17
18
  WaveformZoomResetPayload,
18
19
  WaveformAnnotationStyle,
@@ -26,6 +26,17 @@ export type WaveformOverlayMode = 'single-axis' | 'multi-axis'
26
26
  /** 标注工具模式 */
27
27
  export type WaveformInteractionMode = 'zoom' | 'annotation'
28
28
 
29
+ /** Controls how the initial X viewport is derived when no explicit domain is configured. */
30
+ export interface WaveformXDomainStrategy {
31
+ type: 'data' | 'nice'
32
+ /** Selects which bounds are expanded when type is `nice`. Defaults to `both`. */
33
+ bounds?: 'both' | 'end'
34
+ /** Stable tick count used to calculate nice bounds. Defaults to 10. */
35
+ tickCount?: number
36
+ /** Applies the strategy to explicit initial domains. Defaults to false. */
37
+ includeExplicit?: boolean
38
+ }
39
+
29
40
  /** Describes the X-axis viewport after a zoom gesture completes. */
30
41
  export interface WaveformZoomEndPayload {
31
42
  start: number
package/src/types/data.ts CHANGED
@@ -47,6 +47,8 @@ export type SingleWaveformData =
47
47
  */
48
48
  export interface WaveformSeries {
49
49
  id?: string
50
+ /** 炮号,未提供时 Tooltip 显示“未配置炮号”。 */
51
+ shotNo?: string
50
52
  /** 相同 trackId 的系列叠加在同一图框中;默认每个系列独占一个图框。 */
51
53
  trackId?: string
52
54
  name: string
@@ -74,6 +76,7 @@ export type WaveformData =
74
76
  */
75
77
  export interface NormalizedWaveformSeries {
76
78
  id: string
79
+ shotNo?: string
77
80
  trackId?: string
78
81
  name: string
79
82
  unit?: string
@@ -8,6 +8,7 @@ export type {
8
8
  WaveformDisplayMode,
9
9
  WaveformOverlayMode,
10
10
  WaveformInteractionMode,
11
+ WaveformXDomainStrategy,
11
12
  WaveformZoomEndPayload,
12
13
  WaveformZoomResetPayload,
13
14
  WaveformAnnotationStyle,
@@ -19,6 +19,7 @@ const chartData: WaveformData = {
19
19
  series: [
20
20
  {
21
21
  id: 'voltage',
22
+ shotNo: '13300',
22
23
  name: '电压',
23
24
  unit: 'V',
24
25
  color: '#1677ff',
@@ -33,6 +34,7 @@ const chartData: WaveformData = {
33
34
  },
34
35
  {
35
36
  id: 'current',
37
+ shotNo: '13300',
36
38
  name: '电流',
37
39
  unit: 'mA',
38
40
  color: '#d4380d',