npm package: @industream/flowmaker-flowbox-ui-components
Description: Reusable Svelte components for FlowMaker FlowBox UI
Latest version: 1.0.1

# @industream/flowmaker-flowbox-ui-components

Reusable Svelte 5 components for FlowMaker FlowBox configuration UIs.

**Components:**
- [DCSourceConnection](#dcsourceconnection) - Source connection selector
- [DCCatalogEntry](#dccatalogentry) - Catalog entry selector

## Installation

```bash
npm install @industream/flowmaker-flowbox-ui-components
```

**Peer dependencies:**
- `svelte@^5.0.0`
- `@industream/datacatalog-client@^1.0.0-preview.1`

---

## Components

### DataCatalog Integration

#### DCSourceConnection

A dropdown component that fetches and displays source connections from the DataCatalog API, allowing users to select a data source for their FlowBox configuration.

### Quick Start

```svelte
    <script>
        let conn = $state('');
    </script>

    Selection: { conn ?? '-'}

    <DCSourceConnection
        dcapiurl="http://localhost:8002"
        sourcetypefilter="DataBridge"
        onsourceselect={(newValue) => conn = (newValue?.id ?? '')}
    />
```

##### Environment Configuration with `jsonEnv`

```svelte
<script>
    import { flowMakerBridge } from '@industream/flowmaker-flowbox-ui';
    import { DCSourceConnection } from '@industream/flowmaker-flowbox-ui-components';

    const props = $props();
    const { values, jsonEnv } = flowMakerBridge(props);

    // Get DataCatalog config from environment variables (reactive derived store)
    const dcApiUrl = jsonEnv('datacatalog');

    // Source type filter (can also come from context/values/environment)
    const sourceTypeFilter = "MQTT";
</script>

<div class="dc-selector-container">
    <div>Data Catalog Source Connection</div>

    <DCSourceConnection
        dcapiurl={$dcApiUrl?.url}
        sourcetypefilter={sourceTypeFilter}
        initialselection={$values?.sourceConnectionId ?? ''}
        onsourceselect={(conn) => $values.sourceConnectionId = conn.id}
    />

    {#if $values.sourceConnectionId}
        <div class="selection-info">
            <h5>Selected Connection</h5>
            <p><strong>ID:</strong> {$values.sourceConnectionId}</p>
        </div>
    {/if}
</div>
```




The `jsonEnv(key)` helper from `flowMakerBridge` parses JSON environment variables from `context.environmentVars["environment/{key}"]`. It returns a reactive derived store that updates when context changes.

```svelte
<script>
    const { jsonEnv } = flowMakerBridge(props);

    // Returns a derived store - use with $ prefix
    const dcConfig = jsonEnv('datacatalog');

    // Reactively access parsed values
    const apiUrl = $derived($dcConfig?.url ?? null);
</script>
```

The environment variable `environment/datacatalog` should contain a JSON string:

```json
{
    "url": "https://datacatalog.example.com/api",
}
```

##### Filtering by Source Type

```svelte
<!-- Single type -->
<DCSourceConnection
    dcapiurl={dcApiUrl}
    sourcetypefilter="DataBridge"
    onsourceselect={handleSelect}
/>

<!-- Multiple types -->
<DCSourceConnection
    dcapiurl={dcApiUrl}
    sourcetypefilter={["Relational", "DataBridge", "Mqtt"]}
    onsourceselect={handleSelect}
/>
```

##### Programmatic Selection

```typescript
// Select by ID
dcSourceConnection.select('xxxx-guid-1234-4567');

// Select by connection object
dcSourceConnection.select(connectionObject);

// Get current selection
const selected = dcSourceConnection.getSelection();

// Get all loaded connections
const all = dcSourceConnection.getConnections();
```

---

## API Reference

### DCSourceConnection

##### Import

```typescript
import { DCSourceConnection, type SourceConnection } from '@industream/flowmaker-flowbox-ui-components';
```

##### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `dcapiurl` | `string` | `''` | Base URL of the DataCatalog API |
| `sourcetypefilter` | `string \| string[] \| null` | `null` | Filter connections by source type(s) |
| `initialselection` | `string \| null` | `null` | ID to auto-select when items load |
| `onsourceselect` | `(connection: SourceConnection) => void` | `null` | Callback when a connection is selected |
| `onitemsloaded` | `(connections: SourceConnection[]) => void` | `null` | Callback when connections are loaded |

The `initialselection` prop automatically restores the selection when items are loaded - no need for `onitemsloaded` handler.

##### Exported Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `select` | `(idOrConnection: string \| SourceConnection) => void` | Programmatically select a connection |
| `getSelection` | `() => SourceConnection \| null` | Get the currently selected connection |
| `getConnections` | `() => SourceConnection[]` | Get all loaded connections |

##### Types

```typescript
interface SourceConnection {
    id: string;
    name: string;
    sourceType?: { name: string };
    [key: string]: any;
}
```

---

### DCCatalogEntry

A dropdown component that fetches and displays catalog entries from the DataCatalog API. Catalog entries represent data sources with their connection parameters and entry-specific parameters.

#### Quick Start

```svelte
<script>
    import { DCCatalogEntry } from '@industream/flowmaker-flowbox-ui-components';

    let selectedEntry = $state(null);
</script>

<DCCatalogEntry
    dcapiurl="http://localhost:8002"
    onentryselect={(entry) => selectedEntry = entry}
/>

{#if selectedEntry}
    <p>Selected: {selectedEntry.name} ({selectedEntry.dataType})</p>
{/if}
```

#### Environment Configuration with `jsonEnv`

```svelte
<script>
    import { flowMakerBridge } from '@industream/flowmaker-flowbox-ui';
    import { DCCatalogEntry } from '@industream/flowmaker-flowbox-ui-components';

    const props = $props();
    const { values, jsonEnv } = flowMakerBridge(props);

    // Get DataCatalog config from environment variables (reactive derived store)
    const dcConfig = jsonEnv('datacatalog');

    // Optional: data type filter
    const dataTypeFilter = "string";
</script>

<div class="dc-selector-container">
    <div>Data Catalog Entry</div>

    <DCCatalogEntry
        dcapiurl={$dcConfig?.url}
        datatypefilter={dataTypeFilter}
        initialselection={$values?.catalogEntryId ?? ''}
        onentryselect={(entry) => $values.catalogEntryId = entry.id}
    />

    {#if $values.catalogEntryId}
        <div class="selection-info">
            <h5>Selected Entry</h5>
            <p><strong>ID:</strong> {$values.catalogEntryId}</p>
        </div>
    {/if}
</div>
```

#### Filtering

```svelte
<!-- Filter by source type -->
<DCCatalogEntry
    dcapiurl={dcApiUrl}
    sourcetypefilter="InfluxDB2"
    onentryselect={handleSelect}
/>

<!-- Filter by data type -->
<DCCatalogEntry
    dcapiurl={dcApiUrl}
    datatypefilter="string"
    onentryselect={handleSelect}
/>

<!-- Filter by name(s) - sent to API -->
<DCCatalogEntry
    dcapiurl={dcApiUrl}
    namefilter={["Entry1", "Entry2"]}
    onentryselect={handleSelect}
/>

<!-- Multiple filters combined -->
<DCCatalogEntry
    dcapiurl={dcApiUrl}
    sourcetypefilter={["InfluxDB2", "MQTT"]}
    datatypefilter={["string", "number"]}
    onentryselect={handleSelect}
/>
```

#### Programmatic Methods

```typescript
// Select by ID
dcCatalogEntry.select('xxxx-guid-1234-4567');

// Select by entry object
dcCatalogEntry.select(entryObject);

// Get current selection
const selected = dcCatalogEntry.getSelection();

// Get all loaded entries (filtered)
const filtered = dcCatalogEntry.getEntries();

// Get all loaded entries (unfiltered)
const all = dcCatalogEntry.getAllEntries();
```

---

## API Reference

### DCCatalogEntry

##### Import

```typescript
import { DCCatalogEntry, type CatalogEntry, type DataType, type SourceType } from '@industream/flowmaker-flowbox-ui-components';
```

##### Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | `string` | `undefined` | HTML id attribute for the dropdown |
| `dcapiurl` | `string` | `''` | Base URL of the DataCatalog API |
| `sourcetypefilter` | `SourceType \| SourceType[] \| null` | `null` | Filter entries by source type(s) (client-side) |
| `datatypefilter` | `DataType \| DataType[] \| null` | `null` | Filter entries by data type(s) (client-side) |
| `namefilter` | `string \| string[] \| null` | `null` | Filter entries by name(s) (API query) |
| `initialselection` | `string \| null` | `null` | Entry ID to auto-select when items load |
| `onentryselect` | `(entry: CatalogEntry) => void` | `null` | Callback when an entry is selected |
| `onitemsloaded` | `(entries: CatalogEntry[]) => void` | `null` | Callback when entries are loaded |

##### Exported Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `select` | `(idOrEntry: string \| CatalogEntry) => void` | Programmatically select an entry |
| `getSelection` | `() => CatalogEntry \| null` | Get the currently selected entry |
| `getEntries` | `() => CatalogEntry[]` | Get all loaded entries (filtered) |
| `getAllEntries` | `() => CatalogEntry[]` | Get all loaded entries (unfiltered) |

##### CatalogEntry Type

The `CatalogEntry` object returned on selection contains the full entry data including:

- **sourceConnection**: The parent source connection with all connection parameters (hostname, credentials, etc.)
- **sourceParams**: Entry-specific parameters that override or extend the connection settings
- **labels**: User-defined labels for categorization
- **metadata**: Additional metadata key-value pairs

```typescript
interface CatalogEntry {
    id: string;
    name: string;
    dataType: string;                    // e.g., "string", "number", "boolean"
    sourceConnection: {
        id: string;
        name: string;
        sourceType: {
            id: string;
            name: string;               // e.g., "InfluxDB2", "MQTT", "DataBridge"
            isProtected: boolean;
        };
        // Connection-level parameters (varies by source type)
        hostname?: string;
        token?: string;
        bucket?: string;
        organization?: string;
        // ... other connection params
    };
    sourceParams: {                      // Entry-specific parameters
        bucket?: string;                 // e.g., override bucket for this entry
        // ... other entry-specific params
    };
    labels: Array<{
        id: string;
        name: string;
    }>;
    metadata: Record<string, any>;
}
```

**Example CatalogEntry:**

```json
{
    "id": "57c14290-4dc7-408f-84fa-8fbe568bd506",
    "name": "Influx with myBucket",
    "dataType": "string",
    "sourceConnection": {
        "id": "6e75699f-1e97-493d-9718-930a809b93a4",
        "name": "Influx Localhost",
        "sourceType": {
            "id": "InfluxDB2",
            "name": "InfluxDB2",
            "isProtected": true
        },
        "hostname": "http://influxdb:8086",
        "token": "DQxcrQBORed9pSzH11Ngvrn...",
        "bucket": "test",
        "organization": "industream",
        "ingressHostname": "http://localhost:8086"
    },
    "sourceParams": {
        "bucket": "myBucket"
    },
    "labels": [
        { "id": "1f405a8c-...", "name": "zerzer" },
        { "id": "76432802-...", "name": "Toto" }
    ],
    "metadata": {}
}
```

In this example, the `sourceConnection` defines the InfluxDB connection to `test` bucket, but `sourceParams.bucket` overrides it to `myBucket` for this specific catalog entry.