diff --git a/src/api/types/canvas-kit/Components.ts b/src/api/types/canvas-kit/Components.ts new file mode 100644 index 00000000..7fe67384 --- /dev/null +++ b/src/api/types/canvas-kit/Components.ts @@ -0,0 +1,358 @@ +/** + * A sheet action opens the link you give within the Messenger as an embedded iframe. + * + * [More on how Sheets work is in our Canvas Kit documentation.](https://developers.intercom.com/docs/canvas-kit#sheets-optional) + */ +export interface SheetActionComponent { + /** The type of action you are attaching to a component. */ + type: "sheet"; + /** The link which hosts your sheet. */ + url: string; +} + +/** + * A submit action triggers a [Submit Request](https://developers.intercom.com/docs/canvas-kit#submit-request) to be sent. This request will include all values which have been entered into all the interactive components on the current canvas. + */ +export interface SubmitActionComponent { + /** The type of action you are attaching to a component. */ + type: "submit"; +} + +/** + * A URL action opens a given link in a new browser tab. + */ +export interface UrlActionComponent { + /** The type of action you are attaching to a component. */ + type: "sheet"; + /** The link which will open in a new tab. */ + url: string; +} + +export type ActionComponent = SheetActionComponent | UrlActionComponent | SubmitActionComponent; + +/** + * A button component is used to take an action by clicking a button. This can either: + * - [Trigger a submit request to be sent](https://developers.intercom.com/docs/references/canvas-kit/actioncomponents/submit-action) Inbox Messenger + * - [Open a link in a new page](https://developers.intercom.com/docs/references/canvas-kit/actioncomponents/url-action) Inbox Messenger + * - [Open a sheet](https://developers.intercom.com/docs/references/canvas-kit/actioncomponents/sheets-action) Messenger + */ +export interface ButtonComponent { + /** The type of component you are rendering. */ + type: "button"; + /** A unique identifier for the component. */ + id: string; + /** The text that will be rendered inside the button. */ + label: string; + /** This can be a Submit Action, URL Action, or Sheets Action. */ + action: ActionComponent; + /** Styles the button. Default is `primary`. */ + style?: "primary" | "secondary" | "link"; + /** Styles the button and prevents the action. Default is `false`. */ + disabled?: boolean; +} + +type CheckboxOption = { + /** The type of component you are rendering. */ + type: "option"; + /** A unique identifier for the option. */ + id: string; + /** The text shown next to the checkbox. */ + text: string; + /** Styles the option and prevents the action. Default is `false`. */ + disabled?: boolean; +}; + +/** + * A checkbox component is used to capture multiple choices from as many options as you want to provide. You can submit the options by: + * + * - Using a {@link ButtonComponent} (which will submit all interactive components in the canvas) + * + * When a submit action takes place, the results are given in a hash with the `id` from the checkbox component used as the key and an array containing the `id` of each chosen option as the value. + */ +export interface CheckboxComponent { + /** The type of component you are rendering. */ + type: "checkbox"; + /** A unique identifier for the component. */ + id: string; + /** The list of options.Minimum of 1. */ + option: Array; + /** The text shown above the options. */ + label: string; + /** The option's that are selected by default. */ + value?: Array; + /** Styles the input. Default is `unsaved`. Prevent action with `saved`. */ + save_state?: "unsaved" | "saved" | "failed"; + /** Styles all options and prevents the action. Default is `false`. Will be overridden if `save_state` is `saved`. */ + disabled?: boolean; +} + +type DropdownOption = { + /** The type of component you are rendering. */ + type: "option"; + /** A unique identifier for the option. */ + id: string; + /** The text shown within this option. */ + text: string; + /** Styles the option and prevents the action. Default is `false`. */ + disabled?: boolean; +}; + +/** + * A dropdown component is used to capture a choice from the options that you provide. + * + * When submitted, the dropdown choices are returned in a hash with the id from the dropdown component used as the key and the id from the chosen option as the value. + */ +export interface DropdownComponent { + /** The type of component you are rendering. */ + type: "dropdown"; + /** A unique identifier for the component. */ + id: string; + /** The list of options.Can provide 2 to 10. */ + options: Array; + /** The text shown above the dropdown. */ + label?: string; + /** The option that is selected by default. */ + value?: DropdownOption["id"]; + /** Styles all options and prevents the action. Default is `false`. Will be overridden if `save_state` is `saved`. */ + save_state?: "unsaved" | "saved" | "failed"; + /** Styles all options and prevents the action. Default is `false`. Will be overridden if `save_state` is saved. */ + disabled?: boolean; +} + +/** + * An input component is used to capture text input from the end user. You can submit the value of the input by: + * + * - Adding an `action` to the input component (which will render an inline button) + * - Using a {@link ButtonComponent} (which will submit all interactive components in the canvas) + */ +export interface InputComponent { + /** The type of component you are rendering. */ + type: "input"; + /** A unique identifier for the component. */ + id: string; + /** The text shown above the input. */ + label?: string; + /** An example value shown inside the component when it’s empty. */ + placeholder?: string; + /** An entered value which is already inside the component. */ + value?: string; + /** This can be a Submit Action, URL Action, or Sheets Action. */ + action?: ActionComponent; + /** Styles the input. Default is `unsaved`. Prevent action with `saved`. */ + save_state?: "unsaved" | "saved" | "failed"; + /** Styles the input and prevents the action. Default is `false`. Will be overridden if `save_state` is `saved`. */ + disabled?: boolean; +} + +type ListItem = { + /** The type of component you are rendering. */ + type: "item"; + /** A unique identifier for the item. */ + id: string; + /** The text shown as the title for the item. */ + title: string; + /** The text shown underneath the item's title. */ + subtitle?: string; + /** The text shown next to the subtitle, separates by a bullet. */ + tertiary_text?: string; + /** Rounds the corners of the image. Default is `false`. */ + rounded_image?: boolean; + /** The defined state of the inputted value to render a specific style. */ + disabled?: boolean; + /** This can be a Submit Action, URL Action, or Sheets Action. */ + action?: ActionComponent; +}; + +type ListItemWithoutImage = ListItem & { + /** An image that will be displayed to the left of the item. */ + image?: string; + /** The exact width of the image in pixels. */ + image_width?: number; + /** The exact height of the image in pixels. */ + image_height?: number; +}; + +type ListItemWithImage = ListItem & { + /** An image that will be displayed to the left of the item. */ + image: string; + /** The exact width of the image in pixels. */ + image_width: number; + /** The exact height of the image in pixels. */ + image_height: number; +}; + +/** + * A list component renders a list of items which you provide in an array. You can make each list item take an action by adding the relevant action object to the item: + * + * - [Trigger a submit request to be sent](https://developers.intercom.com/docs/references/canvas-kit/actioncomponents/submit-action) Inbox Messenger + * - [Open a link in a new page](https://developers.intercom.com/docs/references/canvas-kit/actioncomponents/url-action) Inbox Messenger + * - [Open a sheet](https://developers.intercom.com/docs/references/canvas-kit/actioncomponents/sheets-action) Messenger + */ +export interface ListComponent { + /** The type of component you are rendering. */ + type: "list"; + /** The items that will be rendered in the list. */ + items: Array; + /** Styles all list items and prevents the action. Default is `false`. */ + disabled?: boolean; +} + +type SingleSelectOption = { + /** The type of component you are rendering. */ + type: "option"; + /** A unique identifier for the option. */ + id: string; + /** The text shown within this option. */ + text: string; + /** Styles the option and prevents the action. Default is `false`. */ + disabled?: boolean; +}; + +/** + * A single-select component is used to capture a choice from up to 10 options that you provide. You can submit the value of the select option by: + * + * - Adding an `action` to the single-select component + * - Using a {@link ButtonComponent} (which will submit all interactive components in the canvas) + * When a submit action takes place, the results are given in a hash with the `id` from the single-select component used as the key and the `id` from the chosen option as the value. + */ +export interface SingleSelectComponent { + /** The type of component you are rendering. */ + type: "single-select"; + /** A unique identifier for the component. */ + id: string; + /** The list of options.Can provide 2 to 10. */ + options: Array; + /** The text shown above the options. */ + label?: string; + /** The option that is selected by default. */ + value?: SingleSelectOption["id"]; + /** Styles the input. Default is `unsaved`. Prevent action with `saved`. */ + save_state?: "unsaved" | "saved" | "failed"; + /** Styles all options and prevents the action. Default is `false`. Will be overridden if `save_state` is `saved`. */ + disabled?: boolean; + /** This can be a Submit Action, URL Action, or Sheets Action. */ + action?: ActionComponent; +} + +/** + * A text area component is used to capture a large amount of text as input with a multi-line text box. You can submit the value of the text area by: + * + * - Using a {@link ButtonComponent} (which will submit all interactive components in the canvas) + */ +export interface TextAreaComponent { + /** The type of component you are rendering */ + type: "textarea"; + /** A unique identifier for the component. */ + id: string; + /** The text shown above the text area. */ + label?: string; + /** An example value shown inside the component when it’s empty. */ + placeholder?: string; + /** An entered value which is already inside the component. */ + value?: string; + /** Styles the input as failed. Default is `false`. */ + error?: boolean; + /** Styles the input and prevents the action. Default is `false`. */ + disabled?: boolean; +} + +type DataTableItem = { + /** The type of component you are rendering. */ + type: "field-value"; + /** The text of the key in your key-value pair. */ + field: string; + /** The text of the value in your key-value pair. */ + value: string; +}; + +/* + * A data-table component is used for rendering a table of key-value pairs. For Messenger, text will wrap around on multiple lines. For Inbox and Frame (ie. Configure) views, we will truncate and use tooltips on hover if the text overflows. + */ +export interface DataTableComponent { + /** The type of component you are rendering. */ + type: "data-table"; + /** The items that will be rendered in the data-table. */ + items: Array; +} + +/* + * A divider component is used to separate components with a line. + */ +export interface DividerComponent { + // The type of component you are rendering. + type: "divider"; + /** A unique identifier for the component. */ + id?: string; + /** Disables a component’s margin-bottom of 10px. */ + bottom_margin?: "none"; +} + +/** An image component is used to display an image. + * + * HTTPS Images: + * If your request URLs (or website URLs) are over HTTPS, you will need to ensure that images are loaded over HTTPS likewise. Otherwise, they will not work. + */ +export interface ImageComponent { + /** The type of component you are rendering. */ + type: "image"; + /** A unique identifier for the component. */ + id?: string; + /** The URL where the image is located. */ + url: string; + /** Aligns the image inside the component. Default is `left`. */ + align?: "left" | "center" | "right" | "full_width"; + /** The exact width of the image in pixels. */ + width: number; + /** The exact height of the image in pixels. */ + height: number; + /** Rounds the corners of the image. Default is `false`. */ + rounded?: boolean; + /** Disables a component’s margin-bottom of 10px. */ + bottom_margin?: "none"; + /** This can be a URL Action only. */ + action?: UrlActionComponent; +} + +/** + * A spacer component is used to create empty space between components. + */ +export interface SpacerComponent { + /** The type of component you are rendering. */ + type: "spacer"; + /** A unique identifier for the component. */ + id?: string; + /** The amount of space between components. Default is `s`. */ + size?: "xs" | "s" | "m" | "l" | "xl"; +} + +/** + * The text component is used for rendering blocks of text. Links and bold font can be rendered through Markdown. There are different styles provided which edit the color, weight, and font size. These cannot be edited through Markdown. + */ +export interface TextComponent { + /** The type of component you are rendering. */ + type: "text"; + /** A unique identifier for the component. */ + id?: string; + /** The text that will be rendered. */ + text: string; + /** Aligns the text. Default is `left`. */ + align?: "left" | "center" | "right"; + /** Styles the text. Default is `paragraph`. */ + style?: "header" | "paragraph" | "muted" | "error"; + /** Disables a component’s margin-bottom of 10px. */ + bottom_margin?: "none"; +} + +export type Component = + | ButtonComponent + | CheckboxComponent + | DropdownComponent + | InputComponent + | ListComponent + | SingleSelectComponent + | TextAreaComponent + | DataTableComponent + | DividerComponent + | ImageComponent + | SpacerComponent + | TextComponent; diff --git a/src/api/types/canvas-kit/RequestObjects.ts b/src/api/types/canvas-kit/RequestObjects.ts new file mode 100644 index 00000000..6500b7c9 --- /dev/null +++ b/src/api/types/canvas-kit/RequestObjects.ts @@ -0,0 +1,125 @@ +import { Admin, Contact, Conversation } from "api/resources"; +import { CanvasObject } from "./ResponseObjects"; + +/** + * The context object provides additional details on where the app has been added (or is currently being used), what page the app is being used on, and information on the Messenger settings. This is in order for you give a fully customised experience based on the customers use case. + * + * If the `location` is `conversation` then you will also be given a `conversation_id`. If you need to use details about the conversation, then you have to use the `conversation_id` to [make a call to our Conversations API and retrieve the conversation object](https://developers.intercom.com/intercom-api-reference/reference#get-a-single-conversation). + */ +export interface Context { + /** The id of the conversation where the app is added or being used. */ + conversation_id?: number; + /** Where the app is added or the action took place. Can be either 'conversation', 'home', 'message', or 'operator'. */ + location?: string; + /** The default end-user language of the Messenger. Use to localise Messenger App content. */ + locale?: string; + /** The messengers action colour. Use in Sheets and Icons to make a Messenger App experience feel part of the host Messenger. */ + messenger_action_colour?: string; + /** The messengers background colour. Use in Sheets and Icons to make a Messenger App experience feel part of the host Messenger. */ + messenger_background_colour?: string; + /** The current page URL where the app is being used. */ + referrer?: string; +} + +/** + * The current_canvas object mirrors the same format as the Canvas Object ({@link CanvasObject}). This will be the canvas that was most recently showing before the request was sent. + */ +export interface CurrentCanvas { + current_canvas: CanvasObject; +} + +/** + * The request payload will have all the data needed for you to understand who is using your app, where they are using it, and how you should respond. There are different request payloads for Messenger capabilities and Inbox capabilities. + */ +export interface InitializeRequest { + /** The workspace ID of the teammate. Attribute is `app_id` for V1.2 and below. */ + workspace_id: string; + /** The Intercom hosted region that this app is located in. */ + workspace_region: string; + /** The Intercom teammate {@link Admin} viewing the conversation. */ + admin: Admin; + /** Key-value pairs which were given as [results](https://developers.intercom.com/docs/references/unstable/canvas-kit/responseobjects/results) in response to the [Configure request](https://developers.intercom.com/docs/canvas-kit#configure). */ + card_creation_options: Record; + /** The [context](https://developers.intercom.com/docs/references/unstable/canvas-kit/requestobjects/context) of where the app is added, where the user last visited, and information on the Messenger settings. */ + context: Context; + /** The {@link Conversation} your app is being shown for. */ + conversation: Conversation; + /** The {@link Contact} which is currently being viewed by the teammate in the conversation details panel. We send an individual initialize request for each customer when it's a group conversation. */ + contact: Contact; +} + +/** + * The Submit request is triggered when: + * + * A component with a [submit action](https://developers.intercom.com/docs/references/unstable/canvas-kit/actioncomponents/submit-action) is interacted with Messenger Inbox + */ +export interface SubmitRequest { + /** The workspace ID of the teammate. Attribute is `app_id` for V1.2 and below. */ + workspace_id: string; + /** The Intercom hosted region that this app is located in. */ + workspace_region: string; + /** The Intercom teammate {@link Admin} viewing the conversation. */ + admin: Admin; + /** The id of the component clicked by the teammate to trigger the request. */ + component_id: string; + /** The {@link Context} of where the app is added, where the user last visited, and information on the Messenger settings. */ + context: Context; + /** The {@link Conversation} where your app is being shown. */ + conversation: Conversation; + /** The current_canvas {@link CanvasObject} the teammate can see. */ + current_canvas: CanvasObject; + /** The {@link Contact} which is currently being viewed by the teammate in the conversation details panel. */ + contact: Contact; + /** A list of key/value pairs of data, inputted by the teammate on the current canvas. */ + input_values: Record; + /** The user {@link Contact} who took the action. */ + user: Contact; +} + +/** + * The first request we send will allow you to know the workspace where this is happening, the admin who will be configuring the app, and additional context such as where this will be added once complete. + * + * For subsequent requests whereby an admin has interacted with a component with a submit action, the request payload will contain the same details with `current_canvas`, `input_values` and the `component_id` also present. This allows you to understand what component the request came from, see what the value of any input was, action anything in your codebase, and then respond knowing what canvas was previously shown beforehand. + */ +export type ConfigureRequest = + | { + /** The workspace ID of the teammate. Attribute is app_id for V1.2 and below. */ + workspace_id: string; + /** The Intercom hosted region that this app is located in. */ + admin: Admin; + /** The context {@link Context} of where the app is added, where the user last visited, and information on the Messenger settings. */ + context: Context; + } + | { + /** The workspace ID of the teammate. Attribute is app_id for V1.2 and below. */ + workspace_id: string; + /** The Intercom hosted region that this app is located in. */ + worspace_region: string; + /** The id of the component clicked by the teammate to trigger the request. */ + component_id: string; + admin: Admin; + /** The context {@link Context} of where the app is added, where the user last visited, and information on the Messenger settings. */ + context: Context; + /** The current_canvas {@link CanvasObject} the teammate can see. */ + current_canvas: CanvasObject; + /** A list of key/value pairs of data, inputted by the teammate on the current canvas. */ + input_values: Record; + }; + +/** + * Canvases are static by default and require a new request to come through in order to update them. Live canvases however will make requests every time the card is viewed without any interaction needed, meaning the canvas can be kept up-to-date with no action from the user. + * + * This works for every Messenger request that you can respond with a canvas object {@link CanvasObject} to. Instead of returning the content object {@link ContentObject} within the canvas object, you should provide a `content_url` attribute instead with the value being the URL you want us to send a POST request to when someone views the app. + */ +export interface LiveCanvasRequest { + /** The workspace ID of the teammate. Attribute is `app_id` for V1.2 and below. */ + workspace_id: string; + /** The Intercom hosted region that this app is located in. */ + workspace_region: string; + /** The current_canvas {@link CanvasObject} the teammate can see. */ + canvas: CanvasObject; + /** The context {@link Context} of where the app is added, where the user last visited, and information on the Messenger settings. */ + context: Context; + /** The contact {@link Contact} who viewed the card. */ + contact: Contact; +} diff --git a/src/api/types/canvas-kit/ResponseObjects.ts b/src/api/types/canvas-kit/ResponseObjects.ts new file mode 100644 index 00000000..5a8324c8 --- /dev/null +++ b/src/api/types/canvas-kit/ResponseObjects.ts @@ -0,0 +1,82 @@ +import { Component } from "./Components"; + +/** + * The content object is where you specify the UI of your app. You provide us with a set of `components` in a components array that we then render. + * + * The content object should usually be returned within the [canvas object](https://developers.intercom.com/docs/references/canvas-kit/responseobjects/canvas). If you're responding to a Live Canvas request however, then you should only respond with the content object. + */ +export interface ContentObject { + /** The list of components to be rendered. See the {@link Component} further in this reference. */ + components: Array; +} + +/** + * You have to respond to the majority of requests with a canvas object. This will tell us what UI to show for your app. + * + * A canvas can either be static (meaning we send you the next request only when an action takes place) or live (meaning we send you the next request when someone views the app). + * + * - A static canvas needs a {@link ContentObject} which will contain the components to show. + * - A live canvas needs a `content_url` which we we will make the [Live Canvas requests](https://developers.intercom.com/build-an-integration/docs/canvas-kit#section-live-canvas-optional) to when the app is viewed. This is only possible for apps viewed or used in the Messenger. + */ +export interface CanvasObject { + /** The {@link ContentObject} that will be shown as the UI of the app. Max Size is 64KB. */ + content: ContentObject; + /** The URL which we make [Live Canvas requests](https://developers.intercom.com/build-an-integration/docs/canvas-kit#section-live-canvas-optional) to. You must respond to these with a {@link ContentObject}. Max size is 64KB. */ + content_url?: string; + /** Optional [Stored Data](https://developers.intercom.com/docs/references/canvas-kit/responseobjects/stored-data) that you want to be returned in the next sent request. Max Size is 64KB. */ + stored_data?: Record; +} + +/** + * The event object enables Intercom to know more about the actions that took place in your app. Currently, you can only tell us when an app's flow has been completed. + */ +export interface EventResponse { + /** What action took place. The only value currently accepted is `completed`. */ + type: "completed"; +} + +/** + * The results object should be sent when you want to end configuration of the app and trigger the [Initialize request](https://developers.intercom.com/docs/canvas-kit/#initialize) to be sent. You provide the key-value pairs of data you want access to and we will send these in the Initialize request within a [card_creation_options object](https://developers.intercom.com/docs/references/canvas-kit/requestobjects/card-creation-options/#card-creation-options). + */ +export interface ResultsResponse { + results: Record; +} + +/** + * We expect a {@link CanvasObject} object in response to the request. This is where you'll specify the UI for the first screen of the app using {@link Component}. + */ +export interface InitializeResponse { + canvas: CanvasObject; +} + +/** + * We expect a {@link CanvasObject} in response to the request. This will **replace the previous canvas** that was visible until the app was interacted with. + * + * You can optionally provide an event object {@link EventResponse} with the attribute `type` given as `completed` to **tell us if the app has completed its purpose**. For example, an email collector app would be complete when the end-user submits their email address. + * + * Apps in conversation details can also optionally **insert an app into the conversation reply:** + * + * 1. You respond with a [card_creation_options object](https://developers.intercom.com/canvas-kit-reference/reference/card-creation-options). + * 2. We send a request to the [initialize URL for Messenger capabilities](https://developers.intercom.com/docs/build-an-integration/getting-started/build-an-app-for-your-messenger/request-flows) with the [card_creation_options](https://developers.intercom.com/canvas-kit-reference/reference/card-creation-options) object present. + * 3. You respond with a canvas object {@link CanvasObject} with the components {@link Component} you want to insert into the conversation reply. + */ +export interface SubmitResponse { + canvas: CanvasObject; + card_creation_options?: Record; + event?: EventResponse; +} + +/** + * We either expect: + * + * - A canvas object {@link CanvasObject} which will **replace the previous canvas** that was visible until the teammate interacted with your app. + * - A results object {@link ResultsResponse} which will end the configuration and trigger the initialize request to be sent. There will be a [card_creation_options](https://developers.intercom.com/canvas-kit-reference/reference/card-creation-options) object in the payload showing your key-value pairs from the results object. + */ +export type ConfigureResponse = ResultsResponse | { canvas: CanvasObject }; + +/** + * We expect a content {@link ContentObject} object back in response that contains the components you want to show. + */ +export interface LiveCanvasResponse { + content: ContentObject; +} diff --git a/src/api/types/canvas-kit/index.ts b/src/api/types/canvas-kit/index.ts new file mode 100644 index 00000000..fde0ca32 --- /dev/null +++ b/src/api/types/canvas-kit/index.ts @@ -0,0 +1,3 @@ +export * from "./Components"; +export * from "./RequestObjects"; +export * from "./ResponseObjects"; diff --git a/src/api/types/index.ts b/src/api/types/index.ts index 03b2def2..b4d5318f 100644 --- a/src/api/types/index.ts +++ b/src/api/types/index.ts @@ -155,4 +155,5 @@ export * from "./UpdateVisitorRequest"; export * from "./UrlActionComponent"; export * from "./Visitor"; export * from "./VisitorDeletedObject"; +export * from "./canvas-kit"; export * from "./CustomAttributes";