diff --git a/.changeset/data-visualization-block.md b/.changeset/data-visualization-block.md new file mode 100644 index 000000000..7dd4ba447 --- /dev/null +++ b/.changeset/data-visualization-block.md @@ -0,0 +1,5 @@ +--- +"@slack/types": minor +--- + +feat: add `DataVisualizationBlock` type for the `data_visualization` Block Kit block diff --git a/packages/types/src/block-kit/blocks.ts b/packages/types/src/block-kit/blocks.ts index 365492d93..451950cd7 100644 --- a/packages/types/src/block-kit/blocks.ts +++ b/packages/types/src/block-kit/blocks.ts @@ -60,6 +60,7 @@ export type KnownBlock = | CarouselBlock | ContextBlock | ContextActionsBlock + | DataVisualizationBlock | DividerBlock | FileBlock | HeaderBlock @@ -226,6 +227,131 @@ export interface ContextActionsBlock extends Block { elements: ContextActionsBlockElement[]; } +/** + * @description A single slice of a {@link DataVisualizationPieChart}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationPieSegment { + /** + * @description The label for the segment. Maximum length is 20 characters. + */ + label: string; + /** + * @description The value for the segment. Must be greater than 0. + */ + value: number; +} + +/** + * @description A single data point within a {@link DataVisualizationSeries}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationDataPoint { + /** + * @description The label for the data point. Maximum length is 20 characters. Must match a category defined in + * the chart's {@link DataVisualizationAxisConfig}. + */ + label: string; + /** + * @description The value for the data point. Negative values are permitted. + */ + value: number; +} + +/** + * @description A series of data points displayed in a bar, area, or line {@link DataVisualizationBlock} chart. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationSeries { + /** + * @description The name of the series. Maximum length is 20 characters. Must be unique within the chart. + */ + name: string; + /** + * @description An array of {@link DataVisualizationDataPoint} objects. Minimum 1, maximum 20 data points. + */ + data: DataVisualizationDataPoint[]; +} + +/** + * @description Axis configuration for a bar, area, or line {@link DataVisualizationBlock} chart. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationAxisConfig { + /** + * @description The x-axis category labels. The order of categories determines the x-axis display sequence. Maximum + * length for each category is 20 characters. + */ + categories: string[]; + /** + * @description An optional label for the x-axis. Maximum length is 50 characters. + */ + x_label?: string; + /** + * @description An optional label for the y-axis. Maximum length is 50 characters. + */ + y_label?: string; +} + +/** + * @description A pie chart for a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationPieChart { + /** + * @description The type of chart. For a pie chart, `type` is always `pie`. + */ + type: 'pie'; + /** + * @description An array of {@link DataVisualizationPieSegment} objects. Minimum 1, maximum 6 segments. + */ + segments: DataVisualizationPieSegment[]; +} + +/** + * @description A bar, area, or line chart for a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationSeriesChart { + /** + * @description The type of chart. One of `bar`, `area`, or `line`. + */ + type: 'bar' | 'area' | 'line'; + /** + * @description An array of {@link DataVisualizationSeries} objects. Minimum 1, maximum 6 series. + */ + series: DataVisualizationSeries[]; + /** + * @description The {@link DataVisualizationAxisConfig} describing the chart axes. + */ + axis_config: DataVisualizationAxisConfig; +} + +/** + * @description A helper union type of all chart shapes supported by a {@link DataVisualizationBlock}. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export type DataVisualizationChart = DataVisualizationPieChart | DataVisualizationSeriesChart; + +/** + * @description Displays a chart visualizing a dataset, such as a pie, bar, area, or line chart. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block Data visualization block reference}. + */ +export interface DataVisualizationBlock extends Block { + /** + * @description The type of block. For a data visualization block, `type` is always `data_visualization`. + */ + type: 'data_visualization'; + /** + * @description The title of the chart. Maximum length is 50 characters. + */ + title: string; + /** + * @description The {@link DataVisualizationChart} to render. One of a pie, bar, area, or line chart. + */ + chart: DataVisualizationChart; +} + /** * @description Visually separates pieces of info inside of a message. A content divider, like an `
`, to split up * different blocks inside of a message. The divider block is nice and neat, requiring only a `type`. diff --git a/packages/types/test/blocks.test-d.ts b/packages/types/test/blocks.test-d.ts index e154b6c1b..fb8fff008 100644 --- a/packages/types/test/blocks.test-d.ts +++ b/packages/types/test/blocks.test-d.ts @@ -1,5 +1,5 @@ import { expectAssignable, expectError } from 'tsd'; -import type { AlertBlock, CardBlock, CarouselBlock, KnownBlock } from '../src/index'; +import type { AlertBlock, CardBlock, CarouselBlock, DataVisualizationBlock, KnownBlock } from '../src/index'; // CardBlock // -- sad path @@ -62,3 +62,69 @@ expectAssignable({ type: 'carousel', elements: [{ type: 'card' }], }); + +// DataVisualizationBlock +// -- sad path +expectError({}); // missing type, title and chart +expectError({ type: 'data_visualization', title: 'Sales' }); // missing required chart +expectError({ + type: 'data_visualization', + title: 'Sales', + chart: { type: 'pie' }, // pie chart missing required segments +}); +expectError({ + type: 'data_visualization', + title: 'Sales', + chart: { type: 'bar', series: [{ name: 'Q1', data: [{ label: 'Jan', value: 1 }] }] }, // series chart missing axis_config +}); +expectError({ + type: 'data_visualization', + title: 'Sales', + chart: { type: 'scatter', segments: [{ label: 'A', value: 1 }] }, // unknown chart type +}); +// -- happy path +expectAssignable({ + type: 'data_visualization', + title: 'Revenue by region', + chart: { + type: 'pie', + segments: [ + { label: 'North', value: 40 }, + { label: 'South', value: 60 }, + ], + }, +}); +expectAssignable({ + type: 'data_visualization', + title: 'Quarterly revenue', + block_id: 'viz_1', + chart: { + type: 'bar', + series: [ + { + name: 'Product A', + data: [ + { label: 'Q1', value: 10 }, + { label: 'Q2', value: 20 }, + ], + }, + { + name: 'Product B', + data: [ + { label: 'Q1', value: 5 }, + { label: 'Q2', value: -3 }, + ], + }, + ], + axis_config: { categories: ['Q1', 'Q2'], x_label: 'Quarter', y_label: 'Revenue' }, + }, +}); +expectAssignable({ + type: 'data_visualization', + title: 'Trend', + chart: { + type: 'line', + series: [{ name: 'Users', data: [{ label: 'Mon', value: 1 }] }], + axis_config: { categories: ['Mon'] }, + }, +});