# Pitch Deck Editor Library

A reusable Canva-like pitch deck editor component that can be integrated into any React project.

## Features

- Drag-and-drop slide editor
- Rich text elements
- Shapes and icons
- Image support
- Tables and charts
- Drawing tools
- AI panel integration
- Template library
- Presentation mode
- Undo/redo functionality
- Auto-save with custom API endpoints
- Dark/light theme support
- Fully customizable API layer

## Documentation

| Document | Audience |
|----------|----------|
| [docs/PITCH_DECK_EDITOR_SPEC.md](docs/PITCH_DECK_EDITOR_SPEC.md) | Full JSON schema, element types, canvas rules, React/API integration |
| [docs/AI_GENERATION_PROMPT.md](docs/AI_GENERATION_PROMPT.md) | Copy-paste **system prompt**: editor **tools + JSON rules** only (no fixed slide templates) |

Use these when wiring **AI-generated decks** in production: the system prompt explains capabilities; the **user message** carries topic, outline, and brand. Pass parsed JSON as `initialDeck` to `PitchDeckEditor`.

---

## Installation

Install the package:

```bash
npm install @tech-alfia/pitch-deck-editor
```

If you use `pnpm`:

```bash
pnpm add @tech-alfia/pitch-deck-editor
```

---

# Required Setup

This library depends on Tailwind CSS v3.

## 1. Install Tailwind CSS

```bash
pnpm install -D tailwindcss@3
```

Or with npm:

```bash
npm install -D tailwindcss@3
```

---

## 2. Initialize Tailwind

```bash
npx tailwindcss init
```

---

## 3. Generate Tailwind CSS Output

```bash
npx tailwindcss -i ./src/index.css -o ./src/app.css --watch
```

---

## 4. Configure `tailwind.config.js`

```js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,jsx,ts,tsx}",
    "./node_modules/@alfia/pitch-deck-editor/dist/**/*.{js,jsx,ts,tsx}"
  ],
  darkMode: "class",
  theme: {
    extend: {
      colors: {
        "alfia-black": "#000000",
        "alfia-white": "#ffffff",

        "alfia-bg-root": "#000000",
        "alfia-bg-surface": "#0b0b0b",
        "alfia-bg-elevated": "#111111",
        "alfia-bg-hover": "#1a1a1a",
        "alfia-bg-active": "#222222",

        "alfia-bg-root-light": "#ffffff",
        "alfia-bg-surface-light": "#F9F9F9",
        "alfia-bg-elevated-light": "#fafafa",
        "alfia-bg-hover-light": "#EAEAEA",
        "alfia-bg-active-light": "#EAEAEA",

        "alfia-border-subtle": "#1f1f1f",
        "alfia-border-default": "#2a2a2a",
        "alfia-border-strong": "#3a3a3a",

        "alfia-border-subtle-light": "#e0e0e0",
        "alfia-border-default-light": "#d4d4d4",
        "alfia-border-strong-light": "#b3b3b3",

        "alfia-text-primary": "#ffffff",
        "alfia-text-secondary": "#b3b3b3",
        "alfia-text-muted": "#7a7a7a",
        "alfia-text-disabled": "#4d4d4d",
        "alfia-text-inverse": "#000000",

        "alfia-text-primary-light": "#000000",
        "alfia-text-secondary-light": "#838383",
        "alfia-text-muted-light": "#7a7a7a",
        "alfia-text-disabled-light": "#b3b3b3",
        "alfia-text-inverse-light": "#ffffff",

        "alfia-btn-primary": "#ffffff",
        "alfia-btn-primary-hover": "#e6e6e6",
        "alfia-btn-secondary": "#1a1a1a",
        "alfia-btn-secondary-hover": "#262626",
        "alfia-btn-ghost-hover": "#1f1f1f",

        "alfia-btn-primary-light": "#000000",
        "alfia-btn-primary-hover-light": "#1a1a1a",
        "alfia-btn-secondary-light": "#f5f5f5",
        "alfia-btn-secondary-hover-light": "#e6e6e6",
        "alfia-btn-ghost-hover-light": "#e0e0e0",

        "alfia-icon-default": "#b3b3b3",
        "alfia-icon-active": "#ffffff",
        "alfia-icon-muted": "#666666",

        "alfia-icon-default-light": "#4d4d4d",
        "alfia-icon-active-light": "#000000",
        "alfia-icon-muted-light": "#7a7a7a",

        "alfia-grad-start": "#ffffff",
        "alfia-grad-mid": "#bfbfbf",
        "alfia-grad-end": "#000000",

        "alfia-accent": "#3b82f6",
        "alfia-accent-hover": "#2563eb",

        "alfia-status-pending": "#6b7280",
        "alfia-status-rejected": "#dc2626",
        "alfia-status-live": "#16a34a",
        "alfia-status-upcoming": "#2563eb",
        "alfia-status-completed": "#6b7280",
      },

      backgroundImage: {
        "alfia-gradient-main":
          "linear-gradient(135deg, #ffffff 0%, #bfbfbf 50%, #000000 100%)",
      },

      keyframes: {
        "ai-glow-border": {
          "0%": { backgroundPosition: "0% 50%" },
          "100%": { backgroundPosition: "100% 50%" },
        },
      },

      animation: {
        "ai-glow-border": "ai-glow-border 3.5s linear infinite",
      },
    },
  },

  plugins: [],
};
```

---

## 5. Configure `postcss.config.js`

```js
export default {
  plugins: {
    tailwindcss: {},
  },
}
```

---

## 6. Import Your CSS File

Inside your main entry file (`main.jsx`, `main.tsx`, etc.):

```js
import "./app.css";
```

---

# Usage

## Basic Usage

```jsx
import React from 'react';
import { PitchDeckEditor } from '@alfia/pitch-deck-editor';

function App() {
  const handleDeckChange = (deck) => {
    console.log('Deck changed:', deck);
  };

  return (
    <div style={{ height: '100vh' }}>
      <PitchDeckEditor
        initialDeck={null}
        onChange={handleDeckChange}
        onNavigateBack={() => console.log('Navigate back')}
      />
    </div>
  );
}

export default App;
```

---

## With Custom API Integration

```jsx
import React from 'react';
import { PitchDeckEditor } from '@alfia/pitch-deck-editor';

function App() {
  const apiClient = {
    updatePitchDeck: async (deckId, payload) => {
      const response = await fetch(`/api/decks/${deckId}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      return response.json();
    },

    getPitchDeck: async (deckId) => {
      const response = await fetch(`/api/decks/${deckId}`);
      return response.json();
    }
  };

  return (
    <div style={{ height: '100vh' }}>
      <PitchDeckEditor
        initialDeck={null}
        apiClient={apiClient}
        deckId="my-deck-id"
        onChange={(deck) => console.log(deck)}
        onNavigateBack={() => console.log('Back')}
      />
    </div>
  );
}

export default App;
```

---

## With AI Integration

```jsx
import React from 'react';
import { PitchDeckEditor } from '@alfia/pitch-deck-editor';

function App() {
  const ai = {
    generateSlide: async (prompt) => {
      // Your AI generation logic
    },

    improveDeck: async (deck) => {
      // Your AI deck improvement logic
    }
  };

  return (
    <div style={{ height: '100vh' }}>
      <PitchDeckEditor
        initialDeck={null}
        ai={ai}
        onChange={(deck) => console.log(deck)}
        onNavigateBack={() => console.log('Back')}
      />
    </div>
  );
}

export default App;
```

---

# API Reference

## `PitchDeckEditor` Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `initialDeck` | `Object` | No | Initial deck state |
| `onChange` | `Function` | Yes | Callback when deck changes |
| `onNavigateBack` | `Function` | Yes | Callback for back navigation |
| `saveStatus` | `String` | No | Save status (`idle`, `saving`, `saved`, `error`) |
| `className` | `String` | No | Additional CSS classes |
| `apiClient` | `Object` | No | Custom API client for persistence |
| `deckId` | `String` | No | Deck ID for API operations |
| `ai` | `Object` | No | AI integration methods |

---

## API Client Interface

```ts
interface ApiClient {
  updatePitchDeck: (deckId: string, payload: any) => Promise<any>;
  getPitchDeck?: (deckId: string) => Promise<any>;
  createPitchDeck?: (payload: any) => Promise<any>;
  deletePitchDeck?: (deckId: string) => Promise<any>;
}
```

---

## Re-exported Hooks and Types

```js
import {
  useEditor,
  createEmptyEditorDeck,
  ElementType,
  ShapeType,
  BackgroundType,
  CANVAS_WIDTH,
  CANVAS_HEIGHT,
  FONT_FAMILIES,
  DEFAULT_THEME
} from '@alfia/pitch-deck-editor';
```

---

# Development

```bash
# Install dependencies
npm install

# Build the library
npm run build

# Run development mode
npm run dev

# Run tests
npm test

# Lint code
npm run lint
```

---

# Troubleshooting

## Tailwind styles are not working

Make sure:

- Tailwind CSS v3 is installed
- The library path is included inside `content`
- Your generated CSS file is imported
- The Tailwind watcher/build process is running

Correct path:

```js
"./node_modules/@alfia/pitch-deck-editor/dist/**/*.{js,jsx,ts,tsx}"
```

---

## Dark mode does not work

Ensure your application adds the `dark` class to the root HTML element:

```js
document.documentElement.classList.add("dark");
```

---

# License

MIT License — see `LICENSE` file for details.
