import type React from 'react'; import type { Rect } from '@coinbase/cds-common/types/Rect'; import { type AxisBounds, type Series } from './chart'; import type { CartesianChartLayout } from './context'; import { type ChartAxisScaleType, type ChartScaleFunction, type PointAnchor } from './scale'; export declare const defaultAxisId = 'DEFAULT_AXIS_ID'; export declare const defaultAxisScaleType = 'linear'; /** * Position options for band scale axis elements (grid lines, tick marks, labels). * * - `'start'` - At the start of each step (before bar padding) * - `'middle'` - At the center of each band * - `'end'` - At the end of each step (after bar padding) * - `'edges'` - At start of each tick, plus end for the last tick (encloses the chart) * * @note These properties only apply when using a band scale (`scaleType: 'band'`). */ export type AxisBandPlacement = 'start' | 'middle' | 'end' | 'edges'; /** * Converts an AxisBandPlacement to the corresponding PointAnchor for use with getPointOnScale. * * @param placement - The axis placement value * @returns The corresponding PointAnchor for scale calculations */ export declare const toPointAnchor: (placement: AxisBandPlacement) => PointAnchor; /** * Axis configuration with computed bounds */ export type AxisConfig = { /** The type of scale to use */ scaleType: ChartAxisScaleType; /** * Domain bounds for the axis (data space) */ domain: AxisBounds; /** * Range bounds for the axis (visual space in pixels) */ range: AxisBounds; /** * Data for the axis. * @note only used by the category axis. */ data?: string[] | number[]; /** * Padding between categories for band scales (0-1, where 0.1 = 10% spacing) * Only used when scaleType is 'band' * @default 0.1 */ categoryPadding?: number; /** * Domain limit type for numeric scales * - 'nice': Rounds the domain to human-friendly values * - 'strict': Uses the exact min/max values from the data */ domainLimit: 'nice' | 'strict'; }; export type CartesianAxisConfig = AxisConfig & { /** * Baseline value used as the origin for numeric series on this axis. * Only applies when this axis is the value axis for the current chart layout. * - Non-stacked numeric series render from `[baseline, value]`. * - Multi-series stacks are normalized around this baseline before stacking. * * @default 0 for value axes, undefined for category axes */ baseline?: number; }; /** * Axis configuration without computed bounds (used for input) */ export type CartesianAxisConfigProps = Omit & { /** * Unique identifier for this axis. */ id: string; /** * Domain configuration for the axis (data space). * * The domainLimit parameter (inherited from AxisConfig) controls how initial domain bounds are calculated: * - 'nice' (default for y axes): Rounds the domain to human-friendly values (e.g., 0-100 instead of 1.2-97.8) * - 'strict' (default for x axes): Uses the exact min/max values from the data * * The domain can be: * - A partial bounds object to override specific min/max values * - A function that receives the limit-processed bounds and allows further customization * * This allows you to first apply nice/strict processing, then optionally transform the result. */ domain?: Partial | ((bounds: AxisBounds) => AxisBounds); /** * Range configuration for the axis (visual space in pixels). * Can be a partial bounds object to override specific values, or a function that transforms the calculated range. * * When using a function, it receives the initial calculated range bounds and allows you to adjust them. * This replaces the previous rangeOffset approach and provides more flexibility for range customization. */ range?: Partial | ((bounds: AxisBounds) => AxisBounds); }; export declare const withBaselineDomain: ( domain: CartesianAxisConfigProps['domain'], baseline?: number, ) => CartesianAxisConfigProps['domain']; /** * Gets a D3 scale based on the cartesian axis configuration. * Handles both numeric (linear/log) and categorical (band) scales. * * For numeric scales, the domain limit controls whether bounds are "nice" (human-friendly) * or "strict" (exact min/max). Range can be customized using function-based configuration. * * @param params - Scale parameters * @returns The D3 scale function * @throws An Error if bounds are invalid */ export declare const getCartesianAxisScale: ({ config, type, range, dataDomain, layout, }: { config?: CartesianAxisConfig; type: 'x' | 'y'; range: AxisBounds; dataDomain: AxisBounds; layout?: CartesianChartLayout; }) => ChartScaleFunction; /** * Formats the array of user-provided axis configs with default values and validates axis ids. * Ensures at least one axis config exists if no input is provided. * Requires specific axis ids when there are more than 1 axes. * Defaults the axis id for a single axis config if there is no id. * @param type - the type of axis, 'x' or 'y' * @param axes - array of axis configs or single axis config * @param defaultId - the default id to use for the axis * @param defaultScaleType - the default scale type to use for the axis * @returns array of axis configs with IDs */ export declare const getAxisConfig: ( type: 'x' | 'y', axes: Partial | Partial[] | undefined, defaultId?: string, defaultScaleType?: ChartAxisScaleType, ) => CartesianAxisConfigProps[]; /** * Calculates the data domain for an axis based on its configuration and series data. * Handles both x and y axes, categorical data, custom domain configurations, and stacking. * * @param axisParam - The axis configuration * @param series - Array of series objects (for stacking support) * @param axisType - Whether this is an 'x' or 'y' axis * @param layout - The chart layout orientation * @returns The calculated axis bounds */ export declare const getCartesianAxisDomain: ( axisParam: CartesianAxisConfigProps, series: Series[], axisType: 'x' | 'y', layout?: CartesianChartLayout, ) => AxisBounds; /** * Calculates the visual range for an axis based on the chart rectangle and configuration. * Handles custom range configurations including functions and partial bounds. * * @param axisParam - The axis configuration * @param chartRect - The chart drawing area rectangle * @param axisType - Whether this is an 'x' or 'y' axis * @returns The calculated axis range bounds */ export declare const getAxisRange: ( axisParam: CartesianAxisConfigProps, chartRect: Rect, axisType: 'x' | 'y', ) => AxisBounds; /** * Options for tick generation behavior */ type TickGenerationOptions = { /** * Minimum step size allowed for ticks. * Prevents the step from being smaller than this value. * @example 1 // Prevents fractional steps like 0.5 */ minStep?: number; /** * Maximum step size allowed for ticks. * Prevents the step from being larger than this value. * @example 100 // Prevents steps larger than 100 */ maxStep?: number; /** * Minimum number of ticks to generate when using tickInterval. * @default 4 */ minTickCount?: number; /** * Anchor position for band/categorical scales. * Controls where tick labels are positioned within each band. * @default 'middle' */ anchor?: PointAnchor; }; export type GetAxisTicksDataProps = { /** * Custom tick configuration for the axis. * - **Array**: Uses these exact values for tick positioning and labels. * - For numeric scales: exact values to display * - For band scales: category indices to display * - **Function**: Filters based on the predicate function. * - For numeric scales: filters generated tick values * - For band scales: filters category indices */ ticks?: number[] | ((value: number) => boolean); /** * The scale function to use for positioning and tick generation. * Can be either a numeric scale or a band scale. */ scaleFunction: ChartScaleFunction; /** * Requested number of ticks to display (only used for numeric scales). * For band/categorical scales, use the `ticks` parameter to control which categories are shown. */ requestedTickCount?: number; /** * Categories for band scales */ categories?: string[]; /** * Possible tick values to filter from when using function-based ticks. * Used for discrete data (such as 'band' scale indices). */ possibleTickValues?: number[]; /** * Interval at which to show ticks in pixels. * When provided, calculates tick count based on available space and generates * evenly distributed ticks that always include first and last domain values. * Only applies to numeric scales and overrides requestedTickCount. * * @example * // For a chart with 400px width, tickInterval: 64 would generate ~6 ticks * // evenly distributed across the data range, always including first and last values * getAxisTicksData({ * scaleFunction: numericScale, * tickInterval: 32, * possibleTickValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * }); * // Result: ticks at indices [0, 2, 4, 6, 8, 10] with their corresponding positions */ tickInterval?: number; /** * Options for tick generation behavior */ options?: TickGenerationOptions; }; /** * Formats a tick value for display on an axis. * Consolidates the identical formatting logic shared between XAxis and YAxis. * * @param value - The raw tick value to format * @param tickFormatter - Optional custom formatter function * @returns The formatted tick value as a React node */ export declare const formatAxisTick: ( value: any, tickFormatter?: (value: any) => React.ReactNode, ) => React.ReactNode; /** * Processes tick configuration and returns tick data with positions. * * **Parameter Precedence by Scale Type:** * * **For Numeric Scales (linear/log):** * 1. `ticks` (array) - Explicit tick values override all other options * 2. `ticks` (function) - Filter function for tick selection * 3. `ticks` (boolean) - Show/hide all possible ticks * 4. `requestedTickCount` - D3 automatic tick generation (overrides tickInterval) * 5. `tickInterval` - Pixel-based spacing (fallback) * * **For Categorical Scales (band):** * 1. `ticks` (array) - Explicit category indices to display * 2. `ticks` (function) - Filter function for category selection * 3. `ticks` (boolean) - Show/hide all categories * 4. Default - Show all categories (requestedTickCount and tickInterval are ignored) * * @param params - Tick processing parameters * @param params.ticks - Custom tick configuration with multiple formats: * - **Array**: For numeric scales: exact tick values; For band scales: category indices * - **Function**: Predicate to filter tick values or category indices * - **Boolean**: Show all (true) or no ticks (false) for both scale types * @param params.scaleFunction - D3 scale function (numeric or band scale) * @param params.requestedTickCount - Number of ticks for D3 generation (**numeric scales only**, overrides tickInterval) * @param params.categories - Category labels (**band scales only**) * @param params.possibleTickValues - Available tick values for filtering/selection (**numeric scales only**) * @param params.tickInterval - Pixel spacing between ticks (**numeric scales only**, fallback option) * @returns Array of tick data with values and positions * * @example * // Basic usage with tickInterval for pixel-based spacing * import { scaleLinear } from 'd3-scale'; * * const numericScale = scaleLinear().domain([0, 10]).range([0, 400]); * const result = getAxisTicksData({ * scaleFunction: numericScale, * tickInterval: 80, // 80 pixels between ticks * possibleTickValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * }); * // Returns: [ * // { tick: 0, position: 0 }, // Always includes first * // { tick: 2, position: 80 }, * // { tick: 5, position: 200 }, * // { tick: 7, position: 280 }, * // { tick: 10, position: 400 } // Always includes last * // ] * * @example * // Using requestedTickCount for D3-generated ticks * const result = getAxisTicksData({ * scaleFunction: numericScale, * requestedTickCount: 5 * }); * // Uses D3's tick generation algorithm * * @example * // Using explicit tick values * const result = getAxisTicksData({ * scaleFunction: numericScale, * ticks: [0, 2.5, 5, 7.5, 10] * }); * // Returns exact positions for specified values * * @example * // Using tick filter function * const result = getAxisTicksData({ * scaleFunction: numericScale, * ticks: (value) => value % 2 === 0, // Only even numbers * possibleTickValues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] * }); * // Returns: [0, 2, 4, 6, 8, 10] with their positions * * @example * // Band scale with categories (requestedTickCount and tickInterval are ignored) * import { scaleBand } from 'd3-scale'; * * const bandScale = scaleBand().domain([0, 1, 2, 3, 4]).range([0, 400]).padding(0.1); * const result = getAxisTicksData({ * scaleFunction: bandScale, * categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], * ticks: [0, 2, 4], // Show only Jan (index 0), Mar (index 2), May (index 4) * requestedTickCount: 10, // IGNORED for band scales * tickInterval: 50 // IGNORED for band scales * }); * // Returns tick positions centered in each selected band */ export declare const getAxisTicksData: ({ ticks, scaleFunction, requestedTickCount, categories, possibleTickValues, tickInterval, options, }: GetAxisTicksDataProps) => Array<{ tick: number; position: number; }>; export type RegisteredAxis = { id: string; position: 'top' | 'bottom' | 'left' | 'right'; size: number; }; /** * Calculates the total amount of padding needed to render a set of axes on the main drawing area of the chart. * Returns the registed axes, an API for adding/removing axes as well as the total calculated padding that must be reserved in the drawing area. */ export declare const useTotalAxisPadding: () => { renderedAxes: Map; axisPadding: { top: number; right: number; bottom: number; left: number; }; registerAxis: (id: string, position: 'top' | 'bottom' | 'left' | 'right', size: number) => void; unregisterAxis: (id: string) => void; }; export {}; //# sourceMappingURL=axis.d.ts.map