Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7637f411d7 |
@@ -114,7 +114,7 @@ const data = ref<WaveformData>({
|
||||
| `xDomainStrategy` | `WaveformXDomainStrategy` | `{ type: 'data' }` | 自动 X 轴视口范围策略 |
|
||||
| `yDomain` | `[number, number]` | 未设置 | 所有波形的固定 Y 轴范围 |
|
||||
| `yDomains` | `Record<string, [number, number]>` | 未设置 | 按 track/series ID 配置固定范围 |
|
||||
| `grid` | `WaveformGridOptions` | `{ rowCount: 2, columnCount: 1, showPagination: true }` | 网格和分页 |
|
||||
| `grid` | `WaveformGridOptions` | `{ rowCount: 2, columnCount: 1, showPagination: true, fillIncompleteLastRow: false }` | 网格和分页 |
|
||||
| `axes` | `WaveformAxesOptions` | 轴线均显示 | X/Y 轴基线、Y 轴分割数与 X 轴 label 格式化 |
|
||||
| `rendering` | `WaveformRenderingOptions` | `{}` | 降采样与点/误差棒间距 |
|
||||
| `title` / `legend` / `frameStyle` | 对应公开类型 | 未设置 | 标题、图例和图框样式 |
|
||||
@@ -544,6 +544,10 @@ scale 定位零线:
|
||||
`grid` 控制独立图框的行列数(范围 `1–10`)以及是否显示分页器。默认值为 `2` 行、
|
||||
`1` 列并开启分页;当图框数量超过网格容量时,分页器会显示在图表右下角。
|
||||
|
||||
`fillIncompleteLastRow` 默认关闭。开启后,分页容量仍由 `rowCount * columnCount` 决定;
|
||||
最后一页或未满页会移除没有数据的整行,并将最后一行的实际图框等宽铺满可用宽度。例如 2 列
|
||||
网格的最后一行只有一个图框时,该图框会占满整行。完整页和关闭该选项时的布局保持不变。
|
||||
|
||||
还可以通过 `trackLines` 按轨道 ID 分别控制水平/垂直网格线的显隐和颜色。颜色未配置时,
|
||||
继续使用组件默认的主/次网格颜色:
|
||||
|
||||
@@ -554,6 +558,7 @@ scale 定位零线:
|
||||
rowCount: 2,
|
||||
columnCount: 2,
|
||||
showPagination: true,
|
||||
fillIncompleteLastRow: true,
|
||||
trackLines: {
|
||||
voltage: {
|
||||
horizontal: false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "waveform-analysis",
|
||||
"version": "0.1.41",
|
||||
"version": "0.1.42",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/types/index.d.ts",
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
/* The modal is teleported to body. Keep its entire subtree namespaced so host
|
||||
application resets (for example `button { ... }`) cannot change the editor. */
|
||||
:global(.waveform-annotation-editor-root),
|
||||
:global(.waveform-annotation-editor-root *) {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:global(.waveform-annotation-editor-root) {
|
||||
color: #344054;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||
'Noto Sans', sans-serif;
|
||||
line-height: 1.5715;
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
:global(.waveform-annotation-editor-root button),
|
||||
:global(.waveform-annotation-editor-root input),
|
||||
:global(.waveform-annotation-editor-root select),
|
||||
:global(.waveform-annotation-editor-root textarea) {
|
||||
font-family: inherit;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
:global(.waveform-annotation-editor-root button) {
|
||||
appearance: auto;
|
||||
}
|
||||
|
||||
.waveform-annotation-editor__content {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
|
||||
@@ -126,6 +126,7 @@ function handleSeriesChange(event: Event) {
|
||||
cancel-text="取消"
|
||||
ok-text="保存标注"
|
||||
:ok-button-props="{ disabled: !canConfirm }"
|
||||
root-class-name="waveform-annotation-editor-root"
|
||||
wrap-class-name="waveform-annotation-editor"
|
||||
@cancel="emit('cancel')"
|
||||
@ok="confirm"
|
||||
|
||||
@@ -18,13 +18,14 @@ const modalStub = defineComponent({
|
||||
'cancelText',
|
||||
'okText',
|
||||
'okButtonProps',
|
||||
'rootClassName',
|
||||
],
|
||||
emits: ['cancel', 'ok'],
|
||||
setup(props, { emit, slots }) {
|
||||
return () => {
|
||||
const title = slots.title?.() ?? []
|
||||
const titleId = (title[0]?.props as { id?: string } | undefined)?.id
|
||||
return h('div', { class: 'ant-modal-root' }, [
|
||||
return h('div', { class: ['ant-modal-root', props.rootClassName] }, [
|
||||
h(
|
||||
'div',
|
||||
{
|
||||
@@ -96,6 +97,18 @@ describe('waveform annotation controls', () => {
|
||||
expect(second.get('[role="dialog"]').attributes('aria-labelledby')).toBe(secondTitleId)
|
||||
})
|
||||
|
||||
it('uses a dedicated root class to isolate teleported modal styles', () => {
|
||||
const wrapper = mountEditor({
|
||||
props: {
|
||||
annotation: { id: 'isolated', seriesId: 'a', x: 1, y: 2, text: '说明' },
|
||||
mode: 'add',
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.get('.ant-modal-root').classes()).toContain('waveform-annotation-editor-root')
|
||||
expect(wrapper.get('.ant-modal-wrap').classes()).toContain('waveform-annotation-editor')
|
||||
})
|
||||
|
||||
it.each(['add', 'edit'] as const)('shows the X-axis snapping hint in %s mode', (mode) => {
|
||||
const wrapper = mountEditor({
|
||||
props: {
|
||||
|
||||
@@ -53,7 +53,13 @@ describe('fixed Y-domain layout', () => {
|
||||
series: sourceTrack,
|
||||
},
|
||||
],
|
||||
grid: { rowCount: 1, columnCount: 1, showPagination: false, trackLines: {} },
|
||||
grid: {
|
||||
rowCount: 1,
|
||||
columnCount: 1,
|
||||
showPagination: false,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
},
|
||||
displayMode: 'independent',
|
||||
overlayMode: 'single-axis',
|
||||
independentTransforms: [zoomIdentity],
|
||||
@@ -89,7 +95,13 @@ describe('fixed Y-domain layout', () => {
|
||||
series: track([series('a', 0, 100)]),
|
||||
},
|
||||
],
|
||||
grid: { rowCount: 1, columnCount: 1, showPagination: false, trackLines: {} },
|
||||
grid: {
|
||||
rowCount: 1,
|
||||
columnCount: 1,
|
||||
showPagination: false,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
},
|
||||
displayMode: 'independent',
|
||||
overlayMode: 'single-axis',
|
||||
independentTransforms: [zoomIdentity],
|
||||
@@ -124,7 +136,13 @@ describe('fixed Y-domain layout', () => {
|
||||
series: track([series('a', 3, 97)]),
|
||||
},
|
||||
],
|
||||
grid: { rowCount: 1, columnCount: 1, showPagination: false, trackLines: {} },
|
||||
grid: {
|
||||
rowCount: 1,
|
||||
columnCount: 1,
|
||||
showPagination: false,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
},
|
||||
displayMode: 'independent',
|
||||
overlayMode: 'single-axis',
|
||||
independentTransforms: [zoomIdentity],
|
||||
|
||||
@@ -15,12 +15,14 @@ describe('waveform grid helpers', () => {
|
||||
rowCount: 2,
|
||||
columnCount: 1,
|
||||
showPagination: true,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
})
|
||||
expect(normalizeGridOptions({ rowCount: 0, columnCount: 99 })).toEqual({
|
||||
rowCount: 1,
|
||||
columnCount: 10,
|
||||
showPagination: true,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
})
|
||||
})
|
||||
@@ -131,4 +133,50 @@ describe('waveform grid helpers', () => {
|
||||
expect(cells[1].left).toBe(232)
|
||||
expect(cells[2].top).toBe(cells[0].plotHeight + X_AXIS_BAND + 14)
|
||||
})
|
||||
|
||||
it('fills incomplete final rows without changing page capacity', () => {
|
||||
const oneColumn = resolveGridCellGeometry(
|
||||
400,
|
||||
400,
|
||||
normalizeGridOptions({ rowCount: 4, columnCount: 1, fillIncompleteLastRow: true }),
|
||||
'separated',
|
||||
[true, true, true],
|
||||
)
|
||||
expect(oneColumn).toHaveLength(3)
|
||||
expect(oneColumn.map((cell) => cell.width)).toEqual([400, 400, 400])
|
||||
expect(oneColumn.at(-1)?.isLastRow).toBe(true)
|
||||
|
||||
const twoColumns = resolveGridCellGeometry(
|
||||
400,
|
||||
300,
|
||||
normalizeGridOptions({ rowCount: 2, columnCount: 2, fillIncompleteLastRow: true }),
|
||||
'separated',
|
||||
[true, true, true],
|
||||
)
|
||||
expect(twoColumns).toHaveLength(3)
|
||||
expect(twoColumns[2]).toMatchObject({ row: 1, column: 0, left: 0, width: 400 })
|
||||
|
||||
const threeColumns = resolveGridCellGeometry(
|
||||
400,
|
||||
300,
|
||||
normalizeGridOptions({ rowCount: 2, columnCount: 3, fillIncompleteLastRow: true }),
|
||||
'separated',
|
||||
[true, true, true, true, true],
|
||||
)
|
||||
expect(threeColumns).toHaveLength(5)
|
||||
expect(threeColumns.slice(3).map((cell) => cell.width)).toEqual([192, 192])
|
||||
expect(threeColumns.slice(3).map((cell) => cell.left)).toEqual([0, 208])
|
||||
})
|
||||
|
||||
it('keeps full pages and the disabled option byte-for-byte compatible', () => {
|
||||
const base = normalizeGridOptions({ rowCount: 2, columnCount: 2 })
|
||||
const filled = normalizeGridOptions({ rowCount: 2, columnCount: 2, fillIncompleteLastRow: true })
|
||||
const fullSlots = [true, true, true, true]
|
||||
expect(resolveGridCellGeometry(400, 300, filled, 'independent', fullSlots)).toEqual(
|
||||
resolveGridCellGeometry(400, 300, base, 'independent', fullSlots),
|
||||
)
|
||||
expect(resolveGridCellGeometry(400, 300, base, 'independent', [true, true, true])).toHaveLength(
|
||||
4,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface WaveformGridOptions {
|
||||
rowCount?: number
|
||||
columnCount?: number
|
||||
showPagination?: boolean
|
||||
fillIncompleteLastRow?: boolean
|
||||
trackLines?: WaveformGridTrackLines
|
||||
}
|
||||
|
||||
@@ -33,6 +34,7 @@ export interface NormalizedWaveformGridOptions {
|
||||
rowCount: number
|
||||
columnCount: number
|
||||
showPagination: boolean
|
||||
fillIncompleteLastRow: boolean
|
||||
trackLines: Record<string, NormalizedWaveformGridLineOptions>
|
||||
}
|
||||
|
||||
@@ -48,6 +50,7 @@ export interface GridCellGeometry {
|
||||
plotHeight: number
|
||||
cellHeight: number
|
||||
xAxisBand: number
|
||||
isLastRow?: boolean
|
||||
}
|
||||
|
||||
const normalizeCount = (value: unknown, fallback: number) => {
|
||||
@@ -78,6 +81,7 @@ export function normalizeGridOptions(options?: WaveformGridOptions): NormalizedW
|
||||
rowCount: normalizeCount(options?.rowCount, 2),
|
||||
columnCount: normalizeCount(options?.columnCount, 1),
|
||||
showPagination: options?.showPagination ?? true,
|
||||
fillIncompleteLastRow: options?.fillIncompleteLastRow ?? false,
|
||||
trackLines,
|
||||
}
|
||||
}
|
||||
@@ -114,20 +118,23 @@ export function resolveGridCellGeometry(
|
||||
horizontalGap?: number,
|
||||
showXAxis = true,
|
||||
): GridCellGeometry[] {
|
||||
const pageSize = getPageSize(options)
|
||||
const seriesCount = slotHasSeries.filter(Boolean).length
|
||||
const filledLastRow = options.fillIncompleteLastRow && seriesCount > 0 && seriesCount < pageSize
|
||||
const rowCount = filledLastRow ? Math.ceil(seriesCount / options.columnCount) : options.rowCount
|
||||
const defaultGap = getGridGap(displayMode)
|
||||
const columnGap = Number.isFinite(horizontalGap)
|
||||
? Math.max(0, horizontalGap as number)
|
||||
: defaultGap
|
||||
const totalHorizontalGap = Math.max(0, options.columnCount - 1) * columnGap
|
||||
const axisRows = new Set<number>()
|
||||
if (!showXAxis) {
|
||||
// Net view uses the full drawing area for waveform pixels.
|
||||
} else if (displayMode === 'independent') {
|
||||
for (let row = 0; row < options.rowCount; row += 1) axisRows.add(row)
|
||||
for (let row = 0; row < rowCount; row += 1) axisRows.add(row)
|
||||
} else if (displayMode === 'compact') {
|
||||
// Compact tracks share one continuous plot stack. Reserve the X-axis band
|
||||
// only beneath the final grid row, including when that row is empty.
|
||||
axisRows.add(options.rowCount - 1)
|
||||
axisRows.add(rowCount - 1)
|
||||
} else {
|
||||
for (let column = 0; column < options.columnCount; column += 1) {
|
||||
for (let slotIndex = getPageSize(options) - 1; slotIndex >= 0; slotIndex -= 1) {
|
||||
@@ -139,17 +146,22 @@ export function resolveGridCellGeometry(
|
||||
}
|
||||
}
|
||||
}
|
||||
const totalVerticalGap = Math.max(0, options.rowCount - 1) * defaultGap
|
||||
const totalVerticalGap = Math.max(0, rowCount - 1) * defaultGap
|
||||
const totalAxisBand = axisRows.size * X_AXIS_BAND
|
||||
const width = Math.max(1, (innerWidth - totalHorizontalGap) / options.columnCount)
|
||||
const plotHeight = Math.max(
|
||||
1,
|
||||
(innerHeight - totalVerticalGap - totalAxisBand) / options.rowCount,
|
||||
(innerHeight - totalVerticalGap - totalAxisBand) / rowCount,
|
||||
)
|
||||
|
||||
return Array.from({ length: getPageSize(options) }, (_, slotIndex) => {
|
||||
return Array.from({ length: filledLastRow ? seriesCount : pageSize }, (_, slotIndex) => {
|
||||
const row = Math.floor(slotIndex / options.columnCount)
|
||||
const column = slotIndex % options.columnCount
|
||||
const rowSeriesCount =
|
||||
filledLastRow && row === rowCount - 1
|
||||
? seriesCount - row * options.columnCount
|
||||
: options.columnCount
|
||||
const rowGap = Math.max(0, rowSeriesCount - 1) * columnGap
|
||||
const width = Math.max(1, (innerWidth - rowGap) / rowSeriesCount)
|
||||
const xAxisBand = axisRows.has(row) ? X_AXIS_BAND : 0
|
||||
const cellHeight = plotHeight + xAxisBand
|
||||
const top = Array.from({ length: row }, (_, previousRow) => {
|
||||
@@ -167,6 +179,7 @@ export function resolveGridCellGeometry(
|
||||
plotHeight,
|
||||
cellHeight,
|
||||
xAxisBand,
|
||||
isLastRow: row === rowCount - 1,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -65,7 +65,13 @@ function layoutForSeries(
|
||||
series: sourceTrack,
|
||||
},
|
||||
],
|
||||
grid: { rowCount: 1, columnCount: 1, showPagination: false, trackLines: {} },
|
||||
grid: {
|
||||
rowCount: 1,
|
||||
columnCount: 1,
|
||||
showPagination: false,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
},
|
||||
displayMode: 'independent',
|
||||
overlayMode: 'single-axis',
|
||||
independentTransforms: [transform],
|
||||
@@ -107,7 +113,13 @@ describe('multi-value Y-axis grouping', () => {
|
||||
series: sourceTrack,
|
||||
},
|
||||
],
|
||||
grid: { rowCount: 1, columnCount: 1, showPagination: false, trackLines: {} },
|
||||
grid: {
|
||||
rowCount: 1,
|
||||
columnCount: 1,
|
||||
showPagination: false,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
},
|
||||
displayMode: 'independent',
|
||||
overlayMode: 'single-axis',
|
||||
independentTransforms: [zoomIdentity],
|
||||
@@ -217,7 +229,13 @@ describe('multi-value Y-axis grouping', () => {
|
||||
series: track([series('left', 1000, 3000), series('right', 1000, 3000)]),
|
||||
},
|
||||
],
|
||||
grid: { rowCount: 1, columnCount: 1, showPagination: false, trackLines: {} },
|
||||
grid: {
|
||||
rowCount: 1,
|
||||
columnCount: 1,
|
||||
showPagination: false,
|
||||
fillIncompleteLastRow: false,
|
||||
trackLines: {},
|
||||
},
|
||||
displayMode: 'independent',
|
||||
overlayMode: 'multi-axis',
|
||||
independentTransforms: [zoomIdentity],
|
||||
|
||||
@@ -266,7 +266,7 @@ export function buildTrackLayouts(options: BuildTrackLayoutsOptions): TrackLayou
|
||||
(isEmpty || hasVisibleSeries) &&
|
||||
(options.displayMode === 'independent' ||
|
||||
(options.displayMode === 'compact'
|
||||
? cell.row === options.grid.rowCount - 1
|
||||
? (cell.isLastRow ?? cell.row === options.grid.rowCount - 1)
|
||||
: bottomCells.has(cell.slotIndex))),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
|
||||
import type { AnnotationSeriesCandidate } from '../annotation'
|
||||
import type { useWaveformAnnotationInteraction } from '../annotation'
|
||||
import type { NormalizedWaveformGridOptions } from './grid'
|
||||
import type { DisplaySeries, DisplayTrack, TrackLayout } from './types'
|
||||
import type { ResolvedWaveformChartProps, WaveformChartEmit } from './waveformChartTypes'
|
||||
import { constrainZoomDomain, transformForDomain } from '../interaction/zoomConstraints'
|
||||
@@ -33,7 +34,7 @@ interface LifecycleContext {
|
||||
currentPage: Ref<number>
|
||||
pageCount: ComputedRef<number>
|
||||
pagedTracks: ComputedRef<Array<DisplayTrack | undefined>>
|
||||
gridOptions: ComputedRef<{ rowCount: number; columnCount: number }>
|
||||
gridOptions: ComputedRef<NormalizedWaveformGridOptions>
|
||||
chartSeries: ComputedRef<DisplaySeries[]>
|
||||
chartTracks: ComputedRef<DisplayTrack[]>
|
||||
trackLayouts: ComputedRef<TrackLayout[]>
|
||||
@@ -220,6 +221,7 @@ export function useWaveformChartLifecycle(context: LifecycleContext) {
|
||||
currentPage,
|
||||
() => gridOptions.value.rowCount,
|
||||
() => gridOptions.value.columnCount,
|
||||
() => gridOptions.value.fillIncompleteLastRow,
|
||||
activeInteractionMode,
|
||||
],
|
||||
async () => {
|
||||
@@ -239,7 +241,14 @@ export function useWaveformChartLifecycle(context: LifecycleContext) {
|
||||
},
|
||||
)
|
||||
|
||||
watch([pageCount, () => props.grid?.rowCount, () => props.grid?.columnCount], () => {
|
||||
watch(
|
||||
[
|
||||
pageCount,
|
||||
() => props.grid?.rowCount,
|
||||
() => props.grid?.columnCount,
|
||||
() => props.grid?.fillIncompleteLastRow,
|
||||
],
|
||||
() => {
|
||||
const previousPage = currentPage.value
|
||||
currentPage.value =
|
||||
currentPage.value > pageCount.value
|
||||
@@ -252,7 +261,8 @@ export function useWaveformChartLifecycle(context: LifecycleContext) {
|
||||
}
|
||||
clearHover()
|
||||
void nextTick(configureZoom)
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
watch(activeInteractionMode, () => {
|
||||
editorSeriesOptions.value = []
|
||||
|
||||
95
src/components/waveformChartCases/gridFill.test.ts
Normal file
95
src/components/waveformChartCases/gridFill.test.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { gridSeries, mountSizedChart } from '../../test/waveformChart'
|
||||
|
||||
function geometry(track: { attributes: (name: string) => string | undefined }) {
|
||||
return {
|
||||
left: Number(track.attributes('data-track-left')),
|
||||
top: Number(track.attributes('data-track-top')),
|
||||
width: Number(track.attributes('data-track-width')),
|
||||
height: Number(track.attributes('data-track-height')),
|
||||
}
|
||||
}
|
||||
|
||||
describe('WaveformChart incomplete grid rows', () => {
|
||||
it.each(['independent', 'separated', 'compact'] as const)(
|
||||
'fills an incomplete two by two row in %s mode',
|
||||
async (displayMode) => {
|
||||
const wrapper = await mountSizedChart(gridSeries(3), {
|
||||
displayMode,
|
||||
grid: { rowCount: 2, columnCount: 2, fillIncompleteLastRow: true },
|
||||
})
|
||||
const tracks = wrapper.findAll('.waveform-chart__track')
|
||||
const first = geometry(tracks[0]!)
|
||||
const last = geometry(tracks[2]!)
|
||||
|
||||
expect(tracks).toHaveLength(3)
|
||||
expect(wrapper.findAll('.waveform-chart__track--empty')).toHaveLength(0)
|
||||
expect(wrapper.findAll('.waveform-chart__grid-slot-placeholder')).toHaveLength(0)
|
||||
expect(last.left).toBe(0)
|
||||
expect(last.width).toBeGreaterThan(first.width * 1.8)
|
||||
expect(last.top).toBeGreaterThan(first.top)
|
||||
if (displayMode === 'independent') {
|
||||
const overlays = wrapper.findAll('.waveform-chart__overlay--independent')
|
||||
expect(overlays).toHaveLength(3)
|
||||
expect(Number(overlays[2]?.attributes('width'))).toBe(last.width)
|
||||
} else {
|
||||
expect(wrapper.findAll('.waveform-chart__overlay--shared')).toHaveLength(1)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
it('removes unused one-column rows and redistributes chart height', async () => {
|
||||
const base = await mountSizedChart(gridSeries(3), {
|
||||
displayMode: 'independent',
|
||||
grid: { rowCount: 4, columnCount: 1 },
|
||||
})
|
||||
const filled = await mountSizedChart(gridSeries(3), {
|
||||
displayMode: 'independent',
|
||||
grid: { rowCount: 4, columnCount: 1, fillIncompleteLastRow: true },
|
||||
})
|
||||
const baseFirst = geometry(base.findAll('.waveform-chart__track')[0]!)
|
||||
const filledTracks = filled.findAll('.waveform-chart__track')
|
||||
const filledFirst = geometry(filledTracks[0]!)
|
||||
const filledLast = geometry(filledTracks[2]!)
|
||||
|
||||
expect(filledTracks).toHaveLength(3)
|
||||
expect(filledFirst.height).toBeGreaterThan(baseFirst.height)
|
||||
expect(filledLast.top + filledLast.height).toBeGreaterThan(baseFirst.height * 3)
|
||||
})
|
||||
|
||||
it('keeps the final two tracks evenly distributed in a two by three grid', async () => {
|
||||
const wrapper = await mountSizedChart(gridSeries(5), {
|
||||
displayMode: 'separated',
|
||||
grid: { rowCount: 2, columnCount: 3, fillIncompleteLastRow: true },
|
||||
})
|
||||
const tracks = wrapper.findAll('.waveform-chart__track').map(geometry)
|
||||
|
||||
expect(tracks).toHaveLength(5)
|
||||
expect(tracks[3]?.left).toBe(0)
|
||||
expect(tracks[3]?.width).toBeCloseTo(tracks[4]?.width ?? 0)
|
||||
expect(tracks[4]?.left).toBeGreaterThan((tracks[3]?.width ?? 0) + 1)
|
||||
})
|
||||
|
||||
it('keeps full pages unchanged and fills a partial second page', async () => {
|
||||
const data = gridSeries(5)
|
||||
const standard = await mountSizedChart(data, {
|
||||
displayMode: 'separated',
|
||||
grid: { rowCount: 2, columnCount: 2 },
|
||||
})
|
||||
const filled = await mountSizedChart(data, {
|
||||
displayMode: 'separated',
|
||||
grid: { rowCount: 2, columnCount: 2, fillIncompleteLastRow: true },
|
||||
})
|
||||
const standardFirstPage = standard.findAll('.waveform-chart__track').map(geometry)
|
||||
expect(filled.findAll('.waveform-chart__track').map(geometry)).toEqual(standardFirstPage)
|
||||
|
||||
await filled.get('.ant-pagination-next button').trigger('click')
|
||||
await flushPromises()
|
||||
const secondPage = filled.findAll('.waveform-chart__track').map(geometry)
|
||||
expect(secondPage).toHaveLength(1)
|
||||
expect(secondPage[0]?.left).toBe(0)
|
||||
expect(secondPage[0]?.width).toBeGreaterThan(standardFirstPage[0]?.width ?? 0)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user