waveform-analysis 0.1.77 → 0.1.78

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.
@@ -274,6 +274,7 @@ export declare function useWaveformChartController(inputProps: ResolvedWaveformC
274
274
  innerWidth: number;
275
275
  hasVisibleWaveformData: boolean;
276
276
  hasWaveformData: boolean;
277
+ hasWaveformSamples: boolean;
277
278
  hasChartArea: boolean;
278
279
  resolvedXLabel: string;
279
280
  activeInteractionMode: import("..").WaveformInteractionMode | undefined;
@@ -35,6 +35,7 @@ export declare function useWaveformLayout(context: LayoutContext): {
35
35
  innerWidth: ComputedRef<number>;
36
36
  hasVisibleWaveformData: ComputedRef<boolean>;
37
37
  hasWaveformData: ComputedRef<boolean>;
38
+ hasWaveformSamples: ComputedRef<boolean>;
38
39
  hasChartArea: ComputedRef<boolean>;
39
40
  resolvedXLabel: ComputedRef<string>;
40
41
  activeInteractionMode: ComputedRef<import("..").WaveformInteractionMode | undefined>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waveform-analysis",
3
- "version": "0.1.77",
3
+ "version": "0.1.78",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -46,6 +46,7 @@ const {
46
46
  chartWidth,
47
47
  drawingHeight,
48
48
  hasWaveformData,
49
+ hasWaveformSamples,
49
50
  trackLayouts,
50
51
  presentationTracks,
51
52
  presentationAnnotations,
@@ -186,7 +187,7 @@ function handleChartPointerLeave() {
186
187
  :width="chartWidth"
187
188
  :height="drawingHeight"
188
189
  role="img"
189
- :aria-label="hasWaveformData ? '波形折线图' : '暂无波形数据'"
190
+ :aria-label="hasWaveformSamples ? '波形折线图' : '暂无波形数据'"
190
191
  >
191
192
  <defs>
192
193
  <clipPath
@@ -343,7 +344,7 @@ function handleChartPointerLeave() {
343
344
  </text>
344
345
 
345
346
  <text
346
- v-if="hasChartArea && !hasWaveformData"
347
+ v-if="hasChartArea && !hasWaveformSamples"
347
348
  class="waveform-chart__empty"
348
349
  :x="chartWidth / 2"
349
350
  :y="drawingHeight / 2"
@@ -92,7 +92,7 @@ export function transitionTrack(
92
92
  const series = new Map<string, SeriesGeometry>()
93
93
  for (const [id, next] of to.series) {
94
94
  const previous = from.series.get(id)
95
- if (!previous) {
95
+ if (!previous || (next.path.series.source?.length ?? next.path.series.points.length) === 0) {
96
96
  series.set(id, next)
97
97
  continue
98
98
  }
@@ -122,13 +122,15 @@ export function useChartCommands(c: Context) {
122
122
  ? tracks.some((t) => c.independentYDomains.value[t.index])
123
123
  : Object.keys(c.sharedYDomains.value).length > 0)
124
124
  const boundaryChanged = tracks.length && !same(bounds, boundary(tracks))
125
- const status: WaveformTargetResult['status'] = !nonempty
126
- ? 'empty-data'
127
- : c.props.presentationMode || !c.props.zoomable
128
- ? 'disabled'
129
- : before && same(before.xDomain, xDomain) && !hasY && !boundaryChanged
130
- ? 'unchanged'
131
- : 'applied'
125
+ const hasSeries = tracks.some((t) => t.seriesList.length > 0)
126
+ const status: WaveformTargetResult['status'] =
127
+ !hasSeries || (action === 'fit' && !nonempty)
128
+ ? 'empty-data'
129
+ : c.props.presentationMode || !c.props.zoomable
130
+ ? 'disabled'
131
+ : before && same(before.xDomain, xDomain) && !hasY && !boundaryChanged
132
+ ? 'unchanged'
133
+ : 'applied'
132
134
  return { id, tracks, before, bounds, xDomain, status, resetsY }
133
135
  })
134
136
  return { entries }
@@ -32,7 +32,6 @@ import { resolveCompactPaginationBand } from './pagination'
32
32
  import type { WaveformHoverState } from './types'
33
33
  import { useWaveformChartLifecycle } from './useWaveformChartLifecycle'
34
34
  import { usePreparedWaveformSeries } from './useWaveformData'
35
- import { remotePanBoundary } from '../interaction/remoteViewport'
36
35
  import { useWaveformLayout } from './useWaveformLayout'
37
36
  import { useWaveformPresentation } from './useWaveformPresentation'
38
37
  import { usePlotLabelLayout } from './usePlotLabelLayout'
@@ -103,7 +102,7 @@ export function useWaveformChartController(
103
102
  handleBeforeDataReferenceChange()
104
103
  },
105
104
  () => handleDataReferenceChange(),
106
- () => Boolean(remotePanBoundary(props)),
105
+ () => true,
107
106
  )
108
107
 
109
108
  const presentation = useWaveformPresentation({
@@ -71,7 +71,19 @@ export function usePreparedWaveformSeries(
71
71
  )
72
72
  watch([data, retainEmpty], ([nextData, preserveEmpty]) => {
73
73
  onBeforeDataChange()
74
- preparedSeries.value = prepareWaveformSeries(nextData, preserveEmpty)
74
+ const previousById = new Map(preparedSeries.value.map((series) => [series.id, series]))
75
+ preparedSeries.value = prepareWaveformSeries(nextData, preserveEmpty).map((series) => {
76
+ const previous = previousById.get(series.id)
77
+ // Preserve axes, never geometry, across empty windows of the same channel/track.
78
+ if (series.source.length || !previous || series.trackId !== previous.trackId) return series
79
+ return {
80
+ ...series,
81
+ xDomain: previous.xDomain,
82
+ yDomain: previous.yDomain,
83
+ rawYMaximum: previous.rawYMaximum,
84
+ rawYMinimum: previous.rawYMinimum,
85
+ }
86
+ })
75
87
  onDataChange()
76
88
  })
77
89
  return preparedSeries
@@ -149,6 +149,9 @@ export function useWaveformLayout(context: LayoutContext) {
149
149
  yAxisTickCount,
150
150
  })
151
151
  const hasWaveformData = computed(() => chartSeries.value.length > 0)
152
+ const hasWaveformSamples = computed(() =>
153
+ chartSeries.value.some((series) => (series.source?.length ?? series.points.length) > 0),
154
+ )
152
155
  const hasChartArea = computed(() => innerWidth.value > 0 && innerHeight.value > 0)
153
156
  const resolvedXLabel = computed(() => props.xLabel ?? `时间(${props.timeUnit})`)
154
157
  const activeInteractionMode = computed(() => props.interactionMode)
@@ -349,6 +352,7 @@ export function useWaveformLayout(context: LayoutContext) {
349
352
  innerWidth,
350
353
  hasVisibleWaveformData,
351
354
  hasWaveformData,
355
+ hasWaveformSamples,
352
356
  hasChartArea,
353
357
  resolvedXLabel,
354
358
  activeInteractionMode,
@@ -56,6 +56,7 @@ function minimumPointSpan(
56
56
  let minimumSpan = 0
57
57
  for (const group of groups) {
58
58
  const values = uniqueXValues(group, boundary)
59
+ if (!group.some((series) => (series.source?.length ?? series.points.length) > 0)) continue
59
60
  if (values.length < required) return boundary[1] - boundary[0]
60
61
  let groupSpan = Number.POSITIVE_INFINITY
61
62
  for (let index = 0; index + required <= values.length; index += 1) {
@@ -104,6 +105,7 @@ function expandToMinimumPoints(
104
105
  let expanded = domain
105
106
  for (const group of groups) {
106
107
  const values = uniqueXValues(group, boundary)
108
+ if (!group.some((series) => (series.source?.length ?? series.points.length) > 0)) continue
107
109
  if (values.length < required) return [...boundary]
108
110
  const visibleCount = values.filter(
109
111
  (value) => value >= expanded[0] && value <= expanded[1],
@@ -52,14 +52,19 @@ export function mergeWaveformWindow(
52
52
  response: WaveformData,
53
53
  seriesIds?: string[],
54
54
  ): WaveformData {
55
- if (!seriesIds || current.kind !== 'series' || response.kind !== 'series') return response
56
- const selected = new Set(seriesIds)
55
+ if (current.kind !== 'series' || response.kind !== 'series') return response
56
+ const selected = seriesIds ? new Set(seriesIds) : undefined
57
57
  const byId = new Map(response.series.map((series) => [series.id, series]))
58
+ const knownIds = new Set(current.series.map((series) => series.id))
58
59
  return {
59
60
  kind: 'series',
60
- series: current.series.map((series) =>
61
- series.id && selected.has(series.id) ? (byId.get(series.id) ?? series) : series,
62
- ),
61
+ series: [
62
+ ...current.series.map((series) => {
63
+ if (selected && (!series.id || !selected.has(series.id))) return series
64
+ return byId.get(series.id) ?? { ...series, data: { kind: 'points' as const, points: [] } }
65
+ }),
66
+ ...response.series.filter((series) => !knownIds.has(series.id)),
67
+ ],
63
68
  }
64
69
  }
65
70