> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowx.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Angular SDK

> The Angular renderer SDK renders UI configured in the FlowX Designer as a standalone Angular component.

## Angular project requirements

Your app MUST be created using Angular CLI \~20 and MUST use SCSS for styling.

```bash theme={"system"}
npm install -g @angular/cli@20
ng new my-flowx-app
```

<Check>
  To install the npm libraries provided by FlowX.AI you will need to obtain access to the private FlowX.AI Nexus registry. Please consult with your project DevOps.
</Check>

<Info>
  The library requires Angular **\~20**, **npm ≥ 11.0.0** and **node ≥ 24.0.0**.
</Info>

## Installing the library

Use the following command to install the **renderer** library and its required dependencies:

```bash theme={"system"}
npm install \
  @flowx/core-sdk@<version> \
  @flowx/core-theme@<version> \
  @flowx/angular-sdk@<version> \
  @flowx/angular-theme@<version> \
  @flowx/angular-ui-toolkit@<version> \
  @angular/cdk@20 \
  @types/event-source-polyfill
```

<Warning>
  Replace `<version>` with the correct version corresponding to your platform version.

  To find the right version, navigate to: **Release Notes → Choose your platform version → Deployment guidelines → Component versions**.
</Warning>

A few configurations are needed in the project's `angular.json`. To successfully link the PDF viewer, add the following declaration in the assets property:

```json theme={"system"}
{
  "glob": "**/*",
  "input": "node_modules/ng2-pdfjs-viewer/pdfjs",
  "output": "/assets/pdfjs"
}
```

## Initial setup

Once installed, `FlxProcessModule` is imported in the `AppModule` as `FlxProcessModule.withConfig({})`.

### Theming

Component theming is done through the `@flowx/angular-theme` library. The theme id is a required input for the renderer SDK component and is used to fetch the theme configuration. The id can be obtained from the admin panel in the themes section.

<Frame>
  ![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/2024-04-08%2013.45.10.gif)
</Frame>

### Authorization

<Info>
  It's the responsibility of the client app to implement the authorization flow (using the **OpenID Connect** standard). The renderer SDK expects the authToken to be passed to `flx-process-renderer` as an input.
</Info>

```typescript theme={"system"}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { FlxProcessModule } from '@flowx/angular-sdk';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FlxProcessModule.withConfig({
      components: {},
      services: {},
    }),
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
```

The `withConfig()` call is required in the app module where the process will be rendered. It accepts a config object where you can register **custom components**, **services**, and **custom validators**.

**Custom components** are referenced by name in the template config for a user task.

**Custom validators** are referenced by name (`currentOrLastYear`) in the template config panel under the validators section of each generated form field.

```typescript theme={"system"}
FlxProcessModule.withConfig({
  components: {
    YourCustomComponentIdentifier: CustomComponent,
  },
  services: {
    NomenclatorService,
    LocalDataStoreService,
  },
  validators: { currentOrLastYear },
})
```

### Custom interceptors

Starting from FlowX SDK version 4.6, the Angular `HttpClientModule` is no longer used internally for HTTP requests. A new mechanism allows you to create custom interceptors.

#### Request interceptors

```typescript theme={"system"}
import { FLX_REQUEST_INTERCEPTORS_CONFIG } from '@flowx/angular-sdk'
import { HttpRequestInterceptor } from '@flowx/core-sdk'

const customHeaderInterceptor: HttpRequestInterceptor[] = [
  {
    onFulfilled: (response) => {
      response.headers['custom-header'] = 'custom-value'
      return response
    },
  }
]

// Add to providers in the main app module
{
  provide: FLX_REQUEST_INTERCEPTORS_CONFIG,
  useValue: customHeaderInterceptor,
}
```

#### Response interceptors

```typescript theme={"system"}
import { FLX_RESPONSE_INTERCEPTORS_CONFIG } from '@flowx/angular-sdk'
import { HttpResponseInterceptor } from '@flowx/core-sdk'

const customErrorInterceptor: HttpResponseInterceptor[] = [
  {
    onRejected: (response) => {
      if (response.status !== 200) {
        console.error('Something went wrong!', response.message)
      }
      return response
    }
  }
]

// Add to providers in the main app module
{
  provide: FLX_RESPONSE_INTERCEPTORS_CONFIG,
  useValue: customErrorInterceptor,
}
```

#### Interceptors that use dependency injection

If you need to use a service in your interceptor, use provider factories with the `deps` property:

```typescript theme={"system"}
const interceptorFactory = (customService: CustomService): HttpRequestInterceptor[] => [{
  onFulfilled: (response) => {
    // use customService here
    return response
  }
}]

// Add to providers in the main app module
{
  provide: FLX_REQUEST_INTERCEPTORS_CONFIG,
  useFactory: (customService: CustomService) => [
    interceptorFactory(customService),
  ],
  deps: [CustomService],
}
```

### Using custom icons

```typescript theme={"system"}
import { FlxIconModule } from '@flowx/angular-ui-toolkit'

const customIconDictionary = {
  'custom-icon': 'custom icon svg'
}

providers: [
  importProvidersFrom(FlxIconModule),
  provideExtraIconSet(customIconDictionary),
]
```

### Analytics

<Info>
  The SDK provides a mechanism for collecting analytics events through a unified `CustomEvent` system. These events can be used to track screens and action events.
</Info>

To use analytics features, import the necessary SDK module:

```typescript theme={"system"}
import {
   ANALYTICS_EVENTS,
   AnalyticsData,
   pushAnalyticsData,
} from '@flowx/core-sdk';
```

#### Emitting analytics events

Analytics events are dispatched using the `pushAnalyticsData(payload: AnalyticsData)` method. The SDK defines two event types:

```typescript theme={"system"}
enum ANALYTICS_EVENTS {
  SCREEN = 'SCREEN',
  ACTION = 'ACTION',
}
```

Each analytics event should be an object of type `AnalyticsData`:

```typescript theme={"system"}
type AnalyticsData = {
  type: ANALYTICS_EVENTS;
  value: string;
  screen?: string;
  component?: string;
  label?: string;
  customPayload?: object;
}
```

<Info>
  The `value` property represents the identifier set in the process definition.

  For `ACTION` type events there are additional properties:

  * `component` - the type of component triggering the action
  * `label` - the label of the component
  * `screen` - the identifier of the screen containing the component, if set
</Info>

#### Listening for analytics events

```typescript theme={"system"}
ngOnInit(): void {
  document.addEventListener('flowx:analytics', this.analyticsListener);
}

analyticsListener = (event: CustomEvent<AnalyticsData>) => {
  console.log('Received flowx:analytics event:', event.detail);
};

ngOnDestroy(): void {
  document.removeEventListener('flowx:analytics', this.analyticsListener);
}
```

<Check>Ensure that you remove the event listener on component destruction to avoid memory leaks.</Check>

#### Custom payload

This allows you to capture and send custom data alongside standard analytics events.

When analytics custom payload is configured in FlowX Designer, the renderer automatically processes variable substitution and includes the resulting data in analytics events.

<Steps>
  <Step title="Receive custom payload configuration">
    The renderer receives the analytics configuration as a JSON string with variable placeholders:

    ```json theme={"system"}
    "analyticsCustomPayload": "{\n \"name\": ${app.input}\n}"
    ```
  </Step>

  <Step title="Process variable substitution">
    The SDK replaces variables with actual values from the process data store:

    <CodeGroup>
      ```json Template theme={"system"}
      {
          "name": "${app.input}",
          "client": "${app.client}",
          "amount": "${app.amount}"
      }
      ```

      ```json Result theme={"system"}
      {
          "name": "john",
          "client": { "id": "123", "name": "John Doe" },
          "amount": 1500
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Add to analytics event">
    The processed payload is included in the analytics event under the `customPayload` property:

    ```typescript theme={"system"}
    {
        type: 'ACTION', // or 'SCREEN'
        info: {
            value: 'Save personal data',
            screen: 'Personal Data',
            component: 'BUTTON',
            label: 'Save',
            customPayload: {
                name: "john",
                client: { id: "123", name: "John Doe" },
                amount: 1500
            }
        }
    }
    ```
  </Step>
</Steps>

***

## Starting a process

### Prerequisites

* **Process name**: You need to know the name of the process you want to start. This name identifies the process in the system.
* **FlowX Project UUID**: You need the UUID of the FlowX Project that contains the process. Obtain it from the FlowX Dashboard.
* **Locale**: You can specify the locale to apply date, currency, and number formatting to data model values.
* **Language**: You can specify the language used to localize enumerations inside the app.

### Getting the project UUID

The project UUID can be obtained from the FlowX Dashboard. Navigate to the Projects section and select the project you want to start a process in. The UUID can be copied from the project actions popover.

![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/4.5/react/copy_uuid_application.png)

### Getting the process identifier

Open the FlowX Designer, navigate to the process, and copy the process name from the breadcrumbs. Use this value as `processName`.

### Initializing the process renderer

```typescript theme={"system"}
import { Component } from '@angular/core';

@Component({
  selector: 'app-process',
  template: `
    <flx-process-renderer
      [apiUrl]="apiUrl"
      [processApiPath]="processApiPath"
      [authToken]="authToken"
      [themeId]="themeId"
      [staticAssetsPath]="staticAssetsPath"
      [processName]="processName"
      [workspaceId]="workspaceId"
      [projectInfo]="projectInfo"
      [organizationId]="organizationId"
      [locale]="'en-US'"
      [language]="'en'"
    />
  `
})
export class ProcessComponent {
  projectInfo = { projectId: 'your-project-uuid' }
}
```

The entry point of the library is the `<flx-process-renderer>` component. A list of accepted inputs is found below:

```html theme={"system"}
<flx-process-renderer
  [apiUrl]="baseApiUrl"
  [processApiPath]="processApiPath"
  [authToken]="authToken"
  [themeId]="themeId"
  [staticAssetsPath]="staticAssetsPath"
  [processName]="processName"
  [processStartData]="processStartData"
  [workspaceId]="workspaceId"
  [projectInfo]="projectInfo"
  [organizationId]="organizationId"
  [language]="language"
  [locale]="locale"
  [cache]="cache"
  [buildId]="buildId"
/>
```

**Parameters:**

| Name                | Description                                                                                                                                                                                                                            | Type      | Mandatory | Default value | Example                                        |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | --------- | ------------- | ---------------------------------------------- |
| `apiUrl`            | Your base URL                                                                                                                                                                                                                          | `string`  | true      | -             | `https://yourDomain.dev`                       |
| `processApiPath`    | Process subpath                                                                                                                                                                                                                        | `string`  | true      | -             | `onboarding`                                   |
| `authToken`         | Authorization token                                                                                                                                                                                                                    | `string`  | true      | -             | `'eyJhbGciOiJSUzI1NiIsIn....'`                 |
| `themeId`           | Theme id used to style the process. Can be obtained from the themes section in the admin                                                                                                                                               | `string`  | true      | -             | `'123-456-789'`                                |
| `staticAssetsPath`  | Path to static assets                                                                                                                                                                                                                  | `string`  | true      | -             | -                                              |
| `projectInfo`       | Defines which FlowX Project will be run. Shape: `{ projectId: string, appVersionId?: string }`                                                                                                                                         | `object`  | true      | -             | `{ projectId: '111-222-333' }`                 |
| `organizationId`    | FlowX-issued organization UUID. On self-hosted deployments it matches the `ORGANIZATION_ID` configured during the backend upgrade — see [License and organization configuration](/5.9/migrating-from-5.1-lts/organization-deployment). | `string`  | true      | -             | `'10000001-0001-0001-8001-100000000001'`       |
| `processName`       | Identifies a process                                                                                                                                                                                                                   | `string`  | true      | -             | `client_identification`                        |
| `processStartData`  | Data required to start the process                                                                                                                                                                                                     | `json`    | true      | -             | `{ "firstName": "John", "lastName": "Smith" }` |
| `workspaceId`       | Workspace id                                                                                                                                                                                                                           | `string`  | true      | -             | `'8f52744-8403-4e8d....'`                      |
| `language`          | Language used to localize the enumerations inside the app                                                                                                                                                                              | `string`  | false     | `en`          | -                                              |
| `locale`            | Locale used to apply date, currency, and number formatting to data model values                                                                                                                                                        | `string`  | false     | `ro-RO`       | `'en-US'`                                      |
| `isDraft`           | When true, starts the process in draft state                                                                                                                                                                                           | `boolean` | false     | `false`       | -                                              |
| `cache`             | Enable caching of CMS resources (theme, substitution tags, enumerations, media library assets)                                                                                                                                         | `boolean` | false     | `true`        | -                                              |
| `legacyHttpVersion` | Set to `true` only for HTTP versions \< 2, required for SSE to work properly in those environments                                                                                                                                     | `boolean` | false     | `false`       | -                                              |
| `buildId`           | Pinned build identifier                                                                                                                                                                                                                | `string`  | false     | -             | -                                              |
| `customLoader`      | Custom loader components for different loading scenarios                                                                                                                                                                               | `object`  | false     | -             | `{ startProcess: StartLoaderComponent }`       |

#### `projectInfo` shape

```typescript theme={"system"}
projectInfo: {
  projectId: string      // required
  appVersionId?: string  // pin a specific app version
}
```

***

## Custom components

Custom components receive data through the `data$` signal input and are registered via `FlxProcessModule.withConfig({ components: {} })`.

<Warning>
  The object keys passed in `components` **MUST** match the custom component names defined in the FlowX process.
</Warning>

`data$` is a signal holding an `Observable` that emits a `FlxCustomComponentData` object each time the process model updates:

```typescript theme={"system"}
interface FlxCustomComponentData {
  data: any                                                         // value at the configured inputKey path - object or primitive
  actions: ProcessAction[]                                          // metadata for each bound action
  actionsFn: Record<string, (params?: any) => Observable<any>>     // call to trigger a process action; returns an Observable
}
```

```typescript theme={"system"}
@Component({
  selector: 'my-custom-component',
  templateUrl: './custom-component.component.html',
  styleUrls: ['./custom-component.component.scss'],
})
export class CustomComponentComponent {
  data$ = input<Observable<FlxCustomComponentData> | null>(null)
}
```

To add a custom component in the template config tree, you need its unique identifier and the data it should receive from the process model.

![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/building-blocks/ui-designer/ui_designer_custom.png)

The properties that can be configured are:

* **Identifier** - enables the custom component to be displayed within the component hierarchy and determines available actions.
* **Input keys** - specify the path to process data that components will use to receive their information.
* [**Event Handlers**](../docs/building-blocks/ui-designer/event-handlers) - actions defined here will be made available to the custom component.

<Frame>
  ![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/building-blocks/ui-designer/ui_designer_custom_settings.png#center)
</Frame>

### Prerequisites (before creation)

* **Angular knowledge**: Custom components are created and imported using Angular.
* **Development environment**: Node.js and npm set up for Angular development.
* **Component identifier**: A unique identifier used to reference the component within the app.

### Creating a custom component

1. Create a new Angular component.
2. Implement the HTML structure, TypeScript logic, and SCSS styling to define the appearance and behavior.

### Importing the component

Register the component in `FlxProcessModule.withConfig()`:

```typescript theme={"system"}
FlxProcessModule.withConfig({
  components: {
    MyCustomComponentIdentifier: MyCustomComponent,
  },
})
```

### Using the custom component

Once declared, you can configure it in the FlowX Designer.

![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/release34/loader_component.gif)

### Data input and actions

The custom component receives input data from processes and can include actions extracted from a process. These allow you to configure and interact with the component dynamically.

![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/release34/cst_input_data.png)

<Frame>
  ![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/release34/cst_loader_input.png)
</Frame>

<Warning>
  Make sure that the Angular action names match the names of the process actions.
</Warning>

### Custom component validation

Custom components can validate their own status using the `FLX_VALIDATOR_SERVICE` injection token.

The service exposes:

* `validate(isValid: boolean)` - validates the component
* `saveData(data: any)` - saves data
* `validated$` - Observable for monitoring external submission from the process

```typescript theme={"system"}
import { FLX_VALIDATOR_SERVICE } from '@flowx/angular-sdk'

@Component({
  selector: 'flx-custom-validation',
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    Custom validation:
    <input [formControl]="fc" />
    @if (formSubmitted() && fc.invalid) {
      <span>error</span>
    }
  `
})
export class FlxCustomValidationComponent implements OnInit {
  data$ = input<Observable<any> | null>(null)

  validationService = inject(FLX_VALIDATOR_SERVICE)

  fc = new FormControl('', Validators.required)
  formSubmitted = signal(false)

  ngOnInit(): void {
    this.fc.statusChanges.subscribe((status) => {
      this.validationService.validate(status === 'VALID')
    })
    this.fc.valueChanges.subscribe((value) => {
      this.validationService.saveData({ app: { test1: value, test2: `${value}${value}` } })
    })
    this.validationService.validated$.subscribe(() => {
      this.formSubmitted.set(true)
    })
  }
}
```

***

## Custom validators

You may define custom validators in your FlowX processes and pass their implementation via `FlxProcessModule.withConfig({ validators: {} })`.

<Warning>
  The object keys passed in `validators` **MUST** match the custom validator names defined in the FlowX process.
</Warning>

```typescript theme={"system"}
currentOrLastYear: function currentOrLastYear(AC: AbstractControl): { [key: string]: any } {
  if (!AC) {
    return null;
  }

  const yearDate = moment(AC.value, YEAR_FORMAT, true);
  const currentDateYear = moment(new Date()).startOf('year');
  const lastYear = moment(new Date()).subtract(1, 'year').startOf('year');

  if (!yearDate.isSame(currentDateYear) && !yearDate.isSame(lastYear)) {
    return { currentOrLastYear: true };
  }

  return null;
}
```

<Warning>
  The error that the validator returns **MUST** match the validator name.
</Warning>

***

## Process end handling

The SDK provides a mechanism for handling process completion events through the `(processEnd)` output event. This allows you to implement custom logic when a main process reaches an end state, such as redirecting users or triggering cleanup operations.

The `processEnd` event is triggered when the **main process** (not subprocesses) reaches any terminal state:

* `FINISHED` - process completed successfully
* `FAILED` - process encountered an error
* `ABORTED` - process was manually terminated
* Other terminal states

<Info>
  Only the main process triggers this event. Subprocess completions do not trigger it to avoid unnecessary interruptions during complex process flows.
</Info>

### Implementation

```typescript theme={"system"}
import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-process',
  template: `
    <flx-process-renderer
      [apiUrl]="apiUrl"
      [authToken]="authToken"
      [processName]="processName"
      [processStartData]="processStartData"
      [workspaceId]="workspaceId"
      [processApiPath]="processApiPath"
      [themeId]="themeId"
      [staticAssetsPath]="staticAssetsPath"
      [projectInfo]="projectInfo"
      [organizationId]="organizationId"
      (processEnd)="onProcessEnd()"
    />
  `
})
export class ProcessComponent {
  constructor(private router: Router) {}

  onProcessEnd(): void {
    console.log('Process has ended');
    this.router.navigate(['/dashboard']);
  }
}
```

***

## Process start handling

The SDK provides a mechanism for reacting to process start events through the `(processStart)` output event. It emits the new `processInstanceUuid` once the main process instance has been created - useful for tracking, deep linking, or storing the instance reference for later resume.

### Implementation

```typescript theme={"system"}
import { Component } from '@angular/core';

@Component({
  selector: 'app-process',
  template: `
    <flx-process-renderer
      [apiUrl]="apiUrl"
      [authToken]="authToken"
      [processName]="processName"
      [processStartData]="processStartData"
      [workspaceId]="workspaceId"
      [processApiPath]="processApiPath"
      [themeId]="themeId"
      [staticAssetsPath]="staticAssetsPath"
      [projectInfo]="projectInfo"
      [organizationId]="organizationId"
      (processStart)="onProcessStart($event)"
    />
  `
})
export class ProcessComponent {
  onProcessStart(processInstanceUuid: string): void {
    console.log('process started', processInstanceUuid);
  }
}
```

***

## Custom loader

The SDK provides a mechanism for customizing the loader UI displayed during process execution.

### Configuration

Register custom loaders via `FlxProcessModule.withConfig({ customLoader: {} })`:

```typescript theme={"system"}
import { FlxProcessModule } from '@flowx/angular-sdk';
import { Type } from '@angular/core';

@Component({
  selector: 'app-start-loader',
  template: `
    <div class="custom-start-loader">
      <div class="spinner"></div>
      <p>Starting process...</p>
    </div>
  `
})
export class StartProcessLoaderComponent {}

@Component({
  selector: 'app-specific-action-loader',
  template: `
    <div class="custom-specific-action-loader">
      <div class="spinner"></div>
      <p>Executing specific action...</p>
    </div>
  `
})
export class SpecificActionLoaderComponent {}

@NgModule({
  imports: [
    FlxProcessModule.withConfig({
      customLoader: {
        startProcess: StartProcessLoaderComponent,
        // reloadProcess: ReloadProcessLoaderComponent,
        // defaultAction: DefaultActionLoaderComponent,
        // defaultUpload: DefaultUploadLoaderComponent,
        actions: {
          action1: SpecificActionLoaderComponent,
        },
      },
      components: {},
      services: {},
    }),
  ],
})
export class AppModule {}
```

### API specification

The custom loader configuration accepts an object of type `CustomLoader`:

```typescript theme={"system"}
type CustomLoader = {
  actions?: Record<string, Type<any>>
  startProcess?: Type<any>
  reloadProcess?: Type<any>
  defaultAction?: Type<any>
  defaultUpload?: Type<any>
}
```

#### Loader types

* **`startProcess`** - displayed when starting or resuming a process
* **`reloadProcess`** - displayed when reloading a process
* **`defaultAction`** - default loader for actions when `loaderType` is `'action'`. Used when no specific action loader is found in the `actions` record
* **`defaultUpload`** - default loader for file uploads when `loaderType` is `'upload'`
* **`actions`** - record mapping specific action identifiers to custom loaders. When an action is executed, the SDK checks this record before falling back to `defaultAction`

### Fallback behavior

<Info>
  If no custom loader is provided for a specific type, the SDK automatically falls back to the built-in FlowX loader. This ensures your app continues to function even with partial custom loader configuration.
</Info>

<Tip>
  You can use substitution tags and media library assets within your custom loader components to create rich, branded loading experiences that match your app's design system.
</Tip>

***

## Chat component

To use the `FlxChatRendererComponent`, import the module in your project:

```typescript theme={"system"}
import { FlxChatRendererComponent } from '@flowx/angular-sdk';
```

#### Usage

Include the component in your template:

```html theme={"system"}
<flx-chat-renderer
  [apiUrl]="apiUrl"
  [authToken]="accessToken()"
  [staticAssetsPath]="staticAssetsPath"
  [language]="language()"
  [locale]="locale()"
  [themeId]="themeId()"
  [projectId]="projectId()"
  [workspaceId]="workspaceId()"
  [source]="source()"
  [chatConfig]="chatConfig()"
  [cache]="cache()"
/>
```

Parameters:

| Name               | Description                                   | Type      | Mandatory | Example                           |
| ------------------ | --------------------------------------------- | --------- | --------- | --------------------------------- |
| `apiUrl`           | Your base API URL                             | `string`  | ✅         | `https://yourDomain.dev`          |
| `authToken`        | Authorization token                           | `string`  | ✅         | (retrieved from auth provider)    |
| `staticAssetsPath` | Path for static resources                     | `string`  | ✅         | (set via environment)             |
| `language`         | Language used to localize the chat interface  | `string`  | ✅         | `en`                              |
| `locale`           | Locale setting for date and number formatting | `string`  | ✅         | `en-US`                           |
| `themeId`          | Theme identifier for styling                  | `string`  | ✅         | (retrieved dynamically)           |
| `projectId`        | The FlowX project ID                          | `string`  | ✅         | (retrieved dynamically)           |
| `workspaceId`      | The workspace ID                              | `string`  | ✅         | (retrieved dynamically)           |
| `source`           | Source object with type and id                | `object`  | ✅         | `{ type: 'WORKFLOW', id: '...' }` |
| `chatConfig`       | Chat configuration object                     | `object`  | ✅         | `{ welcomeMessage: '...', ... }`  |
| `cache`            | Enable caching for chat responses             | `boolean` | ❌         | `true`                            |
| `buildId`          | Pinned build identifier                       | `string`  | ❌         | (retrieved dynamically)           |

#### chatConfig parameters

The `chatConfig` object accepts the following properties:

| Name               | Description                                  | Type      | Default value            |
| ------------------ | -------------------------------------------- | --------- | ------------------------ |
| `welcomeMessage`   | Message displayed when chat is first opened  | `string`  | `'Welcome to the chat!'` |
| `thinkingMessage`  | Message displayed while waiting for response | `string`  | `'Thinking...'`          |
| `title`            | Chat window title                            | `string`  | `'Chat'`                 |
| `subtitle`         | Chat window subtitle                         | `string`  | `'Chat subtitle'`        |
| `showChatIcon`     | Whether to display the chat icon             | `boolean` | `true`                   |
| `showSeparator`    | Whether to show separator between messages   | `boolean` | `true`                   |
| `newChatLabel`     | Label for the new chat button                | `string`  | `'New chat'`             |
| `inputPlaceholder` | Placeholder text for the message input field | `string`  | `'Enter your message'`   |
| `maxInputRows`     | Maximum number of rows for the input field   | `number`  | `10`                     |
| `historyTitle`     | Title displayed on the chat history panel    | `string`  | -                        |
| `errorMessage`     | Message shown when an error occurs           | `string`  | `'Error message'`        |
| `canRegenerate`    | Show a regenerate button on responses        | `boolean` | `true`                   |
| `regenerateLabel`  | Label for the regenerate button              | `string`  | `'Regenerate'`           |

***

## Task management component

To use the `FlxTasksManagementComponent`, import the module in your project:

```typescript theme={"system"}
import { FlxTasksManagementComponent } from '@flowx/angular-sdk';
```

#### Usage

Include the component in your template:

```html theme={"system"}
<flx-task-management
  [apiUrl]="apiUrl"
  [authToken]="accessToken"
  [appId]="appId()"
  [language]="language()"
  [themeId]="themeId()"
  [staticAssetsPath]="staticUrl"
  [viewDefinitionId]="viewDefinitionId()"
  [locale]="locale()"
  [buildId]="buildId()"
  [workspaceId]="workspaceId()"
/>
```

Parameters:

| Name               | Description                            | Type              | Mandatory | Example                        |
| ------------------ | -------------------------------------- | ----------------- | --------- | ------------------------------ |
| `apiUrl`           | Endpoint where the tasks are available | `string`          | ✅         | `https://yourDomain.dev/tasks` |
| `authToken`        | Authorization token                    | `string`          | ✅         | (retrieved from local storage) |
| `appId`            | The app ID                             | `string`          | ✅         | (retrieved dynamically)        |
| `viewDefinitionId` | The view configuration identifier      | `string`          | ❌         | (retrieved dynamically)        |
| `workspaceId`      | The workspace ID                       | `string`          | ❌         | (retrieved dynamically)        |
| `themeId`          | The theme identifier                   | `string`          | ❌         | (retrieved dynamically)        |
| `language`         | The selected language                  | `string`          | ❌         | `en`                           |
| `locale`           | The localization setting               | `string`          | ❌         | (retrieved dynamically)        |
| `buildId`          | The current build identifier           | `string`          | ❌         | (retrieved dynamically)        |
| `staticAssetsPath` | Path for static resources              | `string`          | ❌         | (set via environment)          |
| `stages`           | Pre-loaded enumeration stages          | `TMEnumeration[]` | ❌         | -                              |
| `cache`            | Enable caching                         | `boolean`         | ❌         | `true`                         |

***

## Task management public API

The Angular SDK provides a comprehensive public API for building custom task management interfaces. This API allows you to fetch tasks, manage comments, handle task actions, and interact with task data programmatically.

### Importing the service

Inject `PublicTasksService` from `@flowx/angular-sdk`:

```typescript theme={"system"}
import { PublicTasksService } from '@flowx/angular-sdk';
import { inject } from '@angular/core';

export class MyComponent {
  private taskService = inject(PublicTasksService);
}
```

### Available types

```typescript theme={"system"}
import {
  PublicTasksService,
  TMView,
  TMViewTask,
  TMViewColumn,
  TMTaskComment,
  TMTaskHistory,
  TMUser,
  TMEnumerations,
  TMEnumeration,
  TMFilterOperators,
  TMFilters,
  TMSort,
  TMPaginatedResponse,
  TMSetupOptions,
  TMExecuteTaskActions,
  TMOperatorsType,
} from '@flowx/angular-sdk';
```

### Initialization

Before using the task management API, initialize the task manager resources. This fetches the view configuration, enumerations, and filter operators.

```typescript theme={"system"}
this.taskService.getTaskManagerResources({
  apiUrl: 'https://yourDomain.dev/tasks',
  authToken: 'your-auth-token',
  appInfo: { appId: 'app-123' },
  viewId: 'view-456',
  workspaceId: 'workspace-789',
  themeId: 'theme-012', // Optional
  language: 'en', // Optional
  locale: 'en-US', // Optional
  buildId: 'build-345', // Optional
  staticAssetsPath: '/static', // Optional
}).subscribe(({ view, enumerations, filterOperators }) => {
  // Use the view, enumerations, and filterOperators
});
```

**Parameters:**

| Name               | Description                            | Type                | Mandatory | Example                        |
| ------------------ | -------------------------------------- | ------------------- | --------- | ------------------------------ |
| `apiUrl`           | Endpoint where the tasks are available | `string`            | ✅         | `https://yourDomain.dev/tasks` |
| `authToken`        | Authorization token                    | `string`            | ✅         | (retrieved from local storage) |
| `appInfo`          | App information containing appId       | `{ appId: string }` | ✅         | `{ appId: "app-123" }`         |
| `viewId`           | The view configuration identifier      | `string`            | ✅         | (retrieved dynamically)        |
| `workspaceId`      | The workspace ID                       | `string`            | ✅         | (retrieved dynamically)        |
| `themeId`          | The theme identifier                   | `string`            | ❌         | (retrieved dynamically)        |
| `language`         | The selected language                  | `string`            | ❌         | `"en"`                         |
| `locale`           | The localization setting               | `string`            | ❌         | `"en-US"`                      |
| `buildId`          | The current build identifier           | `string`            | ❌         | (retrieved dynamically)        |
| `staticAssetsPath` | Path for static resources              | `string`            | ❌         | (set via environment)          |

**Returns:** Observable emitting an object containing:

* `view`: The view configuration object (`TMView`)
* `enumerations`: Available enumeration options for filters (`TMEnumerations`)
* `filterOperators`: Available filter operators for each column (`TMFilterOperators`)

### Fetching tasks

#### `getViewTasks`

Fetches tasks for a specific view with support for sorting, filtering, pagination, and search.

```typescript theme={"system"}
this.taskService.getViewTasks(
  page,      // page number (0-based)
  sort,      // array of sort configurations
  filters,   // array of filter configurations
  keyword,   // search string
  size       // page size
).subscribe((response) => {
  const tasks = response.content;
});
```

**Parameters:**

| Name      | Description                    | Type          | Mandatory | Example                                       |
| --------- | ------------------------------ | ------------- | --------- | --------------------------------------------- |
| `page`    | Page number (0-based)          | `number`      | ✅         | `0`                                           |
| `sort`    | Array of sort configurations   | `TMSort[]`    | ✅         | `[{ keyName: "priority", direction: "ASC" }]` |
| `filters` | Array of filter configurations | `TMFilters[]` | ✅         | See filter examples below                     |
| `keyword` | Search string for task search  | `string`      | ✅         | `"urgent"`                                    |
| `size`    | Number of items per page       | `number`      | ✅         | `10`                                          |

**Returns:** Observable emitting `TMPaginatedResponse<TMViewTask>` with `content`, `totalElements`, `totalPages`.

#### `getViewTask`

Fetches a specific task by ID and token UUID.

```typescript theme={"system"}
this.taskService.getViewTask(taskId, tokenUuid)
  .subscribe((task) => {
    // Use the task
  });
```

**Parameters:**

| Name        | Description                         | Type     | Mandatory | Example            |
| ----------- | ----------------------------------- | -------- | --------- | ------------------ |
| `taskId`    | The unique task ID                  | `string` | ✅         | `"task-123"`       |
| `tokenUuid` | The token UUID associated with task | `string` | ✅         | `"token-uuid-456"` |

**Returns:** Observable emitting a `TMViewTask` object.

### Task details

#### `getTaskComments`

Fetches all comments for a specific task.

```typescript theme={"system"}
this.taskService.getTaskComments(taskId)
  .subscribe((comments) => {
    // TMTaskComment[]
  });
```

**Parameters:**

| Name     | Description        | Type     | Mandatory | Example      |
| -------- | ------------------ | -------- | --------- | ------------ |
| `taskId` | The unique task ID | `string` | ✅         | `"task-123"` |

**Returns:** Observable emitting an array of `TMTaskComment` objects.

#### `getTaskHistory`

Fetches the history/audit trail for a specific task.

```typescript theme={"system"}
this.taskService.getTaskHistory(taskId)
  .subscribe((history) => {
    // TMTaskHistory[]
  });
```

**Parameters:**

| Name     | Description        | Type     | Mandatory | Example      |
| -------- | ------------------ | -------- | --------- | ------------ |
| `taskId` | The unique task ID | `string` | ✅         | `"task-123"` |

**Returns:** Observable emitting an array of `TMTaskHistory` objects.

#### `getAssignees`

Fetches available assignees for a task, with optional search filtering.

```typescript theme={"system"}
this.taskService.getAssignees(task, { keyword: 'john' })
  .subscribe((users) => {
    // TMUser[]
  });
```

**Parameters:**

| Name    | Description     | Type                  | Mandatory | Example               |
| ------- | --------------- | --------------------- | --------- | --------------------- |
| `task`  | The task object | `TMViewTask`          | ✅         | (task object)         |
| `query` | Search options  | `{ keyword: string }` | ✅         | `{ keyword: "john" }` |

**Note:** The keyword must be at least 4 characters long. If shorter, the Observable will emit an error.

**Returns:** Observable emitting an array of `TMUser` objects.

#### `getBulkAssignees`

Fetches available assignees for multiple tasks in bulk.

```typescript theme={"system"}
this.taskService.getBulkAssignees(
  [{ id: 'task-1', tokenUuid: 'token-1' }, { id: 'task-2', tokenUuid: 'token-2' }],
  { keyword: 'john' }
).subscribe((users) => {
  // TMUser[]
});
```

**Parameters:**

| Name    | Description                                     | Type                                  | Mandatory | Example                                |
| ------- | ----------------------------------------------- | ------------------------------------- | --------- | -------------------------------------- |
| `tasks` | Array of task objects with `id` and `tokenUuid` | `{ id: string; tokenUuid: string }[]` | ✅         | `[{ id: "task-1", tokenUuid: "..." }]` |
| `query` | Search options                                  | `{ keyword: string }`                 | ✅         | `{ keyword: "john" }`                  |

**Returns:** Observable emitting an array of `TMUser` objects.

### Task actions

#### `executeTaskAction`

Executes an action on a specific task (e.g., assign, complete, cancel).

```typescript theme={"system"}
this.taskService.executeTaskAction(action, task, payload)
  .subscribe(() => {
    // action completed
  });
```

**Parameters:**

| Name      | Description                        | Type                   | Mandatory | Example              |
| --------- | ---------------------------------- | ---------------------- | --------- | -------------------- |
| `action`  | The action to execute              | `TMExecuteTaskActions` | ✅         | `TaskActions.ASSIGN` |
| `task`    | The task object                    | `TMViewTask`           | ✅         | (task object)        |
| `payload` | Additional payload (e.g. username) | `any`                  | ❌         | `"john.doe"`         |

**Available actions:**

* `TaskActions.ASSIGN` - assign task to a user
* `TaskActions.COMPLETE` - mark task as complete
* `TaskActions.CANCEL` - cancel the task
* `TaskActions.CHANGE_PRIORITY` - change task priority
* `TaskActions.VIEW` - view task details

#### `bulkUpdate`

Applies an action to multiple tasks at once.

```typescript theme={"system"}
this.taskService.bulkUpdate(
  [{ id: 'task-1', tokenUuid: 'token-1' }, { id: 'task-2', tokenUuid: 'token-2' }],
  TaskActions.COMPLETE,
  'username' // Optional, for assign action
).subscribe(() => {
  // bulk action completed
});
```

**Parameters:**

| Name       | Description                                     | Type                                  | Mandatory | Example                                |
| ---------- | ----------------------------------------------- | ------------------------------------- | --------- | -------------------------------------- |
| `tasks`    | Array of task objects with `id` and `tokenUuid` | `{ id: string; tokenUuid: string }[]` | ✅         | `[{ id: "task-1", tokenUuid: "..." }]` |
| `action`   | The action to execute                           | `TMExecuteTaskActions`                | ✅         | `TaskActions.COMPLETE`                 |
| `username` | Username for assign action                      | `string`                              | ❌         | `"john.doe"`                           |

#### `updatePriority`

Updates the priority of a specific task.

```typescript theme={"system"}
this.taskService.updatePriority(taskId, priority)
  .subscribe(() => {
    // priority updated
  });
```

**Parameters:**

| Name       | Description        | Type     | Mandatory | Example      |
| ---------- | ------------------ | -------- | --------- | ------------ |
| `taskId`   | The unique task ID | `string` | ✅         | `"task-123"` |
| `priority` | New priority value | `number` | ✅         | `5`          |

### Comments management

#### `addComment`

Adds a new comment to a task.

```typescript theme={"system"}
this.taskService.addComment(taskId, { message: 'New comment text' })
  .subscribe((comment) => {
    // TMTaskComment
  });
```

**Parameters:**

| Name      | Description         | Type                  | Mandatory | Example                           |
| --------- | ------------------- | --------------------- | --------- | --------------------------------- |
| `taskId`  | The unique task ID  | `string`              | ✅         | `"task-123"`                      |
| `comment` | Comment data object | `{ message: string }` | ✅         | `{ message: "New comment text" }` |

**Returns:** Observable emitting the created `TMTaskComment` object.

#### `deleteComment`

Removes a comment from a task.

```typescript theme={"system"}
this.taskService.deleteComment(taskId, commentId)
  .subscribe(() => {
    // comment deleted
  });
```

**Parameters:**

| Name        | Description           | Type     | Mandatory | Example         |
| ----------- | --------------------- | -------- | --------- | --------------- |
| `taskId`    | The unique task ID    | `string` | ✅         | `"task-123"`    |
| `commentId` | The unique comment ID | `string` | ✅         | `"comment-456"` |

### Service state management

#### `getView`

Gets the current view configuration.

```typescript theme={"system"}
const view = this.taskService.getView(); // TMView | null
```

#### `getEnumerations`

Gets the current enumerations.

```typescript theme={"system"}
const enumerations = this.taskService.getEnumerations(); // TMEnumerations
```

#### `setView`

Sets the view configuration manually.

```typescript theme={"system"}
this.taskService.setView(view, format);
```

**Parameters:**

| Name     | Description                   | Type      | Mandatory | Example       |
| -------- | ----------------------------- | --------- | --------- | ------------- |
| `view`   | The view configuration object | `TMView`  | ✅         | (view object) |
| `format` | Whether to format the view    | `boolean` | ❌         | `false`       |

### Real-time updates (SSE)

#### `initSse`

Initializes an SSE connection for real-time task updates. Call after `getTaskManagerResources()`.

```typescript theme={"system"}
this.taskService.initSse();
```

#### `getSseEvents`

Gets an Observable stream of SSE events.

```typescript theme={"system"}
this.taskService.getSseEvents()
  .subscribe((event) => {
    console.log('SSE event:', event);
  });
```

**Returns:** Observable emitting `MessageEvent<string>` objects.

#### `closeSseConnection`

Closes the SSE connection.

```typescript theme={"system"}
ngOnDestroy(): void {
  this.taskService.closeSseConnection();
}
```

<Info>
  Always close the SSE connection when your component is destroyed to prevent memory leaks.
</Info>

***

## UI Flow renderer

`FlxUiFlowRendererComponent` renders a full UI Flow (multi-view navigation, breadcrumbs, embedded processes, and an optional chat widget) from a single component.

```typescript theme={"system"}
import { FlxUiFlowRendererComponent } from '@flowx/angular-sdk'
```

#### Usage

```html theme={"system"}
<flx-ui-flow
  [apiUrl]="'https://yourDomain.dev'"
  [authToken]="authToken"
  [processApiPath]="'onboarding'"
  [language]="'en'"
  [locale]="'en-US'"
  [themeId]="themeId"
  [staticAssetsPath]="staticAssetsPath"
  [workspaceId]="workspaceId"
  [projectId]="projectId"
  [organizationId]="organizationId"
  [uiFlowName]="'my-ui-flow'"
  [isDraft]="false"
  [cache]="true"
  [buildId]="buildId"
/>
```

#### Parameters

| Name               | Description                                                                                                                                                                                                                          | Type                                                  | Mandatory |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | --------- |
| `apiUrl`           | Base API URL                                                                                                                                                                                                                         | `string`                                              | ✅         |
| `authToken`        | Authorization token                                                                                                                                                                                                                  | `string`                                              | ✅         |
| `staticAssetsPath` | Static resources base path                                                                                                                                                                                                           | `string`                                              | ✅         |
| `workspaceId`      | Workspace identifier                                                                                                                                                                                                                 | `string`                                              | ✅         |
| `projectId`        | FlowX Project ID                                                                                                                                                                                                                     | `string`                                              | ✅         |
| `organizationId`   | FlowX-issued organization UUID. On self-hosted deployments it matches the `ORGANIZATION_ID` configured during the backend upgrade. See [License and organization configuration](/5.9/migrating-from-5.1-lts/organization-deployment) | `string`                                              | ✅         |
| `uiFlowName`       | Name of the UI Flow to start                                                                                                                                                                                                         | `string`                                              | ✅         |
| `themeId`          | Theme identifier                                                                                                                                                                                                                     | `string`                                              | ✅         |
| `language`         | UI language                                                                                                                                                                                                                          | `string`                                              | ✅         |
| `locale`           | Date/number formatting locale                                                                                                                                                                                                        | `string`                                              | ✅         |
| `isDraft`          | Render the draft version of the UI Flow                                                                                                                                                                                              | `boolean`                                             | ✅         |
| `cache`            | Enable caching                                                                                                                                                                                                                       | `boolean`                                             | ✅         |
| `buildId`          | Pinned build identifier                                                                                                                                                                                                              | `string`                                              | ❌         |
| `appVersionId`     | Pin a specific app version                                                                                                                                                                                                           | `string`                                              | ❌         |
| `processApiPath`   | Process subpath used by the embedded process renderer                                                                                                                                                                                | `string`                                              | ❌         |
| `startParams`      | Initial query parameters passed to the UI Flow                                                                                                                                                                                       | `Record<string, unknown>`                             | ❌         |
| `customComponents` | Custom component registry                                                                                                                                                                                                            | `Record<string, Type<any>>`                           | ❌         |
| `customValidators` | Custom validator registry                                                                                                                                                                                                            | `Record<string, NgSyncValidator \| NgAsyncValidator>` | ❌         |

<Info>
  Angular uses separate `projectId` and optional `appVersionId?` inputs rather than a nested `appInfo` object.
</Info>

### Starting a UI Flow

#### Prerequisites

* **UI Flow name**: The name of the UI Flow to start, passed as `uiFlowName`.
* **FlowX Project ID**: The `projectId` value, which identifies which project the UI Flow belongs to. Obtain it the same way as for processes: **FlowX Dashboard → Projects → copy UUID from the project actions popover**.
* **Process API path**: The `processApiPath` subpath used by the embedded process renderer when the UI Flow navigates into a full-screen process.

#### Getting the UI Flow name

Open FlowX Designer and navigate to **UI Flows**. The flow name displayed in the list is the value to pass as `uiFlowName`.

#### Initializing the UI Flow renderer

Minimal working example:

```typescript theme={"system"}
import { Component } from '@angular/core';
import { FlxUiFlowRendererComponent } from '@flowx/angular-sdk';

@Component({
  selector: 'app-ui-flow',
  imports: [FlxUiFlowRendererComponent],
  template: `
    <flx-ui-flow
      [apiUrl]="'https://yourDomain.dev'"
      [authToken]="authToken"
      [processApiPath]="'onboarding'"
      [language]="'en'"
      [locale]="'en-US'"
      [themeId]="themeId"
      [staticAssetsPath]="staticAssetsPath"
      [workspaceId]="workspaceId"
      [projectId]="projectId"
      [organizationId]="organizationId"
      [uiFlowName]="uiFlowName"
      [isDraft]="false"
      [cache]="true"
    />
  `
})
export class UiFlowContainerComponent {
  authToken = '...'
  themeId = '...'
  staticAssetsPath = '...'
  workspaceId = '...'
  projectId = '...'
  organizationId = '...'
  uiFlowName = '...'
}
```

#### Passing initial parameters: `startParams`

Use `startParams` to inject query-string key/value pairs into the UI Flow at startup. The values are available inside the flow as URL query parameters.

```html theme={"system"}
<flx-ui-flow
  [apiUrl]="apiUrl"
  [authToken]="authToken"
  [projectId]="projectId"
  [workspaceId]="workspaceId"
  [organizationId]="organizationId"
  [uiFlowName]="uiFlowName"
  [themeId]="themeId"
  [language]="language"
  [locale]="locale"
  [staticAssetsPath]="staticAssetsPath"
  [isDraft]="false"
  [cache]="true"
  [startParams]="{ referralCode: 'REF123', skipIntro: true }"
/>
```

<Info>
  `startParams` is read once at initialization. To trigger a full re-initialization, change one of the required inputs such as `uiFlowName`.
</Info>

***

## Utility API

These functions and pipes are exported from `@flowx/angular-sdk` and can be used independently of the renderer components.

```typescript theme={"system"}
import {
  getEnumeration,
  getStaticAsset,
  getSubstitutionTag,
  FlxLocalizePipe,
} from '@flowx/angular-sdk'
```

<Warning>
  These methods should only be used inside custom components and within a process context, because internal requests depend on the presence of running project details.
</Warning>

#### `getEnumeration`

Async function to fetch enumeration values.

```typescript theme={"system"}
// get an enumeration by name
const enumeration = await getEnumeration('enumerationName')

// get enumeration with a parent
const enumeration = await getEnumeration('enumerationName', 'parentName')

// get enumeration and cache the result for subsequent calls
const enumeration = await getEnumeration('enumerationName', null, true)
```

| Parameter    | Description                           | Type      | Mandatory |
| ------------ | ------------------------------------- | --------- | --------- |
| `name`       | Enumeration name                      | `string`  | ✅         |
| `parentName` | Parent enumeration name for cascading | `string`  | ❌         |
| `cached`     | Use cached result when available      | `boolean` | ❌         |

#### `getStaticAsset`

Resolves a static asset URL by its key.

```typescript theme={"system"}
const url = getStaticAsset(key)
```

#### `getSubstitutionTag`

Resolves a substitution tag value by its key.

```typescript theme={"system"}
const value = getSubstitutionTag(key)
```

#### `FlxLocalizePipe`

Standalone pipe for managing translations. Import it in the module or component where you want to use it:

```typescript theme={"system"}
import { FlxLocalizePipe } from '@flowx/angular-sdk'

// In your module or component imports:
imports: [
  FlxLocalizePipe
]
```

Use in a template:

```html theme={"system"}
<span>{{ 'hello' | flxLocalize }}</span>
```

Use in a component class:

```typescript theme={"system"}
const localize = new FlxLocalizePipe()
const translatedText = localize.transform('@@substitution_tag')
```

***

## Custom CSS

The renderer SDK allows you to pass custom CSS classes on any component inside the process. These classes are applied to the component's root element.

To add a CSS custom class to a component, define the class in the process designer by navigating to the styles tab of the component, expanding the **Advanced** accordion and writing the CSS class.

![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/4.5/react/add_css_class.gif)

<Warning>
  The classes will be applied last on the element, so they override the classes already defined on the element.
</Warning>

![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/4.5/react/css_class_inspector.png)

***

## Storybook

Below you find a Storybook which demonstrates how components behave under different states, props, and conditions. It allows you to preview and interact with individual UI components in isolation, without the need for a full-fledged app:

<Card title="Storybook" href="https://storybooks.flowxai.dev/" icon="book" />
