/** * Conditional formatting engine. Excel-style declarative rules that color a * cell by its value - color scales, in-cell data bars, icon sets, and plain * predicate rules. This goes beyond `cellClass(ctx)` (which can only toggle * static classes) because color scales and data bars need a value computed * against the column's min/max range. * * Everything here is pure: `resolveCellFormat` takes a value + the column's * numeric range and returns the visual primitives, so the `` render * component just paints the result and the logic is unit-testable. */ /** A single gradient stop along the normalized 0..1 domain. */ export type ColorScaleStop = { offset: number; color: string; }; /** * How `minValue`/`maxValue` (and the derived column extremes) are read: * - `absolute` (default): literal data values. * - `percent`: 0..100 positions along the column's own min..max span, so you * can say "tint the top 20%" without knowing the numbers up front. */ export type ScaleBounds = 'absolute' | 'percent'; export type ColorScaleFormat = { type: 'colorScale'; /** 2-stop (min/max) or 3-stop (min/mid/max) gradient. Hex colors. */ min?: string; mid?: string; max?: string; /** * N-stop gradient along the normalized domain (offsets 0..1). When present * this overrides `min`/`mid`/`max`, enabling banded / traffic-light scales. */ stops?: ReadonlyArray; /** * `hue` (default): interpolate between stop colors into an opaque fill. * `alpha`: keep a single `base` color and interpolate its *opacity*, so the * tint composites over zebra striping, selection, and pinned backgrounds * instead of painting over them - Adaptable's "live heat map" look. */ mode?: 'hue' | 'alpha'; /** Base color for `alpha` mode. Default `#2563eb`. */ base?: string; /** [min, max] opacity for `alpha` mode. Default [0.05, 0.85]. */ alphaBounds?: readonly [number, number]; /** Fix the scale; otherwise derived from the column's data. */ minValue?: number; maxValue?: number; /** Interpret `minValue`/`maxValue` as absolute values or 0..100 percents. */ bounds?: ScaleBounds; /** * Diverging scale pinned at 0: negatives and positives shade outward from a * neutral midpoint, symmetric around zero. Ideal for P&L / price deltas. */ zeroCentred?: boolean; /** Flip the ramp so the lowest values attract the most attention. */ reverse?: boolean; /** * Tint by this cell's value as a proportion of another column's value on the * SAME row (a field key on the row object), instead of the column extremes. * Column comparison - e.g. filled vs target, open vs total. */ compareColumn?: string; /** Attach a tooltip showing the raw value or its % position on the ramp. */ tooltip?: 'value' | 'percent'; }; export type DataBarFormat = { type: 'dataBar'; color: string; negativeColor?: string; minValue?: number; maxValue?: number; /** Interpret `minValue`/`maxValue` as absolute values or 0..100 percents. */ bounds?: ScaleBounds; /** * Size the bar by this cell's value as a proportion of another column's * value on the same row (a field key), instead of the column extremes. */ compareColumn?: string; /** Fill the bar with a left-to-right gradient rather than a flat color. */ gradient?: boolean; /** Show the cell's text on top of the bar. Default true. */ showValue?: boolean; }; export type IconSetName = 'arrows' | 'traffic' | 'triangles'; export type IconSetFormat = { type: 'iconSet'; set?: IconSetName; /** Ascending breakpoints. n thresholds => n+1 buckets/icons. */ thresholds: number[]; /** Hide the numeric text, show only the icon. Default false. */ iconOnly?: boolean; }; export type RuleFormat = { type: 'rule'; /** Apply the styles below when this returns true. */ when: (ctx: { value: unknown; row: TData; }) => boolean; background?: string; color?: string; fontWeight?: string | number; }; export type ConditionalFormatSpec = ColorScaleFormat | DataBarFormat | IconSetFormat | RuleFormat; /** A format scoped to specific columns (omit `columns` to apply to all). */ export type ConditionalFormat = ConditionalFormatSpec & { columns?: ReadonlyArray; }; export type ResolvedCellFormat = { background?: string; color?: string; fontWeight?: string | number; dataBar?: { percent: number; color: string; fromRight: boolean; gradient?: boolean; }; icon?: string; iconOnly?: boolean; /** Tooltip text (value / percentile), when a format requests one. */ title?: string; }; export type ColumnStat = { min: number; max: number; }; /** Min/max of a column's finite numeric values, or null if none. */ export declare function computeColumnStat(values: Iterable): ColumnStat | null; /** * Pick a readable text color (near-black or white) for a given hex * background, using WCAG relative luminance. Lets a color-scale fill or a * tinted rule keep its text legible without the caller hand-picking a color. * Returns null when the background isn't a parseable hex (e.g. a CSS var), * so the caller can leave the default text color in place. */ export declare function contrastText(bg: string): string | null; /** Linear interpolate two hex colors. Falls back to `a` if parsing fails. */ export declare function lerpColor(a: string, b: string, t: number): string; /** Build an `rgba()` string from a hex color + opacity. Falls back to the hex. */ export declare function rgba(hex: string, alpha: number): string; /** * Resolve every format that applies to one cell into a single set of visual * primitives. Later-listed formats override earlier ones for the same * property, so order your `conditionalFormats` from general to specific. */ export declare function resolveCellFormat(value: unknown, row: TData, columnId: string, formats: ReadonlyArray>, stat: ColumnStat | null): ResolvedCellFormat; /** * Whether any format needs a numeric min/max precomputed. Color-scale and * data-bar formats do, EXCEPT when they derive their range from another column * on the same row (`compareColumn`) - those read the row, not column stats. */ export declare function formatNeedsStats(f: ConditionalFormat): boolean; export declare function formatsNeedingStats(formats: ReadonlyArray>): boolean;