diff --git a/.changeset/data-table-block.md b/.changeset/data-table-block.md new file mode 100644 index 000000000..7b6f6b733 --- /dev/null +++ b/.changeset/data-table-block.md @@ -0,0 +1,5 @@ +--- +"@slack/types": minor +--- + +feat: add the [`data_table`](https://docs.slack.dev/reference/block-kit/blocks/data-table-block) Block Kit block type (`DataTableBlock`) diff --git a/packages/types/src/block-kit/blocks.ts b/packages/types/src/block-kit/blocks.ts index 60ab5166c..20cd9561c 100644 --- a/packages/types/src/block-kit/blocks.ts +++ b/packages/types/src/block-kit/blocks.ts @@ -28,6 +28,7 @@ import type { import type { MrkdwnElement, PlainTextElement, + RawNumberElement, RawTextElement, SlackFileImageObject, TextObject, @@ -61,6 +62,7 @@ export type KnownBlock = | ContainerBlock | ContextBlock | ContextActionsBlock + | DataTableBlock | DividerBlock | FileBlock | HeaderBlock @@ -289,6 +291,33 @@ export interface ContextActionsBlock extends Block { elements: ContextActionsBlockElement[]; } +/** + * @description Displays rich tables that support pagination, sorting, filtering, and interactivity. + * @see {@link https://docs.slack.dev/reference/block-kit/blocks/data-table-block Data table block reference}. + */ +export interface DataTableBlock extends Block { + /** + * @description The type of block. For a data table block, `type` is always `data_table`. + */ + type: 'data_table'; + /** + * @description An array consisting of table rows. + */ + rows: (RawTextElement | RawNumberElement | RichTextBlock)[][]; + /** + * @description A caption for the table; used as the value for the HTML caption element. + */ + caption: string; + /** + * @description Number of rows per page. Min `1`, Max `100`. Defaults to `5` if omitted. + */ + page_size?: number; + /** + * @description The 0-based index of the column that uniquely identifies each row (the row header). This column is treated as the row's primary identifier for screen readers. Defaults to `0` if omitted. + */ + row_header_column_index?: number; +} + /** * @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/src/block-kit/composition-objects.ts b/packages/types/src/block-kit/composition-objects.ts index 886830344..b36d1cf50 100644 --- a/packages/types/src/block-kit/composition-objects.ts +++ b/packages/types/src/block-kit/composition-objects.ts @@ -173,6 +173,24 @@ export interface MrkdwnElement { verbatim?: boolean; } +/** + * @description Defines an object containing a numeric value. + */ +export interface RawNumberElement { + /** + * @description The formatting to use for this numeric object. + */ + type: 'raw_number'; + /** + * @description The numeric value. + */ + value: number; + /** + * @description The text used to display the value. The minimum length is 1 character. + */ + text: string; +} + /** * @description Defines an object containing some text. * @see {@link https://docs.slack.dev/reference/block-kit/composition-objects/text-object Text object reference}. diff --git a/packages/types/test/blocks.test-d.ts b/packages/types/test/blocks.test-d.ts index 3169703e5..421941b23 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, ContainerBlock, KnownBlock } from '../src/index'; +import type { AlertBlock, CardBlock, CarouselBlock, ContainerBlock, DataTableBlock, KnownBlock } from '../src/index'; // CardBlock // -- sad path @@ -102,3 +102,53 @@ expectAssignable({ title: { type: 'plain_text', text: 'Known' }, child_blocks: [{ type: 'divider' }], }); + +// DataTableBlock +// -- sad path +expectError({}); // missing type, rows, and caption +expectError({ type: 'data_table' }); // missing required rows and caption +expectError({ + type: 'data_table', + rows: [[{ type: 'raw_text', text: 'Name' }]], +}); // missing required caption +expectError({ + type: 'data_table', + caption: 'A list of fruit and their quantities', +}); // missing required rows +// -- happy path +expectAssignable({ + type: 'data_table', + caption: 'A list of fruit and their quantities', + rows: [ + [ + { type: 'raw_text', text: 'Fruit' }, + { type: 'raw_text', text: 'Quantity' }, + ], + [ + { type: 'raw_text', text: 'Apples' }, + { type: 'raw_number', value: 12, text: '12' }, + ], + ], +}); +expectAssignable({ + type: 'data_table', + caption: 'A list of users', + block_id: 'users_table', + page_size: 10, + row_header_column_index: 0, + rows: [ + [ + { type: 'raw_text', text: 'User' }, + { type: 'raw_text', text: 'Bio' }, + ], + [ + { type: 'raw_text', text: 'Mark' }, + { type: 'rich_text', elements: [{ type: 'rich_text_section', elements: [{ type: 'text', text: 'Founder' }] }] }, + ], + ], +}); +expectAssignable({ + type: 'data_table', + caption: 'A minimal table', + rows: [[{ type: 'raw_text', text: 'Header' }], [{ type: 'raw_text', text: 'Value' }]], +});