Skip to content

Commit

Permalink
Merge pull request #87 from raycharius/v2.5.0
Browse files Browse the repository at this point in the history
✨ Release v2.5.0
  • Loading branch information
raycharius authored Feb 5, 2022
2 parents 9dda415 + d18e885 commit d732ba1
Show file tree
Hide file tree
Showing 19 changed files with 328 additions and 9 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,11 @@ The `Utilities` object contains various utility functions for creating UI. Curre

`AttachmentCollection()` – Accepts multiple arguments or an array of attachments and returns them in an array, in their built state.

These two functions are useful when you wish to keep surface or view configuration separate from UI representation.
`OptionCollection()` – Accepts multiple arguments or an array of options and returns them in an array, in their built state.

`OptionGroupCollection()` – Accepts multiple arguments or an array of option groups and returns them in an array, in their built state.

Both `BlockCollection()` and `AttachmentCollection()` are useful when you wish to keep surface or view configuration separate from UI representation.

An example using Slack's `WebClient` from their [SDK for Node.js](https://github.com/slackapi/node-slack-sdk):

Expand Down Expand Up @@ -382,6 +386,16 @@ const unfurl = ({ channel, ts, url }) => client.chat.unfurl({
.catch((error) => console.log(error));
```

Both `OptionCollection()` and `OptionGroupCollection()` come in handy when returning an array of options or option groups for select menus with external data sources, as seen in [Slack's API docs](https://api.slack.com/reference/block-kit/block-elements#external_multi_select):

```javascript
return { options: OptionCollection( /* Pass in options */ ) };

// Or:

return { options: OptionGroupCollection( /* Pass in option groups */ ) };
```

### Working With Inline Conditionals

There are a few helper functions available to make it easy to work with inline conditionals within your UI source code.
Expand Down
2 changes: 2 additions & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
* **Other**
* [Block Collection](other/block-collection.md "Block Builder – Block Collection – Maintainable JavaScript Code for Slack Block Kit")
* [Attachment Collection](other/attachment-collection.md "Block Builder – Attachment Collection – Maintainable JavaScript Code for Slack Block Kit")
* [Option Collection](other/option-collection.md "Block Builder – Option Collection – Maintainable JavaScript Code for Slack Block Kit")
* [Option Group Collection](other/option-group-collection.md "Block Builder – Option Group Collection – Maintainable JavaScript Code for Slack Block Kit")
* [Conditionals](other/conditionals.md "Block Builder – Conditionals – Maintainable JavaScript Code for Slack Block Kit")
* [Markdown](other/markdown.md "Block Builder – Markdown – Maintainable JavaScript Code for Slack Block Kit")

Expand Down
7 changes: 7 additions & 0 deletions docs/elements/button.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const myObj = Elements.Button(params?);
Each instance of the `ButtonBuilder` object has chainable setter methods for the object's properties. However, properties with primitive values can optionally be passed to the instantiating function, should you prefer:
`accessibilityLabel` – *String*
`actionId` – *String*
`text` – *String*
Expand All @@ -49,6 +51,11 @@ ButtonBuilder.primary(boolean?);
For a button element, this changes the color to green. For confirmation dialogs, this sets the main button in the bottom right corner to green, which is meant to confirm the action. Defaults to `true`.
```javascript
ButtonBuilder.accessibilityLabel(string);
```
A label for longer descriptive text about a button element. This label will be read out by screen readers instead of the button text object.
```javascript
ButtonBuilder.actionId(string);
```
Expand Down
6 changes: 3 additions & 3 deletions docs/other/attachment-collection.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Attachment Collection

?> **Note:** This document is a reference for creating a collection of blocks in **Block Builder**. For information on the business logic for the blocks in the context of the Slack Block Kit framework, visit [the official doc site](https://api.slack.com/block-kit) from Slack.
?> **Note:** This document is a reference for creating a collection of attachments in **Block Builder**. For information on the business logic for the attachments in the context of the Slack Block Kit framework, visit [the official doc site](https://api.slack.com/block-kit) from Slack.

### Creating a Attachment Collection
### Creating an Attachment Collection

A block collection is an array of built block objects. The function that creates a collection, `AttachmentCollection`, is available as both a top-level import and as a member of its 'category', `Utilities`:

Expand All @@ -21,7 +21,7 @@ const myAttachments = Utilities.AttachmentCollection(attachments);

This function behaves in the same way as any other [methods that append](../setter-methods.md).

### When To Use a Attachment Collection
### When To Use an Attachment Collection

In **Block Builder**, the `Message` object is more than a UI representation. It also allow you to configure the behavior of the message. However, you may prefer to keep UI representation and surface configuration separate in your application. When that's the case, using `AttachmentCollection` is the way to go.

Expand Down
30 changes: 30 additions & 0 deletions docs/other/option-collection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Option Collection

?> **Note:** This document is a reference for creating a collection of options in **Block Builder**. For information on the business logic for the options in the context of the Slack Block Kit framework, visit [the official doc site](https://api.slack.com/block-kit) from Slack.

### Creating an Option Collection

An option collection is an array of built option objects. The function that creates a collection, `OptionCollection`, is available as both a top-level import and as a member of its 'category', `Utilities`:

```javascript
import { OptionCollection } from 'slack-block-builder';

const myOptions = OptionCollection(options);

```

```javascript
import { Utilities } from 'slack-block-builder';

const myOptions = Utilities.OptionCollection(options);
```

This function behaves in the same way as any other [methods that append](../setter-methods.md).

### When To Use an Option Collection

The `OptionCollection` function is meant to be used to create a response to requests to your service made from select menus with external data sources, where you return an array of options:

```javascript
return { options: OptionCollection( /* Pass in options */ ) };
```
30 changes: 30 additions & 0 deletions docs/other/option-group-collection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Option Group Collection

?> **Note:** This document is a reference for creating a collection of option groups in **Block Builder**. For information on the business logic for the option groups in the context of the Slack Block Kit framework, visit [the official doc site](https://api.slack.com/block-kit) from Slack.

### Creating an Option Group Collection

An option group collection is an array of built option group objects. The function that creates a collection, `OptionGroupCollection`, is available as both a top-level import and as a member of its 'category', `Utilities`:

```javascript
import { OptionGroupCollection } from 'slack-block-builder';

const myOptionGroups = OptionGroupCollection(optionGroups);

```

```javascript
import { Utilities } from 'slack-block-builder';

const myOptionGroups = Utilities.OptionGroupCollection(optionGroups);
```

This function behaves in the same way as any other [methods that append](../setter-methods.md).

### When To Use an Option Group Collection

The `OptionGroupCollection` function is meant to be used to create a response to requests to your service made from select menus with external data sources, where you return an array of options or option groups:

```javascript
return { options: OptionGroupCollection( /* Pass in option groups */ ) };
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "slack-block-builder",
"version": "2.4.2",
"version": "2.5.0",
"description": "Maintainable code for interactive Slack messages, modals, home tabs, and workflow steps. A must-have for the Slack Block Kit framework.",
"author": {
"name": "Ray East",
Expand Down
6 changes: 5 additions & 1 deletion src/elements/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ElementType } from '../internal/constants';
import { SlackElementDto } from '../internal/dto';
import { applyMixins, getPlainTextObject, getBuilderResult } from '../internal/helpers';
import {
AccessibilityLabel,
ActionId,
Confirm,
Danger,
Expand All @@ -17,13 +18,15 @@ import type { SlackDto } from '../internal/dto';
import type { ConfirmationDialogBuilder } from '../bits';

export interface ButtonParams {
accessibilityLabel?: string;
actionId?: string;
text?: string;
url?: string;
value?: string;
}

export interface ButtonBuilder extends ActionId,
export interface ButtonBuilder extends AccessibilityLabel,
ActionId,
Confirm<ConfirmationDialogBuilder>,
Danger,
End,
Expand Down Expand Up @@ -51,6 +54,7 @@ export class ButtonBuilder extends ElementBuilderBase {
}

applyMixins(ButtonBuilder, [
AccessibilityLabel,
ActionId,
Confirm,
Danger,
Expand Down
1 change: 1 addition & 0 deletions src/elements/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type {

/**
* @param {Object} [params] Parameters passed to the constructor.
* @param {string} [params.accessibilityLabel] Sets a longer descriptive text that will be read out by screen readers instead of the button text object.
* @param {string} [params.actionId] Sets a string to be an identifier for the source of an action in interaction payloads.
* @param {string} [params.text] Sets the display text for the button.
* @param {string} [params.url] Sets the URL to redirect the user to when this button is clicked.
Expand Down
1 change: 1 addition & 0 deletions src/internal/constants/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,5 @@ export enum Prop {
IgnoreMarkdown = 'ignoreMarkdown',
SubmitDisabled = 'submitDisabled',
FocusOnLoad = 'focusOnLoad',
AccessibilityLabel = 'accessibilityLabel',
}
1 change: 1 addition & 0 deletions src/internal/dto/slack-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export enum Param {
submitDisabled = 'submit_disabled',
type = 'type',
focusOnLoad = 'focus_on_load',
accessibilityLabel = 'accessibility_label',
}

export class SlackDto implements ObjectLiteral {
Expand Down
16 changes: 16 additions & 0 deletions src/internal/methods/set-methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ import { Prop } from '../constants';
import type { SectionElementBuilder, Settable } from '../types';
import type { OptionBuilder } from '../../bits';

export abstract class AccessibilityLabel extends Builder {
/**
* @description A label for longer descriptive text about a button element. This label will be read out by screen readers instead of the button text object.
*
* **Slack Validation Rules and Tips:**
* * Maximum of 75 characters.
*
* {@link https://api.slack.com/block-kit|Open Official Slack Block Kit Documentation}
* {@link https://www.blockbuilder.dev|Open Block Builder Documentation}
*/

public accessibilityLabel(label: string): this {
return this.set(label, Prop.AccessibilityLabel);
}
}

export abstract class Accessory extends Builder {
/**
* @description Adds an element to the section block of your view or message.
Expand Down
14 changes: 12 additions & 2 deletions src/utilities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SlackBlockDto, SlackDto } from '../internal/dto';
import { Builder } from '../internal/lib';

import type { BlockBuilder, Appendable } from '../internal/types';
import type { AttachmentBuilder } from '../bits';
import type { AttachmentBuilder, OptionBuilder, OptionGroupBuilder } from '../bits';

type Collection<T> = T[];

Expand All @@ -29,9 +29,19 @@ export function AttachmentCollection(...attachments: Appendable<AttachmentBuilde
return getBuiltCollection<AttachmentBuilder, Readonly<SlackDto>>(...attachments);
}

export function OptionCollection(...options: Appendable<OptionBuilder>): Readonly<SlackDto>[] {
return getBuiltCollection<OptionBuilder, Readonly<SlackDto>>(...options);
}

export function OptionGroupCollection(...optionGroups: Appendable<OptionGroupBuilder>): Readonly<SlackDto>[] {
return getBuiltCollection<OptionGroupBuilder, Readonly<SlackDto>>(...optionGroups);
}

const utilities = {
BlockCollection,
AttachmentCollection,
BlockCollection,
OptionCollection,
OptionGroupCollection,
};

// Strange export. I know. For IDE highlighting purposes.
Expand Down
1 change: 1 addition & 0 deletions tests/elements/button.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const config = {
};

const methodsConfig = [
methods.accessibilityLabel,
methods.actionId,
methods.text,
methods.url,
Expand Down
1 change: 1 addition & 0 deletions tests/elements/mocks/button.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const params = {
actionId: 'actionId',
url: 'url',
value: 'value',
accessibilityLabel: 'accessibilityLabel',
};

export const mock = new ButtonBuilder(params).danger();
18 changes: 18 additions & 0 deletions tests/methods/accessibility-label.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { CompositeBuilderClassConfig } from '../test-config-types';
import { Prop } from '../../src/internal/constants';
import { methodArgMocks } from '../mocks/method-arg-mocks';
import { SlackDto } from '../../src/internal';
import * as checks from '../checks';

export const accessibilityLabel = (params: CompositeBuilderClassConfig): void => {
const config = {
...params,
methodArgMock: methodArgMocks.altText,
methodName: Prop.AccessibilityLabel,
propSetterPropName: Prop.AccessibilityLabel,
slackDtoParamName: SlackDto.mapParam(Prop.AccessibilityLabel),
};

checks.settableProperty(config);
checks.literalBuild(config);
};
1 change: 1 addition & 0 deletions tests/methods/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './accessibility-label';
export * from './accessory';
export * from './action-id';
export * from './alt-text';
Expand Down
1 change: 1 addition & 0 deletions tests/mocks/method-arg-mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ export const methodArgMocks = {
ignoreMarkdown: methodArgMocksByType.falseBool,
submitDisabled: methodArgMocksByType.bool,
focusOnLoad: methodArgMocksByType.bool,
accessibilityLabel: methodArgMocksByType.string,
};
Loading

0 comments on commit d732ba1

Please sign in to comment.