/** * This Source Code is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright (c) Infonomic Company Limited */ /** * The analytics timeseries — one column per explicit UTC reporting bucket. * * A column rather than a continuous line is a claim about the data, not a * style: the rows behind this chart are sums of daily aggregates and visitor * hashes rotate at UTC midnight, so nothing is measured between two points. * The dashboard selects the granularity and passes it into this renderer; * the chart never guesses from the number of rows. */ import type React from 'react'; import type { AnalyticsSummaryDay } from '@byline/analytics'; import type { AnalyticsDashboardPeriod } from '@byline/analytics/config'; export type AnalyticsChartGranularity = 'day' | 'seven-day' | 'month'; export interface AnalyticsChartBucket { from: string; to: string; granularity: AnalyticsChartGranularity; /** Actual number of daily rows, including partial first or last buckets. */ dayCount: number; views: number; /** Sum of the bucket's daily-unique visitor values. */ visitors: number; downloads: number; } export interface AnalyticsColumn { index: number; /** Full-height mark: that bucket's page views. */ x: number; width: number; y: number; height: number; /** Inset mark: summed daily uniques, always no greater than views. */ insetX: number; insetWidth: number; insetY: number; insetHeight: number; /** Full-height transparent target, so narrow columns stay easy to hit. */ hitX: number; hitWidth: number; } /** Resolve chart density outside the renderer so the chosen width is explicit. */ export declare function resolveAnalyticsChartGranularity(period: AnalyticsDashboardPeriod, dayCount: number): AnalyticsChartGranularity; /** Combine complete daily query rows using the caller-selected granularity. */ export declare function bucketAnalyticsTimeseries(days: readonly AnalyticsSummaryDay[], granularity: AnalyticsChartGranularity): readonly AnalyticsChartBucket[]; /** Project reporting buckets into column geometry. */ export declare function buildAnalyticsColumns(buckets: readonly Pick[]): readonly AnalyticsColumn[]; /** * Where the hover card sits relative to the plot box. * * `leftPercent` / `topPercent` are percentages of the plot rather than user * -space units because the card is HTML laid over a stretched SVG: the plot * is drawn `preserveAspectRatio="none"`, so anything measured in viewBox * units would skew with the container width (the same reason the axis labels * are HTML). Percentages survive the stretch. */ export interface AnalyticsHoverCardPlacement { /** Horizontal centre of the hovered column, as a percentage of plot width. */ leftPercent: number; /** Top edge of the hovered column, as a percentage of plot height. */ topPercent: number; /** * How the card lines up with `leftPercent`. Columns near a plot edge anchor * that edge instead of centring, so the card never overhangs the chart. */ align: 'start' | 'center' | 'end'; /** * Which side of the column top the card occupies. A column tall enough that * a card above it would clip the top of the plot takes the card below * instead. */ side: 'above' | 'below'; } /** Project one column's geometry into hover-card placement. */ export declare function resolveHoverCardPlacement(column: AnalyticsColumn): AnalyticsHoverCardPlacement; export interface AnalyticsTimeseriesProps { days: readonly AnalyticsSummaryDay[]; granularity: AnalyticsChartGranularity; locale: string; } export declare function AnalyticsTimeseries({ days, granularity, locale, }: AnalyticsTimeseriesProps): React.JSX.Element;