diff --git a/projects/packages/premium-analytics/changelog/remove-period-step-arrows b/projects/packages/premium-analytics/changelog/remove-period-step-arrows new file mode 100644 index 000000000000..eabeef518231 --- /dev/null +++ b/projects/packages/premium-analytics/changelog/remove-period-step-arrows @@ -0,0 +1,4 @@ +Significance: minor +Type: removed + +Remove the arrows that stepped the date range back and forward a period. diff --git a/projects/packages/premium-analytics/packages/datetime/README.md b/projects/packages/premium-analytics/packages/datetime/README.md index fe4dc2a7e988..0df9f7b24a91 100644 --- a/projects/packages/premium-analytics/packages/datetime/README.md +++ b/projects/packages/premium-analytics/packages/datetime/README.md @@ -197,7 +197,7 @@ same window as an earlier one is dropped. Each option carries the resolved **Returns:** `ComparisonOption[]` - Empty when the range is incomplete or inverted -### Range Measurement and Stepping +### Range Measurement #### `getDateRangeSpan( range? )` @@ -215,22 +215,6 @@ A whole-month range stays in days below two months and only collapses into years from two years up, so "Last 30 days" reads as 30 days and a twelve-month window as 12 months. -#### `stepDateRange( range, direction )` - -Shifts a range backward or forward (`'previous' | 'next'`) by its own length. -Steps move in calendar units, so a step across a DST boundary keeps the wall -clock; where a calendar step cannot be undone, it falls back to whole days. -Returns `undefined` when the range has no measurable span. - -```typescript -stepDateRange( { from, to }, 'previous' ); // Last 7 days -> the 7 days before -``` - -#### `canStepForward( range, now )` - -Whether the next window has already happened in full. Pass the site's `now`, -not the browser's. - ## Types ### `DateRange` diff --git a/projects/packages/premium-analytics/packages/datetime/src/__tests__/get-comparison-range.test.ts b/projects/packages/premium-analytics/packages/datetime/src/__tests__/get-comparison-range.test.ts index 5b668b729484..48c97c2f7637 100644 --- a/projects/packages/premium-analytics/packages/datetime/src/__tests__/get-comparison-range.test.ts +++ b/projects/packages/premium-analytics/packages/datetime/src/__tests__/get-comparison-range.test.ts @@ -7,7 +7,6 @@ import { differenceInDays } from 'date-fns'; */ import { getDateRangeSpan } from '../date-range-span'; import { COMPARISON_PRESETS, getComparisonRangeFromPreset } from '../get-comparison-range'; -import { stepDateRange } from '../step-date-range'; import { createTZDateFromParts } from '../tz'; describe( 'getComparisonRangeFromPreset', () => { @@ -389,8 +388,7 @@ describe( 'getComparisonRangeFromPreset', () => { it( 'falls back to the day count where a month step will not reverse', () => { // 31 January through 30 March measures as two months, but two months // back from 31 January clamps to 30 November: 62 days against the - // reference's 59. The step arrows count days there, and a comparison - // naming a different window than the arrow would is a defect. + // reference's 59, so the comparison counts days instead. const clamping = { from: new Date( 2026, 0, 31, 0, 0, 0, 0 ), to: new Date( 2026, 2, 30, 23, 59, 59, 999 ), @@ -401,7 +399,6 @@ describe( 'getComparisonRangeFromPreset', () => { }; expect( getComparisonRangeFromPreset( clamping, 'previous-period' ) ).toEqual( expected ); - expect( stepDateRange( clamping, 'previous' ) ).toEqual( expected ); } ); it( 'ends the previous whole months on a month end, whatever day the reference ends on', () => { diff --git a/projects/packages/premium-analytics/packages/datetime/src/__tests__/step-date-range.test.ts b/projects/packages/premium-analytics/packages/datetime/src/__tests__/step-date-range.test.ts deleted file mode 100644 index e08e6339436b..000000000000 --- a/projects/packages/premium-analytics/packages/datetime/src/__tests__/step-date-range.test.ts +++ /dev/null @@ -1,215 +0,0 @@ -/** - * External dependencies - */ -import { TZDate } from '@date-fns/tz'; -import { differenceInCalendarDays } from 'date-fns'; -/** - * Internal dependencies - */ -import { canStepForward, stepDateRange } from '../step-date-range'; -import type { DateRange } from '../get-comparison-range'; - -/** - * Build a local-time date, so day boundaries land in the machine's timezone the - * way the span helper reads them. - * - * @param year - Full year. - * @param month - 1-based month. - * @param day - Day of the month. - * @param hour - Hour of the day. - * @param minute - Minute of the hour. - * @return The date. - */ -function at( year: number, month: number, day: number, hour = 0, minute = 0 ): Date { - return new Date( year, month - 1, day, hour, minute ); -} - -/** - * A range covering whole days, which is what a preset produces. - * - * @param from - First day. - * @param to - Last day. - * @return The inclusive whole-day range. - */ -function wholeDays( from: Date, to: Date ) { - return { - from: new Date( from.getFullYear(), from.getMonth(), from.getDate(), 0, 0, 0, 0 ), - to: new Date( to.getFullYear(), to.getMonth(), to.getDate(), 23, 59, 59, 999 ), - }; -} - -describe( 'stepDateRange', () => { - it( 'moves a day-scale window by its own length', () => { - const range = wholeDays( at( 2026, 7, 21 ), at( 2026, 7, 27 ) ); - - const previous = stepDateRange( range, 'previous' ); - - expect( previous?.from ).toEqual( wholeDays( at( 2026, 7, 14 ), at( 2026, 7, 20 ) ).from ); - expect( previous?.to ).toEqual( wholeDays( at( 2026, 7, 14 ), at( 2026, 7, 20 ) ).to ); - } ); - - it( 'moves an hour-snapped window by its full length', () => { - // `last-24-hours`: hour boundaries, a millisecond short of 24 hours. - const range = { - from: at( 2026, 7, 9, 19 ), - to: new Date( 2026, 6, 10, 18, 59, 59, 999 ), - }; - - const previous = stepDateRange( range, 'previous' ); - - expect( previous?.from ).toEqual( at( 2026, 7, 8, 19 ) ); - expect( previous?.to ).toEqual( new Date( 2026, 6, 9, 18, 59, 59, 999 ) ); - } ); - - it( 'moves a month-scale window by calendar months, not by days', () => { - // A whole year: stepping back has to land on the same days of the month. - const range = wholeDays( at( 2026, 1, 1 ), at( 2026, 12, 31 ) ); - - const previous = stepDateRange( range, 'previous' ); - - expect( previous?.from.getFullYear() ).toBe( 2025 ); - expect( previous?.from.getMonth() ).toBe( 0 ); - expect( previous?.from.getDate() ).toBe( 1 ); - expect( previous?.to.getMonth() ).toBe( 11 ); - expect( previous?.to.getDate() ).toBe( 31 ); - } ); - - it( 'steps a sub-day window by hours', () => { - const range = { from: at( 2026, 7, 27, 9 ), to: at( 2026, 7, 28, 9 ) }; - - const previous = stepDateRange( range, 'previous' ); - - expect( previous?.from ).toEqual( at( 2026, 7, 26, 9 ) ); - expect( previous?.to ).toEqual( at( 2026, 7, 27, 9 ) ); - } ); - - /* - * A property rather than one example because of clamping: `addMonths` shortens - * a day the target month cannot hold, and the clamp does not undo. - */ - describe( 'is reversible', () => { - const cases = [ - [ 'days', wholeDays( at( 2026, 7, 21 ), at( 2026, 7, 27 ) ) ], - [ 'whole months', wholeDays( at( 2026, 1, 1 ), at( 2026, 12, 31 ) ) ], - [ 'months from a 31st', wholeDays( at( 2026, 8, 31 ), at( 2026, 10, 30 ) ) ], - [ 'a leap February', wholeDays( at( 2024, 1, 31 ), at( 2024, 3, 30 ) ) ], - [ 'hours', { from: at( 2026, 7, 27, 9 ), to: at( 2026, 7, 28, 9 ) } ], - ] as const; - - it.each( cases )( 'returns to the starting window across %s', ( _name, range ) => { - const back = stepDateRange( range, 'previous' ); - const forward = back && stepDateRange( back, 'next' ); - - expect( forward?.from ).toEqual( range.from ); - expect( forward?.to ).toEqual( range.to ); - } ); - - it.each( cases )( 'returns from several steps out across %s', ( _name, range ) => { - let moved: typeof range | undefined = range; - - for ( let i = 0; i < 3; i++ ) { - moved = moved && ( stepDateRange( moved, 'previous' ) as typeof range ); - } - for ( let i = 0; i < 3; i++ ) { - moved = moved && ( stepDateRange( moved, 'next' ) as typeof range ); - } - - expect( moved?.from ).toEqual( range.from ); - expect( moved?.to ).toEqual( range.to ); - } ); - } ); - - /* - * Counted in calendar days, not elapsed milliseconds: a window crossing a DST - * change is an hour longer, and the step preserves the days a reader sees. - */ - it( 'preserves the window length when a calendar step would clamp', () => { - const range = wholeDays( at( 2026, 8, 31 ), at( 2026, 10, 30 ) ); - - const previous = stepDateRange( range, 'previous' ); - const daysIn = ( r?: DateRange ) => - r?.from && r.to ? differenceInCalendarDays( r.to, r.from ) : null; - - expect( daysIn( previous ) ).toBe( daysIn( range ) ); - } ); - - it( 'returns undefined for a range it cannot measure', () => { - expect( - stepDateRange( { from: undefined, to: at( 2026, 7, 27 ) }, 'previous' ) - ).toBeUndefined(); - expect( stepDateRange( { from: at( 2026, 7, 21 ), to: undefined }, 'next' ) ).toBeUndefined(); - expect( stepDateRange( {}, 'next' ) ).toBeUndefined(); - } ); -} ); - -describe( 'canStepForward', () => { - const now = at( 2026, 7, 27, 12 ); - - /* - * Live presets end in the future (`Last 24 hours`, `today`) or before the - * present (`Last 7 days`), yet all are the latest window available. - */ - it( 'is false on a rolling window whose end has just gone stale', () => { - const to = at( 2026, 7, 27, 11, 59 ); - - expect( canStepForward( { from: at( 2026, 7, 26, 11, 59 ), to }, now ) ).toBe( false ); - } ); - - // The live window ends in the future on purpose; counting that bucket is what - // keeps it reachable after a step back. - it( 'is true on the window right behind a live hour-snapped one', () => { - const live = { - from: at( 2026, 7, 26, 13 ), - to: new Date( 2026, 6, 27, 12, 59, 59, 999 ), - }; - const back = stepDateRange( live, 'previous' ); - - expect( canStepForward( live, now ) ).toBe( false ); - expect( canStepForward( back!, now ) ).toBe( true ); - } ); - - it( 'is true on yesterday while today is still running', () => { - const today = wholeDays( at( 2026, 7, 27 ), at( 2026, 7, 27 ) ); - const yesterday = stepDateRange( today, 'previous' ); - - expect( canStepForward( today, now ) ).toBe( false ); - expect( canStepForward( yesterday!, now ) ).toBe( true ); - } ); - - it( 'closes the bucket on the window timezone, not the machine one', () => { - const site = '+00:00'; - const yesterday = { - from: new TZDate( 2026, 6, 26, 0, 0, 0, 0, site ), - to: new TZDate( 2026, 6, 26, 23, 59, 59, 999, site ), - }; - // 02:00 UTC on the next site day, whatever timezone runs the tests. - const nowInstant = new Date( Date.UTC( 2026, 6, 27, 2, 0 ) ); - - expect( canStepForward( yesterday, nowInstant ) ).toBe( true ); - } ); - - it( 'is false on a window ending at the end of yesterday', () => { - const range = wholeDays( at( 2026, 7, 20 ), at( 2026, 7, 26 ) ); - - expect( canStepForward( range, now ) ).toBe( false ); - } ); - - it( 'is true once the window has been stepped back', () => { - const range = wholeDays( at( 2026, 7, 13 ), at( 2026, 7, 19 ) ); - - expect( canStepForward( range, now ) ).toBe( true ); - } ); - - // Stepping forward from there lands on the latest window, which is where the - // control has to disappear again. - it( 'turns false again on the window a forward step lands on', () => { - const range = wholeDays( at( 2026, 7, 13 ), at( 2026, 7, 19 ) ); - const next = stepDateRange( range, 'next' ); - - expect( canStepForward( next!, now ) ).toBe( false ); - } ); - - it( 'is false without an end to step from', () => { - expect( canStepForward( { from: at( 2026, 7, 14 ), to: undefined }, now ) ).toBe( false ); - } ); -} ); diff --git a/projects/packages/premium-analytics/packages/datetime/src/__tests__/to-date-range.test.ts b/projects/packages/premium-analytics/packages/datetime/src/__tests__/to-date-range.test.ts index 50a920b477fb..e44f0a689e98 100644 --- a/projects/packages/premium-analytics/packages/datetime/src/__tests__/to-date-range.test.ts +++ b/projects/packages/premium-analytics/packages/datetime/src/__tests__/to-date-range.test.ts @@ -6,7 +6,7 @@ import { TZDate } from '@date-fns/tz'; * Internal dependencies */ import { getDateRangeSpan } from '../date-range-span'; -import { clampRangeEndToToday, completeToDateRange } from '../to-date-range'; +import { completeToDateRange } from '../to-date-range'; /** * A zone away from UTC, so a boundary computed on the wrong clock lands on a @@ -92,47 +92,3 @@ describe( 'completeToDateRange', () => { expect( completeToDateRange( open, 'last-12-months' ) ).toBe( open ); } ); } ); - -describe( 'clampRangeEndToToday', () => { - // Where a forward step out of "12 months" lands: the running month closed, - // which reaches eleven days past the day it was taken on. - const steppedForward = { from: at( 2025, 9, 1 ), to: endOf( 2026, 8, 31 ) }; - const noon = new TZDate( 2026, 7, 20, 12, 0, 0, 0, TIMEZONE ); - - it( 'pulls a window ending after today back to the end of today', () => { - expect( clampRangeEndToToday( steppedForward, noon ) ).toEqual( { - from: at( 2025, 9, 1 ), - to: endOf( 2026, 8, 20 ), - } ); - } ); - - it( 'closes the day on the window’s own clock', () => { - // 02:00 UTC is still the 26th in New York, so a clamp read on the - // browser's clock would leave the window a day long. - const clamped = clampRangeEndToToday( - steppedForward, - new Date( Date.UTC( 2026, 7, 27, 2, 0 ) ) - ); - - expect( clamped.to ).toEqual( endOf( 2026, 8, 26 ) ); - expect( clamped.to ).toBeInstanceOf( TZDate ); - } ); - - it( 'leaves a window that already ends today where it is', () => { - const toDate = { from: at( 2025, 9, 1 ), to: endOf( 2026, 8, 20 ) }; - - expect( clampRangeEndToToday( toDate, noon ) ).toBe( toDate ); - } ); - - it( 'leaves a window ending in the past where it is', () => { - const past = { from: at( 2024, 9, 1 ), to: endOf( 2025, 8, 31 ) }; - - expect( clampRangeEndToToday( past, noon ) ).toBe( past ); - } ); - - it( 'returns a range without an end untouched', () => { - const open = { from: at( 2025, 9, 1 ) }; - - expect( clampRangeEndToToday( open, noon ) ).toBe( open ); - } ); -} ); diff --git a/projects/packages/premium-analytics/packages/datetime/src/get-comparison-range.ts b/projects/packages/premium-analytics/packages/datetime/src/get-comparison-range.ts index b57b68a0e818..6a8d2b78999b 100644 --- a/projects/packages/premium-analytics/packages/datetime/src/get-comparison-range.ts +++ b/projects/packages/premium-analytics/packages/datetime/src/get-comparison-range.ts @@ -71,8 +71,8 @@ function getInclusiveDayCount( from: Date, to: Date ): number { * whole number of months. Detected by round trip against the day after the * range ends, and again from the start stepped back by that count: a start a * month step cannot undo (31 January two months back clamps to 30 November) - * measures in days, the way the step arrows measure it. Shared by the - * previous-period shift and its label, so both take the same branch; unlike + * measures in days instead. Shared by the previous-period shift and its + * label, so both take the same branch; unlike * `getDateRangeSpan`, a single month counts. * * @param from - Range start. diff --git a/projects/packages/premium-analytics/packages/datetime/src/index.ts b/projects/packages/premium-analytics/packages/datetime/src/index.ts index d29ae84a9ebf..fba3832bddee 100644 --- a/projects/packages/premium-analytics/packages/datetime/src/index.ts +++ b/projects/packages/premium-analytics/packages/datetime/src/index.ts @@ -21,9 +21,6 @@ export { INTERVAL_TYPES, isIntervalType, type IntervalType } from './interval'; export { getDateRangeSpan, type DateRangeSpan, type DateRangeSpanUnit } from './date-range-span'; -export { stepDateRange, canStepForward, type StepDirection } from './step-date-range'; -export { completeToDateRange, clampRangeEndToToday } from './to-date-range'; - export { drillDateRange } from './drill-date-range'; export { toBucketStamp, resolveBucketStamp } from './bucket-stamp'; diff --git a/projects/packages/premium-analytics/packages/datetime/src/step-date-range.ts b/projects/packages/premium-analytics/packages/datetime/src/step-date-range.ts deleted file mode 100644 index 456037eb6c66..000000000000 --- a/projects/packages/premium-analytics/packages/datetime/src/step-date-range.ts +++ /dev/null @@ -1,122 +0,0 @@ -/** - * External dependencies - */ -import { TZDate } from '@date-fns/tz'; -import { - addDays, - addHours, - addMonths, - addYears, - differenceInCalendarDays, - endOfDay, - endOfHour, - endOfMonth, - endOfYear, -} from 'date-fns'; -/** - * Internal dependencies - */ -import { getDateRangeSpan, type DateRangeSpanUnit } from './date-range-span'; -import type { DateRange } from './get-comparison-range'; - -/** - * Which way a step moves the window. - */ -export type StepDirection = 'previous' | 'next'; - -/** - * Calendar adders rather than a millisecond offset: twelve months back has to - * land on the same days of the month, and a step across a DST boundary has to - * keep the wall clock. - */ -const ADD_BY_UNIT: Record< DateRangeSpanUnit, ( date: Date, amount: number ) => Date > = { - hour: addHours, - day: addDays, - month: addMonths, - year: addYears, -}; - -/** - * Move both ends of a range by the same calendar amount. - * - * @param from - Range start. - * @param to - Range end. - * @param unit - The unit to move in. - * @param amount - How far, signed. - * @return The shifted range. - */ -function shift( from: Date, to: Date, unit: DateRangeSpanUnit, amount: number ): DateRange { - const add = ADD_BY_UNIT[ unit ]; - - return { from: add( from, amount ), to: add( to, amount ) }; -} - -/** - * Shift a range backward or forward by its own length. - * - * Falls back to the day count where a calendar step will not undo — `addMonths` - * clamps a day the target month is too short for, and reversibility wins. - * - * @param range - The window to move. - * @param direction - Which way to move it. - * @return The shifted range, or `undefined` when the range has no measurable span. - */ -export function stepDateRange( range: DateRange, direction: StepDirection ): DateRange | undefined { - const { from, to } = range; - const span = getDateRangeSpan( range ); - - if ( ! from || ! to || ! span ) { - return undefined; - } - - const sign = direction === 'previous' ? -1 : 1; - const stepped = shift( from, to, span.unit, sign * span.value ); - const returned = shift( stepped.from!, stepped.to!, span.unit, -sign * span.value ); - - if ( returned.from!.getTime() === from.getTime() && returned.to!.getTime() === to.getTime() ) { - return stepped; - } - - const days = differenceInCalendarDays( to, from ) + 1; - - return shift( from, to, 'day', sign * days ); -} - -/** - * End of the bucket an instant sits in, at each granularity a window measures - * in. - */ -const END_OF_BUCKET: Record< DateRangeSpanUnit, ( date: Date ) => Date > = { - hour: endOfHour, - day: endOfDay, - month: endOfMonth, - year: endOfYear, -}; - -/** - * Whether there is a later window to step into. - * - * The next window qualifies once it ends within the bucket `now` sits in, so a - * live preset ending in the running hour or day stays reachable. - * - * @param range - The window to test. - * @param now - The instant to compare against. - * @return Whether a forward step lands on a window already worth showing. - */ -export function canStepForward( range: DateRange, now: Date ): boolean { - const span = getDateRangeSpan( range ); - const next = stepDateRange( range, 'next' ); - - if ( ! span || ! next?.to ) { - return false; - } - - // Anchored to the window's own timezone, so a site offset from the browser - // closes its buckets on its own clock. - const timeZone = range.to && 'timeZone' in range.to ? ( range.to as TZDate ).timeZone : undefined; - const horizon = END_OF_BUCKET[ span.unit ]( - timeZone ? new TZDate( now.getTime(), timeZone ) : now - ); - - return next.to.getTime() <= horizon.getTime(); -} diff --git a/projects/packages/premium-analytics/packages/datetime/src/to-date-range.ts b/projects/packages/premium-analytics/packages/datetime/src/to-date-range.ts index 37c05b688312..7c1a3491ba05 100644 --- a/projects/packages/premium-analytics/packages/datetime/src/to-date-range.ts +++ b/projects/packages/premium-analytics/packages/datetime/src/to-date-range.ts @@ -1,8 +1,7 @@ /** * External dependencies */ -import { TZDate } from '@date-fns/tz'; -import { endOfDay, endOfMonth } from 'date-fns'; +import { endOfMonth } from 'date-fns'; /** * Internal dependencies */ @@ -15,9 +14,9 @@ import type { DateRange } from './get-comparison-range'; * `last-12-months` runs from the first of a month to the end of today, so * measuring it reports the shape of today's date rather than of the * selection: 354 days mid-month, 12 months on the last day of one. Anything - * that describes or moves the window in whole units — its length, the step - * arrows, the previous period — measures this window instead. What the reader - * sees stays the range as selected. + * that describes the window in whole units — its length, the previous + * period — measures this window instead. What the reader sees stays the range + * as selected. * * Every other preset comes back untouched. A hand-picked range that happens * to start on the first has no running month to complete, so it is measured @@ -40,30 +39,3 @@ export function completeToDateRange< T extends DateRange >( return { ...range, to: endOfMonth( range.to ) }; } - -/** - * Pull a window's end back to the end of today when it runs past it. - * - * A window measured in whole months or years may step forward into the month - * or year in progress, which `canStepForward` counts as reachable so the - * window a reader stepped back from stays reachable. The step itself lands on - * the end of that unit, days the report has no data for and the chart would - * draw as empty buckets. Stepping forward out of "12 months" therefore returns - * the to-date window the reader started from. - * - * @param range - The window to clamp. - * @param now - The current instant. - * @return The clamped window, or `range` itself when it already ends today or earlier. - */ -export function clampRangeEndToToday< T extends DateRange >( range: T, now: Date ): T { - if ( ! range.to ) { - return range; - } - - // Anchored to the window's own timezone, so a site offset from the browser - // closes the day on its own clock. - const timeZone = 'timeZone' in range.to ? ( range.to as TZDate ).timeZone : undefined; - const endOfToday = endOfDay( timeZone ? new TZDate( now.getTime(), timeZone ) : now ); - - return range.to.getTime() > endOfToday.getTime() ? { ...range, to: endOfToday } : range; -} diff --git a/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/build-range-patch.test.ts b/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/build-range-patch.test.ts index 00918dfa1f68..2e7e28e967f1 100644 --- a/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/build-range-patch.test.ts +++ b/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/build-range-patch.test.ts @@ -7,10 +7,6 @@ jest.mock( '@jetpack-premium-analytics/datetime', () => ( { ...jest.requireActual( '@jetpack-premium-analytics/datetime' ), reportingTimeZone: () => '+00:00', } ) ); -/** - * External dependencies - */ -import { canStepForward, stepDateRange } from '@jetpack-premium-analytics/datetime'; /** * Internal dependencies */ @@ -151,35 +147,6 @@ describe( 'buildRangePatch', () => { expect( patch?.to ).toBe( '2026-07-10T14:30:00.000+00:00' ); } ); - /* - * Rounding a stepped `to` up to the end of its day stretches a rolling - * window on every step and pushes its next window into the future, hiding - * the forward arrow. - */ - it( 'steps a rolling window back and forward without changing its length', () => { - const previous = stepDateRange( { from, to }, 'previous' ); - const back = buildRangePatch( { - nextRange: previous, - nextPresetId: 'custom', - exactRange: true, - effective: { preset: 'last-24-hours', interval: 'hour' }, - } ); - - expect( back ).toMatchObject( { - from: '2026-07-08T14:30:00.000+00:00', - to: '2026-07-09T14:30:00.000+00:00', - interval: 'hour', - preset: 'custom', - } ); - - const backRange = { from: new Date( back?.from ?? '' ), to: new Date( back?.to ?? '' ) }; - expect( canStepForward( backRange, to ) ).toBe( true ); - - const returned = stepDateRange( backRange, 'next' ); - expect( returned?.from?.getTime() ).toBe( from.getTime() ); - expect( returned?.to?.getTime() ).toBe( to.getTime() ); - } ); - it( 're-derives the comparison range from the new primary range when enabled', () => { const patch = buildRangePatch( { nextRange: { from, to }, diff --git a/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/use-report-date-filters.test.tsx b/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/use-report-date-filters.test.tsx index 64e705fbd7f4..26dfb8f8f329 100644 --- a/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/use-report-date-filters.test.tsx +++ b/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/__tests__/use-report-date-filters.test.tsx @@ -374,39 +374,6 @@ describe( 'useReportDateFilters', () => { } ); } ); - /* - * The step commits the exact stepped window: rounding its `to` up to the - * end of the day would stretch a rolling window on every step. - */ - it( 'steps the applied window by its own length and commits it as custom', () => { - const { result, rerender } = renderDateFilters( { - from: '2026-07-09T14:30:00.000+00:00', - to: '2026-07-10T14:30:00.000+00:00', - preset: 'last-24-hours', - interval: 'hour', - } ); - - act( () => result.current.onStep( 'previous' ) ); - rerender(); - - expect( mockNavigate ).toHaveBeenCalledTimes( 1 ); - expect( mockSearch ).toMatchObject( { - from: '2026-07-08T14:30:00.000+00:00', - to: '2026-07-09T14:30:00.000+00:00', - preset: 'custom', - interval: 'hour', - } ); - expect( result.current.appliedPresetId ).toBe( 'custom' ); - } ); - - it( 'ignores a step without a measurable window', () => { - const { result } = renderDateFilters(); - - act( () => result.current.onStep( 'previous' ) ); - - expect( mockNavigate ).not.toHaveBeenCalled(); - } ); - it( 'replaces the current entry when the page reconciles the range', () => { const { result, rerender } = renderDateFilters( { from: '2026-07-01T00:00:00.000+00:00', @@ -636,53 +603,4 @@ describe( 'useReportDateFilters', () => { expect( result.current.presetId ).toBe( 'custom' ); } ); } ); - - it( 'steps a to-date preset by whole months and compares it with the months before', () => { - // `last-12-months` as read on 20 August 2026. Stepped by its day count - // the window would start on 12 September and its comparison on the 24th. - const { result, rerender } = renderDateFilters( { - from: '2025-09-01T00:00:00.000+00:00', - to: '2026-08-20T23:59:59.999+00:00', - preset: 'last-12-months', - interval: 'month', - comp: '1', - compare_preset: 'previous-period', - } ); - - act( () => result.current.onStep( 'previous' ) ); - rerender(); - - expect( mockSearch ).toMatchObject( { - from: '2024-09-01T00:00:00.000+00:00', - to: '2025-08-31T23:59:59.999+00:00', - preset: 'custom', - interval: 'month', - compare_from: '2023-09-01T00:00:00.000+00:00', - compare_to: '2024-08-31T23:59:59.999+00:00', - } ); - } ); - - it( 'lands back on the to-date window when a step forward closes the running month', () => { - // The window a step back out of `last-12-months` leaves. Stepping - // forward again closes August, eleven days past the day it is read on: - // days the report has no data for, and the forward arrow would then - // disappear on a window nobody can leave. - jest.useFakeTimers().setSystemTime( Date.parse( '2026-08-20T12:00:00.000Z' ) ); - - const { result, rerender } = renderDateFilters( { - from: '2024-09-01T00:00:00.000+00:00', - to: '2025-08-31T23:59:59.999+00:00', - preset: 'custom', - interval: 'month', - } ); - - act( () => result.current.onStep( 'next' ) ); - rerender(); - - expect( mockSearch ).toMatchObject( { - from: '2025-09-01T00:00:00.000+00:00', - to: '2026-08-20T23:59:59.999+00:00', - preset: 'custom', - } ); - } ); } ); diff --git a/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/use-report-date-filters.tsx b/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/use-report-date-filters.tsx index 097f85148e3b..1346e8a89642 100644 --- a/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/use-report-date-filters.tsx +++ b/projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/use-report-date-filters.tsx @@ -7,12 +7,9 @@ import { resolveIntervalForRange, } from '@jetpack-premium-analytics/data'; import { - clampRangeEndToToday, - completeToDateRange, drillDateRange, PRESET_CUSTOM, reportingTimeZone, - stepDateRange, toLocalTZ, } from '@jetpack-premium-analytics/datetime'; import { useCallback, useMemo } from 'react'; @@ -28,7 +25,6 @@ import type { DateRange, IntervalType, PrimaryPresetId, - StepDirection, } from '@jetpack-premium-analytics/datetime'; type PickerRange = { from: Date | undefined; to: Date | undefined }; @@ -70,11 +66,6 @@ export type ReportDateFilters = { onComparisonChange: ( range: DateRange | undefined, presetId?: ComparisonPresetId ) => void; onIntervalChange: ( interval: IntervalType ) => void; - /** - * Step the applied window backward or forward by its own length. - */ - onStep: ( direction: StepDirection ) => void; - /** * Open the chart bucket containing a date, narrowing to the next finer * interval. `interval` is the bucket size the chart drew; defaults to the @@ -259,46 +250,9 @@ export function useReportDateFilters< TFrom extends string >( from?: TFrom ): Re ); /* - * Commits and pushes a history entry so Back undoes the step. Steps the - * applied range, not the staged one — the arrows sit outside the picker, - * so stepping must not apply an open draft. - */ - const onStep = useCallback( - ( direction: StepDirection ) => { - // A to-date window steps as its completed window, so the arrows move - // "12 months" by whole months rather than by the days read so far. - const stepped = stepDateRange( - completeToDateRange( appliedRange, appliedPresetId ), - direction - ); - - if ( ! stepped ) { - return; - } - - const patch = buildRangePatch( { - // A forward step closes the running unit the window was measured - // against, which reaches past today. Stepping forward out of - // "12 months" returns the to-date window, not a month of empty - // buckets. - nextRange: clampRangeEndToToday( stepped, toLocalTZ( undefined, timeZone ) ), - nextPresetId: PRESET_CUSTOM, - exactRange: true, - effective, - } ); - - if ( patch ) { - stage( patch ); - commit(); - } - }, - [ appliedPresetId, appliedRange, commit, effective, stage, timeZone ] - ); - - /* - * Commits and pushes a history entry, like `onStep`, so Back exits a - * drill-down. Reads the applied range/interval, not the staged one: the - * chart draws what's applied, so the click belongs to that window. + * Commits and pushes a history entry, so Back exits a drill-down. Reads the + * applied range/interval, not the staged one: the chart draws what's + * applied, so the click belongs to that window. */ const drillDown = useCallback( ( date: Date, bucketInterval: IntervalType = appliedInterval ) => { @@ -375,7 +329,6 @@ export function useReportDateFilters< TFrom extends string >( from?: TFrom ): Re onChange, onComparisonChange, onIntervalChange, - onStep, drillDown, onApply, onCancel, diff --git a/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/__tests__/date-filters-panel.test.tsx b/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/__tests__/date-filters-panel.test.tsx index f0b933ef7c86..453035b08ba9 100644 --- a/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/__tests__/date-filters-panel.test.tsx +++ b/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/__tests__/date-filters-panel.test.tsx @@ -43,32 +43,6 @@ describe( 'DateFiltersPanel', () => { expect( screen.queryByRole( 'button', { name: 'Compare' } ) ).not.toBeInTheDocument(); } ); - it( 'steps the applied window from the navigation arrows', async () => { - const onStep = jest.fn(); - const user = userEvent.setup(); - - // A window whose next one has fully happened, so both arrows render. - renderPanel( { - onStep, - appliedRange: { - from: new Date( '2020-07-01T00:00:00.000Z' ), - to: new Date( '2020-07-30T23:59:59.999Z' ), - }, - } ); - - await user.click( screen.getByRole( 'button', { name: 'Previous period' } ) ); - expect( onStep ).toHaveBeenCalledWith( 'previous' ); - - await user.click( screen.getByRole( 'button', { name: 'Next period' } ) ); - expect( onStep ).toHaveBeenCalledWith( 'next' ); - } ); - - it( 'renders no period navigation without onStep', () => { - renderPanel(); - - expect( screen.queryByRole( 'button', { name: 'Previous period' } ) ).not.toBeInTheDocument(); - } ); - // The comparison qualifies the range the presets just set; the interval only // buckets the charts. Reading order follows that, so it is worth pinning. it( 'places the comparison before the chart interval', () => { @@ -167,20 +141,15 @@ describe( 'DateFiltersPanel', () => { it( 'greys every control out while disabled', () => { renderPanel( { disabled: true, - onStep: jest.fn(), - appliedRange: { - from: new Date( '2020-07-01T00:00:00.000Z' ), - to: new Date( '2020-07-30T23:59:59.999Z' ), - }, withIntervalControl: true, intervalOptions: [ 'day', 'week' ], interval: 'day', onIntervalChange: jest.fn(), } ); - // Both arrows, the period, the comparison and the interval. + // The period, the comparison and the interval. const buttons = screen.getAllByRole( 'button' ); - expect( buttons ).toHaveLength( 5 ); + expect( buttons ).toHaveLength( 3 ); buttons.forEach( button => { expect( button ).toHaveAttribute( 'aria-disabled', 'true' ); } ); diff --git a/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.scss b/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.scss index ef53bf602833..5b6a4555151a 100644 --- a/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.scss +++ b/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.scss @@ -27,8 +27,7 @@ } // A glyph in a square box: nothing to give back when the row runs short. - .date-interval-dropdown, - .date-period-navigation { + .date-interval-dropdown { flex: 0 0 auto; } } diff --git a/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.tsx b/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.tsx index e83a0bf8b82e..17bed79f5cad 100644 --- a/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.tsx +++ b/projects/packages/premium-analytics/packages/ui/src/date-filters-panel/date-filters-panel.tsx @@ -3,14 +3,12 @@ */ import { useReportScope } from '@jetpack-premium-analytics/data'; import { - canStepForward, isComparisonPresetId, isPrimaryPreset, type ComparisonPresetId, type IntervalType, type PrimaryPresetId, type QuickSurfacePresetId, - type StepDirection, } from '@jetpack-premium-analytics/datetime'; import { Stack } from '@jetpack-premium-analytics/externals'; import { BaseControl } from '@wordpress/components'; @@ -21,7 +19,6 @@ import { useMemo, useCallback, useState } from 'react'; import { DateComparisonDropdown } from '../date-comparison-dropdown'; import { DateIntervalDropdown } from '../date-interval-dropdown'; import { DatePeriodDropdown } from '../date-period-dropdown'; -import { DatePeriodNavigation } from '../date-period-navigation'; import { useComparisonDatePresets } from '../use-comparison-date-presets'; import './date-filters-panel.scss'; @@ -95,13 +92,6 @@ export type DateFiltersPanelProps = { onIntervalChange?: ( interval: IntervalType ) => void; - /** - * Steps the applied window backward or forward by its own length. Left out, - * the navigation controls are not rendered at all: a surface whose range is - * not a movable window has nowhere to step. - */ - onStep?: ( direction: StepDirection ) => void; - /** * Props for the date range popover. */ @@ -150,7 +140,6 @@ export function DateFiltersPanel( { onChange, onComparisonChange, onIntervalChange, - onStep, rangeControlProps = { label: null, help: null, @@ -217,11 +206,6 @@ export function DateFiltersPanel( { const comparisonLabel = typeof comparisonControlProps.label === 'string' ? comparisonControlProps.label : undefined; - /* - * Built once and rendered twice: the row the user sees, and the probe that - * measures it. The same element in both places means the measurement cannot - * drift from what it measures. - */ const comparisonControl = useMemo( () => ( { - if ( ! onStep ) { - return null; - } - - const committedRange = appliedRange ?? range; - - return ( - - ); - }, [ appliedRange, disabled, onStep, range ] ); - - // Same arrangement as the comparison control: built once, rendered in the - // row and in the probe. const intervalControl = useMemo( () => withIntervalControl && intervalOptions && onIntervalChange ? ( @@ -284,8 +245,6 @@ export function DateFiltersPanel( { return (
- { navigationControl } - { - const stepped = stepDateRange( stagedPrimaryRef.current.range, direction ); - - if ( ! stepped?.from || ! stepped.to ) { - return; - } - - const nextPrimary: PrimaryFilterState = { - range: { from: stepped.from, to: stepped.to }, - presetId: PRESET_CUSTOM, - }; - - stagedPrimaryRef.current = nextPrimary; - setStagedPrimary( nextPrimary ); - setCommittedPrimary( nextPrimary ); - }, [] ); - /* * The interval follows the range being edited, so switching preset re-derives * the menu. A pick the new range still allows survives; one it does not falls @@ -214,7 +192,6 @@ function DateFiltersPanelStory( { onChange={ handlePrimaryChange } onComparisonChange={ handleComparisonChange } onIntervalChange={ setPickedInterval } - onStep={ handleStep } onApply={ handlePrimaryApply } onCancel={ handlePrimaryCancel } canApply={ canApplyPrimary } @@ -393,7 +370,7 @@ const LADDER_WIDTHS = [ 960, 782, 600, 360, 280 ]; /** * One locale's bar at each reference width, so where it stops fitting is * visible rather than asserted. Annotated against the four preset pills - * alone — a floor, since the trigger/comparison/interval/navigation share the line. + * alone — a floor, since the trigger/comparison/interval share the line. */ function WidthLadder( { fixture }: { fixture: LocaleFixture } ) { return ( diff --git a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/__tests__/date-period-navigation.test.tsx b/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/__tests__/date-period-navigation.test.tsx deleted file mode 100644 index a63e68de2bea..000000000000 --- a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/__tests__/date-period-navigation.test.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { DatePeriodNavigation } from '../date-period-navigation'; - -describe( 'DatePeriodNavigation', () => { - it( 'steps backward', async () => { - const onStep = jest.fn(); - const user = userEvent.setup(); - - render( ); - - await user.click( screen.getByRole( 'button', { name: 'Previous period' } ) ); - - expect( onStep ).toHaveBeenCalledWith( 'previous' ); - } ); - - it( 'steps forward', async () => { - const onStep = jest.fn(); - const user = userEvent.setup(); - - render( ); - - await user.click( screen.getByRole( 'button', { name: 'Next period' } ) ); - - expect( onStep ).toHaveBeenCalledWith( 'next' ); - } ); - - /* - * Absent rather than disabled. A disabled arrow states a rule the reader has - * to work out, and on a live preset that rule holds for as long as they stay - * on it. - */ - it( 'omits the forward control while the window reaches the present', () => { - render( ); - - expect( screen.getByRole( 'button', { name: 'Previous period' } ) ).toBeInTheDocument(); - expect( screen.queryByRole( 'button', { name: 'Next period' } ) ).not.toBeInTheDocument(); - } ); - - it( 'greys both arrows out while disabled, focusable still', async () => { - const onStep = jest.fn(); - const user = userEvent.setup(); - - render( ); - - const previous = screen.getByRole( 'button', { name: 'Previous period' } ); - expect( previous ).toHaveAttribute( 'aria-disabled', 'true' ); - expect( screen.getByRole( 'button', { name: 'Next period' } ) ).toHaveAttribute( - 'aria-disabled', - 'true' - ); - - previous.focus(); - expect( previous ).toHaveFocus(); - - await user.click( previous ); - expect( onStep ).not.toHaveBeenCalled(); - } ); -} ); diff --git a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/date-period-navigation.scss b/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/date-period-navigation.scss deleted file mode 100644 index d3c61b02c0ba..000000000000 --- a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/date-period-navigation.scss +++ /dev/null @@ -1,21 +0,0 @@ -@use "../styles/preset-surface"; - -// Its own bordered group, to the left of the presets rather than inside them: -// the pills are a set to choose from and these move the choice, so sharing one -// frame would read as a fifth and sixth preset. -.date-period-navigation { - - @include preset-surface.group; -} - -.date-period-navigation__step { - - @include preset-surface.pill; - - // A glyph in a square box, sized like the pills beside it, which take this - // from `.date-filters-panel`. Set here too so the group holds its shape - // wherever else it is mounted. - --wp-ui-button-height: calc(var(--wpds-dimension-size-lg) - 2px); - - min-width: var(--wpds-dimension-size-lg); -} diff --git a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/date-period-navigation.tsx b/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/date-period-navigation.tsx deleted file mode 100644 index fb922d828da7..000000000000 --- a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/date-period-navigation.tsx +++ /dev/null @@ -1,72 +0,0 @@ -/** - * External dependencies - */ -import { Button } from '@jetpack-premium-analytics/externals'; -import { __ } from '@wordpress/i18n'; -import { chevronLeft, chevronRight } from '@wordpress/icons'; -import clsx from 'clsx'; - -import './date-period-navigation.scss'; - -type DatePeriodNavigationProps = { - /** - * Whether the window has a future to step into. Derived upstream from the - * range rather than from a layout rule, so the control follows where the - * window sits in time. - */ - canStepForward: boolean; - - /** Greys the arrows out but keeps them focusable: a passing state, not a missing control. */ - disabled?: boolean; - - /** - * Fired with the direction the reader asked for. - */ - onStep: ( direction: 'previous' | 'next' ) => void; -}; - -/** - * Steps the active window backward and forward by its own length. - * - * The forward control is absent rather than disabled on the latest window — - * a disabled arrow states a rule the reader has to work out for themselves. - * - * @param {DatePeriodNavigationProps} props - The props for the DatePeriodNavigation component. - * @return The navigation element. - */ -export function DatePeriodNavigation( { - canStepForward, - disabled = false, - onStep, -}: DatePeriodNavigationProps ) { - return ( -
- { /* The glyph carries no wording, so the name is the whole label. */ } - - - { canStepForward && ( - - ) } -
- ); -} diff --git a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/index.ts b/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/index.ts deleted file mode 100644 index 819b14bb50ae..000000000000 --- a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { DatePeriodNavigation } from './date-period-navigation'; diff --git a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/stories/date-period-navigation.stories.tsx b/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/stories/date-period-navigation.stories.tsx deleted file mode 100644 index 944e2dba3ade..000000000000 --- a/projects/packages/premium-analytics/packages/ui/src/date-period-navigation/stories/date-period-navigation.stories.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { canStepForward, stepDateRange } from '@jetpack-premium-analytics/datetime'; -import { useState } from 'react'; -import { DatePeriodNavigation } from '../date-period-navigation'; -import type { DateRange, StepDirection } from '@jetpack-premium-analytics/datetime'; -import type { Meta, StoryObj } from '@storybook/react'; - -const meta: Meta< typeof DatePeriodNavigation > = { - title: 'Packages/Premium Analytics/UI/DatePeriodNavigation', - component: DatePeriodNavigation, - tags: [ 'autodocs' ], - parameters: { - docs: { - description: { - component: - 'Steps the active window backward and forward by its own length.\n\n' + - 'The forward control is absent rather than disabled while the window is the ' + - 'latest one available. `canStepForward` is a prop, derived upstream from the ' + - 'range, so availability follows where the window sits in time rather than a ' + - 'layout rule.', - }, - }, - }, - argTypes: { - onStep: { control: false }, - }, -}; - -export default meta; - -type Story = StoryObj< typeof DatePeriodNavigation >; - -/** - * Seven whole days ending at the given day. - * - * @param endingDaysAgo - How many days back the window ends. - * @return The window. - */ -function weekEnding( endingDaysAgo: number ): DateRange { - const to = new Date(); - to.setDate( to.getDate() - endingDaysAgo ); - to.setHours( 23, 59, 59, 999 ); - - const from = new Date( to ); - from.setDate( from.getDate() - 6 ); - from.setHours( 0, 0, 0, 0 ); - - return { from, to }; -} - -/** - * The control wired to a real window, so stepping moves it and the forward - * arrow appears and disappears the way it does in the panel. - * - * @param props - Story props. - * @param props.initialEndsAgo - How many days back the starting window ends. - * @return The wired control. - */ -function DatePeriodNavigationWithState( { initialEndsAgo }: { initialEndsAgo: number } ) { - const [ range, setRange ] = useState( () => weekEnding( initialEndsAgo ) ); - - const step = ( direction: StepDirection ) => { - const next = stepDateRange( range, direction ); - - if ( next ) { - setRange( next ); - } - }; - - return ( - - ); -} - -/** - * The latest window: only the back arrow, since there is nothing after it. - */ -export const Default: Story = { - render: () => , -}; - -/** - * A window already stepped back. Both arrows show; stepping forward to the - * latest window drops the forward one again. - */ -export const SteppedBack: Story = { - render: () => , -}; diff --git a/projects/packages/premium-analytics/packages/ui/src/index.ts b/projects/packages/premium-analytics/packages/ui/src/index.ts index b86ab77244b9..9fe58ee6a001 100644 --- a/projects/packages/premium-analytics/packages/ui/src/index.ts +++ b/projects/packages/premium-analytics/packages/ui/src/index.ts @@ -9,7 +9,6 @@ export { export { DateFiltersPanel } from './date-filters-panel'; export { DateIntervalDropdown } from './date-interval-dropdown'; export { DatePeriodDropdown } from './date-period-dropdown'; -export { DatePeriodNavigation } from './date-period-navigation'; export { DateYearFilter, type DateYearFilterProps } from './date-year-filter'; export { OnboardingWelcomeModal, diff --git a/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/__tests__/report-page-layout.test.tsx b/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/__tests__/report-page-layout.test.tsx index bba0fab005eb..9bb4d25b2e2d 100644 --- a/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/__tests__/report-page-layout.test.tsx +++ b/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/__tests__/report-page-layout.test.tsx @@ -43,7 +43,6 @@ function buildDateFilters(): ReportDateFilters { onChange: jest.fn(), onComparisonChange: jest.fn(), onIntervalChange: jest.fn(), - onStep: jest.fn(), onApply: jest.fn(), onCancel: jest.fn(), canApply: true, diff --git a/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/stories/report-page.stories.tsx b/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/stories/report-page.stories.tsx index 430de235d741..db2a0317538b 100644 --- a/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/stories/report-page.stories.tsx +++ b/projects/packages/premium-analytics/packages/widgets-toolkit/src/components/report-page/stories/report-page.stories.tsx @@ -183,7 +183,6 @@ const STORY_DATE_FILTERS: ReportDateFilters = { onChange: () => {}, onComparisonChange: () => {}, onIntervalChange: () => {}, - onStep: () => {}, onApply: () => {}, onCancel: () => {}, canApply: false, diff --git a/projects/packages/premium-analytics/routes/use-detail-date-controls.test.ts b/projects/packages/premium-analytics/routes/use-detail-date-controls.test.ts index a57a4493c135..0cb75b16bc48 100644 --- a/projects/packages/premium-analytics/routes/use-detail-date-controls.test.ts +++ b/projects/packages/premium-analytics/routes/use-detail-date-controls.test.ts @@ -51,7 +51,6 @@ describe( 'useDetailDateControls', () => { presetIds: DETAIL_SURFACE_PRESETS, withCustomRange: false, withIntervalControl: false, - onStep: undefined, } ); // Half past midnight in Taipei, not in the runner's zone. expect( result.current.allTimeStart?.toISOString() ).toBe( '2026-07-07T16:29:35.000Z' ); diff --git a/projects/packages/premium-analytics/routes/use-detail-date-controls.ts b/projects/packages/premium-analytics/routes/use-detail-date-controls.ts index 0869e867e828..4d4da11b7259 100644 --- a/projects/packages/premium-analytics/routes/use-detail-date-controls.ts +++ b/projects/packages/premium-analytics/routes/use-detail-date-controls.ts @@ -16,7 +16,6 @@ type DetailDateControls = { allTimeStart: Date | undefined; withCustomRange: false; withIntervalControl: false; - onStep: undefined; }; /** @@ -36,8 +35,8 @@ type DetailDateFilters = { * render before the summary loads, so an all-time range applied against an * unknown or stale start is re-anchored in place once it resolves. * - * Spread after the date-filter controller's props — `onStep` and the interval - * props it hands out are what this unsets. + * Spread after the date-filter controller's props: the interval props it + * hands out are what this unsets. * * @param publishedDate - The resource's publish date, as the summary carries it: * a site-local wall time, or an offset-bearing instant. @@ -80,7 +79,6 @@ export function useDetailDateControls( allTimeStart, withCustomRange: false, withIntervalControl: false, - onStep: undefined, } ), [ allTimeStart ] ); diff --git a/projects/packages/premium-analytics/tests/groups/datetime-no-mocks-part2.test.tsx b/projects/packages/premium-analytics/tests/groups/datetime-no-mocks-part2.test.tsx index fb7dfef7881b..f52eee4a2470 100644 --- a/projects/packages/premium-analytics/tests/groups/datetime-no-mocks-part2.test.tsx +++ b/projects/packages/premium-analytics/tests/groups/datetime-no-mocks-part2.test.tsx @@ -2,6 +2,5 @@ import '../../packages/datetime/src/__tests__/site-time-zone.test'; import '../../packages/datetime/src/__tests__/site-timestamp.test'; -import '../../packages/datetime/src/__tests__/step-date-range.test'; import '../../packages/datetime/src/__tests__/tz.test'; import '../../packages/datetime/src/__tests__/year-presets.test'; diff --git a/projects/packages/premium-analytics/tests/groups/ui-no-mocks-part1.test.tsx b/projects/packages/premium-analytics/tests/groups/ui-no-mocks-part1.test.tsx index cd383c7da195..ff08ebcfed1f 100644 --- a/projects/packages/premium-analytics/tests/groups/ui-no-mocks-part1.test.tsx +++ b/projects/packages/premium-analytics/tests/groups/ui-no-mocks-part1.test.tsx @@ -5,5 +5,4 @@ import '../../packages/ui/src/dataviews-drilldown-native/__tests__/dataviews-dri import '../../packages/ui/src/dataviews-drilldown-native/__tests__/process-hierarchy-levels.test'; import '../../packages/ui/src/date-comparison-dropdown/__tests__/date-comparison-dropdown.test'; import '../../packages/ui/src/date-interval-dropdown/__tests__/date-interval-dropdown.test'; -import '../../packages/ui/src/date-period-navigation/__tests__/date-period-navigation.test'; import '../../packages/ui/src/onboarding-welcome-modal/__tests__/onboarding-welcome-modal.test'; diff --git a/projects/plugins/jetpack/changelog/remove-period-step-arrows b/projects/plugins/jetpack/changelog/remove-period-step-arrows new file mode 100644 index 000000000000..be526ff1933c --- /dev/null +++ b/projects/plugins/jetpack/changelog/remove-period-step-arrows @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Premium Analytics: Remove the arrows that stepped the date range back and forward a period. diff --git a/projects/plugins/premium-analytics/changelog/remove-period-step-arrows b/projects/plugins/premium-analytics/changelog/remove-period-step-arrows new file mode 100644 index 000000000000..eabeef518231 --- /dev/null +++ b/projects/plugins/premium-analytics/changelog/remove-period-step-arrows @@ -0,0 +1,4 @@ +Significance: minor +Type: removed + +Remove the arrows that stepped the date range back and forward a period.