npm package: @fastn-ai/react
Description: React library for fastn.ai
Author: fastn.ai
Latest version: 1.6.4

# @fastn-ai/react

A React library to integrate the fastn connector marketplace in your application.

## Installation

Install the package via npm:

```bash
npm install @fastn-ai/react
```

## Usage

### Setup Application Context

To begin, wrap your application in the FastnProvider and provide the required configuration:

```jsx
import { useState } from "react";
import { FastnProvider } from "@fastn-ai/react";

function App() {
  const [config] = useState({
    projectId: "your-workspace-id",
    tenantId: "your-tenant-id",
    authToken: "your-auth-token",
    env: "your-environment", // e.g., "LIVE", "DRAFT"
    configurationId: "your-configuration-id",
  });

  return (
    <FastnProvider config={config}>
      {/* Your components go here */}
    </FastnProvider>
  );
}
```

#### Application Configuration Properties

| Prop Name       | Type   | Required | Description                                                           |
| --------------- | ------ | -------- | --------------------------------------------------------------------- |
| projectId       | string | Yes      | The ID of the workspace whose widgets/connectors you want to embed.   |
| authToken       | string | Yes      | The token used to authenticate your application users.                |
| tenantId        | string | No       | The ID of the tenant (e.g., user, organization, etc.) (optional).     |
| env             | string | No       | The environment of the widget (e.g. "LIVE", "DRAFT" ... ) (optional). |
| configurationId | string | No       | The ID corresponding to stored connector configurations.              |

### Embedding Connector Widgets

Use the useConnectors hook to fetch and display connector information in your application.

```jsx
import { useConnectors } from "@fastn-ai/react";

const ConnectorsList = () => {
  const { connectors, loading, error } = useConnectors();

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      {connectors?.length ? (
        connectors.map((connector) => (
          <div key={connector.id}>{/** Your Connector Card Component */}</div>
        ))
      ) : (
        <p>No connectors found</p>
      )}
    </div>
  );
};
```

#### Hook Return Properties

| Prop Name  | Type    | Description                                                     |
| ---------- | ------- | --------------------------------------------------------------- |
| connectors | array   | An array of connector objects.                                  |
| loading    | boolean | A boolean value to indicate if the connectors are being loaded. |
| error      | string  | An error message if the connectors fail to load.                |

##### Connector Object Structure

| Prop Name   | Type   | Description                                           |
| ----------- | ------ | ----------------------------------------------------- |
| id          | string | The ID of the connector.                              |
| name        | string | The name of the connector. (e.g. Slack)               |
| status      | string | The status of the connector ("ACTIVE" or "INACTIVE"). |
| imageUri    | string | The URI of the connector image.                       |
| description | string | The description of the connector.                     |
| actions     | array  | An array of action objects.                           |

##### Action Object Structure

| Prop Name  | Type     | Description                                                 |
| ---------- | -------- | ----------------------------------------------------------- |
| name       | string   | The name of the action.                                     |
| onClick    | function | Function to handle click events, returning a Promise.       |
| actionType | string   | Action type ("ACTIVATION" or "DEACTIVATION").               |
| form       | object   | Form metadata, required for actions needing user input.     |
| onSubmit   | function | Submit handler function, required if the action has a form. |

#### Form Object

| Prop Name         | Type   | Description                                      |
| ----------------- | ------ | ------------------------------------------------ |
| fields            | array  | Array of field objects defining the form inputs. |
| description       | string | Description or instructions for the form.        |
| submitButtonLabel | string | Label for the form's submit button.              |

##### Field Object Structure

| Prop Name    | Type    | Description                                  |
| ------------ | ------- | -------------------------------------------- |
| name         | string  | Name of the field.                           |
| label        | string  | Label for the field.                         |
| initialValue | string  | Default value of the field.                  |
| required     | boolean | Indicates if the field is required.          |
| type         | string  | Input type, e.g., "text", "number", "email". |
| hidden       | boolean | If true, the field will be hidden.           |
| disabled     | boolean | If true, the field will be disabled.         |

### Embedding Connector Configuration

Use the useConfigurations hook to fetch and display connector configurations in your application.

```jsx
import { useConfigurations } from "@fastn-ai/react";

const ConfigurationsList = () => {
  const { configurations, loading, error } = useConfigurations();

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      {configurations?.length ? (
        configurations.map((configuration) => (
          <div key={configuration.id}>
            {/** Your Configuration Card Component */}
          </div>
        ))
      ) : (
        <p>No configurations found</p>
      )}
    </div>
  );
};
```

#### Hook Return Properties

| Prop Name      | Type    | Description                                                         |
| -------------- | ------- | ------------------------------------------------------------------- |
| configurations | array   | An array of configuration objects.                                  |
| loading        | boolean | A boolean value to indicate if the configurations are being loaded. |
| error          | string  | An error message if the configurations failed to load.              |

##### Configuration Object Structure

| Prop Name   | Type   | Description                                                        |
| ----------- | ------ | ------------------------------------------------------------------ |
| name        | string | The name of the connector.                                         |
| status      | string | The status of the configuration ("ENABLED", "DISABLED" or "IDLE"). |
| description | string | The description of the connector.                                  |
| imageUri    | string | The URI of the connector image.                                    |
| actions     | array  | An array of action objects.                                        |
| metadata    | object | The configuration metadata.                                        |

##### Action Object Structure

| Prop Name  | Type     | Description                                                 |
| ---------- | -------- | ----------------------------------------------------------- |
| name       | string   | The name of the action.                                     |
| onClick    | function | Function to handle click events, returning a Promise.       |
| actionType | string   | Action type. ("ENABLE" or "DISABLE").                       |
| form       | object   | Form metadata, required for actions needing user input.     |
| onSubmit   | function | Submit handler function, required if the action has a form. |

#### Sample Configurations

```json
[
  {
    "id": "66da971c-5c57-4de8-9b85-371d24c5fb45",
    "connectorId": "66da971c-5c57-4de8-9b85-371d24c5fb45",
    "configurationId": "12345678910",
    "name": "Microsoft Teams",
    "flowId": "configureTeams",
    "description": "Send notifications to Microsoft Teams",
    "imageUri": "assets/PNG/Microsoft_Office_Teams_Logo_512px.png",
    "status": "ENABLED",
    "actions": [
      {
        "name": "Disable",
        "actionType": "DISABLE"
      }
    ],
    "metadata": {
      "id": "12345678910",
      "connectorId": "66da971c-5c57-4de8-9b85-371d24c5fb45",
      "chats": [
        {
          "value": "19:meeting_MGVmNTdjMDgtYjNlYS00MjRiLTk5YTQtMzNkZjkwZWU4ZTY3@thread.v2",
          "label": "Microsoft Graph User flow"
        },
        {
          "value": "19:meeting_MWMwMTBlN2QtM2ZlMy00NGNhLWJhZDYtYTE1MTM1N2RmZmE4@thread.v2",
          "label": "Microsoft Teams Integration Sync & Solution Architecture Review"
        }
      ]
    }
  }
]
```

### Embedding Configuration Form

Use the ConfigurationForm component to display a form for configuring a connector.
The wrapper component should be displayed only after the onClick handler for the enable action has been successfully completed, so the user can activate the specific connector.
For updates, the component should simply be displayed when the Update button is clicked. The update functionality is not part of the actions array.

```jsx
import { ConfigurationForm } from "@fastn-ai/react";

const ConfigurationFormWrapper = ({
  configuration,
}: {
  configuration: any,
}) => {
  return (
    <ConfigurationForm
      configuration={configuration}
      onComplete={onClose}
      onCancel={onClose}
      primaryButtonAs={(props) => (
        <button {...props}>{props?.isLoading ? "Loading..." : "Save"}</button>
      )}
      secondaryButtonAs={(props) => <button {...props}>Cancel</button>}
      placeButtonFirst="secondary"
      placeButtons="left"
      style={{ ...customStyles } as CustomStyle}
    />
  );
};

```

#### Custom Styling Object structure

The ConfigurationForm component accepts a style prop to apply custom styles to the form.

| Properties  | Type           | Description                               |
| ----------- | -------------- | ----------------------------------------- |
| form        | FormStyle      | Custom styles for the form.               |
| title       | CSS.Properties | Custom styles for the form title.         |
| description | CSS.Properties | Custom styles for the form description.   |
| avatar      | CSS.Properties | Custom styles for the form avatar.        |
| error       | CSS.Properties | Custom styles for the form error message. |

#### FormStyle Object structure

| Properties | Type           | Description                        |
| ---------- | -------------- | ---------------------------------- |
| field      | FormFieldStyle | Custom styles for the form fields. |
| customMessage | CSS.Properties | Custom styles for the async select custom message (e.g., 'Can't find what you need?'). |

#### FormFieldStyle Object structure

| Properties              | Type             | Description                                        |
| ----------------------- | ---------------- | -------------------------------------------------- |
| input                   | CSS.Properties   | Custom styles for the form input field.            |
| label                   | CSS.Properties   | Custom styles for the form field label.            |
| error                   | CSS.Properties   | Custom styles for the form field error message.    |
| dropdown                | CSS.Properties   | Custom styles for the form dropdown fields.        |
| option                  | CSS.Properties   | Custom styles for the form option fields.          |
| selectedOption          | CSS.Properties   | Custom styles for the form selected option fields. |
| selectedOptionCloseIcon | CSS.Properties   | Custom styles for the selected option close icon.  |
| actionBar               | ActionBarStyle   | Custom styles for the async select action bar.     |
| reactSelectStyles       | StylesConfig     | Custom styles for the react-select component.      |
| reactSelectTheme        | ThemeConfig      | Custom theme for the react-select component.       |
| reactSelectClassNames   | ClassNamesConfig | Custom class names for the react-select component. |
| customMessage           | CSS.Properties   | Custom styles for the async select custom message (e.g., 'Can't find what you need?'). |

#### ActionBarStyle Object structure

The `actionBar` property allows you to customize the styling of the action bar that appears at the bottom of async select fields (used for pagination, refresh, and clear actions).

| Properties     | Type           | Description                                    |
| -------------- | -------------- | ---------------------------------------------- |
| container      | CSS.Properties | Custom styles for the action bar container.    |
| counter        | CSS.Properties | Custom styles for the options counter display. |
| button         | CSS.Properties | Custom styles for the default action buttons.  |
| buttonHover    | CSS.Properties | Custom styles for button hover states.         |
| buttonDisabled | CSS.Properties | Custom styles for disabled button states.      |

##### Action Bar Styling Examples

The action bar now comes with **beautiful default styles** that look great out of the box! The default styles provide a clean, professional appearance with proper spacing, semantic colors, and smooth transitions. You can easily override specific elements while keeping the rest of the defaults.

**Default Styles (Recommended):**

```jsx
// The action bar now looks great by default - no customization needed!
const defaultStyles = {
  form: {
    field: {
      actionBar: undefined, // Uses the improved default styles
    },
  },
};
```

**Basic Custom Styling:**

```jsx
const customStyles = {
  form: {
    field: {
      actionBar: {
        container: {
          backgroundColor: "#f8fafc",
          borderTop: "2px solid #e2e8f0",
          padding: "16px",
        },
        counter: {
          backgroundColor: "#3b82f6",
          color: "#ffffff",
          fontWeight: "600",
          borderRadius: "20px",
          padding: "8px 16px",
        },
        button: {
          backgroundColor: "#ffffff",
          border: "1px solid #d1d5db",
          borderRadius: "6px",
          fontWeight: "500",
        },
        buttonHover: {
          backgroundColor: "#f3f4f6",
          borderColor: "#9ca3af",
        },
      },
    },
  },
};
```

**Simple Override Example:**

```jsx
// Just override what you need - everything else uses the improved defaults
const customStyles = {
  form: {
    field: {
      actionBar: {
        container: {
          backgroundColor: "#f0f9ff", // Light blue background
          borderTop: "3px solid #0ea5e9",
        },
      },
    },
  },
};
```

**Using the Styling Utilities:**

```jsx
import { getActionBarStyles } from "@fastn-ai/react";

// Merge custom styles with the improved defaults
const customActionBar = getActionBarStyles({
  container: {
    backgroundColor: "#fef3c7", // Yellow background
  },
});

// Use the merged styles
const customStyles = {
  form: {
    field: {
      actionBar: customActionBar,
    },
  },
};
```

**Complete Example with Enhanced Styling:**

```jsx
import { ConfigurationForm } from "@fastn-ai/react";

const MyConfigurationForm = () => {
  const customStyles = {
    form: {
      field: {
        actionBar: {
          container: {
            display: "flex",
            gap: "12px",
            justifyContent: "space-between",
            alignItems: "center",
            padding: "8px 16px",
            borderTop: "1px solid rgba(0, 0, 0, 0.1)",
            minHeight: "52px",
          },
          counter: {
            fontSize: "0.875rem",
            color: "rgba(0, 0, 0, 0.6)",
            fontWeight: "500",
            padding: "6px 12px",
          },
          button: {
            padding: "8px 14px",
            fontSize: "0.875rem",
            border: "1px solid rgba(0, 0, 0, 0.15)",
            borderRadius: "6px",
            color: "rgba(0, 0, 0, 0.8)",
            cursor: "pointer",
            transition: "all 0.2s ease",
            fontWeight: "500",
            minHeight: "36px",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
          },
          buttonHover: {
            transform: "translateY(-1px)",
          },
          buttonDisabled: {
            opacity: 0.5,
            cursor: "not-allowed",
          },
        },
        // Other field styles...
        input: {
          borderColor: "#0ea5e9",
          borderRadius: "8px",
        },
        label: {
          color: "#0f172a",
          fontWeight: "600",
        },
      },
    },
    title: {
      color: "#0f172a",
      fontSize: "24px",
      fontWeight: "700",
    },
    description: {
      color: "#64748b",
      fontSize: "16px",
    },
  };

  return (
    <ConfigurationForm
      configuration={configuration}
      onComplete={onClose}
      onCancel={onClose}
      style={customStyles}
    />
  );
};
```

### Need Help?

If you have any questions or need help, please contact us at [support@fastn.ai](mailto:support@fastn.ai).