waveform-analysis 0.1.57 → 0.1.59

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 (54) hide show
  1. package/README.md +12 -7
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +752 -680
  4. package/dist/types/components/WaveformChart.vue.d.ts +2 -0
  5. package/dist/types/components/core/grid.d.ts +3 -0
  6. package/dist/types/components/core/trackPagination.d.ts +4 -0
  7. package/dist/types/components/core/useWaveformChartController.d.ts +3 -1
  8. package/dist/types/components/core/useWaveformChartLifecycle.d.ts +1 -2
  9. package/dist/types/components/core/useWaveformLayout.d.ts +2 -1
  10. package/dist/types/components/core/waveformChartTypes.d.ts +4 -1
  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/interaction/useWaveformZoom.d.ts +2 -1
  14. package/dist/types/components/interaction/zoomEventPayload.d.ts +7 -0
  15. package/dist/types/core/rendering.d.ts +1 -1
  16. package/dist/types/core/renderingOptions.d.ts +1 -1
  17. package/dist/types/core/wasmSampling.d.ts +1 -1
  18. package/dist/types/core/workerSampling/multiresolution.d.ts +1 -1
  19. package/dist/types/core/workerSampling/protocol.d.ts +1 -1
  20. package/dist/types/core/workerSampling/repositoryDataset.d.ts +1 -1
  21. package/dist/types/core/workerSampling/repositorySupport.d.ts +1 -1
  22. package/dist/types/index.d.ts +1 -1
  23. package/dist/types/types/chart.d.ts +8 -0
  24. package/dist/types/types/index.d.ts +1 -1
  25. package/dist/types/utils/geometry.d.ts +1 -1
  26. package/dist/types/wasm/waveform_sampling_wasm.d.ts +74 -0
  27. package/dist/types/wasm/waveform_sampling_wasm_bg.wasm.d.ts +19 -0
  28. package/package.json +5 -4
  29. package/src/components/WaveformChartView.vue +3 -3
  30. package/src/components/core/grid.test.ts +3 -0
  31. package/src/components/core/grid.ts +4 -0
  32. package/src/components/core/trackPagination.ts +40 -0
  33. package/src/components/core/useWaveformChartController.ts +6 -1
  34. package/src/components/core/useWaveformChartLifecycle.ts +15 -9
  35. package/src/components/core/useWaveformLayout.ts +12 -9
  36. package/src/components/core/waveformChartTypes.ts +4 -0
  37. package/src/components/data/types.ts +1 -0
  38. package/src/components/index.ts +1 -0
  39. package/src/components/interaction/useWaveformViewport.ts +2 -0
  40. package/src/components/interaction/useWaveformZoom.ts +58 -61
  41. package/src/components/interaction/zoomEventPayload.ts +88 -0
  42. package/src/components/waveformChartCases/trackOrder.test.ts +62 -0
  43. package/src/components/waveformChartCases/zoomIntentAndDataRebind.test.ts +213 -0
  44. package/src/core/rendering.ts +1 -1
  45. package/src/core/renderingOptions.ts +1 -1
  46. package/src/core/workerSampling/multiresolution.ts +1 -1
  47. package/src/core/workerSampling/protocol.ts +1 -1
  48. package/src/core/workerSampling/repository.ts +1 -1
  49. package/src/core/workerSampling/repositoryDataset.ts +1 -1
  50. package/src/core/workerSampling/repositorySupport.ts +1 -1
  51. package/src/index.ts +1 -0
  52. package/src/types/chart.ts +9 -0
  53. package/src/types/index.ts +1 -0
  54. package/src/utils/geometry.ts +1 -1
@@ -4,6 +4,7 @@ declare const __VLS_export: import("vue").DefineComponent<WaveformChartProps, {
4
4
  setViewportDomain: (domain: [number, number], trackIndex?: number) => void;
5
5
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
6
  "point-hover": (point: import("..").WaveformPoint | null) => any;
7
+ "zoom-intent": (payload: import("..").WaveformZoomIntentPayload) => any;
7
8
  "zoom-change": (domain: [number, number]) => any;
8
9
  "zoom-end": (payload: import("..").WaveformZoomEndPayload) => any;
9
10
  "zoom-reset": (payload: import("..").WaveformZoomResetPayload) => any;
@@ -27,6 +28,7 @@ declare const __VLS_export: import("vue").DefineComponent<WaveformChartProps, {
27
28
  "sampling-error": (error: import("..").WaveformSamplingError) => any;
28
29
  }, string, import("vue").PublicProps, Readonly<WaveformChartProps> & Readonly<{
29
30
  "onPoint-hover"?: ((point: import("..").WaveformPoint | null) => any) | undefined;
31
+ "onZoom-intent"?: ((payload: import("..").WaveformZoomIntentPayload) => any) | undefined;
30
32
  "onZoom-change"?: ((domain: [number, number]) => any) | undefined;
31
33
  "onZoom-end"?: ((payload: import("..").WaveformZoomEndPayload) => any) | undefined;
32
34
  "onZoom-reset"?: ((payload: import("..").WaveformZoomResetPayload) => any) | undefined;
@@ -9,6 +9,8 @@ export interface WaveformGridOptions {
9
9
  fillIncompleteLastRow?: boolean;
10
10
  /** Stable grid slots. Empty IDs remain as empty chart frames and keep their page position. */
11
11
  trackOrder?: string[];
12
+ /** Omits ordered tracks without waveform series from layout and pagination. */
13
+ hideEmptyTracks?: boolean;
12
14
  trackLines?: WaveformGridTrackLines;
13
15
  }
14
16
  export interface WaveformGridLineOptions {
@@ -32,6 +34,7 @@ export interface NormalizedWaveformGridOptions {
32
34
  showPagination: boolean;
33
35
  fillIncompleteLastRow: boolean;
34
36
  trackOrder?: string[];
37
+ hideEmptyTracks?: boolean;
35
38
  trackLines: Record<string, NormalizedWaveformGridLineOptions>;
36
39
  }
37
40
  export interface GridCellGeometry {
@@ -0,0 +1,4 @@
1
+ import type { DisplayTrack } from './types';
2
+ export declare const resolvePageableTracks: (tracks: DisplayTrack[], hideEmptyTracks?: boolean) => DisplayTrack[];
3
+ export declare const resolveTrackFrameNumber: (frameNumber: string | number | undefined, frameNumbers: Record<string, string | number> | undefined, trackCount: number, trackIndex: number, trackId: string) => string | number | undefined;
4
+ export declare const createFrameNumberResolver: (getFrameNumber: () => string | number | undefined, getFrameNumbers: () => Record<string, string | number> | undefined, getTracks: () => DisplayTrack[]) => (trackId: string) => string | number | undefined;
@@ -246,6 +246,7 @@ export declare function useWaveformChartController(props: ResolvedWaveformChartP
246
246
  confirmAnnotation: (annotation: import("..").WaveformAnnotation) => void;
247
247
  chartSeries: import("./types").DisplaySeries[];
248
248
  chartTracks: import("./types").DisplayTrack[];
249
+ pageableTracks: import("./types").DisplayTrack[];
249
250
  renderingOptions: import("../..").ResolvedWaveformRenderingOptions;
250
251
  gridOptions: import("./grid").NormalizedWaveformGridOptions;
251
252
  pageCount: number;
@@ -281,7 +282,7 @@ export declare function useWaveformChartController(props: ResolvedWaveformChartP
281
282
  annotationTrackLayouts: import("../annotation").AnnotationTrackLayout[];
282
283
  renderedAnnotations: import("../annotation").RenderedAnnotation[];
283
284
  editorSeries: import("../annotation").AnnotationSeriesInfo | undefined;
284
- resolveFrameNumber: (trackIndex: number) => string | number | undefined;
285
+ resolveFrameNumber: (trackId: string) => string | number | undefined;
285
286
  fixedWidth: number | undefined;
286
287
  fixedHeight: number | undefined;
287
288
  chartWidth: number;
@@ -341,6 +342,7 @@ export declare function useWaveformChartController(props: ResolvedWaveformChartP
341
342
  yDomains?: Record<string, [number, number]> | undefined;
342
343
  timeUnit: "s" | "ms";
343
344
  frameNumber?: string | number | undefined;
345
+ frameNumbers?: Record<string, string | number> | undefined;
344
346
  frameStyle?: import("..").WaveformFrameStyle | undefined;
345
347
  axes?: import("..").WaveformAxesOptions | undefined;
346
348
  annotations: import("..").WaveformAnnotation[];
@@ -1,7 +1,6 @@
1
1
  import { type ZoomTransform } from 'd3';
2
2
  import { type ComputedRef, type Ref, type ShallowRef } from 'vue';
3
- import type { AnnotationSeriesCandidate } from '../annotation';
4
- import type { useWaveformAnnotationInteraction } from '../annotation';
3
+ import type { AnnotationSeriesCandidate, useWaveformAnnotationInteraction } from '../annotation';
5
4
  import type { NormalizedWaveformGridOptions } from './grid';
6
5
  import type { DisplaySeries, DisplayTrack, TrackLayout } from './types';
7
6
  import type { ResolvedWaveformChartProps, WaveformChartEmit } from './waveformChartTypes';
@@ -23,6 +23,7 @@ interface LayoutContext {
23
23
  export declare function useWaveformLayout(context: LayoutContext): {
24
24
  chartSeries: ComputedRef<DisplaySeries[]>;
25
25
  chartTracks: ComputedRef<DisplayTrack[]>;
26
+ pageableTracks: ComputedRef<DisplayTrack[]>;
26
27
  renderingOptions: ComputedRef<import("../..").ResolvedWaveformRenderingOptions>;
27
28
  gridOptions: ComputedRef<import("./grid").NormalizedWaveformGridOptions>;
28
29
  pageCount: ComputedRef<number>;
@@ -58,6 +59,6 @@ export declare function useWaveformLayout(context: LayoutContext): {
58
59
  annotationTrackLayouts: ComputedRef<AnnotationTrackLayout[]>;
59
60
  renderedAnnotations: ComputedRef<import("../annotation").RenderedAnnotation[]>;
60
61
  editorSeries: ComputedRef<AnnotationSeriesInfo | undefined>;
61
- resolveFrameNumber: (trackIndex: number) => string | number | undefined;
62
+ resolveFrameNumber: (trackId: string) => string | number | undefined;
62
63
  };
63
64
  export {};
@@ -1,4 +1,4 @@
1
- import type { WaveformAnnotation, WaveformAxesOptions, WaveformData, WaveformDisplayMode, WaveformFrameStyle, WaveformInteractionMode, WaveformLegendOptions, WaveformOverlayMode, WaveformPlotMargin, WaveformPoint, WaveformRenderingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformTitleOptions, WaveformXDomainStrategy, WaveformZeroLineOptions, WaveformZoomEndPayload, WaveformZoomResetPayload } from '../data/types';
1
+ import type { WaveformAnnotation, WaveformAxesOptions, WaveformData, WaveformDisplayMode, WaveformFrameStyle, WaveformInteractionMode, WaveformLegendOptions, WaveformOverlayMode, WaveformPlotMargin, WaveformPoint, WaveformRenderingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformTitleOptions, WaveformXDomainStrategy, WaveformZeroLineOptions, WaveformZoomIntentPayload, WaveformZoomEndPayload, WaveformZoomResetPayload } from '../data/types';
2
2
  import type { WaveformGridOptions } from './grid';
3
3
  export interface WaveformChartProps {
4
4
  data: WaveformData;
@@ -22,6 +22,8 @@ export interface WaveformChartProps {
22
22
  yDomains?: Record<string, [number, number]>;
23
23
  timeUnit?: 's' | 'ms';
24
24
  frameNumber?: string | number;
25
+ /** Per-track frame watermark overrides, keyed by stable trackId. */
26
+ frameNumbers?: Record<string, string | number>;
25
27
  frameStyle?: WaveformFrameStyle;
26
28
  axes?: WaveformAxesOptions;
27
29
  annotations?: WaveformAnnotation[];
@@ -42,6 +44,7 @@ type DefaultedProp = 'displayMode' | 'overlayMode' | 'yLabel' | 'lineColor' | 's
42
44
  export type ResolvedWaveformChartProps = Readonly<WaveformChartProps & Required<Pick<WaveformChartProps, DefaultedProp>>>;
43
45
  export interface WaveformChartEmit {
44
46
  (event: 'point-hover', point: WaveformPoint | null): void;
47
+ (event: 'zoom-intent', payload: WaveformZoomIntentPayload): void;
45
48
  (event: 'zoom-change', domain: [number, number]): void;
46
49
  (event: 'zoom-end', payload: WaveformZoomEndPayload): void;
47
50
  (event: 'zoom-reset', payload: WaveformZoomResetPayload): void;
@@ -2,6 +2,6 @@
2
2
  * 数据系统类型定义
3
3
  * 重新导出 src/types 中的类型,方便组件内部使用
4
4
  */
5
- export type { WaveformPoint, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformXDomainStrategy, WaveformZoomEndPayload, WaveformZoomResetPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformSamplingMode, WaveformSamplingStrategy, WaveformSamplingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformAxesOptions, WaveformZeroLineOptions, SingleWaveformData, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, ResolvedWaveformErrorBarOptions, WaveformTypedValues, TypedSampleData, TypedPointData, WaveformSeries, WaveformData, NormalizedWaveformSeries, } from '../../types';
5
+ export type { WaveformPoint, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformXDomainStrategy, WaveformZoomIntentPayload, WaveformZoomEndPayload, WaveformZoomResetPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformSamplingMode, WaveformSamplingStrategy, WaveformSamplingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformAxesOptions, WaveformZeroLineOptions, SingleWaveformData, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, ResolvedWaveformErrorBarOptions, WaveformTypedValues, TypedSampleData, TypedPointData, WaveformSeries, WaveformData, NormalizedWaveformSeries, } from '../../types';
6
6
  export type { WaveformGridOptions, WaveformGridLineOptions, WaveformGridTrackLines, } from '../core/grid';
7
7
  export { normalizeWaveformData, normalizeWaveformSeries } from '../../core';
@@ -1,5 +1,5 @@
1
1
  export { default as WaveformChart } from './WaveformChart.vue';
2
- export type { SingleWaveformData, WaveformData, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformZoomEndPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformAxesOptions, WaveformZeroLineOptions, WaveformPoint, WaveformSeries, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, WaveformGridOptions, WaveformGridLineOptions, WaveformGridTrackLines, } from './data/types';
2
+ export type { SingleWaveformData, WaveformData, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformZoomIntentPayload, WaveformZoomEndPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformAxesOptions, WaveformZeroLineOptions, WaveformPoint, WaveformSeries, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, WaveformGridOptions, WaveformGridLineOptions, WaveformGridTrackLines, } from './data/types';
3
3
  export type { WaveformGridOptions as WaveformGridConfig } from './core/grid';
4
4
  export { WaveformTooltip } from './interaction';
5
5
  export { WaveformTrack } from './rendering';
@@ -22,9 +22,10 @@ interface ZoomContext {
22
22
  }
23
23
  export declare function useWaveformZoom(context: ZoomContext): {
24
24
  cancelPendingZoom: () => void;
25
- clearZoomBindings: () => void;
25
+ clearZoomBindings: (preservePendingWheel?: boolean) => void;
26
26
  canZoomTrack: (track: TrackLayout) => boolean;
27
27
  canZoomSharedTracks: () => boolean;
28
28
  configureZoom: () => void;
29
+ prepareForDataChange: () => void;
29
30
  };
30
31
  export {};
@@ -0,0 +1,7 @@
1
+ import type { TrackLayout } from '../core/types';
2
+ import type { WaveformChartEmit } from '../core/waveformChartTypes';
3
+ export declare function seriesIdentity(seriesIds: readonly string[]): string;
4
+ export declare function findTrackBySeriesIds(trackLayouts: readonly TrackLayout[], seriesIds: readonly string[]): TrackLayout | undefined;
5
+ export declare function emitBoxZoomIntent(emit: WaveformChartEmit, domain: [number, number], track: TrackLayout, independent: boolean): void;
6
+ export declare function emitIndependentWheelZoomEnds(emit: WaveformChartEmit, trackLayouts: readonly TrackLayout[], pendingSeriesIds: Iterable<readonly string[]>): void;
7
+ export declare function emitSharedWheelZoomEnd(emit: WaveformChartEmit, domain: [number, number], trackLayouts: readonly TrackLayout[]): void;
@@ -1,4 +1,4 @@
1
- import type { WaveformPoint } from '@/types';
1
+ import type { WaveformPoint } from '../types';
2
2
  import type { ResolvedWaveformRenderingOptions } from './renderingOptions';
3
3
  import { type VisiblePointRange } from './renderingStrategies';
4
4
  export { DEFAULT_WAVEFORM_RENDERING_OPTIONS, resolveWaveformRenderingOptions, type ResolvedWaveformRenderingOptions, type ResolvedWaveformSamplingOptions, } from './renderingOptions';
@@ -1,4 +1,4 @@
1
- import type { WaveformRenderingOptions, WaveformSamplingMode, WaveformSamplingStrategy } from '@/types';
1
+ import type { WaveformRenderingOptions, WaveformSamplingMode, WaveformSamplingStrategy } from '../types';
2
2
  export interface ResolvedWaveformSamplingOptions {
3
3
  mode: WaveformSamplingMode;
4
4
  autoThreshold: number;
@@ -1,4 +1,4 @@
1
- import type { InitInput } from '../../wasm/pkg/waveform_sampling_wasm';
1
+ import type { InitInput } from '../wasm/waveform_sampling_wasm';
2
2
  import type { ReferenceSamplingStrategy } from './samplingReference';
3
3
  import type { WorkerSamplingBackend, WorkerSamplingOutput } from './workerSampling/protocol';
4
4
  export type WasmSamplingStrategy = ReferenceSamplingStrategy;
@@ -1,4 +1,4 @@
1
- import type { WaveformPoint } from '@/types';
1
+ import type { WaveformPoint } from '../../types';
2
2
  import type { WorkerSamplingOutput } from './protocol';
3
3
  export type IndexedSamplingStrategy = 'none' | 'peak' | 'lttb' | 'average' | 'min' | 'max' | 'minmax' | 'sum';
4
4
  export interface MultiResolutionSamplingIndexOptions {
@@ -1,4 +1,4 @@
1
- import type { WaveformPoint, WaveformLineType, WaveformPointType, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingMode, WaveformSamplingStrategy } from '@/types';
1
+ import type { WaveformPoint, WaveformLineType, WaveformPointType, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingMode, WaveformSamplingStrategy } from '../../types';
2
2
  import type { WorkerSamplingDataset } from '../waveformPointSource';
3
3
  export declare const DEFAULT_WORKER_SAMPLING_AUTO_THRESHOLD = 1000;
4
4
  export declare const DEFAULT_WORKER_SAMPLING_MAX_POINTS_PER_PIXEL = 4;
@@ -1,4 +1,4 @@
1
- import type { WaveformPoint } from '@/types';
1
+ import type { WaveformPoint } from '../../types';
2
2
  import type { WorkerSamplingDataset } from '../waveformPointSource';
3
3
  import type { WasmDatasetSamplingBackend } from '../wasmSampling';
4
4
  import { MultiResolutionSamplingIndex } from './multiresolution';
@@ -1,4 +1,4 @@
1
- import type { WaveformPoint } from '@/types';
1
+ import type { WaveformPoint } from '../../types';
2
2
  import { type WorkerSamplingBackendKind, type WorkerSamplingDatasetMetrics, type WorkerSamplingDiagnostics, type WorkerSamplingOutput, type WorkerSamplingSeriesRequest, type WorkerSamplingStatus } from './protocol';
3
3
  export declare function copyFinitePoints(points: readonly WaveformPoint[]): WaveformPoint[];
4
4
  export declare function metricsFor(points: readonly WaveformPoint[], inputPointCount: number): WorkerSamplingDatasetMetrics;
@@ -3,7 +3,7 @@
3
3
  * @packageDocumentation
4
4
  */
5
5
  export { default as WaveformChart } from './components/WaveformChart.vue';
6
- export type { WaveformPoint, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformXDomainStrategy, WaveformZoomEndPayload, WaveformZoomResetPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformSamplingMode, WaveformSamplingStrategy, WaveformSamplingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformXAxisLabelKind, WaveformXAxisLabelFormatterContext, WaveformXAxisLabelFormatter, WaveformAxesOptions, WaveformZeroLineOptions, SingleWaveformData, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, ResolvedWaveformErrorBarOptions, WaveformTypedValues, TypedSampleData, TypedPointData, WaveformSeries, WaveformData, NormalizedWaveformSeries, } from './types';
6
+ export type { WaveformPoint, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformXDomainStrategy, WaveformZoomIntentPayload, WaveformZoomEndPayload, WaveformZoomResetPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformSamplingMode, WaveformSamplingStrategy, WaveformSamplingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformXAxisLabelKind, WaveformXAxisLabelFormatterContext, WaveformXAxisLabelFormatter, WaveformAxesOptions, WaveformZeroLineOptions, SingleWaveformData, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, ResolvedWaveformErrorBarOptions, WaveformTypedValues, TypedSampleData, TypedPointData, WaveformSeries, WaveformData, NormalizedWaveformSeries, } from './types';
7
7
  export type { WaveformGridOptions, WaveformGridLineOptions, WaveformGridTrackLines, } from './components/core/grid';
8
8
  export { normalizeWaveformData, normalizeWaveformSeries } from './core';
9
9
  export { paddedDomain, buildMinorTicks, displayTime, formatEndpointTime, formatAxisTime, formatTooltipTime, resolveTrackGeometry, clamp, type TimeUnit, type TrackGeometry, } from './utils';
@@ -43,6 +43,14 @@ export interface WaveformZoomEndPayload {
43
43
  seriesIds?: string[];
44
44
  gesture?: 'wheel' | 'box';
45
45
  }
46
+ /** Describes the X-axis viewport targeted by a user zoom gesture before rendering settles. */
47
+ export interface WaveformZoomIntentPayload {
48
+ start: number;
49
+ end: number;
50
+ gesture: 'wheel' | 'box';
51
+ trackIndex?: number;
52
+ seriesIds?: string[];
53
+ }
46
54
  /** Identifies the viewport reset by a double-click gesture. */
47
55
  export interface WaveformZoomResetPayload {
48
56
  trackIndex?: number;
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * 类型定义统一导出
3
3
  */
4
- export type { WaveformPoint, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformXDomainStrategy, WaveformZoomEndPayload, WaveformZoomResetPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformSamplingMode, WaveformSamplingStrategy, WaveformSamplingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformXAxisLabelKind, WaveformXAxisLabelFormatterContext, WaveformXAxisLabelFormatter, WaveformAxesOptions, WaveformZeroLineOptions, } from './chart';
4
+ export type { WaveformPoint, WaveformDisplayMode, WaveformOverlayMode, WaveformInteractionMode, WaveformXDomainStrategy, WaveformZoomIntentPayload, WaveformZoomEndPayload, WaveformZoomResetPayload, WaveformAnnotationStyle, WaveformAnnotation, WaveformSamplingMode, WaveformSamplingStrategy, WaveformSamplingOptions, WaveformSamplingBackend, WaveformSamplingDiagnostics, WaveformSamplingError, WaveformRenderingOptions, WaveformPlotMargin, WaveformTitleTextStyle, WaveformTitleOptions, WaveformLegendPosition, WaveformLegendOrientation, WaveformLegendOptions, WaveformFrameStyle, WaveformXAxisLabelKind, WaveformXAxisLabelFormatterContext, WaveformXAxisLabelFormatter, WaveformAxesOptions, WaveformZeroLineOptions, } from './chart';
5
5
  export type { SingleWaveformData, WaveformLineType, WaveformLineStyle, WaveformPointType, WaveformErrorBarOptions, ResolvedWaveformErrorBarOptions, WaveformTypedValues, TypedSampleData, TypedPointData, WaveformSeries, WaveformData, NormalizedWaveformSeries, } from './data';
@@ -1,4 +1,4 @@
1
- import type { WaveformDisplayMode } from '@/types';
1
+ import type { WaveformDisplayMode } from '../types';
2
2
  /**
3
3
  * 轨道几何信息
4
4
  */
@@ -0,0 +1,74 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Returns [minimum X, maximum X, minimum Y, maximum Y], or an empty array for no valid points.
6
+ */
7
+ export function calculate_range(x: Float64Array, y: Float64Array): Float64Array;
8
+
9
+ export function dataset_index_bytes(handle: number): number;
10
+
11
+ export function dispose_all_datasets(): void;
12
+
13
+ export function dispose_dataset(handle: number): boolean;
14
+
15
+ /**
16
+ * Returns the half-open [start, end) range in the normalized ascending-X point sequence.
17
+ */
18
+ export function find_visible_range(x: Float64Array, y: Float64Array, domain_start: number, domain_end: number): Uint32Array;
19
+
20
+ export function register_dataset(x: Float64Array, y: Float64Array, index_max_bytes: number): number;
21
+
22
+ export function register_sample_dataset(y: Float64Array, source_indexes: Uint32Array, start_time: number, sample_rate: number, index_max_bytes: number): number;
23
+
24
+ export function sample_aggregates(x: Float64Array, y: Float64Array, strategy: number, target: number): Float64Array;
25
+
26
+ export function sample_dataset_aggregates(handle: number, start: number, end: number, strategy: number, target: number): Float64Array;
27
+
28
+ export function sample_dataset_indexes(handle: number, start: number, end: number, strategy: number, target: number): Uint32Array;
29
+
30
+ export function sample_indexes(x: Float64Array, y: Float64Array, strategy: number, target: number): Uint32Array;
31
+
32
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
33
+
34
+ export interface InitOutput {
35
+ readonly memory: WebAssembly.Memory;
36
+ readonly calculate_range: (a: number, b: number, c: number, d: number) => [number, number, number, number];
37
+ readonly dispose_dataset: (a: number) => number;
38
+ readonly find_visible_range: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
39
+ readonly register_dataset: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
40
+ readonly register_sample_dataset: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
41
+ readonly sample_aggregates: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
42
+ readonly sample_dataset_aggregates: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
43
+ readonly sample_dataset_indexes: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
44
+ readonly sample_indexes: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
45
+ readonly dispose_all_datasets: () => void;
46
+ readonly dataset_index_bytes: (a: number) => number;
47
+ readonly __wbindgen_externrefs: WebAssembly.Table;
48
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
49
+ readonly __externref_table_dealloc: (a: number) => void;
50
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
51
+ readonly __wbindgen_start: () => void;
52
+ }
53
+
54
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
55
+
56
+ /**
57
+ * Instantiates the given `module`, which can either be bytes or
58
+ * a precompiled `WebAssembly.Module`.
59
+ *
60
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
61
+ *
62
+ * @returns {InitOutput}
63
+ */
64
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
65
+
66
+ /**
67
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
68
+ * for everything else, calls `WebAssembly.instantiate` directly.
69
+ *
70
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
71
+ *
72
+ * @returns {Promise<InitOutput>}
73
+ */
74
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
@@ -0,0 +1,19 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const calculate_range: (a: number, b: number, c: number, d: number) => [number, number, number, number];
5
+ export const dispose_dataset: (a: number) => number;
6
+ export const find_visible_range: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
7
+ export const register_dataset: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
8
+ export const register_sample_dataset: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number];
9
+ export const sample_aggregates: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
10
+ export const sample_dataset_aggregates: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
11
+ export const sample_dataset_indexes: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
12
+ export const sample_indexes: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
13
+ export const dispose_all_datasets: () => void;
14
+ export const dataset_index_bytes: (a: number) => number;
15
+ export const __wbindgen_externrefs: WebAssembly.Table;
16
+ export const __wbindgen_malloc: (a: number, b: number) => number;
17
+ export const __externref_table_dealloc: (a: number) => void;
18
+ export const __wbindgen_free: (a: number, b: number, c: number) => void;
19
+ export const __wbindgen_start: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waveform-analysis",
3
- "version": "0.1.57",
3
+ "version": "0.1.59",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -22,6 +22,7 @@
22
22
  ],
23
23
  "type": "module",
24
24
  "dependencies": {
25
+ "@types/d3": "7.4.3",
25
26
  "ant-design-vue": "3.2.20",
26
27
  "d3": "^7.9.0",
27
28
  "vue-router": "^4.6.4",
@@ -33,7 +34,6 @@
33
34
  },
34
35
  "devDependencies": {
35
36
  "@eslint/js": "10.0.1",
36
- "@types/d3": "7.4.3",
37
37
  "@types/node": "26.1.1",
38
38
  "@vitejs/plugin-vue": "6.0.8",
39
39
  "@vitest/coverage-v8": "4.1.10",
@@ -57,7 +57,7 @@
57
57
  "build": "pnpm typecheck && pnpm build:lib && pnpm build:types && pnpm build:demo",
58
58
  "build:wasm": "wasm-pack build wasm --target web --release --out-dir pkg --locked",
59
59
  "build:lib": "vite build --config vite.lib.config.ts",
60
- "build:types": "node scripts/clean-types.mjs && vue-tsc -p tsconfig.lib.json",
60
+ "build:types": "node scripts/clean-types.mjs && vue-tsc -p tsconfig.lib.json && node scripts/prepare-package-types.mjs",
61
61
  "build:demo": "vite build",
62
62
  "preview": "vite preview --outDir dist-demo",
63
63
  "typecheck": "pnpm build:wasm && vue-tsc -b",
@@ -68,6 +68,7 @@
68
68
  "format": "prettier --write .",
69
69
  "format:check": "prettier --check .",
70
70
  "test": "pnpm build:wasm && vitest run",
71
- "test:coverage": "pnpm build:wasm && vitest run --coverage"
71
+ "test:coverage": "pnpm build:wasm && vitest run --coverage",
72
+ "test:package": "node scripts/test-package.mjs"
72
73
  }
73
74
  }
@@ -80,7 +80,7 @@ const {
80
80
  pageCount,
81
81
  currentPage,
82
82
  getPageSize,
83
- chartTracks,
83
+ pageableTracks,
84
84
  goToPage,
85
85
  annotationInteraction,
86
86
  editorDraft,
@@ -230,7 +230,7 @@ function handleChartPointerLeave() {
230
230
  :interactive="!isPresentationMode"
231
231
  :display-mode="displayMode"
232
232
  :interaction-mode="activeInteractionMode"
233
- :frame-number="resolveFrameNumber(track.index)"
233
+ :frame-number="resolveFrameNumber(track.id)"
234
234
  :frame-style="frameStyle"
235
235
  :axes="axes"
236
236
  :clean-view="isCleanView"
@@ -326,7 +326,7 @@ function handleChartPointerLeave() {
326
326
  aria-label="波形分页"
327
327
  :current="currentPage"
328
328
  :page-size="getPageSize(gridOptions)"
329
- :total="chartTracks.length"
329
+ :total="pageableTracks.length"
330
330
  :show-size-changer="false"
331
331
  :show-quick-jumper="false"
332
332
  @change="goToPage"
@@ -17,6 +17,7 @@ describe('waveform grid helpers', () => {
17
17
  showPagination: true,
18
18
  fillIncompleteLastRow: false,
19
19
  trackOrder: [],
20
+ hideEmptyTracks: false,
20
21
  trackLines: {},
21
22
  })
22
23
  expect(normalizeGridOptions({ rowCount: 0, columnCount: 99 })).toEqual({
@@ -25,8 +26,10 @@ describe('waveform grid helpers', () => {
25
26
  showPagination: true,
26
27
  fillIncompleteLastRow: false,
27
28
  trackOrder: [],
29
+ hideEmptyTracks: false,
28
30
  trackLines: {},
29
31
  })
32
+ expect(normalizeGridOptions({ hideEmptyTracks: true }).hideEmptyTracks).toBe(true)
30
33
  })
31
34
 
32
35
  it('normalizes track order by trimming, dropping blanks, and removing duplicates', () => {
@@ -11,6 +11,8 @@ export interface WaveformGridOptions {
11
11
  fillIncompleteLastRow?: boolean
12
12
  /** Stable grid slots. Empty IDs remain as empty chart frames and keep their page position. */
13
13
  trackOrder?: string[]
14
+ /** Omits ordered tracks without waveform series from layout and pagination. */
15
+ hideEmptyTracks?: boolean
14
16
  trackLines?: WaveformGridTrackLines
15
17
  }
16
18
 
@@ -38,6 +40,7 @@ export interface NormalizedWaveformGridOptions {
38
40
  showPagination: boolean
39
41
  fillIncompleteLastRow: boolean
40
42
  trackOrder?: string[]
43
+ hideEmptyTracks?: boolean
41
44
  trackLines: Record<string, NormalizedWaveformGridLineOptions>
42
45
  }
43
46
 
@@ -95,6 +98,7 @@ export function normalizeGridOptions(options?: WaveformGridOptions): NormalizedW
95
98
  showPagination: options?.showPagination ?? true,
96
99
  fillIncompleteLastRow: options?.fillIncompleteLastRow ?? false,
97
100
  trackOrder: normalizeTrackOrder(options?.trackOrder),
101
+ hideEmptyTracks: options?.hideEmptyTracks ?? false,
98
102
  trackLines,
99
103
  }
100
104
  }
@@ -0,0 +1,40 @@
1
+ import type { DisplayTrack } from './types'
2
+
3
+ export const resolvePageableTracks = (
4
+ tracks: DisplayTrack[],
5
+ hideEmptyTracks?: boolean,
6
+ ): DisplayTrack[] => (hideEmptyTracks ? tracks.filter((track) => track.series.length > 0) : tracks)
7
+
8
+ export const resolveTrackFrameNumber = (
9
+ frameNumber: string | number | undefined,
10
+ frameNumbers: Record<string, string | number> | undefined,
11
+ trackCount: number,
12
+ trackIndex: number,
13
+ trackId: string,
14
+ ): string | number | undefined => {
15
+ const mappedFrameNumber = frameNumbers?.[trackId]
16
+ if (mappedFrameNumber !== undefined) return mappedFrameNumber
17
+ if (frameNumber === undefined) return undefined
18
+ if (trackCount === 1) return frameNumber
19
+ return typeof frameNumber === 'number'
20
+ ? frameNumber + trackIndex
21
+ : `${frameNumber}-${trackIndex + 1}`
22
+ }
23
+
24
+ export const createFrameNumberResolver =
25
+ (
26
+ getFrameNumber: () => string | number | undefined,
27
+ getFrameNumbers: () => Record<string, string | number> | undefined,
28
+ getTracks: () => DisplayTrack[],
29
+ ) =>
30
+ (trackId: string): string | number | undefined => {
31
+ const tracks = getTracks()
32
+ const trackIndex = tracks.findIndex((track) => track.id === trackId)
33
+ return resolveTrackFrameNumber(
34
+ getFrameNumber(),
35
+ getFrameNumbers(),
36
+ tracks.length,
37
+ trackIndex >= 0 ? trackIndex : 0,
38
+ trackId,
39
+ )
40
+ }
@@ -87,9 +87,13 @@ export function useWaveformChartController(
87
87
  const pointerInsideChart = ref(false)
88
88
  let handleBeforeDataReferenceChange: () => void = () => undefined
89
89
  let handleDataReferenceChange: () => void = () => undefined
90
+ let prepareForDataChange: () => void = () => undefined
90
91
  const preparedSeries = usePreparedWaveformSeries(
91
92
  () => props.data,
92
- () => handleBeforeDataReferenceChange(),
93
+ () => {
94
+ prepareForDataChange()
95
+ handleBeforeDataReferenceChange()
96
+ },
93
97
  () => handleDataReferenceChange(),
94
98
  )
95
99
 
@@ -184,6 +188,7 @@ export function useWaveformChartController(
184
188
  resolveInitialTrackDomain,
185
189
  cancelPendingHover: () => hover.cancelPendingHover(),
186
190
  })
191
+ prepareForDataChange = zoom.prepareForDataChange
187
192
 
188
193
  const annotations = useWaveformChartAnnotations({
189
194
  props,
@@ -9,12 +9,12 @@ import {
9
9
  type ShallowRef,
10
10
  } from 'vue'
11
11
 
12
- import type { AnnotationSeriesCandidate } from '../annotation'
13
- import type { useWaveformAnnotationInteraction } from '../annotation'
12
+ import type { AnnotationSeriesCandidate, useWaveformAnnotationInteraction } from '../annotation'
14
13
  import type { NormalizedWaveformGridOptions } from './grid'
15
14
  import type { DisplaySeries, DisplayTrack, TrackLayout } from './types'
16
15
  import type { ResolvedWaveformChartProps, WaveformChartEmit } from './waveformChartTypes'
17
16
  import { constrainZoomDomain, transformForDomain } from '../interaction/zoomConstraints'
17
+ import { seriesIdentity } from '../interaction/zoomEventPayload'
18
18
 
19
19
  interface LifecycleContext {
20
20
  props: ResolvedWaveformChartProps
@@ -152,16 +152,20 @@ export function useWaveformChartLifecycle(context: LifecycleContext) {
152
152
  }
153
153
 
154
154
  let pendingSharedXDomain: [number, number] | undefined
155
- let pendingIndependentXDomains: Array<[number, number] | undefined> | undefined
155
+ let pendingIndependentXDomains: Map<string, [number, number]> | undefined
156
156
 
157
157
  function handleBeforeDataReferenceChange() {
158
158
  if (props.displayMode === 'independent') {
159
159
  pendingSharedXDomain = undefined
160
- pendingIndependentXDomains = trackLayouts.value.map((track) => {
161
- const current = track.xScale.domain() as [number, number]
162
- const boundary = resolveInitialTrackDomain(track)
163
- return current[1] - current[0] < boundary[1] - boundary[0] - 1e-12 ? current : undefined
164
- })
160
+ pendingIndependentXDomains = new Map(
161
+ trackLayouts.value.flatMap((track) => {
162
+ const current = track.xScale.domain() as [number, number]
163
+ const boundary = resolveInitialTrackDomain(track)
164
+ return current[1] - current[0] < boundary[1] - boundary[0] - 1e-12
165
+ ? [[seriesIdentity(track.seriesList.map((series) => series.id)), current]]
166
+ : []
167
+ }),
168
+ )
165
169
  return
166
170
  }
167
171
  pendingIndependentXDomains = undefined
@@ -184,7 +188,9 @@ export function useWaveformChartLifecycle(context: LifecycleContext) {
184
188
  if (props.displayMode === 'independent' && pendingIndependentXDomains) {
185
189
  const nextTransforms = chartTracks.value.map(() => zoomIdentity)
186
190
  trackLayouts.value.forEach((track) => {
187
- const previousDomain = pendingIndependentXDomains?.[track.index]
191
+ const previousDomain = pendingIndependentXDomains?.get(
192
+ seriesIdentity(track.seriesList.map((series) => series.id)),
193
+ )
188
194
  if (!previousDomain) return
189
195
  const boundary = resolveInitialTrackDomain(track)
190
196
  const domain = constrainZoomDomain(previousDomain, boundary, [track.seriesList], props)