Skip to content

Commit

Permalink
feat(types): improve generic types in specs, and spec prop types (#1421)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The `xAccessor` and `yAccessor` are now required on all xy chart specs. Stronger typing on `data` prop that may cause type errors when using untyped array (i.e. `const arr: never[] = []`). Other minor type changes related to spec types.
  • Loading branch information
nickofthyme authored Jan 5, 2022
1 parent 8139973 commit 562929e
Show file tree
Hide file tree
Showing 70 changed files with 1,215 additions and 914 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
"@elastic/datemath": "^5.0.3",
"@elastic/eui": "^41.3.0",
"@mdx-js/loader": "^1.6.6",
"@microsoft/api-documenter": "^7.13.54",
"@microsoft/api-extractor": "^7.18.11",
"@microsoft/api-documenter": "^7.13.63",
"@microsoft/api-extractor": "^7.18.16",
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/commit-analyzer": "^8.0.1",
"@semantic-release/exec": "^5.0.0",
Expand Down
266 changes: 148 additions & 118 deletions packages/charts/api/charts.api.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ export type ShapeViewModel = {
};

const commonDefaults = {
specType: SpecType.Series,
subtype: GoalSubtype.Goal,
base: 0,
actual: 50,
ticks: [0, 25, 50, 75, 100],
Expand All @@ -88,6 +86,8 @@ export const defaultGoalSpec = {
/** @internal */
export const nullGoalViewModel = {
...commonDefaults,
specType: SpecType.Series,
subtype: GoalSubtype.Goal,
bands: [],
ticks: [],
labelMajor: '',
Expand Down
49 changes: 17 additions & 32 deletions packages/charts/src/chart_types/goal_chart/specs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
* Side Public License, v 1.
*/

import React from 'react';
import { ComponentProps } from 'react';

import { ChartType } from '../..';
import { Color } from '../../../common/colors';
import { Spec } from '../../../specs';
import { SpecType } from '../../../specs/constants';
import { getConnect, specComponentFactory } from '../../../state/spec_factory';
import { specComponentFactory } from '../../../state/spec_factory';
import { LabelAccessor, ValueFormatter } from '../../../utils/common';
import { defaultGoalSpec } from '../layout/types/viewmodel_types';
import { GoalSubtype } from './constants';
Expand All @@ -35,11 +35,6 @@ export type BandFillColorAccessor = (input: BandFillColorAccessorInput) => Color
/** @alpha */
export type GoalLabelAccessor = LabelAccessor<BandFillColorAccessorInput>;

const defaultProps = {
chartType: ChartType.Goal,
...defaultGoalSpec,
};

/** @alpha */
export interface GoalSpec extends Spec {
specType: typeof SpecType.Series;
Expand All @@ -62,29 +57,19 @@ export interface GoalSpec extends Spec {
tooltipValueFormatter: ValueFormatter;
}

type SpecRequiredProps = Pick<GoalSpec, 'id' | 'actual'>;
type SpecOptionalProps = Partial<Omit<GoalSpec, 'chartType' | 'specType' | 'id' | 'data'>>;

/** @alpha */
export const Goal: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()(
specComponentFactory<
GoalSpec,
| 'chartType'
| 'subtype'
| 'base'
| 'target'
| 'actual'
| 'bands'
| 'bandLabels'
| 'ticks'
| 'bandFillColor'
| 'tickValueFormatter'
| 'labelMajor'
| 'labelMinor'
| 'centralMajor'
| 'centralMinor'
| 'angleStart'
| 'angleEnd'
| 'tooltipValueFormatter'
>(defaultProps),
/**
* Add Goal spec to chart
* @alpha
*/
export const Goal = specComponentFactory<GoalSpec>()(
{
specType: SpecType.Series,
chartType: ChartType.Goal,
},
{
...defaultGoalSpec,
},
);

/** @public */
export type GoalProps = ComponentProps<typeof Goal>;
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { ScaleType } from '../../../../scales/constants';
import { LinearScale, OrdinalScale, RasterTimeScale } from '../../../../specs';
import { TextMeasure, withTextMeasure } from '../../../../utils/bbox/canvas_text_bbox_calculator';
import { addIntervalToTime } from '../../../../utils/chrono/elasticsearch';
import { clamp } from '../../../../utils/common';
import { clamp, Datum } from '../../../../utils/common';
import { Dimensions, horizontalPad, innerPad, pad } from '../../../../utils/dimensions';
import { Logger } from '../../../../utils/logger';
import { HeatmapStyle, Theme, Visible } from '../../../../utils/themes/theme';
Expand All @@ -34,6 +34,7 @@ import {
ShapeViewModel,
TextBox,
} from '../types/viewmodel_types';
import { BaseDatum } from './../../../xy_chart/utils/specs';

/** @public */
export interface HeatmapCellDatum {
Expand Down Expand Up @@ -78,9 +79,9 @@ function estimatedNonOverlappingTickCount(
});
}
/** @internal */
export function shapeViewModel(
export function shapeViewModel<D extends BaseDatum = Datum>(
textMeasure: TextMeasure,
spec: HeatmapSpec,
spec: HeatmapSpec<D>,
{ heatmap: heatmapTheme, axes: { axisTitle }, background }: Theme,
elementSizes: ChartElementSizes,
heatmapTable: HeatmapTable,
Expand Down
113 changes: 58 additions & 55 deletions packages/charts/src/chart_types/heatmap/specs/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,21 @@
* Side Public License, v 1.
*/

import React from 'react';
import { ComponentProps, useRef } from 'react';

import { ChartType } from '../..';
import { Color } from '../../../common/colors';
import { Predicate } from '../../../common/predicate';
import { ScaleType } from '../../../scales/constants';
import { Spec } from '../../../specs';
import { BaseDatum, Spec } from '../../../specs';
import { SpecType } from '../../../specs/constants';
import { getConnect, specComponentFactory } from '../../../state/spec_factory';
import { buildSFProps, SFProps, useSpecFactory } from '../../../state/spec_factory';
import { Accessor, AccessorFn } from '../../../utils/accessor';
import { ESCalendarInterval, ESFixedInterval } from '../../../utils/chrono/elasticsearch';
import { Datum } from '../../../utils/common';
import { Datum, LabelAccessor, stripUndefined, ValueFormatter } from '../../../utils/common';
import { Cell } from '../layout/types/viewmodel_types';
import { X_SCALE_DEFAULT } from './scale_defaults';

const defaultProps = {
chartType: ChartType.Heatmap,
specType: SpecType.Series,
data: [],
xAccessor: ({ x }: { x: string | number }) => x,
yAccessor: ({ y }: { y: string | number }) => y,
xScale: { type: X_SCALE_DEFAULT.type },
valueAccessor: ({ value }: { value: string | number }) => value,
valueFormatter: (value: number) => `${value}`,
xSortPredicate: Predicate.AlphaAsc,
ySortPredicate: Predicate.AlphaAsc,
timeZone: 'UTC',
xAxisTitle: '',
yAxisTitle: '',
xAxisLabelName: 'X Value',
xAxisLabelFormatter: String,
yAxisLabelName: 'Y Value',
yAxisLabelFormatter: String,
};

/** @public */
export type HeatmapScaleType =
| typeof ScaleType.Linear
Expand Down Expand Up @@ -91,15 +71,15 @@ export interface OrdinalScale {
}

/** @alpha */
export interface HeatmapSpec extends Spec {
export interface HeatmapSpec<D extends BaseDatum = Datum> extends Spec {
specType: typeof SpecType.Series;
chartType: typeof ChartType.Heatmap;
data: Datum[];
data: D[];
colorScale: HeatmapBandsColorScale;
xAccessor: Accessor | AccessorFn;
yAccessor: Accessor | AccessorFn;
valueAccessor: Accessor | AccessorFn;
valueFormatter: (value: number) => string;
xAccessor: Accessor<D> | AccessorFn<D>;
yAccessor: Accessor<D> | AccessorFn<D>;
valueAccessor: Accessor<never> | AccessorFn;
valueFormatter: ValueFormatter;
xSortPredicate: Predicate;
ySortPredicate: Predicate;
xScale: RasterTimeScale | OrdinalScale | LinearScale;
Expand All @@ -109,33 +89,56 @@ export interface HeatmapSpec extends Spec {
onBrushEnd?: (brushArea: HeatmapBrushEvent) => void;
xAxisTitle: string;
xAxisLabelName: string;
xAxisLabelFormatter: (value: string | number) => string;
xAxisLabelFormatter: LabelAccessor<string | number>;
yAxisTitle: string;
yAxisLabelName: string;
yAxisLabelFormatter: (value: string | number) => string;
yAxisLabelFormatter: LabelAccessor<string | number>;
}

type SpecRequiredProps = Pick<HeatmapSpec, 'id' | 'data' | 'colorScale'>;
type SpecOptionalProps = Partial<Omit<HeatmapSpec, 'chartType' | 'specType' | 'id' | 'data'>>;
/**
* Adds heatmap spec to chart specs
* @alpha
*/
export const Heatmap = function <D extends BaseDatum = Datum>(
props: SFProps<
HeatmapSpec<D>,
keyof typeof buildProps.current['overrides'],
keyof typeof buildProps.current['defaults'],
keyof typeof buildProps.current['optionals'],
keyof typeof buildProps.current['requires']
>,
) {
const buildProps = useRef(
// @ts-ignore - excessively deep types
buildSFProps<HeatmapSpec<D>>()(
{
chartType: ChartType.Heatmap,
specType: SpecType.Series,
},
{
data: [],
valueAccessor: ({ value }) => value,
xScale: { type: X_SCALE_DEFAULT.type },
valueFormatter: (value) => `${value}`,
xSortPredicate: Predicate.AlphaAsc,
ySortPredicate: Predicate.AlphaAsc,
// TODO: make accessors required
xAccessor: (d) => (d as any)?.x,
yAccessor: (d) => (d as any)?.y,
timeZone: 'UTC',
xAxisTitle: '',
yAxisTitle: '',
xAxisLabelName: 'X Value',
xAxisLabelFormatter: String,
yAxisLabelName: 'Y Value',
yAxisLabelFormatter: String,
},
),
);
const { defaults, overrides } = buildProps.current;
useSpecFactory<HeatmapSpec<D>>({ ...defaults, ...stripUndefined(props), ...overrides });
return null;
};

/** @alpha */
export const Heatmap: React.FunctionComponent<SpecRequiredProps & SpecOptionalProps> = getConnect()(
specComponentFactory<
HeatmapSpec,
| 'xAccessor'
| 'yAccessor'
| 'valueAccessor'
| 'data'
| 'ySortPredicate'
| 'xSortPredicate'
| 'valueFormatter'
| 'xScale'
| 'timeZone'
| 'xAxisTitle'
| 'xAxisLabelName'
| 'xAxisLabelFormatter'
| 'yAxisTitle'
| 'yAxisLabelName'
| 'yAxisLabelFormatter'
>(defaultProps),
);
/** @public */
export type HeatmapProps = ComponentProps<typeof Heatmap>;
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const getHeatmapTableSelector = createCustomCachedSelector(
const resultData = data.reduce<HeatmapTable>(
(acc, curr, index) => {
const x = getAccessorValue(curr, xAccessor);

const y = getAccessorValue(curr, yAccessor);
const value = getAccessorValue(curr, valueAccessor);

Expand Down
Loading

0 comments on commit 562929e

Please sign in to comment.