npm package: @fluid-commerce/dam-picker
Description: Embeddable DAM file picker for Fluid Commerce applications
Author: Fluid Commerce
Latest version: 0.1.0

# @fluid-app/dam-picker

Embeddable DAM (Digital Asset Management) file picker for Fluid Commerce applications.

## Features

- **Browse DAM Library** - Search and navigate your existing assets
- **Upload Files** - Drag & drop or click to upload from computer
- **Import from URL** - Import files directly from any public URL
- **Asset Type Filtering** - Filter by images, videos, documents, or audio
- **Framework Agnostic** - Works with React, Vue, Angular, or vanilla JavaScript

## Installation

```bash
npm install @fluid-app/dam-picker
# or
pnpm add @fluid-app/dam-picker
# or
yarn add @fluid-app/dam-picker
```

## Quick Start

### Vanilla JavaScript

```javascript
import { DamPicker } from '@fluid-app/dam-picker';

const picker = new DamPicker({
  token: 'your-fluid-api-token',
  onSelect: (asset) => {
    console.log('Selected asset:', asset.url);
    // Use the asset URL in your application
  },
  onCancel: () => {
    console.log('User cancelled');
  },
  onError: (error) => {
    console.error('Error:', error.message);
  },
});

// Open the picker
document.getElementById('choose-image').addEventListener('click', () => {
  picker.open();
});
```

### React (Hook)

```jsx
import { useDamPicker } from '@fluid-app/dam-picker/react';

function ImageSelector() {
  const [imageUrl, setImageUrl] = useState(null);
  const { open } = useDamPicker({ token: 'your-fluid-api-token' });

  const handleChooseImage = () => {
    open({
      onSelect: (asset) => setImageUrl(asset.url),
      onCancel: () => console.log('Cancelled'),
    });
  };

  return (
    <div>
      <button onClick={handleChooseImage}>Choose Image</button>
      {imageUrl && <img src={imageUrl} alt="Selected" />}
    </div>
  );
}
```

### React (Component)

```jsx
import { useState } from 'react';
import { DamPickerModal } from '@fluid-app/dam-picker/react';

function ImageSelector() {
  const [isOpen, setIsOpen] = useState(false);
  const [imageUrl, setImageUrl] = useState(null);

  return (
    <div>
      <button onClick={() => setIsOpen(true)}>Choose Image</button>
      {imageUrl && <img src={imageUrl} alt="Selected" />}

      <DamPickerModal
        isOpen={isOpen}
        token="your-fluid-api-token"
        onSelect={(asset) => {
          setImageUrl(asset.url);
          setIsOpen(false);
        }}
        onCancel={() => setIsOpen(false)}
      />
    </div>
  );
}
```

## API Reference

### DamPicker

The main class for vanilla JavaScript usage.

#### Constructor Options

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `token` | `string` | Yes | Your Fluid API token |
| `onSelect` | `(asset: SelectedAsset) => void` | Yes | Called when user selects an asset |
| `onCancel` | `() => void` | No | Called when user cancels |
| `onError` | `(error: DamPickerError) => void` | No | Called on errors |
| `onReady` | `() => void` | No | Called when picker is ready |
| `baseUrl` | `string` | No | Override the picker app URL (for local development) |
| `zIndex` | `number` | No | Modal z-index (default: 10000) |
| `filters.assetTypes` | `string[]` | No | Filter by asset types: 'images', 'videos', 'documents', 'audio' |

#### Methods

- `open()` - Opens the picker modal
- `close()` - Closes the picker modal
- `destroy()` - Cleans up the picker instance
- `isOpen()` - Returns whether the picker is currently open

### SelectedAsset

The asset object returned on selection (both from library selection and uploads).

```typescript
interface SelectedAsset {
  url: string;           // Public URL to the asset
  assetCode: string;     // Unique asset identifier
  name: string;          // Display name
  mimeType: string;      // MIME type (e.g., "image/png")
  metadata?: {
    width?: number;      // Image/video width
    height?: number;     // Image/video height
    fileSize?: number;   // File size in bytes
  };
  variantId?: string;    // Selected variant ID (if applicable)
}
```

### DamPickerError

Error object passed to onError callback.

```typescript
interface DamPickerError {
  code: 'AUTHENTICATION_ERROR' | 'NETWORK_ERROR' | 'TIMEOUT' | 'UNKNOWN';
  message: string;
}
```

## Filtering Asset Types

You can restrict which asset types users can browse and upload:

```javascript
const picker = new DamPicker({
  token: 'your-token',
  filters: {
    assetTypes: ['images', 'videos'], // Only show images and videos
  },
  onSelect: (asset) => console.log(asset),
});
```

Available asset types:
- `'images'` - Image files (jpg, png, gif, webp, svg, etc.)
- `'videos'` - Video files (mp4, webm, mov, etc.)
- `'documents'` - Documents (pdf, doc, docx, xls, xlsx, etc.)
- `'audio'` - Audio files (mp3, wav, ogg, etc.)

## Upload Behavior

When users upload a file (either from computer or URL):

1. The file is uploaded to Fluid's DAM via ImageKit
2. Once complete, the `onSelect` callback is fired with the new asset
3. The picker automatically closes after successful upload

This means you handle uploads the same way as library selections - just listen for `onSelect`.

## Vue.js Integration

Use the vanilla JavaScript API in Vue:

```vue
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { DamPicker } from '@fluid-app/dam-picker';

const imageUrl = ref(null);
let picker = null;

onMounted(() => {
  picker = new DamPicker({
    token: 'your-fluid-api-token',
    onSelect: (asset) => {
      imageUrl.value = asset.url;
    },
  });
});

onUnmounted(() => {
  picker?.destroy();
});

const openPicker = () => picker?.open();
</script>

<template>
  <div>
    <button @click="openPicker">Choose Image</button>
    <img v-if="imageUrl" :src="imageUrl" alt="Selected" />
  </div>
</template>
```

## Angular Integration

```typescript
import { Component, OnDestroy } from '@angular/core';
import { DamPicker } from '@fluid-app/dam-picker';

@Component({
  selector: 'app-image-selector',
  template: `
    <button (click)="openPicker()">Choose Image</button>
    <img *ngIf="imageUrl" [src]="imageUrl" alt="Selected" />
  `,
})
export class ImageSelectorComponent implements OnDestroy {
  imageUrl: string | null = null;
  private picker: DamPicker;

  constructor() {
    this.picker = new DamPicker({
      token: 'your-fluid-api-token',
      onSelect: (asset) => {
        this.imageUrl = asset.url;
      },
    });
  }

  openPicker() {
    this.picker.open();
  }

  ngOnDestroy() {
    this.picker.destroy();
  }
}
```

## Local Development

For local development, point the SDK to your local fluid-admin instance:

```javascript
const picker = new DamPicker({
  token: 'your-token',
  baseUrl: 'http://localhost:3007/dam-picker',
  onSelect: (asset) => console.log(asset),
});
```

## License

MIT